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 3 // found in the LICENSE file. 4 5 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" 6 7 #include "ui/gfx/canvas.h" 8 #include "ui/gfx/rect.h" 9 #include "ui/views/controls/scrollbar/base_scroll_bar.h" 10 11 namespace { 12 // The distance the mouse can be dragged outside the bounds of the thumb during 13 // dragging before the scrollbar will snap back to its regular position. 14 static const int kScrollThumbDragOutSnap = 100; 15 } 16 17 namespace views { 18 19 BaseScrollBarThumb::BaseScrollBarThumb(BaseScrollBar* scroll_bar) 20 : scroll_bar_(scroll_bar), 21 drag_start_position_(-1), 22 mouse_offset_(-1), 23 state_(CustomButton::STATE_NORMAL) { 24 } 25 26 BaseScrollBarThumb::~BaseScrollBarThumb() { 27 } 28 29 void BaseScrollBarThumb::SetSize(int size) { 30 // Make sure the thumb is never sized smaller than its minimum possible 31 // display size. 32 gfx::Size prefsize = GetPreferredSize(); 33 size = std::max(size, scroll_bar_->IsHorizontal() ? prefsize.width() : 34 prefsize.height()); 35 gfx::Rect thumb_bounds = bounds(); 36 if (scroll_bar_->IsHorizontal()) { 37 thumb_bounds.set_width(size); 38 } else { 39 thumb_bounds.set_height(size); 40 } 41 SetBoundsRect(thumb_bounds); 42 } 43 44 int BaseScrollBarThumb::GetSize() const { 45 if (scroll_bar_->IsHorizontal()) 46 return width(); 47 return height(); 48 } 49 50 void BaseScrollBarThumb::SetPosition(int position) { 51 gfx::Rect thumb_bounds = bounds(); 52 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); 53 if (scroll_bar_->IsHorizontal()) { 54 thumb_bounds.set_x(track_bounds.x() + position); 55 } else { 56 thumb_bounds.set_y(track_bounds.y() + position); 57 } 58 SetBoundsRect(thumb_bounds); 59 } 60 61 int BaseScrollBarThumb::GetPosition() const { 62 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); 63 if (scroll_bar_->IsHorizontal()) 64 return x() - track_bounds.x(); 65 return y() - track_bounds.y(); 66 } 67 68 void BaseScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) { 69 SetState(CustomButton::STATE_HOVERED); 70 } 71 72 void BaseScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) { 73 SetState(CustomButton::STATE_NORMAL); 74 } 75 76 bool BaseScrollBarThumb::OnMousePressed(const ui::MouseEvent& event) { 77 mouse_offset_ = scroll_bar_->IsHorizontal() ? event.x() : event.y(); 78 drag_start_position_ = GetPosition(); 79 SetState(CustomButton::STATE_PRESSED); 80 return true; 81 } 82 83 bool BaseScrollBarThumb::OnMouseDragged(const ui::MouseEvent& event) { 84 // If the user moves the mouse more than |kScrollThumbDragOutSnap| outside 85 // the bounds of the thumb, the scrollbar will snap the scroll back to the 86 // point it was at before the drag began. 87 if (scroll_bar_->IsHorizontal()) { 88 if ((event.y() < y() - kScrollThumbDragOutSnap) || 89 (event.y() > (y() + height() + kScrollThumbDragOutSnap))) { 90 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); 91 return true; 92 } 93 } else { 94 if ((event.x() < x() - kScrollThumbDragOutSnap) || 95 (event.x() > (x() + width() + kScrollThumbDragOutSnap))) { 96 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); 97 return true; 98 } 99 } 100 if (scroll_bar_->IsHorizontal()) { 101 int thumb_x = event.x() - mouse_offset_; 102 if (base::i18n::IsRTL()) 103 thumb_x *= -1; 104 scroll_bar_->ScrollToThumbPosition(GetPosition() + thumb_x, false); 105 } else { 106 int thumb_y = event.y() - mouse_offset_; 107 scroll_bar_->ScrollToThumbPosition(GetPosition() + thumb_y, false); 108 } 109 return true; 110 } 111 112 void BaseScrollBarThumb::OnMouseReleased(const ui::MouseEvent& event) { 113 SetState(HitTestPoint(event.location()) ? 114 CustomButton::STATE_HOVERED : CustomButton::STATE_NORMAL); 115 } 116 117 void BaseScrollBarThumb::OnMouseCaptureLost() { 118 SetState(CustomButton::STATE_HOVERED); 119 } 120 121 CustomButton::ButtonState BaseScrollBarThumb::GetState() const { 122 return state_; 123 } 124 125 void BaseScrollBarThumb::SetState(CustomButton::ButtonState state) { 126 if (state_ == state) 127 return; 128 129 CustomButton::ButtonState old_state = state_; 130 state_ = state; 131 scroll_bar_->OnThumbStateChanged(old_state, state); 132 SchedulePaint(); 133 } 134 135 } // namespace views 136