Chromium Code Reviews| 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 |