OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "ui/views/controls/button/label_button_border.h" | 5 #include "ui/views/controls/button/label_button_border.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
10 #include "ui/base/animation/animation.h" | 10 #include "ui/base/animation/animation.h" |
11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
12 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
13 #include "ui/views/controls/button/label_button.h" | 13 #include "ui/views/controls/button/label_button.h" |
14 | 14 |
15 namespace { | 15 namespace { |
16 | 16 |
17 // Preferred padding between content and edge. | 17 // Preferred padding between content and edge. |
18 static const int kPreferredPaddingHorizontal = 6; | 18 static const int kPreferredPaddingHorizontal = 6; |
19 static const int kPreferredPaddingVertical = 5; | 19 static const int kPreferredPaddingVertical = 5; |
20 | 20 |
21 // Preferred padding between content and edge for NativeTheme border. | 21 // Preferred padding between content and edge for NativeTheme border. |
22 static const int kPreferredNativeThemePaddingHorizontal = 12; | 22 static const int kPreferredNativeThemePaddingHorizontal = 12; |
23 static const int kPreferredNativeThemePaddingVertical = 5; | 23 static const int kPreferredNativeThemePaddingVertical = 5; |
24 | 24 |
25 const int kHoverImageSet[] = { | |
26 IDR_TEXTBUTTON_HOVER_TOP_LEFT, | |
27 IDR_TEXTBUTTON_HOVER_TOP, | |
28 IDR_TEXTBUTTON_HOVER_TOP_RIGHT, | |
29 IDR_TEXTBUTTON_HOVER_LEFT, | |
30 IDR_TEXTBUTTON_HOVER_CENTER, | |
31 IDR_TEXTBUTTON_HOVER_RIGHT, | |
32 IDR_TEXTBUTTON_HOVER_BOTTOM_LEFT, | |
33 IDR_TEXTBUTTON_HOVER_BOTTOM, | |
34 IDR_TEXTBUTTON_HOVER_BOTTOM_RIGHT, | |
35 }; | |
36 | |
37 const int kPressedImageSet[] = { | |
38 IDR_TEXTBUTTON_PRESSED_TOP_LEFT, | |
39 IDR_TEXTBUTTON_PRESSED_TOP, | |
40 IDR_TEXTBUTTON_PRESSED_TOP_RIGHT, | |
41 IDR_TEXTBUTTON_PRESSED_LEFT, | |
42 IDR_TEXTBUTTON_PRESSED_CENTER, | |
43 IDR_TEXTBUTTON_PRESSED_RIGHT, | |
44 IDR_TEXTBUTTON_PRESSED_BOTTOM_LEFT, | |
45 IDR_TEXTBUTTON_PRESSED_BOTTOM, | |
46 IDR_TEXTBUTTON_PRESSED_BOTTOM_RIGHT, | |
47 }; | |
48 | |
49 } // namespace | 25 } // namespace |
50 | 26 |
51 namespace views { | 27 namespace views { |
52 | 28 |
53 LabelButtonBorder::LabelButtonBorder(NativeThemeDelegate* delegate) | 29 LabelButtonBorder::LabelButtonBorder() : native_theme_(false) { |
54 : native_theme_delegate_(delegate), | 30 SetImages(CustomButton::BS_HOT, BorderImages(BorderImages::kHot)); |
55 native_theme_(false) { | 31 SetImages(CustomButton::BS_PUSHED, BorderImages(BorderImages::kPushed)); |
56 SetImages(CustomButton::BS_HOT, BorderImages(kHoverImageSet)); | |
57 SetImages(CustomButton::BS_PUSHED, BorderImages(kPressedImageSet)); | |
58 } | 32 } |
59 | 33 |
60 LabelButtonBorder::~LabelButtonBorder() {} | 34 LabelButtonBorder::~LabelButtonBorder() {} |
61 | 35 |
62 void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) const { | 36 void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) const { |
63 const CustomButton* button = static_cast<const CustomButton*>(&view); | 37 if (native_theme()) |
64 if (native_theme()) { | |
65 PaintNativeTheme(view, canvas); | 38 PaintNativeTheme(view, canvas); |
66 } else if (native_theme_delegate_->GetThemeAnimation() && | 39 else |
67 native_theme_delegate_->GetThemeAnimation()->is_animating()) { | 40 PaintImages(view, canvas); |
68 // TODO(msw): Crossfade between image sets; no-op for equivalent images. | |
69 canvas->SaveLayerAlpha(static_cast<uint8>(native_theme_delegate_-> | |
70 GetThemeAnimation()->CurrentValueBetween(0, 255))); | |
71 canvas->DrawColor(SkColorSetARGB(0x00, 0xFF, 0xFF, 0xFF), | |
72 SkXfermode::kClear_Mode); | |
73 PaintImages(view, canvas, button->state()); | |
74 canvas->Restore(); | |
75 } else { | |
76 PaintImages(view, canvas, button->state()); | |
77 } | |
78 } | 41 } |
79 | 42 |
80 void LabelButtonBorder::GetInsets(gfx::Insets* insets) const { | 43 void LabelButtonBorder::GetInsets(gfx::Insets* insets) const { |
81 if (native_theme()) { | 44 if (native_theme()) { |
82 insets->Set(kPreferredNativeThemePaddingVertical, | 45 insets->Set(kPreferredNativeThemePaddingVertical, |
83 kPreferredNativeThemePaddingHorizontal, | 46 kPreferredNativeThemePaddingHorizontal, |
84 kPreferredNativeThemePaddingVertical, | 47 kPreferredNativeThemePaddingVertical, |
85 kPreferredNativeThemePaddingHorizontal); | 48 kPreferredNativeThemePaddingHorizontal); |
86 } else { | 49 } else { |
87 insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal, | 50 insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal, |
88 kPreferredPaddingVertical, kPreferredPaddingHorizontal); | 51 kPreferredPaddingVertical, kPreferredPaddingHorizontal); |
89 } | 52 } |
90 } | 53 } |
91 | 54 |
92 LabelButtonBorder::BorderImages::BorderImages() {} | |
93 | |
94 LabelButtonBorder::BorderImages::~BorderImages() {} | |
95 | |
96 LabelButtonBorder::BorderImages::BorderImages(const int image_ids[]) { | |
97 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
98 top_left = *rb.GetImageSkiaNamed(image_ids[0]); | |
99 top = *rb.GetImageSkiaNamed(image_ids[1]); | |
100 top_right = *rb.GetImageSkiaNamed(image_ids[2]); | |
101 left = *rb.GetImageSkiaNamed(image_ids[3]); | |
102 center = *rb.GetImageSkiaNamed(image_ids[4]); | |
103 right = *rb.GetImageSkiaNamed(image_ids[5]); | |
104 bottom_left = *rb.GetImageSkiaNamed(image_ids[6]); | |
105 bottom = *rb.GetImageSkiaNamed(image_ids[7]); | |
106 bottom_right = *rb.GetImageSkiaNamed(image_ids[8]); | |
107 } | |
108 | |
109 void LabelButtonBorder::SetImages(CustomButton::ButtonState state, | 55 void LabelButtonBorder::SetImages(CustomButton::ButtonState state, |
110 const BorderImages& set) { | 56 const BorderImages& set) { |
111 images_[state] = set; | 57 images_[state] = set; |
112 } | 58 } |
113 | 59 |
114 void LabelButtonBorder::PaintImages(const View& view, | 60 void LabelButtonBorder::PaintImages(const View& view, |
115 gfx::Canvas* canvas, | 61 gfx::Canvas* canvas) const { |
116 CustomButton::ButtonState state) const { | 62 const LabelButton* button = static_cast<const LabelButton*>(&view); |
117 const BorderImages& set = images_[state]; | 63 const BorderImages& set = images_[button->state()]; |
118 if (set.top_left.isNull()) | 64 if (!set.top_left.isNull()) { |
119 return; | 65 const ui::Animation* animation = button->GetThemeAnimation(); |
120 | 66 if (animation && animation->is_animating()) { |
121 const int width = view.bounds().width(); | 67 // TODO(msw): Crossfade between image sets; no-op for equivalent images. |
122 const int height = view.bounds().height(); | 68 const int alpha = animation->CurrentValueBetween(0, 255); |
123 const int tl_width = set.top_left.width(); | 69 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); |
124 const int tl_height = set.top_left.height(); | 70 set.Paint(view.GetLocalBounds(), canvas); |
125 const int t_height = set.top.height(); | 71 canvas->Restore(); |
126 const int tr_height = set.top_right.height(); | 72 } else { |
127 const int l_width = set.left.width(); | 73 set.Paint(view.GetLocalBounds(), canvas); |
128 const int r_width = set.right.width(); | 74 } |
129 const int bl_width = set.bottom_left.width(); | 75 } |
130 const int bl_height = set.bottom_left.height(); | |
131 const int b_height = set.bottom.height(); | |
132 const int br_width = set.bottom_right.width(); | |
133 const int br_height = set.bottom_right.height(); | |
134 | |
135 canvas->DrawImageInt(set.top_left, 0, 0); | |
136 canvas->DrawImageInt(set.top, 0, 0, set.top.width(), t_height, tl_width, 0, | |
137 width - tl_width - set.top_right.width(), t_height, false); | |
138 canvas->DrawImageInt(set.top_right, width - set.top_right.width(), 0); | |
139 canvas->DrawImageInt(set.left, 0, 0, l_width, set.left.height(), 0, | |
140 tl_height, tl_width, height - tl_height - bl_height, false); | |
141 canvas->DrawImageInt(set.center, 0, 0, set.center.width(), | |
142 set.center.height(), l_width, t_height, width - l_width - r_width, | |
143 height - t_height - b_height, false); | |
144 canvas->DrawImageInt(set.right, 0, 0, r_width, set.right.height(), | |
145 width - r_width, tr_height, r_width, | |
146 height - tr_height - br_height, false); | |
147 canvas->DrawImageInt(set.bottom_left, 0, height - bl_height); | |
148 canvas->DrawImageInt(set.bottom, 0, 0, set.bottom.width(), b_height, | |
149 bl_width, height - b_height, | |
150 width - bl_width - br_width, b_height, false); | |
151 canvas->DrawImageInt(set.bottom_right, width - br_width, | |
152 height - br_height); | |
153 } | 76 } |
154 | 77 |
155 void LabelButtonBorder::PaintNativeTheme(const View& view, | 78 void LabelButtonBorder::PaintNativeTheme(const View& view, |
156 gfx::Canvas* canvas) const { | 79 gfx::Canvas* canvas) const { |
| 80 const LabelButton* button = static_cast<const LabelButton*>(&view); |
157 const ui::NativeTheme* theme = ui::NativeTheme::instance(); | 81 const ui::NativeTheme* theme = ui::NativeTheme::instance(); |
158 ui::NativeTheme::Part part = native_theme_delegate_->GetThemePart(); | 82 ui::NativeTheme::Part part = button->GetThemePart(); |
159 gfx::Rect rect(native_theme_delegate_->GetThemePaintRect()); | 83 gfx::Rect rect(button->GetThemePaintRect()); |
160 | 84 |
161 ui::NativeTheme::State state; | 85 ui::NativeTheme::State state; |
162 ui::NativeTheme::ExtraParams extra; | 86 ui::NativeTheme::ExtraParams extra; |
163 const ui::Animation* animation = native_theme_delegate_->GetThemeAnimation(); | 87 const ui::Animation* animation = button->GetThemeAnimation(); |
164 if (animation && animation->is_animating()) { | 88 if (animation && animation->is_animating()) { |
165 // Paint the background state. | 89 // Paint the background state. |
166 state = native_theme_delegate_->GetBackgroundThemeState(&extra); | 90 state = button->GetBackgroundThemeState(&extra); |
167 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 91 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
168 | 92 |
169 // Composite the foreground state above the background state. | 93 // Composite the foreground state above the background state. |
170 state = native_theme_delegate_->GetForegroundThemeState(&extra); | 94 state = button->GetForegroundThemeState(&extra); |
171 const int alpha = animation->CurrentValueBetween(0, 255); | 95 const int alpha = animation->CurrentValueBetween(0, 255); |
172 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); | 96 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); |
173 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 97 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
174 canvas->Restore(); | 98 canvas->Restore(); |
175 } else { | 99 } else { |
176 state = native_theme_delegate_->GetThemeState(&extra); | 100 state = button->GetThemeState(&extra); |
177 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 101 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
178 } | 102 } |
179 | 103 |
180 // Draw the Views focus border for the native theme style. | 104 // Draw the Views focus border for the native theme style. |
181 if (view.focus_border() && extra.button.is_focused) | 105 if (view.focus_border() && extra.button.is_focused) |
182 view.focus_border()->Paint(view, canvas); | 106 view.focus_border()->Paint(view, canvas); |
183 } | 107 } |
184 | 108 |
185 } // namespace views | 109 } // namespace views |
OLD | NEW |