Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / scrollbar / native_scroll_bar_views.cc
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.
4
5 #include "ui/views/controls/scrollbar/native_scroll_bar_views.h"
6
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"
17
18 namespace views {
19
20 namespace {
21
22 // Wrapper for the scroll buttons.
23 class ScrollBarButton : public BaseScrollBarButton {
24  public:
25   enum Type {
26     UP,
27     DOWN,
28     LEFT,
29     RIGHT,
30   };
31
32   ScrollBarButton(ButtonListener* listener, Type type);
33   ~ScrollBarButton() override;
34
35   gfx::Size GetPreferredSize() const override;
36   const char* GetClassName() const override { return "ScrollBarButton"; }
37
38  protected:
39   void OnPaint(gfx::Canvas* canvas) override;
40
41  private:
42   ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
43   ui::NativeTheme::Part GetNativeThemePart() const;
44   ui::NativeTheme::State GetNativeThemeState() const;
45
46   Type type_;
47 };
48
49 // Wrapper for the scroll thumb
50 class ScrollBarThumb : public BaseScrollBarThumb {
51  public:
52   explicit ScrollBarThumb(BaseScrollBar* scroll_bar);
53   ~ScrollBarThumb() override;
54
55   gfx::Size GetPreferredSize() const override;
56   const char* GetClassName() const override { return "ScrollBarThumb"; }
57
58  protected:
59   void OnPaint(gfx::Canvas* canvas) override;
60
61  private:
62   ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
63   ui::NativeTheme::Part GetNativeThemePart() const;
64   ui::NativeTheme::State GetNativeThemeState() const;
65
66   ScrollBar* scroll_bar_;
67 };
68
69 /////////////////////////////////////////////////////////////////////////////
70 // ScrollBarButton
71
72 ScrollBarButton::ScrollBarButton(ButtonListener* listener, Type type)
73     : BaseScrollBarButton(listener),
74       type_(type) {
75   SetFocusable(false);
76   SetAccessibilityFocusable(false);
77 }
78
79 ScrollBarButton::~ScrollBarButton() {
80 }
81
82 gfx::Size ScrollBarButton::GetPreferredSize() const {
83   return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
84                                        GetNativeThemeState(),
85                                        GetNativeThemeParams());
86 }
87
88 void ScrollBarButton::OnPaint(gfx::Canvas* canvas) {
89   gfx::Rect bounds(GetPreferredSize());
90   GetNativeTheme()->Paint(canvas->sk_canvas(), GetNativeThemePart(),
91                           GetNativeThemeState(), bounds,
92                           GetNativeThemeParams());
93 }
94
95 ui::NativeTheme::ExtraParams
96     ScrollBarButton::GetNativeThemeParams() const {
97   ui::NativeTheme::ExtraParams params;
98
99   switch (state_) {
100     case CustomButton::STATE_HOVERED:
101       params.scrollbar_arrow.is_hovering = true;
102       break;
103     default:
104       params.scrollbar_arrow.is_hovering = false;
105       break;
106   }
107
108   return params;
109 }
110
111 ui::NativeTheme::Part
112     ScrollBarButton::GetNativeThemePart() const {
113   switch (type_) {
114     case UP:
115       return ui::NativeTheme::kScrollbarUpArrow;
116     case DOWN:
117       return ui::NativeTheme::kScrollbarDownArrow;
118     case LEFT:
119       return ui::NativeTheme::kScrollbarLeftArrow;
120     case RIGHT:
121       return ui::NativeTheme::kScrollbarRightArrow;
122     default:
123       return ui::NativeTheme::kScrollbarUpArrow;
124   }
125 }
126
127 ui::NativeTheme::State
128     ScrollBarButton::GetNativeThemeState() const {
129   ui::NativeTheme::State state;
130
131   switch (state_) {
132     case CustomButton::STATE_HOVERED:
133       state = ui::NativeTheme::kHovered;
134       break;
135     case CustomButton::STATE_PRESSED:
136       state = ui::NativeTheme::kPressed;
137       break;
138     case CustomButton::STATE_DISABLED:
139       state = ui::NativeTheme::kDisabled;
140       break;
141     case CustomButton::STATE_NORMAL:
142     default:
143       state = ui::NativeTheme::kNormal;
144       break;
145   }
146
147   return state;
148 }
149
150 /////////////////////////////////////////////////////////////////////////////
151 // ScrollBarThumb
152
153 ScrollBarThumb::ScrollBarThumb(BaseScrollBar* scroll_bar)
154     : BaseScrollBarThumb(scroll_bar),
155       scroll_bar_(scroll_bar) {
156   SetFocusable(false);
157   SetAccessibilityFocusable(false);
158 }
159
160 ScrollBarThumb::~ScrollBarThumb() {
161 }
162
163 gfx::Size ScrollBarThumb::GetPreferredSize() const {
164   return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
165                                        GetNativeThemeState(),
166                                        GetNativeThemeParams());
167 }
168
169 void ScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
170   const gfx::Rect local_bounds(GetLocalBounds());
171   const ui::NativeTheme::State theme_state = GetNativeThemeState();
172   const ui::NativeTheme::ExtraParams extra_params(GetNativeThemeParams());
173   GetNativeTheme()->Paint(canvas->sk_canvas(),
174                           GetNativeThemePart(),
175                           theme_state,
176                           local_bounds,
177                           extra_params);
178   const ui::NativeTheme::Part gripper_part = scroll_bar_->IsHorizontal() ?
179       ui::NativeTheme::kScrollbarHorizontalGripper :
180       ui::NativeTheme::kScrollbarVerticalGripper;
181   GetNativeTheme()->Paint(canvas->sk_canvas(), gripper_part, theme_state,
182                           local_bounds, extra_params);
183 }
184
185 ui::NativeTheme::ExtraParams ScrollBarThumb::GetNativeThemeParams() const {
186   // This gives the behavior we want.
187   ui::NativeTheme::ExtraParams params;
188   params.scrollbar_thumb.is_hovering =
189       (GetState() != CustomButton::STATE_HOVERED);
190   return params;
191 }
192
193 ui::NativeTheme::Part ScrollBarThumb::GetNativeThemePart() const {
194   if (scroll_bar_->IsHorizontal())
195     return ui::NativeTheme::kScrollbarHorizontalThumb;
196   return ui::NativeTheme::kScrollbarVerticalThumb;
197 }
198
199 ui::NativeTheme::State ScrollBarThumb::GetNativeThemeState() const {
200   ui::NativeTheme::State state;
201
202   switch (GetState()) {
203     case CustomButton::STATE_HOVERED:
204       state = ui::NativeTheme::kHovered;
205       break;
206     case CustomButton::STATE_PRESSED:
207       state = ui::NativeTheme::kPressed;
208       break;
209     case CustomButton::STATE_DISABLED:
210       state = ui::NativeTheme::kDisabled;
211       break;
212     case CustomButton::STATE_NORMAL:
213     default:
214       state = ui::NativeTheme::kNormal;
215       break;
216   }
217
218   return state;
219 }
220
221 }  // namespace
222
223 ////////////////////////////////////////////////////////////////////////////////
224 // NativeScrollBarViews, public:
225
226 const char NativeScrollBarViews::kViewClassName[] = "NativeScrollBarViews";
227
228 NativeScrollBarViews::NativeScrollBarViews(NativeScrollBar* scroll_bar)
229     : BaseScrollBar(scroll_bar->IsHorizontal(),
230                     new ScrollBarThumb(this)),
231       native_scroll_bar_(scroll_bar) {
232   set_controller(native_scroll_bar_->controller());
233
234   if (native_scroll_bar_->IsHorizontal()) {
235     prev_button_ = new ScrollBarButton(this, ScrollBarButton::LEFT);
236     next_button_ = new ScrollBarButton(this, ScrollBarButton::RIGHT);
237
238     part_ = ui::NativeTheme::kScrollbarHorizontalTrack;
239   } else {
240     prev_button_ = new ScrollBarButton(this, ScrollBarButton::UP);
241     next_button_ = new ScrollBarButton(this, ScrollBarButton::DOWN);
242
243     part_ = ui::NativeTheme::kScrollbarVerticalTrack;
244   }
245
246   state_ = ui::NativeTheme::kNormal;
247
248   AddChildView(prev_button_);
249   AddChildView(next_button_);
250
251   prev_button_->set_context_menu_controller(this);
252   next_button_->set_context_menu_controller(this);
253 }
254
255 NativeScrollBarViews::~NativeScrollBarViews() {
256 }
257
258 ////////////////////////////////////////////////////////////////////////////////
259 // NativeScrollBarViews, View overrides:
260
261 void NativeScrollBarViews::Layout() {
262   gfx::Size size = prev_button_->GetPreferredSize();
263   prev_button_->SetBounds(0, 0, size.width(), size.height());
264
265   if (native_scroll_bar_->IsHorizontal()) {
266     next_button_->SetBounds(width() - size.width(), 0,
267                             size.width(), size.height());
268   } else {
269     next_button_->SetBounds(0, height() - size.height(),
270                             size.width(), size.height());
271   }
272
273   GetThumb()->SetBoundsRect(GetTrackBounds());
274 }
275
276 void NativeScrollBarViews::OnPaint(gfx::Canvas* canvas) {
277   gfx::Rect bounds = GetTrackBounds();
278
279   if (bounds.IsEmpty())
280     return;
281
282   params_.scrollbar_track.track_x = bounds.x();
283   params_.scrollbar_track.track_y = bounds.y();
284   params_.scrollbar_track.track_width = bounds.width();
285   params_.scrollbar_track.track_height = bounds.height();
286   params_.scrollbar_track.classic_state = 0;
287
288   GetNativeTheme()->Paint(canvas->sk_canvas(), part_, state_, bounds, params_);
289 }
290
291 gfx::Size NativeScrollBarViews::GetPreferredSize() const {
292   const ui::NativeTheme* theme = native_scroll_bar_->GetNativeTheme();
293   if (native_scroll_bar_->IsHorizontal())
294     return gfx::Size(0, GetHorizontalScrollBarHeight(theme));
295   return gfx::Size(GetVerticalScrollBarWidth(theme), 0);
296 }
297
298 const char* NativeScrollBarViews::GetClassName() const {
299   return kViewClassName;
300 }
301
302 int NativeScrollBarViews::GetLayoutSize() const {
303   gfx::Size size = prev_button_->GetPreferredSize();
304   return IsHorizontal() ? size.height() : size.width();
305 }
306
307 void NativeScrollBarViews::ScrollToPosition(int position) {
308   controller()->ScrollToPosition(native_scroll_bar_, position);
309 }
310
311 int NativeScrollBarViews::GetScrollIncrement(bool is_page, bool is_positive) {
312   return controller()->GetScrollIncrement(native_scroll_bar_,
313                                           is_page,
314                                           is_positive);
315 }
316
317 //////////////////////////////////////////////////////////////////////////////
318 // BaseButton::ButtonListener overrides:
319
320 void NativeScrollBarViews::ButtonPressed(Button* sender,
321                                          const ui::Event& event) {
322   if (sender == prev_button_) {
323     ScrollByAmount(SCROLL_PREV_LINE);
324   } else if (sender == next_button_) {
325     ScrollByAmount(SCROLL_NEXT_LINE);
326   }
327 }
328
329 ////////////////////////////////////////////////////////////////////////////////
330 // NativeScrollBarViews, NativeScrollBarWrapper overrides:
331
332 int NativeScrollBarViews::GetPosition() const {
333   return BaseScrollBar::GetPosition();
334 }
335
336 View* NativeScrollBarViews::GetView() {
337   return this;
338 }
339
340 void NativeScrollBarViews::Update(int viewport_size,
341                                   int content_size,
342                                   int current_pos) {
343   BaseScrollBar::Update(viewport_size, content_size, current_pos);
344 }
345
346 ////////////////////////////////////////////////////////////////////////////////
347 // NativeScrollBarViews, private:
348
349 gfx::Rect NativeScrollBarViews::GetTrackBounds() const {
350   gfx::Rect bounds = GetLocalBounds();
351   gfx::Size size = prev_button_->GetPreferredSize();
352   BaseScrollBarThumb* thumb = GetThumb();
353
354   if (native_scroll_bar_->IsHorizontal()) {
355     bounds.set_x(bounds.x() + size.width());
356     bounds.set_width(std::max(0, bounds.width() - 2 * size.width()));
357     bounds.set_height(thumb->GetPreferredSize().height());
358   } else {
359     bounds.set_y(bounds.y() + size.height());
360     bounds.set_height(std::max(0, bounds.height() - 2 * size.height()));
361     bounds.set_width(thumb->GetPreferredSize().width());
362   }
363
364   return bounds;
365 }
366
367 ////////////////////////////////////////////////////////////////////////////////
368 // NativewScrollBarWrapper, public:
369
370 // static
371 NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper(
372     NativeScrollBar* scroll_bar) {
373   return new NativeScrollBarViews(scroll_bar);
374 }
375
376 // static
377 int NativeScrollBarWrapper::GetHorizontalScrollBarHeight(
378     const ui::NativeTheme* theme) {
379   if (!theme)
380     theme = ui::NativeTheme::instance();
381   ui::NativeTheme::ExtraParams button_params;
382   button_params.scrollbar_arrow.is_hovering = false;
383   gfx::Size button_size = theme->GetPartSize(
384       ui::NativeTheme::kScrollbarLeftArrow,
385       ui::NativeTheme::kNormal,
386       button_params);
387
388   ui::NativeTheme::ExtraParams thumb_params;
389   thumb_params.scrollbar_thumb.is_hovering = false;
390   gfx::Size track_size = theme->GetPartSize(
391       ui::NativeTheme::kScrollbarHorizontalThumb,
392       ui::NativeTheme::kNormal,
393       thumb_params);
394
395   return std::max(track_size.height(), button_size.height());
396 }
397
398 // static
399 int NativeScrollBarWrapper::GetVerticalScrollBarWidth(
400     const ui::NativeTheme* theme) {
401   if (!theme)
402     theme = ui::NativeTheme::instance();
403   ui::NativeTheme::ExtraParams button_params;
404   button_params.scrollbar_arrow.is_hovering = false;
405   gfx::Size button_size = theme->GetPartSize(
406       ui::NativeTheme::kScrollbarUpArrow,
407       ui::NativeTheme::kNormal,
408       button_params);
409
410   ui::NativeTheme::ExtraParams thumb_params;
411   thumb_params.scrollbar_thumb.is_hovering = false;
412   gfx::Size track_size = theme->GetPartSize(
413       ui::NativeTheme::kScrollbarVerticalThumb,
414       ui::NativeTheme::kNormal,
415       thumb_params);
416
417   return std::max(track_size.width(), button_size.width());
418 }
419
420 }  // namespace views