Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / views / controls / scrollbar / native_scroll_bar_views.cc
blobb4f83ccdf7b932e7942e6885e07bac762f73d7c0
1 // Copyright (c) 2012 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.
5 #include "ui/views/controls/scrollbar/native_scroll_bar_views.h"
7 #include "base/logging.h"
8 #include "ui/events/keycodes/keyboard_codes.h"
9 #include "ui/gfx/canvas.h"
10 #include "ui/gfx/path.h"
11 #include "ui/views/controls/button/custom_button.h"
12 #include "ui/views/controls/focusable_border.h"
13 #include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
14 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
15 #include "ui/views/controls/scrollbar/native_scroll_bar.h"
16 #include "ui/views/controls/scrollbar/scroll_bar.h"
18 namespace views {
20 namespace {
22 // Wrapper for the scroll buttons.
23 class ScrollBarButton : public BaseScrollBarButton {
24 public:
25 enum Type {
26 UP,
27 DOWN,
28 LEFT,
29 RIGHT,
32 ScrollBarButton(ButtonListener* listener, Type type);
33 virtual ~ScrollBarButton();
35 virtual gfx::Size GetPreferredSize() const OVERRIDE;
36 virtual const char* GetClassName() const OVERRIDE {
37 return "ScrollBarButton";
40 protected:
41 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
43 private:
44 ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
45 ui::NativeTheme::Part GetNativeThemePart() const;
46 ui::NativeTheme::State GetNativeThemeState() const;
48 Type type_;
51 // Wrapper for the scroll thumb
52 class ScrollBarThumb : public BaseScrollBarThumb {
53 public:
54 explicit ScrollBarThumb(BaseScrollBar* scroll_bar);
55 virtual ~ScrollBarThumb();
57 virtual gfx::Size GetPreferredSize() const OVERRIDE;
58 virtual const char* GetClassName() const OVERRIDE {
59 return "ScrollBarThumb";
62 protected:
63 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
65 private:
66 ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
67 ui::NativeTheme::Part GetNativeThemePart() const;
68 ui::NativeTheme::State GetNativeThemeState() const;
70 ScrollBar* scroll_bar_;
73 /////////////////////////////////////////////////////////////////////////////
74 // ScrollBarButton
76 ScrollBarButton::ScrollBarButton(ButtonListener* listener, Type type)
77 : BaseScrollBarButton(listener),
78 type_(type) {
79 SetFocusable(false);
80 SetAccessibilityFocusable(false);
83 ScrollBarButton::~ScrollBarButton() {
86 gfx::Size ScrollBarButton::GetPreferredSize() const {
87 return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
88 GetNativeThemeState(),
89 GetNativeThemeParams());
92 void ScrollBarButton::OnPaint(gfx::Canvas* canvas) {
93 gfx::Rect bounds(GetPreferredSize());
94 GetNativeTheme()->Paint(canvas->sk_canvas(), GetNativeThemePart(),
95 GetNativeThemeState(), bounds,
96 GetNativeThemeParams());
99 ui::NativeTheme::ExtraParams
100 ScrollBarButton::GetNativeThemeParams() const {
101 ui::NativeTheme::ExtraParams params;
103 switch (state_) {
104 case CustomButton::STATE_HOVERED:
105 params.scrollbar_arrow.is_hovering = true;
106 break;
107 default:
108 params.scrollbar_arrow.is_hovering = false;
109 break;
112 return params;
115 ui::NativeTheme::Part
116 ScrollBarButton::GetNativeThemePart() const {
117 switch (type_) {
118 case UP:
119 return ui::NativeTheme::kScrollbarUpArrow;
120 case DOWN:
121 return ui::NativeTheme::kScrollbarDownArrow;
122 case LEFT:
123 return ui::NativeTheme::kScrollbarLeftArrow;
124 case RIGHT:
125 return ui::NativeTheme::kScrollbarRightArrow;
126 default:
127 return ui::NativeTheme::kScrollbarUpArrow;
131 ui::NativeTheme::State
132 ScrollBarButton::GetNativeThemeState() const {
133 ui::NativeTheme::State state;
135 switch (state_) {
136 case CustomButton::STATE_HOVERED:
137 state = ui::NativeTheme::kHovered;
138 break;
139 case CustomButton::STATE_PRESSED:
140 state = ui::NativeTheme::kPressed;
141 break;
142 case CustomButton::STATE_DISABLED:
143 state = ui::NativeTheme::kDisabled;
144 break;
145 case CustomButton::STATE_NORMAL:
146 default:
147 state = ui::NativeTheme::kNormal;
148 break;
151 return state;
154 /////////////////////////////////////////////////////////////////////////////
155 // ScrollBarThumb
157 ScrollBarThumb::ScrollBarThumb(BaseScrollBar* scroll_bar)
158 : BaseScrollBarThumb(scroll_bar),
159 scroll_bar_(scroll_bar) {
160 SetFocusable(false);
161 SetAccessibilityFocusable(false);
164 ScrollBarThumb::~ScrollBarThumb() {
167 gfx::Size ScrollBarThumb::GetPreferredSize() const {
168 return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
169 GetNativeThemeState(),
170 GetNativeThemeParams());
173 void ScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
174 const gfx::Rect local_bounds(GetLocalBounds());
175 const ui::NativeTheme::State theme_state = GetNativeThemeState();
176 const ui::NativeTheme::ExtraParams extra_params(GetNativeThemeParams());
177 GetNativeTheme()->Paint(canvas->sk_canvas(),
178 GetNativeThemePart(),
179 theme_state,
180 local_bounds,
181 extra_params);
182 const ui::NativeTheme::Part gripper_part = scroll_bar_->IsHorizontal() ?
183 ui::NativeTheme::kScrollbarHorizontalGripper :
184 ui::NativeTheme::kScrollbarVerticalGripper;
185 GetNativeTheme()->Paint(canvas->sk_canvas(), gripper_part, theme_state,
186 local_bounds, extra_params);
189 ui::NativeTheme::ExtraParams ScrollBarThumb::GetNativeThemeParams() const {
190 // This gives the behavior we want.
191 ui::NativeTheme::ExtraParams params;
192 params.scrollbar_thumb.is_hovering =
193 (GetState() != CustomButton::STATE_HOVERED);
194 return params;
197 ui::NativeTheme::Part ScrollBarThumb::GetNativeThemePart() const {
198 if (scroll_bar_->IsHorizontal())
199 return ui::NativeTheme::kScrollbarHorizontalThumb;
200 return ui::NativeTheme::kScrollbarVerticalThumb;
203 ui::NativeTheme::State ScrollBarThumb::GetNativeThemeState() const {
204 ui::NativeTheme::State state;
206 switch (GetState()) {
207 case CustomButton::STATE_HOVERED:
208 state = ui::NativeTheme::kHovered;
209 break;
210 case CustomButton::STATE_PRESSED:
211 state = ui::NativeTheme::kPressed;
212 break;
213 case CustomButton::STATE_DISABLED:
214 state = ui::NativeTheme::kDisabled;
215 break;
216 case CustomButton::STATE_NORMAL:
217 default:
218 state = ui::NativeTheme::kNormal;
219 break;
222 return state;
225 } // namespace
227 ////////////////////////////////////////////////////////////////////////////////
228 // NativeScrollBarViews, public:
230 const char NativeScrollBarViews::kViewClassName[] = "NativeScrollBarViews";
232 NativeScrollBarViews::NativeScrollBarViews(NativeScrollBar* scroll_bar)
233 : BaseScrollBar(scroll_bar->IsHorizontal(),
234 new ScrollBarThumb(this)),
235 native_scroll_bar_(scroll_bar) {
236 set_controller(native_scroll_bar_->controller());
238 if (native_scroll_bar_->IsHorizontal()) {
239 prev_button_ = new ScrollBarButton(this, ScrollBarButton::LEFT);
240 next_button_ = new ScrollBarButton(this, ScrollBarButton::RIGHT);
242 part_ = ui::NativeTheme::kScrollbarHorizontalTrack;
243 } else {
244 prev_button_ = new ScrollBarButton(this, ScrollBarButton::UP);
245 next_button_ = new ScrollBarButton(this, ScrollBarButton::DOWN);
247 part_ = ui::NativeTheme::kScrollbarVerticalTrack;
250 state_ = ui::NativeTheme::kNormal;
252 AddChildView(prev_button_);
253 AddChildView(next_button_);
255 prev_button_->set_context_menu_controller(this);
256 next_button_->set_context_menu_controller(this);
259 NativeScrollBarViews::~NativeScrollBarViews() {
262 ////////////////////////////////////////////////////////////////////////////////
263 // NativeScrollBarViews, View overrides:
265 void NativeScrollBarViews::Layout() {
266 gfx::Size size = prev_button_->GetPreferredSize();
267 prev_button_->SetBounds(0, 0, size.width(), size.height());
269 if (native_scroll_bar_->IsHorizontal()) {
270 next_button_->SetBounds(width() - size.width(), 0,
271 size.width(), size.height());
272 } else {
273 next_button_->SetBounds(0, height() - size.height(),
274 size.width(), size.height());
277 GetThumb()->SetBoundsRect(GetTrackBounds());
280 void NativeScrollBarViews::OnPaint(gfx::Canvas* canvas) {
281 gfx::Rect bounds = GetTrackBounds();
283 if (bounds.IsEmpty())
284 return;
286 params_.scrollbar_track.track_x = bounds.x();
287 params_.scrollbar_track.track_y = bounds.y();
288 params_.scrollbar_track.track_width = bounds.width();
289 params_.scrollbar_track.track_height = bounds.height();
290 params_.scrollbar_track.classic_state = 0;
292 GetNativeTheme()->Paint(canvas->sk_canvas(), part_, state_, bounds, params_);
295 gfx::Size NativeScrollBarViews::GetPreferredSize() const {
296 const ui::NativeTheme* theme = native_scroll_bar_->GetNativeTheme();
297 if (native_scroll_bar_->IsHorizontal())
298 return gfx::Size(0, GetHorizontalScrollBarHeight(theme));
299 return gfx::Size(GetVerticalScrollBarWidth(theme), 0);
302 const char* NativeScrollBarViews::GetClassName() const {
303 return kViewClassName;
306 int NativeScrollBarViews::GetLayoutSize() const {
307 gfx::Size size = prev_button_->GetPreferredSize();
308 return IsHorizontal() ? size.height() : size.width();
311 void NativeScrollBarViews::ScrollToPosition(int position) {
312 controller()->ScrollToPosition(native_scroll_bar_, position);
315 int NativeScrollBarViews::GetScrollIncrement(bool is_page, bool is_positive) {
316 return controller()->GetScrollIncrement(native_scroll_bar_,
317 is_page,
318 is_positive);
321 //////////////////////////////////////////////////////////////////////////////
322 // BaseButton::ButtonListener overrides:
324 void NativeScrollBarViews::ButtonPressed(Button* sender,
325 const ui::Event& event) {
326 if (sender == prev_button_) {
327 ScrollByAmount(SCROLL_PREV_LINE);
328 } else if (sender == next_button_) {
329 ScrollByAmount(SCROLL_NEXT_LINE);
333 ////////////////////////////////////////////////////////////////////////////////
334 // NativeScrollBarViews, NativeScrollBarWrapper overrides:
336 int NativeScrollBarViews::GetPosition() const {
337 return BaseScrollBar::GetPosition();
340 View* NativeScrollBarViews::GetView() {
341 return this;
344 void NativeScrollBarViews::Update(int viewport_size,
345 int content_size,
346 int current_pos) {
347 BaseScrollBar::Update(viewport_size, content_size, current_pos);
350 ////////////////////////////////////////////////////////////////////////////////
351 // NativeScrollBarViews, private:
353 gfx::Rect NativeScrollBarViews::GetTrackBounds() const {
354 gfx::Rect bounds = GetLocalBounds();
355 gfx::Size size = prev_button_->GetPreferredSize();
356 BaseScrollBarThumb* thumb = GetThumb();
358 if (native_scroll_bar_->IsHorizontal()) {
359 bounds.set_x(bounds.x() + size.width());
360 bounds.set_width(std::max(0, bounds.width() - 2 * size.width()));
361 bounds.set_height(thumb->GetPreferredSize().height());
362 } else {
363 bounds.set_y(bounds.y() + size.height());
364 bounds.set_height(std::max(0, bounds.height() - 2 * size.height()));
365 bounds.set_width(thumb->GetPreferredSize().width());
368 return bounds;
371 ////////////////////////////////////////////////////////////////////////////////
372 // NativewScrollBarWrapper, public:
374 // static
375 NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper(
376 NativeScrollBar* scroll_bar) {
377 return new NativeScrollBarViews(scroll_bar);
380 // static
381 int NativeScrollBarWrapper::GetHorizontalScrollBarHeight(
382 const ui::NativeTheme* theme) {
383 if (!theme)
384 theme = ui::NativeTheme::instance();
385 ui::NativeTheme::ExtraParams button_params;
386 button_params.scrollbar_arrow.is_hovering = false;
387 gfx::Size button_size = theme->GetPartSize(
388 ui::NativeTheme::kScrollbarLeftArrow,
389 ui::NativeTheme::kNormal,
390 button_params);
392 ui::NativeTheme::ExtraParams thumb_params;
393 thumb_params.scrollbar_thumb.is_hovering = false;
394 gfx::Size track_size = theme->GetPartSize(
395 ui::NativeTheme::kScrollbarHorizontalThumb,
396 ui::NativeTheme::kNormal,
397 thumb_params);
399 return std::max(track_size.height(), button_size.height());
402 // static
403 int NativeScrollBarWrapper::GetVerticalScrollBarWidth(
404 const ui::NativeTheme* theme) {
405 if (!theme)
406 theme = ui::NativeTheme::instance();
407 ui::NativeTheme::ExtraParams button_params;
408 button_params.scrollbar_arrow.is_hovering = false;
409 gfx::Size button_size = theme->GetPartSize(
410 ui::NativeTheme::kScrollbarUpArrow,
411 ui::NativeTheme::kNormal,
412 button_params);
414 ui::NativeTheme::ExtraParams thumb_params;
415 thumb_params.scrollbar_thumb.is_hovering = false;
416 gfx::Size track_size = theme->GetPartSize(
417 ui::NativeTheme::kScrollbarVerticalThumb,
418 ui::NativeTheme::kNormal,
419 thumb_params);
421 return std::max(track_size.width(), button_size.width());
424 } // namespace views