OLD | NEW |
---|---|
(Empty) | |
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/button/web_style_text_button.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "ui/gfx/canvas.h" | |
10 #include "ui/gfx/color_utils.h" | |
11 #include "ui/views/painter.h" | |
12 #include "ui/views/background.h" | |
13 | |
14 namespace views { | |
15 namespace { | |
16 const int kMinWidth = 72; | |
17 const int kMinHeight = 27; | |
18 | |
19 // Fractional position between top and bottom of button where the | |
20 // gradient starts. | |
21 const SkScalar kGradientStartLocation = 0.38f; | |
22 const SkColor kNormalBackgroundTopColor = SkColorSetRGB(0xf0, 0xf0, 0xf0); | |
23 const SkColor kNormalBackgroundBottomColor = SkColorSetRGB(0xe0, 0xe0, 0xe0); | |
24 const SkColor kHotBackgroundTopColor = SkColorSetRGB(0xf4, 0xf4, 0xf4); | |
25 const SkColor kHotBackgroundBottomColor = SkColorSetRGB(0xe4, 0xe4, 0xe4); | |
26 const SkColor kPushedBackgroundTopColor = SkColorSetRGB(0xeb, 0xeb, 0xeb); | |
27 const SkColor kPushedBackgroundBottomColor = SkColorSetRGB(0xdb, 0xdb, 0xdb); | |
28 const SkColor kDisabledBackgroundTopColor = SkColorSetRGB(0xed, 0xed, 0xed); | |
29 const SkColor kDisabledBackgroundBottomColor = SkColorSetRGB(0xde, 0xde, 0xde); | |
30 | |
31 const SkColor kEnabledTextColor = SkColorSetRGB(0x33, 0x33, 0x33); | |
32 const SkColor kDisabledTextColor = SkColorSetRGB(0xaa, 0xaa, 0xaa); | |
33 const SkColor kHoverTextColor = SkColorSetRGB(0x0, 0x0, 0x0); | |
34 | |
35 const SkColor kTextShadowColor = SkColorSetRGB(0xf0, 0xf0, 0xf0); | |
36 const int kTextShadowOffsetX = 0; | |
37 const int kTextShadowOffsetY = 1; | |
38 | |
39 const int kBorderWidth = 1; | |
40 const int kBorderRadius = 2; | |
41 const SkColor kBorderNormalColor = SkColorSetARGB(0x3f, 0x0, 0x0, 0x0); | |
42 const SkColor kBorderActiveColor = SkColorSetARGB(0x4b, 0x0, 0x0, 0x0); | |
43 const SkColor kBorderDisabledColor = SkColorSetARGB(0x1d, 0x0, 0x0, 0x0); | |
44 | |
45 const int kFocusRingWidth = 2; | |
46 const int kFocusRingRadius = 2; | |
47 const SkColor kFocusRingColor = SkColorSetARGB(0x7f, 0xe5, 0x97, 0x00); | |
48 | |
49 // Returns the uniform inset of the button from its local bounds. | |
50 int GetButtonInset() { | |
51 return std::max(kBorderWidth, kFocusRingWidth); | |
52 } | |
53 } // namespace | |
54 | |
55 class WebStyleTextButtonBackground : public Background { | |
Ben Goodger (Google)
2012/09/17 22:37:26
Also I would like to come up with a different name
Mike Wittman
2012/09/21 22:53:18
Works for me. I wasn't sure what the best name fo
| |
56 public: | |
57 WebStyleTextButtonBackground() { | |
58 } | |
59 | |
60 virtual ~WebStyleTextButtonBackground() { | |
61 } | |
62 | |
63 // Overriden from Background | |
64 virtual void Paint(gfx::Canvas* canvas, View* view) const { | |
65 if (painter_.get()) | |
66 { | |
67 gfx::Rect bounds = view->GetLocalBounds(); | |
68 // Inset to the actual button region. | |
69 int inset = GetButtonInset(); | |
70 bounds.Inset(inset, inset, inset, inset); | |
71 Painter::PaintPainterAt(canvas, painter_.get(), bounds); | |
72 } | |
73 } | |
74 | |
75 void SetColors(SkColor top, SkColor bottom) { | |
76 static const int count = 3; | |
77 SkColor colors[count] = { top, top, bottom }; | |
78 SkScalar pos[count] = { 0.0f, kGradientStartLocation, 1.0f }; | |
79 | |
80 painter_.reset( | |
81 Painter::CreateVerticalMultiColorGradient(colors, pos, count)); | |
82 SetNativeControlColor( | |
83 color_utils::AlphaBlend(colors[0], colors[count - 1], 128)); | |
84 } | |
85 | |
86 private: | |
87 scoped_ptr<Painter> painter_; | |
88 | |
89 DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBackground); | |
90 }; | |
91 | |
92 class WebStyleTextButtonBorderPainter : public views::Painter { | |
93 public: | |
94 WebStyleTextButtonBorderPainter() | |
95 // This value should be updated prior to rendering; it's set to a | |
96 // well-defined value here defensively. | |
97 : color_(SkColorSetRGB(0x0, 0x0, 0x0)) { | |
98 } | |
99 | |
100 // Overriden from Painter | |
101 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) { | |
102 SkPaint paint; | |
103 paint.setStyle(SkPaint::kStroke_Style); | |
104 paint.setColor(color_); | |
105 paint.setStrokeWidth(kBorderWidth); | |
106 | |
107 // Inset by 1/2 pixel to align the stroke with pixel centers. | |
108 SkScalar inset = 0.5f; | |
109 SkRect rect = SkRect::MakeLTRB(inset, inset, | |
110 SkIntToScalar(size.width()) - inset, | |
111 SkIntToScalar(size.height()) - inset); | |
112 | |
113 canvas->sk_canvas()->drawRoundRect( | |
114 rect, kBorderRadius, kBorderRadius, paint); | |
115 } | |
116 | |
117 void set_color(SkColor color) { | |
118 color_ = color; | |
119 } | |
120 | |
121 private: | |
122 SkColor color_; | |
123 | |
124 DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBorderPainter); | |
125 }; | |
126 | |
127 | |
128 class WebStyleTextButtonBorder : public views::Border { | |
129 public: | |
130 WebStyleTextButtonBorder() | |
131 : painter_(new WebStyleTextButtonBorderPainter) { | |
132 } | |
133 | |
134 // Overriden from Border | |
135 virtual void Paint(const View& view, gfx::Canvas* canvas) const { | |
136 gfx::Rect bounds = view.GetLocalBounds(); | |
137 int border_inset = GetButtonInset() - kBorderWidth; | |
138 bounds.Inset(border_inset, border_inset, border_inset, border_inset); | |
139 Painter::PaintPainterAt(canvas, painter_, bounds); | |
140 } | |
141 virtual void GetInsets(gfx::Insets* insets) const { | |
142 DCHECK(insets); | |
143 int inset = GetButtonInset(); | |
144 insets->Set(inset, inset, inset, inset); | |
145 } | |
146 | |
147 void SetColor(SkColor color) { | |
148 painter_->set_color(color); | |
149 } | |
150 | |
151 private: | |
152 WebStyleTextButtonBorderPainter* painter_; | |
153 | |
154 DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBorder); | |
155 }; | |
156 | |
157 | |
158 | |
159 const char WebStyleTextButton::kViewClassName[] = "WebStyleTextButton"; | |
160 | |
161 WebStyleTextButton::WebStyleTextButton(ButtonListener* listener, | |
162 const string16& title) | |
163 : TextButton(listener, title), | |
164 prior_state_(state()), | |
165 web_style_background_(NULL), | |
166 web_style_border_(NULL) { | |
167 set_focusable(true); | |
168 set_request_focus_on_press(false); | |
169 | |
170 set_alignment(ALIGN_CENTER); | |
171 web_style_background_ = new WebStyleTextButtonBackground; | |
172 set_background(web_style_background_); | |
173 | |
174 SetEnabledColor(kEnabledTextColor); | |
175 SetDisabledColor(kDisabledTextColor); | |
176 SetHoverColor(kHoverTextColor); | |
177 | |
178 SetBackgroundForState(state()); | |
179 SetShadowForState(state()); | |
180 | |
181 web_style_border_ = new WebStyleTextButtonBorder; | |
182 set_border(web_style_border_); | |
183 | |
184 SetBorderColorForState(state()); | |
185 } | |
186 | |
187 gfx::Size WebStyleTextButton::GetPreferredSize() { | |
188 gfx::Size prefsize(TextButton::GetPreferredSize()); | |
189 prefsize.set_width(std::max(prefsize.height(), kMinWidth)); | |
190 prefsize.set_height(std::max(prefsize.height(), kMinHeight)); | |
191 | |
192 return prefsize; | |
193 } | |
194 | |
195 void WebStyleTextButton::OnPaintFocusBorder(gfx::Canvas* canvas) { | |
196 if (HasFocus() && (focusable() || IsAccessibilityFocusable())) { | |
197 gfx::Rect rect(GetLocalBounds()); | |
198 SkScalar inset = GetButtonInset() - kFocusRingWidth / 2.0f; | |
199 rect.Inset(inset, inset); | |
200 SkPaint paint; | |
201 paint.setStyle(SkPaint::kStroke_Style); | |
202 paint.setStrokeWidth(SkScalar(kFocusRingWidth)); | |
203 paint.setColor(kFocusRingColor); | |
204 canvas->DrawRoundRect(rect, SkScalar(kFocusRingRadius), paint); | |
205 } | |
206 } | |
207 | |
208 void WebStyleTextButton::StateChanged() { | |
209 TextButton::StateChanged(); | |
210 | |
211 SetBackgroundForState(state()); | |
212 | |
213 // Update text shadow when transitioning to/from pushed state. | |
214 if (state() == BS_PUSHED || prior_state_ == BS_PUSHED) { | |
215 SetShadowForState(state()); | |
216 } | |
217 | |
218 // Update border color. We need to change it in all cases except hot | |
219 // followed by pushed. | |
220 if (!(state() == BS_PUSHED && prior_state_ == BS_HOT)) { | |
221 SetBorderColorForState(state()); | |
222 } | |
223 | |
224 prior_state_ = state(); | |
225 } | |
226 | |
227 std::string WebStyleTextButton::GetClassName() const { | |
228 return kViewClassName; | |
229 } | |
230 | |
231 void WebStyleTextButton::SetBackgroundForState(ButtonState state) { | |
232 SkColor top; | |
233 SkColor bottom; | |
234 | |
235 switch (state) { | |
236 case BS_NORMAL: | |
237 top = kNormalBackgroundTopColor; | |
238 bottom = kNormalBackgroundBottomColor; | |
239 break; | |
240 | |
241 case BS_HOT: | |
242 top = kHotBackgroundTopColor; | |
243 bottom = kHotBackgroundBottomColor; | |
244 break; | |
245 | |
246 case BS_PUSHED: | |
247 top = kPushedBackgroundTopColor; | |
248 bottom = kPushedBackgroundBottomColor; | |
249 break; | |
250 | |
251 case BS_DISABLED: | |
252 top = kDisabledBackgroundTopColor; | |
253 bottom = kDisabledBackgroundBottomColor; | |
254 break; | |
255 | |
256 default: | |
257 NOTREACHED(); | |
258 break; | |
259 } | |
260 | |
261 web_style_background_->SetColors(top, bottom); | |
262 } | |
263 | |
264 void WebStyleTextButton::SetShadowForState(ButtonState state) { | |
265 if (state == BS_PUSHED) { | |
266 // Turn off text shadow. | |
267 ClearEmbellishing(); | |
268 } else { | |
269 SetTextShadowColors(kTextShadowColor, kTextShadowColor); | |
270 SetTextShadowOffset(kTextShadowOffsetX, kTextShadowOffsetY); | |
271 } | |
272 } | |
273 | |
274 void WebStyleTextButton::SetBorderColorForState(ButtonState state) { | |
275 SkColor border_color; | |
276 | |
277 switch (state) { | |
278 case BS_NORMAL: | |
279 border_color = kBorderNormalColor; | |
280 break; | |
281 | |
282 case BS_HOT: | |
283 case BS_PUSHED: | |
284 border_color = kBorderActiveColor; | |
285 break; | |
286 | |
287 case BS_DISABLED: | |
288 border_color = kBorderDisabledColor; | |
289 break; | |
290 | |
291 default: | |
292 NOTREACHED(); | |
293 break; | |
294 } | |
295 | |
296 web_style_border_->SetColor(border_color); | |
297 } | |
298 | |
299 } // namespace views | |
OLD | NEW |