Add ICU message format support
[chromium-blink-merge.git] / ui / views / controls / scrollbar / native_scroll_bar_views.cc
blobd69f79f1ee56e44ce091b25d5960ee8d4e1382f2
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 ~ScrollBarButton() override;
35 gfx::Size GetPreferredSize() const override;
36 const char* GetClassName() const override { return "ScrollBarButton"; }
38 protected:
39 void OnPaint(gfx::Canvas* canvas) override;
41 private:
42 ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
43 ui::NativeTheme::Part GetNativeThemePart() const;
44 ui::NativeTheme::State GetNativeThemeState() const;
46 Type type_;
49 // Wrapper for the scroll thumb
50 class ScrollBarThumb : public BaseScrollBarThumb {
51 public:
52 explicit ScrollBarThumb(BaseScrollBar* scroll_bar);
53 ~ScrollBarThumb() override;
55 gfx::Size GetPreferredSize() const override;
56 const char* GetClassName() const override { return "ScrollBarThumb"; }
58 protected:
59 void OnPaint(gfx::Canvas* canvas) override;
61 private:
62 ui::NativeTheme::ExtraParams GetNativeThemeParams() const;
63 ui::NativeTheme::Part GetNativeThemePart() const;
64 ui::NativeTheme::State GetNativeThemeState() const;
66 ScrollBar* scroll_bar_;
69 /////////////////////////////////////////////////////////////////////////////
70 // ScrollBarButton
72 ScrollBarButton::ScrollBarButton(ButtonListener* listener, Type type)
73 : BaseScrollBarButton(listener),
74 type_(type) {
75 SetFocusable(false);
76 SetAccessibilityFocusable(false);
79 ScrollBarButton::~ScrollBarButton() {
82 gfx::Size ScrollBarButton::GetPreferredSize() const {
83 return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
84 GetNativeThemeState(),
85 GetNativeThemeParams());
88 void ScrollBarButton::OnPaint(gfx::Canvas* canvas) {
89 gfx::Rect bounds(GetPreferredSize());
90 GetNativeTheme()->Paint(canvas->sk_canvas(), GetNativeThemePart(),
91 GetNativeThemeState(), bounds,
92 GetNativeThemeParams());
95 ui::NativeTheme::ExtraParams
96 ScrollBarButton::GetNativeThemeParams() const {
97 ui::NativeTheme::ExtraParams params;
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;
108 return params;
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;
127 ui::NativeTheme::State
128 ScrollBarButton::GetNativeThemeState() const {
129 ui::NativeTheme::State state;
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;
147 return state;
150 /////////////////////////////////////////////////////////////////////////////
151 // ScrollBarThumb
153 ScrollBarThumb::ScrollBarThumb(BaseScrollBar* scroll_bar)
154 : BaseScrollBarThumb(scroll_bar),
155 scroll_bar_(scroll_bar) {
156 SetFocusable(false);
157 SetAccessibilityFocusable(false);
160 ScrollBarThumb::~ScrollBarThumb() {
163 gfx::Size ScrollBarThumb::GetPreferredSize() const {
164 return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
165 GetNativeThemeState(),
166 GetNativeThemeParams());
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);
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;
193 ui::NativeTheme::Part ScrollBarThumb::GetNativeThemePart() const {
194 if (scroll_bar_->IsHorizontal())
195 return ui::NativeTheme::kScrollbarHorizontalThumb;
196 return ui::NativeTheme::kScrollbarVerticalThumb;
199 ui::NativeTheme::State ScrollBarThumb::GetNativeThemeState() const {
200 ui::NativeTheme::State state;
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;
218 return state;
221 } // namespace
223 ////////////////////////////////////////////////////////////////////////////////
224 // NativeScrollBarViews, public:
226 const char NativeScrollBarViews::kViewClassName[] = "NativeScrollBarViews";
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());
234 if (native_scroll_bar_->IsHorizontal()) {
235 prev_button_ = new ScrollBarButton(this, ScrollBarButton::LEFT);
236 next_button_ = new ScrollBarButton(this, ScrollBarButton::RIGHT);
238 part_ = ui::NativeTheme::kScrollbarHorizontalTrack;
239 } else {
240 prev_button_ = new ScrollBarButton(this, ScrollBarButton::UP);
241 next_button_ = new ScrollBarButton(this, ScrollBarButton::DOWN);
243 part_ = ui::NativeTheme::kScrollbarVerticalTrack;
246 state_ = ui::NativeTheme::kNormal;
248 AddChildView(prev_button_);
249 AddChildView(next_button_);
251 prev_button_->set_context_menu_controller(this);
252 next_button_->set_context_menu_controller(this);
255 NativeScrollBarViews::~NativeScrollBarViews() {
258 ////////////////////////////////////////////////////////////////////////////////
259 // NativeScrollBarViews, View overrides:
261 void NativeScrollBarViews::Layout() {
262 gfx::Size size = prev_button_->GetPreferredSize();
263 prev_button_->SetBounds(0, 0, size.width(), size.height());
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());
273 GetThumb()->SetBoundsRect(GetTrackBounds());
276 void NativeScrollBarViews::OnPaint(gfx::Canvas* canvas) {
277 gfx::Rect bounds = GetTrackBounds();
279 if (bounds.IsEmpty())
280 return;
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;
288 GetNativeTheme()->Paint(canvas->sk_canvas(), part_, state_, bounds, params_);
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);
298 const char* NativeScrollBarViews::GetClassName() const {
299 return kViewClassName;
302 int NativeScrollBarViews::GetLayoutSize() const {
303 gfx::Size size = prev_button_->GetPreferredSize();
304 return IsHorizontal() ? size.height() : size.width();
307 void NativeScrollBarViews::ScrollToPosition(int position) {
308 controller()->ScrollToPosition(native_scroll_bar_, position);
311 int NativeScrollBarViews::GetScrollIncrement(bool is_page, bool is_positive) {
312 return controller()->GetScrollIncrement(native_scroll_bar_,
313 is_page,
314 is_positive);
317 //////////////////////////////////////////////////////////////////////////////
318 // BaseButton::ButtonListener overrides:
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);
329 ////////////////////////////////////////////////////////////////////////////////
330 // NativeScrollBarViews, NativeScrollBarWrapper overrides:
332 int NativeScrollBarViews::GetPosition() const {
333 return BaseScrollBar::GetPosition();
336 View* NativeScrollBarViews::GetView() {
337 return this;
340 void NativeScrollBarViews::Update(int viewport_size,
341 int content_size,
342 int current_pos) {
343 BaseScrollBar::Update(viewport_size, content_size, current_pos);
346 ////////////////////////////////////////////////////////////////////////////////
347 // NativeScrollBarViews, private:
349 gfx::Rect NativeScrollBarViews::GetTrackBounds() const {
350 gfx::Rect bounds = GetLocalBounds();
351 gfx::Size size = prev_button_->GetPreferredSize();
352 BaseScrollBarThumb* thumb = GetThumb();
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());
364 return bounds;
367 ////////////////////////////////////////////////////////////////////////////////
368 // NativewScrollBarWrapper, public:
370 // static
371 NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper(
372 NativeScrollBar* scroll_bar) {
373 return new NativeScrollBarViews(scroll_bar);
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);
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);
395 return std::max(track_size.height(), button_size.height());
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);
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);
417 return std::max(track_size.width(), button_size.width());
420 } // namespace views