| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "views/controls/scrollbar/bitmap_scroll_bar.h" | 5 #include "views/controls/scrollbar/bitmap_scroll_bar.h" |
| 6 | 6 |
| 7 #if defined(OS_LINUX) | 7 #if defined(OS_LINUX) |
| 8 #include "views/screen.h" | 8 #include "views/screen.h" |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 }; | 90 }; |
| 91 | 91 |
| 92 /////////////////////////////////////////////////////////////////////////////// | 92 /////////////////////////////////////////////////////////////////////////////// |
| 93 // | 93 // |
| 94 // BitmapScrollBarThumb | 94 // BitmapScrollBarThumb |
| 95 // | 95 // |
| 96 // A view that acts as the thumb in the scroll bar track that the user can | 96 // A view that acts as the thumb in the scroll bar track that the user can |
| 97 // drag to scroll the associated contents view within the viewport. | 97 // drag to scroll the associated contents view within the viewport. |
| 98 // | 98 // |
| 99 /////////////////////////////////////////////////////////////////////////////// | 99 /////////////////////////////////////////////////////////////////////////////// |
| 100 class BitmapScrollBarThumb : public View { | 100 class BitmapScrollBarThumb : public BaseScrollBarThumb { |
| 101 public: | 101 public: |
| 102 explicit BitmapScrollBarThumb(BitmapScrollBar* scroll_bar) | 102 explicit BitmapScrollBarThumb(BitmapScrollBar* scroll_bar) |
| 103 : scroll_bar_(scroll_bar), | 103 : BaseScrollBarThumb(scroll_bar), |
| 104 drag_start_position_(-1), | 104 scroll_bar_(scroll_bar) { |
| 105 mouse_offset_(-1), | |
| 106 state_(CustomButton::BS_NORMAL) { | |
| 107 } | 105 } |
| 108 virtual ~BitmapScrollBarThumb() { } | 106 virtual ~BitmapScrollBarThumb() { } |
| 109 | 107 |
| 110 // Sets the size (width or height) of the thumb to the specified value. | |
| 111 void SetSize(int size) { | |
| 112 // Make sure the thumb is never sized smaller than its minimum possible | |
| 113 // display size. | |
| 114 gfx::Size prefsize = GetPreferredSize(); | |
| 115 size = std::max(size, scroll_bar_->IsHorizontal() ? prefsize.width() : | |
| 116 prefsize.height()); | |
| 117 gfx::Rect thumb_bounds = bounds(); | |
| 118 if (scroll_bar_->IsHorizontal()) { | |
| 119 thumb_bounds.set_width(size); | |
| 120 } else { | |
| 121 thumb_bounds.set_height(size); | |
| 122 } | |
| 123 SetBoundsRect(thumb_bounds); | |
| 124 } | |
| 125 | |
| 126 // Retrieves the size (width or height) of the thumb. | |
| 127 int GetSize() const { | |
| 128 if (scroll_bar_->IsHorizontal()) | |
| 129 return width(); | |
| 130 return height(); | |
| 131 } | |
| 132 | |
| 133 // Sets the position of the thumb on the x or y axis. | |
| 134 void SetPosition(int position) { | |
| 135 gfx::Rect thumb_bounds = bounds(); | |
| 136 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); | |
| 137 if (scroll_bar_->IsHorizontal()) { | |
| 138 thumb_bounds.set_x(track_bounds.x() + position); | |
| 139 } else { | |
| 140 thumb_bounds.set_y(track_bounds.y() + position); | |
| 141 } | |
| 142 SetBoundsRect(thumb_bounds); | |
| 143 } | |
| 144 | |
| 145 // Gets the position of the thumb on the x or y axis. | |
| 146 int GetPosition() const { | |
| 147 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); | |
| 148 if (scroll_bar_->IsHorizontal()) | |
| 149 return x() - track_bounds.x(); | |
| 150 return y() - track_bounds.y(); | |
| 151 } | |
| 152 | |
| 153 // View overrides: | 108 // View overrides: |
| 154 virtual gfx::Size GetPreferredSize() OVERRIDE { | 109 virtual gfx::Size GetPreferredSize() OVERRIDE { |
| 155 return gfx::Size(background_bitmap()->width(), | 110 return gfx::Size(background_bitmap()->width(), |
| 156 start_cap_bitmap()->height() + | 111 start_cap_bitmap()->height() + |
| 157 end_cap_bitmap()->height() + | 112 end_cap_bitmap()->height() + |
| 158 grippy_bitmap()->height()); | 113 grippy_bitmap()->height()); |
| 159 } | 114 } |
| 160 | 115 |
| 161 protected: | 116 protected: |
| 162 // View overrides: | 117 // View overrides: |
| 163 virtual void Paint(gfx::Canvas* canvas) OVERRIDE { | 118 virtual void Paint(gfx::Canvas* canvas) OVERRIDE { |
| 164 canvas->DrawBitmapInt(*start_cap_bitmap(), 0, 0); | 119 canvas->DrawBitmapInt(*start_cap_bitmap(), 0, 0); |
| 165 int top_cap_height = start_cap_bitmap()->height(); | 120 int top_cap_height = start_cap_bitmap()->height(); |
| 166 int bottom_cap_height = end_cap_bitmap()->height(); | 121 int bottom_cap_height = end_cap_bitmap()->height(); |
| 167 int thumb_body_height = height() - top_cap_height - bottom_cap_height; | 122 int thumb_body_height = height() - top_cap_height - bottom_cap_height; |
| 168 canvas->TileImageInt(*background_bitmap(), 0, top_cap_height, | 123 canvas->TileImageInt(*background_bitmap(), 0, top_cap_height, |
| 169 background_bitmap()->width(), thumb_body_height); | 124 background_bitmap()->width(), thumb_body_height); |
| 170 canvas->DrawBitmapInt(*end_cap_bitmap(), 0, | 125 canvas->DrawBitmapInt(*end_cap_bitmap(), 0, |
| 171 height() - bottom_cap_height); | 126 height() - bottom_cap_height); |
| 172 | 127 |
| 173 // Paint the grippy over the track. | 128 // Paint the grippy over the track. |
| 174 int grippy_x = (width() - grippy_bitmap()->width()) / 2; | 129 int grippy_x = (width() - grippy_bitmap()->width()) / 2; |
| 175 int grippy_y = (thumb_body_height - grippy_bitmap()->height()) / 2; | 130 int grippy_y = (thumb_body_height - grippy_bitmap()->height()) / 2; |
| 176 canvas->DrawBitmapInt(*grippy_bitmap(), grippy_x, grippy_y); | 131 canvas->DrawBitmapInt(*grippy_bitmap(), grippy_x, grippy_y); |
| 177 } | 132 } |
| 178 | 133 |
| 179 virtual void OnMouseEntered(const MouseEvent& event) OVERRIDE { | |
| 180 SetState(CustomButton::BS_HOT); | |
| 181 } | |
| 182 | |
| 183 virtual void OnMouseExited(const MouseEvent& event) OVERRIDE { | |
| 184 SetState(CustomButton::BS_NORMAL); | |
| 185 } | |
| 186 | |
| 187 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE { | |
| 188 mouse_offset_ = scroll_bar_->IsHorizontal() ? event.x() : event.y(); | |
| 189 drag_start_position_ = GetPosition(); | |
| 190 SetState(CustomButton::BS_PUSHED); | |
| 191 return true; | |
| 192 } | |
| 193 | |
| 194 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE { | |
| 195 // If the user moves the mouse more than |kScrollThumbDragOutSnap| outside | |
| 196 // the bounds of the thumb, the scrollbar will snap the scroll back to the | |
| 197 // point it was at before the drag began. | |
| 198 if (scroll_bar_->IsHorizontal()) { | |
| 199 if ((event.y() < y() - kScrollThumbDragOutSnap) || | |
| 200 (event.y() > (y() + height() + kScrollThumbDragOutSnap))) { | |
| 201 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); | |
| 202 return true; | |
| 203 } | |
| 204 } else { | |
| 205 if ((event.x() < x() - kScrollThumbDragOutSnap) || | |
| 206 (event.x() > (x() + width() + kScrollThumbDragOutSnap))) { | |
| 207 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); | |
| 208 return true; | |
| 209 } | |
| 210 } | |
| 211 if (scroll_bar_->IsHorizontal()) { | |
| 212 int thumb_x = event.x() - mouse_offset_; | |
| 213 scroll_bar_->ScrollToThumbPosition(x() + thumb_x, false); | |
| 214 } else { | |
| 215 int thumb_y = event.y() - mouse_offset_; | |
| 216 scroll_bar_->ScrollToThumbPosition(y() + thumb_y, false); | |
| 217 } | |
| 218 return true; | |
| 219 } | |
| 220 | |
| 221 virtual void OnMouseReleased(const MouseEvent& event) OVERRIDE { | |
| 222 OnMouseCaptureLost(); | |
| 223 } | |
| 224 | |
| 225 virtual void OnMouseCaptureLost() OVERRIDE { | |
| 226 SetState(CustomButton::BS_HOT); | |
| 227 } | |
| 228 | |
| 229 private: | 134 private: |
| 230 // Returns the bitmap rendered at the start of the thumb. | 135 // Returns the bitmap rendered at the start of the thumb. |
| 231 SkBitmap* start_cap_bitmap() const { | 136 SkBitmap* start_cap_bitmap() const { |
| 232 return scroll_bar_->images_[BitmapScrollBar::THUMB_START_CAP][state_]; | 137 return scroll_bar_->images_[BitmapScrollBar::THUMB_START_CAP][GetState()]; |
| 233 } | 138 } |
| 234 | 139 |
| 235 // Returns the bitmap rendered at the end of the thumb. | 140 // Returns the bitmap rendered at the end of the thumb. |
| 236 SkBitmap* end_cap_bitmap() const { | 141 SkBitmap* end_cap_bitmap() const { |
| 237 return scroll_bar_->images_[BitmapScrollBar::THUMB_END_CAP][state_]; | 142 return scroll_bar_->images_[BitmapScrollBar::THUMB_END_CAP][GetState()]; |
| 238 } | 143 } |
| 239 | 144 |
| 240 // Returns the bitmap that is tiled in the background of the thumb between | 145 // Returns the bitmap that is tiled in the background of the thumb between |
| 241 // the start and the end caps. | 146 // the start and the end caps. |
| 242 SkBitmap* background_bitmap() const { | 147 SkBitmap* background_bitmap() const { |
| 243 return scroll_bar_->images_[BitmapScrollBar::THUMB_MIDDLE][state_]; | 148 return scroll_bar_->images_[BitmapScrollBar::THUMB_MIDDLE][GetState()]; |
| 244 } | 149 } |
| 245 | 150 |
| 246 // Returns the bitmap that is rendered in the middle of the thumb | 151 // Returns the bitmap that is rendered in the middle of the thumb |
| 247 // transparently over the background bitmap. | 152 // transparently over the background bitmap. |
| 248 SkBitmap* grippy_bitmap() const { | 153 SkBitmap* grippy_bitmap() const { |
| 249 return scroll_bar_->images_[BitmapScrollBar::THUMB_GRIPPY] | 154 return scroll_bar_->images_[BitmapScrollBar::THUMB_GRIPPY] |
| 250 [CustomButton::BS_NORMAL]; | 155 [CustomButton::BS_NORMAL]; |
| 251 } | 156 } |
| 252 | 157 |
| 253 // Update our state and schedule a repaint when the mouse moves over us. | |
| 254 void SetState(CustomButton::ButtonState state) { | |
| 255 state_ = state; | |
| 256 SchedulePaint(); | |
| 257 } | |
| 258 | |
| 259 // The BitmapScrollBar that owns us. | 158 // The BitmapScrollBar that owns us. |
| 260 BitmapScrollBar* scroll_bar_; | 159 BitmapScrollBar* scroll_bar_; |
| 261 | 160 |
| 262 int drag_start_position_; | |
| 263 | |
| 264 // The position of the mouse on the scroll axis relative to the top of this | |
| 265 // View when the drag started. | |
| 266 int mouse_offset_; | |
| 267 | |
| 268 // The current state of the thumb button. | |
| 269 CustomButton::ButtonState state_; | |
| 270 | |
| 271 DISALLOW_COPY_AND_ASSIGN(BitmapScrollBarThumb); | 161 DISALLOW_COPY_AND_ASSIGN(BitmapScrollBarThumb); |
| 272 }; | 162 }; |
| 273 | 163 |
| 274 } // anonymous namespace | 164 } // anonymous namespace |
| 275 | 165 |
| 276 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
| 277 // BitmapScrollBar, public: | 167 // BitmapScrollBar, public: |
| 278 | 168 |
| 279 BitmapScrollBar::BitmapScrollBar(bool horizontal, bool show_scroll_buttons) | 169 BitmapScrollBar::BitmapScrollBar(bool horizontal, bool show_scroll_buttons) |
| 280 : contents_size_(0), | 170 : BaseScrollBar(horizontal, new BitmapScrollBarThumb(this)), |
| 281 contents_scroll_offset_(0), | 171 contents_scroll_offset_(0), |
| 282 ALLOW_THIS_IN_INITIALIZER_LIST(prev_button_(new AutorepeatButton(this))), | 172 ALLOW_THIS_IN_INITIALIZER_LIST(prev_button_(new AutorepeatButton(this))), |
| 283 ALLOW_THIS_IN_INITIALIZER_LIST(next_button_(new AutorepeatButton(this))), | 173 ALLOW_THIS_IN_INITIALIZER_LIST(next_button_(new AutorepeatButton(this))), |
| 284 ALLOW_THIS_IN_INITIALIZER_LIST(thumb_(new BitmapScrollBarThumb(this))), | |
| 285 thumb_track_state_(CustomButton::BS_NORMAL), | 174 thumb_track_state_(CustomButton::BS_NORMAL), |
| 286 last_scroll_amount_(SCROLL_NONE), | 175 last_scroll_amount_(SCROLL_NONE), |
| 287 ALLOW_THIS_IN_INITIALIZER_LIST(repeater_( | 176 ALLOW_THIS_IN_INITIALIZER_LIST(repeater_( |
| 288 NewCallback<BitmapScrollBar>(this, | 177 NewCallback<BitmapScrollBar>(this, |
| 289 &BitmapScrollBar::TrackClicked))), | 178 &BitmapScrollBar::TrackClicked))), |
| 290 context_menu_mouse_position_(0), | 179 context_menu_mouse_position_(0), |
| 291 show_scroll_buttons_(show_scroll_buttons), | 180 show_scroll_buttons_(show_scroll_buttons), |
| 292 ScrollBar(horizontal) { | 181 ScrollBar(horizontal) { |
| 293 if (!show_scroll_buttons_) { | 182 if (!show_scroll_buttons_) { |
| 294 prev_button_->SetVisible(false); | 183 prev_button_->SetVisible(false); |
| 295 next_button_->SetVisible(false); | 184 next_button_->SetVisible(false); |
| 296 } | 185 } |
| 297 | 186 |
| 298 AddChildView(prev_button_); | 187 AddChildView(prev_button_); |
| 299 AddChildView(next_button_); | 188 AddChildView(next_button_); |
| 300 AddChildView(thumb_); | |
| 301 | 189 |
| 302 set_context_menu_controller(this); | 190 set_context_menu_controller(this); |
| 303 prev_button_->set_context_menu_controller(this); | 191 prev_button_->set_context_menu_controller(this); |
| 304 next_button_->set_context_menu_controller(this); | 192 next_button_->set_context_menu_controller(this); |
| 305 thumb_->set_context_menu_controller(this); | |
| 306 } | |
| 307 | |
| 308 gfx::Rect BitmapScrollBar::GetTrackBounds() const { | |
| 309 gfx::Size prefsize = prev_button_->GetPreferredSize(); | |
| 310 if (IsHorizontal()) { | |
| 311 if (!show_scroll_buttons_) | |
| 312 prefsize.set_width(0); | |
| 313 int new_width = | |
| 314 std::max(0, width() - (prefsize.width() * 2)); | |
| 315 gfx::Rect track_bounds(prefsize.width(), 0, new_width, prefsize.height()); | |
| 316 return track_bounds; | |
| 317 } | |
| 318 if (!show_scroll_buttons_) | |
| 319 prefsize.set_height(0); | |
| 320 gfx::Rect track_bounds(0, prefsize.height(), prefsize.width(), | |
| 321 std::max(0, height() - (prefsize.height() * 2))); | |
| 322 return track_bounds; | |
| 323 } | 193 } |
| 324 | 194 |
| 325 void BitmapScrollBar::SetImage(ScrollBarPart part, | 195 void BitmapScrollBar::SetImage(ScrollBarPart part, |
| 326 CustomButton::ButtonState state, | 196 CustomButton::ButtonState state, |
| 327 SkBitmap* bitmap) { | 197 SkBitmap* bitmap) { |
| 328 DCHECK(part < PART_COUNT); | 198 DCHECK(part < PART_COUNT); |
| 329 DCHECK(state < CustomButton::BS_COUNT); | 199 DCHECK(state < CustomButton::BS_COUNT); |
| 330 switch (part) { | 200 switch (part) { |
| 331 case PREV_BUTTON: | 201 case PREV_BUTTON: |
| 332 prev_button_->SetImage(state, bitmap); | 202 prev_button_->SetImage(state, bitmap); |
| 333 break; | 203 break; |
| 334 case NEXT_BUTTON: | 204 case NEXT_BUTTON: |
| 335 next_button_->SetImage(state, bitmap); | 205 next_button_->SetImage(state, bitmap); |
| 336 break; | 206 break; |
| 337 case THUMB_START_CAP: | 207 case THUMB_START_CAP: |
| 338 case THUMB_MIDDLE: | 208 case THUMB_MIDDLE: |
| 339 case THUMB_END_CAP: | 209 case THUMB_END_CAP: |
| 340 case THUMB_GRIPPY: | 210 case THUMB_GRIPPY: |
| 341 case THUMB_TRACK: | 211 case THUMB_TRACK: |
| 342 images_[part][state] = bitmap; | 212 images_[part][state] = bitmap; |
| 343 break; | 213 break; |
| 344 } | 214 } |
| 345 } | 215 } |
| 346 | 216 |
| 347 void BitmapScrollBar::ScrollByAmount(ScrollAmount amount) { | 217 int BaseScrollBar::GetLayoutSize() const { |
| 348 ScrollBarController* controller = GetController(); | 218 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
| 349 int offset = contents_scroll_offset_; | 219 return IsHorizontal() ? prefsize.height() : prefsize.width(); |
| 350 switch (amount) { | |
| 351 case SCROLL_START: | |
| 352 offset = GetMinPosition(); | |
| 353 break; | |
| 354 case SCROLL_END: | |
| 355 offset = GetMaxPosition(); | |
| 356 break; | |
| 357 case SCROLL_PREV_LINE: | |
| 358 offset -= controller->GetScrollIncrement(this, false, false); | |
| 359 offset = std::max(GetMinPosition(), offset); | |
| 360 break; | |
| 361 case SCROLL_NEXT_LINE: | |
| 362 offset += controller->GetScrollIncrement(this, false, true); | |
| 363 offset = std::min(GetMaxPosition(), offset); | |
| 364 break; | |
| 365 case SCROLL_PREV_PAGE: | |
| 366 offset -= controller->GetScrollIncrement(this, true, false); | |
| 367 offset = std::max(GetMinPosition(), offset); | |
| 368 break; | |
| 369 case SCROLL_NEXT_PAGE: | |
| 370 offset += controller->GetScrollIncrement(this, true, true); | |
| 371 offset = std::min(GetMaxPosition(), offset); | |
| 372 break; | |
| 373 } | |
| 374 contents_scroll_offset_ = offset; | |
| 375 ScrollContentsToOffset(); | |
| 376 } | 220 } |
| 377 | 221 |
| 378 void BitmapScrollBar::ScrollToThumbPosition(int thumb_position, | 222 gfx::Rect BaseScrollBar::GetTrackBounds() const { |
| 379 bool scroll_to_middle) { | 223 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
| 380 contents_scroll_offset_ = | 224 if (IsHorizontal()) { |
| 381 CalculateContentsOffset(thumb_position, scroll_to_middle); | 225 if (!show_scroll_buttons_) |
| 382 if (contents_scroll_offset_ < GetMinPosition()) { | 226 prefsize.set_width(0); |
| 383 contents_scroll_offset_ = GetMinPosition(); | 227 int new_width = |
| 384 } else if (contents_scroll_offset_ > GetMaxPosition()) { | 228 std::max(0, width() - (prefsize.width() * 2)); |
| 385 contents_scroll_offset_ = GetMaxPosition(); | 229 gfx::Rect track_bounds(prefsize.width(), 0, new_width, prefsize.height()); |
| 230 return track_bounds; |
| 386 } | 231 } |
| 387 ScrollContentsToOffset(); | 232 if (!show_scroll_buttons_) |
| 388 SchedulePaint(); | 233 prefsize.set_height(0); |
| 389 } | 234 gfx::Rect track_bounds(0, prefsize.height(), prefsize.width(), |
| 390 | 235 std::max(0, height() - (prefsize.height() * 2))); |
| 391 void BitmapScrollBar::ScrollByContentsOffset(int contents_offset) { | 236 return track_bounds; |
| 392 contents_scroll_offset_ -= contents_offset; | |
| 393 if (contents_scroll_offset_ < GetMinPosition()) { | |
| 394 contents_scroll_offset_ = GetMinPosition(); | |
| 395 } else if (contents_scroll_offset_ > GetMaxPosition()) { | |
| 396 contents_scroll_offset_ = GetMaxPosition(); | |
| 397 } | |
| 398 ScrollContentsToOffset(); | |
| 399 } | 237 } |
| 400 | 238 |
| 401 /////////////////////////////////////////////////////////////////////////////// | 239 /////////////////////////////////////////////////////////////////////////////// |
| 402 // BitmapScrollBar, View implementation: | 240 // BaseScrollBar, View implementation: |
| 403 | 241 |
| 404 gfx::Size BitmapScrollBar::GetPreferredSize() { | 242 gfx::Size BaseScrollBar::GetPreferredSize() { |
| 405 // In this case, we're returning the desired width of the scrollbar and its | 243 // In this case, we're returning the desired width of the scrollbar and its |
| 406 // minimum allowable height. | 244 // minimum allowable height. |
| 407 gfx::Size button_prefsize = prev_button_->GetPreferredSize(); | 245 gfx::Size button_prefsize = prev_button_->GetPreferredSize(); |
| 408 return gfx::Size(button_prefsize.width(), button_prefsize.height() * 2); | 246 return gfx::Size(button_prefsize.width(), button_prefsize.height() * 2); |
| 409 } | 247 } |
| 410 | 248 |
| 411 void BitmapScrollBar::Layout() { | 249 void BaseScrollBar::Layout() { |
| 412 // Size and place the two scroll buttons. | 250 // Size and place the two scroll buttons. |
| 413 if (show_scroll_buttons_) { | 251 if (show_scroll_buttons_) { |
| 414 gfx::Size prefsize = prev_button_->GetPreferredSize(); | 252 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
| 415 prev_button_->SetBounds(0, 0, prefsize.width(), prefsize.height()); | 253 prev_button_->SetBounds(0, 0, prefsize.width(), prefsize.height()); |
| 416 prefsize = next_button_->GetPreferredSize(); | 254 prefsize = next_button_->GetPreferredSize(); |
| 417 if (IsHorizontal()) { | 255 if (IsHorizontal()) { |
| 418 next_button_->SetBounds(width() - prefsize.width(), 0, prefsize.width(), | 256 next_button_->SetBounds(width() - prefsize.width(), 0, prefsize.width(), |
| 419 prefsize.height()); | 257 prefsize.height()); |
| 420 } else { | 258 } else { |
| 421 next_button_->SetBounds(0, height() - prefsize.height(), prefsize.width(), | 259 next_button_->SetBounds(0, height() - prefsize.height(), prefsize.width(), |
| 422 prefsize.height()); | 260 prefsize.height()); |
| 423 } | 261 } |
| 424 } else { | 262 } else { |
| 425 prev_button_->SetBounds(0, 0, 0, 0); | 263 prev_button_->SetBounds(0, 0, 0, 0); |
| 426 next_button_->SetBounds(0, 0, 0, 0); | 264 next_button_->SetBounds(0, 0, 0, 0); |
| 427 } | 265 } |
| 428 | 266 |
| 267 BaseScrollBarThumb* thumb = GetThumb(); |
| 429 // Size and place the thumb | 268 // Size and place the thumb |
| 430 gfx::Size thumb_prefsize = thumb_->GetPreferredSize(); | 269 gfx::Size thumb_prefsize = thumb->GetPreferredSize(); |
| 431 gfx::Rect track_bounds = GetTrackBounds(); | 270 gfx::Rect track_bounds = GetTrackBounds(); |
| 432 | 271 |
| 433 // Preserve the height/width of the thumb (depending on orientation) as set | 272 // Preserve the height/width of the thumb (depending on orientation) as set |
| 434 // by the last call to |Update|, but coerce the width/height to be the | 273 // by the last call to |Update|, but coerce the width/height to be the |
| 435 // appropriate value for the bitmaps provided. | 274 // appropriate value for the bitmaps provided. |
| 436 if (IsHorizontal()) { | 275 if (IsHorizontal()) { |
| 437 thumb_->SetBounds(thumb_->x(), thumb_->y(), thumb_->width(), | 276 thumb->SetBounds(thumb->x(), thumb->y(), thumb->width(), |
| 438 thumb_prefsize.height()); | 277 thumbprefsize.height()); |
| 439 } else { | 278 } else { |
| 440 thumb_->SetBounds(thumb_->x(), thumb_->y(), thumb_prefsize.width(), | 279 thumb->SetBounds(thumb->x(), thumb->y(), thumbprefsize.width(), |
| 441 thumb_->height()); | 280 thumb->height()); |
| 442 } | 281 } |
| 443 | 282 |
| 444 // Hide the thumb if the track isn't tall enough to display even a tiny | 283 // Hide the thumb if the track isn't tall enough to display even a tiny |
| 445 // thumb. The user can only use the mousewheel, scroll buttons or keyboard | 284 // thumb. The user can only use the mousewheel, scroll buttons or keyboard |
| 446 // in this scenario. | 285 // in this scenario. |
| 447 if ((IsHorizontal() && (track_bounds.width() < thumb_prefsize.width()) || | 286 if ((IsHorizontal() && (track_bounds.width() < thumb_prefsize.width()) || |
| 448 (!IsHorizontal() && (track_bounds.height() < thumb_prefsize.height())))) { | 287 (!IsHorizontal() && (track_bounds.height() < thumb_prefsize.height())))) { |
| 449 thumb_->SetVisible(false); | 288 thumb->SetVisible(false); |
| 450 } else if (!thumb_->IsVisible()) { | 289 } else if (!thumb->IsVisible()) { |
| 451 thumb_->SetVisible(true); | 290 thumb->SetVisible(true); |
| 452 } | 291 } |
| 453 } | 292 } |
| 454 | 293 |
| 455 bool BitmapScrollBar::OnMousePressed(const MouseEvent& event) { | |
| 456 if (event.IsOnlyLeftMouseButton()) { | |
| 457 SetThumbTrackState(CustomButton::BS_PUSHED); | |
| 458 gfx::Rect thumb_bounds = thumb_->bounds(); | |
| 459 if (IsHorizontal()) { | |
| 460 if (event.x() < thumb_bounds.x()) { | |
| 461 last_scroll_amount_ = SCROLL_PREV_PAGE; | |
| 462 } else if (event.x() > thumb_bounds.right()) { | |
| 463 last_scroll_amount_ = SCROLL_NEXT_PAGE; | |
| 464 } | |
| 465 } else { | |
| 466 if (event.y() < thumb_bounds.y()) { | |
| 467 last_scroll_amount_ = SCROLL_PREV_PAGE; | |
| 468 } else if (event.y() > thumb_bounds.bottom()) { | |
| 469 last_scroll_amount_ = SCROLL_NEXT_PAGE; | |
| 470 } | |
| 471 } | |
| 472 TrackClicked(); | |
| 473 repeater_.Start(); | |
| 474 } | |
| 475 return true; | |
| 476 } | |
| 477 | |
| 478 void BitmapScrollBar::OnMouseReleased(const MouseEvent& event) { | |
| 479 OnMouseCaptureLost(); | |
| 480 } | |
| 481 | |
| 482 void BitmapScrollBar::OnMouseCaptureLost() { | |
| 483 SetThumbTrackState(CustomButton::BS_NORMAL); | |
| 484 repeater_.Stop(); | |
| 485 } | |
| 486 | |
| 487 bool BitmapScrollBar::OnKeyPressed(const KeyEvent& event) { | |
| 488 ScrollAmount amount = SCROLL_NONE; | |
| 489 switch (event.key_code()) { | |
| 490 case ui::VKEY_UP: | |
| 491 if (!IsHorizontal()) | |
| 492 amount = SCROLL_PREV_LINE; | |
| 493 break; | |
| 494 case ui::VKEY_DOWN: | |
| 495 if (!IsHorizontal()) | |
| 496 amount = SCROLL_NEXT_LINE; | |
| 497 break; | |
| 498 case ui::VKEY_LEFT: | |
| 499 if (IsHorizontal()) | |
| 500 amount = SCROLL_PREV_LINE; | |
| 501 break; | |
| 502 case ui::VKEY_RIGHT: | |
| 503 if (IsHorizontal()) | |
| 504 amount = SCROLL_NEXT_LINE; | |
| 505 break; | |
| 506 case ui::VKEY_PRIOR: | |
| 507 amount = SCROLL_PREV_PAGE; | |
| 508 break; | |
| 509 case ui::VKEY_NEXT: | |
| 510 amount = SCROLL_NEXT_PAGE; | |
| 511 break; | |
| 512 case ui::VKEY_HOME: | |
| 513 amount = SCROLL_START; | |
| 514 break; | |
| 515 case ui::VKEY_END: | |
| 516 amount = SCROLL_END; | |
| 517 break; | |
| 518 } | |
| 519 if (amount != SCROLL_NONE) { | |
| 520 ScrollByAmount(amount); | |
| 521 return true; | |
| 522 } | |
| 523 return false; | |
| 524 } | |
| 525 | |
| 526 bool BitmapScrollBar::OnMouseWheel(const MouseWheelEvent& event) { | |
| 527 ScrollByContentsOffset(event.offset()); | |
| 528 return true; | |
| 529 } | |
| 530 | |
| 531 /////////////////////////////////////////////////////////////////////////////// | |
| 532 // BitmapScrollBar, ContextMenuController implementation: | |
| 533 | |
| 534 enum ScrollBarContextMenuCommands { | |
| 535 ScrollBarContextMenuCommand_ScrollHere = 1, | |
| 536 ScrollBarContextMenuCommand_ScrollStart, | |
| 537 ScrollBarContextMenuCommand_ScrollEnd, | |
| 538 ScrollBarContextMenuCommand_ScrollPageUp, | |
| 539 ScrollBarContextMenuCommand_ScrollPageDown, | |
| 540 ScrollBarContextMenuCommand_ScrollPrev, | |
| 541 ScrollBarContextMenuCommand_ScrollNext | |
| 542 }; | |
| 543 | |
| 544 void BitmapScrollBar::ShowContextMenuForView(View* source, | |
| 545 const gfx::Point& p, | |
| 546 bool is_mouse_gesture) { | |
| 547 Widget* widget = GetWidget(); | |
| 548 gfx::Rect widget_bounds = widget->GetWindowScreenBounds(); | |
| 549 gfx::Point temp_pt(p.x() - widget_bounds.x(), p.y() - widget_bounds.y()); | |
| 550 View::ConvertPointFromWidget(this, &temp_pt); | |
| 551 context_menu_mouse_position_ = IsHorizontal() ? temp_pt.x() : temp_pt.y(); | |
| 552 | |
| 553 scoped_ptr<Menu> menu( | |
| 554 Menu::Create(this, Menu::TOPLEFT, GetWidget()->GetNativeView())); | |
| 555 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollHere); | |
| 556 menu->AppendSeparator(); | |
| 557 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollStart); | |
| 558 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollEnd); | |
| 559 menu->AppendSeparator(); | |
| 560 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageUp); | |
| 561 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageDown); | |
| 562 menu->AppendSeparator(); | |
| 563 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPrev); | |
| 564 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollNext); | |
| 565 menu->RunMenuAt(p.x(), p.y()); | |
| 566 } | |
| 567 | |
| 568 /////////////////////////////////////////////////////////////////////////////// | |
| 569 // BitmapScrollBar, Menu::Delegate implementation: | |
| 570 | |
| 571 std::wstring BitmapScrollBar::GetLabel(int id) const { | |
| 572 int ids_value = 0; | |
| 573 switch (id) { | |
| 574 case ScrollBarContextMenuCommand_ScrollHere: | |
| 575 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE; | |
| 576 break; | |
| 577 case ScrollBarContextMenuCommand_ScrollStart: | |
| 578 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE | |
| 579 : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME; | |
| 580 break; | |
| 581 case ScrollBarContextMenuCommand_ScrollEnd: | |
| 582 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE | |
| 583 : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND; | |
| 584 break; | |
| 585 case ScrollBarContextMenuCommand_ScrollPageUp: | |
| 586 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEUP; | |
| 587 break; | |
| 588 case ScrollBarContextMenuCommand_ScrollPageDown: | |
| 589 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEDOWN; | |
| 590 break; | |
| 591 case ScrollBarContextMenuCommand_ScrollPrev: | |
| 592 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT | |
| 593 : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP; | |
| 594 break; | |
| 595 case ScrollBarContextMenuCommand_ScrollNext: | |
| 596 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT | |
| 597 : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN; | |
| 598 break; | |
| 599 default: | |
| 600 NOTREACHED() << "Invalid BitmapScrollBar Context Menu command!"; | |
| 601 } | |
| 602 | |
| 603 return ids_value ? UTF16ToWide(l10n_util::GetStringUTF16(ids_value)) : L""; | |
| 604 } | |
| 605 | |
| 606 bool BitmapScrollBar::IsCommandEnabled(int id) const { | |
| 607 switch (id) { | |
| 608 case ScrollBarContextMenuCommand_ScrollPageUp: | |
| 609 case ScrollBarContextMenuCommand_ScrollPageDown: | |
| 610 return !IsHorizontal(); | |
| 611 } | |
| 612 return true; | |
| 613 } | |
| 614 | |
| 615 void BitmapScrollBar::ExecuteCommand(int id) { | |
| 616 switch (id) { | |
| 617 case ScrollBarContextMenuCommand_ScrollHere: | |
| 618 ScrollToThumbPosition(context_menu_mouse_position_, true); | |
| 619 break; | |
| 620 case ScrollBarContextMenuCommand_ScrollStart: | |
| 621 ScrollByAmount(SCROLL_START); | |
| 622 break; | |
| 623 case ScrollBarContextMenuCommand_ScrollEnd: | |
| 624 ScrollByAmount(SCROLL_END); | |
| 625 break; | |
| 626 case ScrollBarContextMenuCommand_ScrollPageUp: | |
| 627 ScrollByAmount(SCROLL_PREV_PAGE); | |
| 628 break; | |
| 629 case ScrollBarContextMenuCommand_ScrollPageDown: | |
| 630 ScrollByAmount(SCROLL_NEXT_PAGE); | |
| 631 break; | |
| 632 case ScrollBarContextMenuCommand_ScrollPrev: | |
| 633 ScrollByAmount(SCROLL_PREV_LINE); | |
| 634 break; | |
| 635 case ScrollBarContextMenuCommand_ScrollNext: | |
| 636 ScrollByAmount(SCROLL_NEXT_LINE); | |
| 637 break; | |
| 638 } | |
| 639 } | |
| 640 | |
| 641 /////////////////////////////////////////////////////////////////////////////// | |
| 642 // BitmapScrollBar, ButtonListener implementation: | |
| 643 | |
| 644 void BitmapScrollBar::ButtonPressed(Button* sender, const views::Event& event) { | |
| 645 if (sender == prev_button_) { | |
| 646 ScrollByAmount(SCROLL_PREV_LINE); | |
| 647 } else if (sender == next_button_) { | |
| 648 ScrollByAmount(SCROLL_NEXT_LINE); | |
| 649 } | |
| 650 } | |
| 651 | |
| 652 /////////////////////////////////////////////////////////////////////////////// | |
| 653 // BitmapScrollBar, ScrollBar implementation: | |
| 654 | |
| 655 void BitmapScrollBar::Update(int viewport_size, int content_size, | |
| 656 int contents_scroll_offset) { | |
| 657 ScrollBar::Update(viewport_size, content_size, contents_scroll_offset); | |
| 658 | |
| 659 // Make sure contents_size is always > 0 to avoid divide by zero errors in | |
| 660 // calculations throughout this code. | |
| 661 contents_size_ = std::max(1, content_size); | |
| 662 | |
| 663 if (content_size < 0) | |
| 664 content_size = 0; | |
| 665 if (contents_scroll_offset < 0) | |
| 666 contents_scroll_offset = 0; | |
| 667 if (contents_scroll_offset > content_size) | |
| 668 contents_scroll_offset = content_size; | |
| 669 | |
| 670 // Thumb Height and Thumb Pos. | |
| 671 // The height of the thumb is the ratio of the Viewport height to the | |
| 672 // content size multiplied by the height of the thumb track. | |
| 673 double ratio = static_cast<double>(viewport_size) / contents_size_; | |
| 674 int thumb_size = static_cast<int>(ratio * GetTrackSize()); | |
| 675 thumb_->SetSize(thumb_size); | |
| 676 | |
| 677 int thumb_position = CalculateThumbPosition(contents_scroll_offset); | |
| 678 thumb_->SetPosition(thumb_position); | |
| 679 } | |
| 680 | |
| 681 int BitmapScrollBar::GetLayoutSize() const { | |
| 682 gfx::Size prefsize = prev_button_->GetPreferredSize(); | |
| 683 return IsHorizontal() ? prefsize.height() : prefsize.width(); | |
| 684 } | |
| 685 | |
| 686 int BitmapScrollBar::GetPosition() const { | |
| 687 return thumb_->GetPosition(); | |
| 688 } | |
| 689 | |
| 690 /////////////////////////////////////////////////////////////////////////////// | 294 /////////////////////////////////////////////////////////////////////////////// |
| 691 // BitmapScrollBar, View implementation: | 295 // BitmapScrollBar, View implementation: |
| 692 | 296 |
| 693 void BitmapScrollBar::OnPaint(gfx::Canvas* canvas) { | 297 void BitmapScrollBar::OnPaint(gfx::Canvas* canvas) { |
| 694 // Paint the track. | 298 // Paint the track. |
| 695 gfx::Rect track_bounds = GetTrackBounds(); | 299 gfx::Rect track_bounds = GetTrackBounds(); |
| 696 canvas->TileImageInt(*images_[THUMB_TRACK][thumb_track_state_], | 300 canvas->TileImageInt(*images_[THUMB_TRACK][thumb_track_state_], |
| 697 track_bounds.x(), track_bounds.y(), | 301 track_bounds.x(), track_bounds.y(), |
| 698 track_bounds.width(), track_bounds.height()); | 302 track_bounds.width(), track_bounds.height()); |
| 699 } | 303 } |
| 700 | 304 |
| 701 /////////////////////////////////////////////////////////////////////////////// | 305 /////////////////////////////////////////////////////////////////////////////// |
| 702 // BitmapScrollBar, private: | 306 // BaseScrollBar, ButtonListener implementation: |
| 703 | 307 |
| 704 void BitmapScrollBar::TrackClicked() { | 308 void BaseScrollBar::ButtonPressed(Button* sender, const views::Event& event) { |
| 705 if (last_scroll_amount_ != SCROLL_NONE) | 309 if (sender == prev_button_) { |
| 706 ScrollByAmount(last_scroll_amount_); | 310 ScrollByAmount(SCROLL_PREV_LINE); |
| 707 } | 311 } else if (sender == next_button_) { |
| 708 | 312 ScrollByAmount(SCROLL_NEXT_LINE); |
| 709 void BitmapScrollBar::ScrollContentsToOffset() { | 313 } |
| 710 GetController()->ScrollToPosition(this, contents_scroll_offset_); | |
| 711 thumb_->SetPosition(CalculateThumbPosition(contents_scroll_offset_)); | |
| 712 } | |
| 713 | |
| 714 int BitmapScrollBar::GetTrackSize() const { | |
| 715 gfx::Rect track_bounds = GetTrackBounds(); | |
| 716 return IsHorizontal() ? track_bounds.width() : track_bounds.height(); | |
| 717 } | |
| 718 | |
| 719 int BitmapScrollBar::CalculateThumbPosition(int contents_scroll_offset) const { | |
| 720 return (contents_scroll_offset * GetTrackSize()) / contents_size_; | |
| 721 } | |
| 722 | |
| 723 int BitmapScrollBar::CalculateContentsOffset(int thumb_position, | |
| 724 bool scroll_to_middle) const { | |
| 725 if (scroll_to_middle) | |
| 726 thumb_position = thumb_position - (thumb_->GetSize() / 2); | |
| 727 return (thumb_position * contents_size_) / GetTrackSize(); | |
| 728 } | |
| 729 | |
| 730 void BitmapScrollBar::SetThumbTrackState(CustomButton::ButtonState state) { | |
| 731 thumb_track_state_ = state; | |
| 732 SchedulePaint(); | |
| 733 } | 314 } |
| 734 | 315 |
| 735 } // namespace views | 316 } // namespace views |
| OLD | NEW |