Index: ui/views/controls/button/web_style_text_button.cc |
diff --git a/ui/views/controls/button/web_style_text_button.cc b/ui/views/controls/button/web_style_text_button.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ce81df785a0eaf5c447072d9b8c681429ff8116a |
--- /dev/null |
+++ b/ui/views/controls/button/web_style_text_button.cc |
@@ -0,0 +1,299 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/views/controls/button/web_style_text_button.h" |
+ |
+#include <algorithm> |
+ |
+#include "ui/gfx/canvas.h" |
+#include "ui/gfx/color_utils.h" |
+#include "ui/views/painter.h" |
+#include "ui/views/background.h" |
+ |
+namespace views { |
+namespace { |
+const int kMinWidth = 72; |
+const int kMinHeight = 27; |
+ |
+// Fractional position between top and bottom of button where the |
+// gradient starts. |
+const SkScalar kGradientStartLocation = 0.38f; |
+const SkColor kNormalBackgroundTopColor = SkColorSetRGB(0xf0, 0xf0, 0xf0); |
+const SkColor kNormalBackgroundBottomColor = SkColorSetRGB(0xe0, 0xe0, 0xe0); |
+const SkColor kHotBackgroundTopColor = SkColorSetRGB(0xf4, 0xf4, 0xf4); |
+const SkColor kHotBackgroundBottomColor = SkColorSetRGB(0xe4, 0xe4, 0xe4); |
+const SkColor kPushedBackgroundTopColor = SkColorSetRGB(0xeb, 0xeb, 0xeb); |
+const SkColor kPushedBackgroundBottomColor = SkColorSetRGB(0xdb, 0xdb, 0xdb); |
+const SkColor kDisabledBackgroundTopColor = SkColorSetRGB(0xed, 0xed, 0xed); |
+const SkColor kDisabledBackgroundBottomColor = SkColorSetRGB(0xde, 0xde, 0xde); |
+ |
+const SkColor kEnabledTextColor = SkColorSetRGB(0x33, 0x33, 0x33); |
+const SkColor kDisabledTextColor = SkColorSetRGB(0xaa, 0xaa, 0xaa); |
+const SkColor kHoverTextColor = SkColorSetRGB(0x0, 0x0, 0x0); |
+ |
+const SkColor kTextShadowColor = SkColorSetRGB(0xf0, 0xf0, 0xf0); |
+const int kTextShadowOffsetX = 0; |
+const int kTextShadowOffsetY = 1; |
+ |
+const int kBorderWidth = 1; |
+const int kBorderRadius = 2; |
+const SkColor kBorderNormalColor = SkColorSetARGB(0x3f, 0x0, 0x0, 0x0); |
+const SkColor kBorderActiveColor = SkColorSetARGB(0x4b, 0x0, 0x0, 0x0); |
+const SkColor kBorderDisabledColor = SkColorSetARGB(0x1d, 0x0, 0x0, 0x0); |
+ |
+const int kFocusRingWidth = 2; |
+const int kFocusRingRadius = 2; |
+const SkColor kFocusRingColor = SkColorSetARGB(0x7f, 0xe5, 0x97, 0x00); |
+ |
+// Returns the uniform inset of the button from its local bounds. |
+int GetButtonInset() { |
+ return std::max(kBorderWidth, kFocusRingWidth); |
+} |
+} // namespace |
+ |
+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
|
+ public: |
+ WebStyleTextButtonBackground() { |
+ } |
+ |
+ virtual ~WebStyleTextButtonBackground() { |
+ } |
+ |
+ // Overriden from Background |
+ virtual void Paint(gfx::Canvas* canvas, View* view) const { |
+ if (painter_.get()) |
+ { |
+ gfx::Rect bounds = view->GetLocalBounds(); |
+ // Inset to the actual button region. |
+ int inset = GetButtonInset(); |
+ bounds.Inset(inset, inset, inset, inset); |
+ Painter::PaintPainterAt(canvas, painter_.get(), bounds); |
+ } |
+ } |
+ |
+ void SetColors(SkColor top, SkColor bottom) { |
+ static const int count = 3; |
+ SkColor colors[count] = { top, top, bottom }; |
+ SkScalar pos[count] = { 0.0f, kGradientStartLocation, 1.0f }; |
+ |
+ painter_.reset( |
+ Painter::CreateVerticalMultiColorGradient(colors, pos, count)); |
+ SetNativeControlColor( |
+ color_utils::AlphaBlend(colors[0], colors[count - 1], 128)); |
+ } |
+ |
+ private: |
+ scoped_ptr<Painter> painter_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBackground); |
+}; |
+ |
+class WebStyleTextButtonBorderPainter : public views::Painter { |
+ public: |
+ WebStyleTextButtonBorderPainter() |
+ // This value should be updated prior to rendering; it's set to a |
+ // well-defined value here defensively. |
+ : color_(SkColorSetRGB(0x0, 0x0, 0x0)) { |
+ } |
+ |
+ // Overriden from Painter |
+ virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) { |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setColor(color_); |
+ paint.setStrokeWidth(kBorderWidth); |
+ |
+ // Inset by 1/2 pixel to align the stroke with pixel centers. |
+ SkScalar inset = 0.5f; |
+ SkRect rect = SkRect::MakeLTRB(inset, inset, |
+ SkIntToScalar(size.width()) - inset, |
+ SkIntToScalar(size.height()) - inset); |
+ |
+ canvas->sk_canvas()->drawRoundRect( |
+ rect, kBorderRadius, kBorderRadius, paint); |
+ } |
+ |
+ void set_color(SkColor color) { |
+ color_ = color; |
+ } |
+ |
+ private: |
+ SkColor color_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBorderPainter); |
+}; |
+ |
+ |
+class WebStyleTextButtonBorder : public views::Border { |
+ public: |
+ WebStyleTextButtonBorder() |
+ : painter_(new WebStyleTextButtonBorderPainter) { |
+ } |
+ |
+ // Overriden from Border |
+ virtual void Paint(const View& view, gfx::Canvas* canvas) const { |
+ gfx::Rect bounds = view.GetLocalBounds(); |
+ int border_inset = GetButtonInset() - kBorderWidth; |
+ bounds.Inset(border_inset, border_inset, border_inset, border_inset); |
+ Painter::PaintPainterAt(canvas, painter_, bounds); |
+ } |
+ virtual void GetInsets(gfx::Insets* insets) const { |
+ DCHECK(insets); |
+ int inset = GetButtonInset(); |
+ insets->Set(inset, inset, inset, inset); |
+ } |
+ |
+ void SetColor(SkColor color) { |
+ painter_->set_color(color); |
+ } |
+ |
+ private: |
+ WebStyleTextButtonBorderPainter* painter_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebStyleTextButtonBorder); |
+}; |
+ |
+ |
+ |
+const char WebStyleTextButton::kViewClassName[] = "WebStyleTextButton"; |
+ |
+WebStyleTextButton::WebStyleTextButton(ButtonListener* listener, |
+ const string16& title) |
+ : TextButton(listener, title), |
+ prior_state_(state()), |
+ web_style_background_(NULL), |
+ web_style_border_(NULL) { |
+ set_focusable(true); |
+ set_request_focus_on_press(false); |
+ |
+ set_alignment(ALIGN_CENTER); |
+ web_style_background_ = new WebStyleTextButtonBackground; |
+ set_background(web_style_background_); |
+ |
+ SetEnabledColor(kEnabledTextColor); |
+ SetDisabledColor(kDisabledTextColor); |
+ SetHoverColor(kHoverTextColor); |
+ |
+ SetBackgroundForState(state()); |
+ SetShadowForState(state()); |
+ |
+ web_style_border_ = new WebStyleTextButtonBorder; |
+ set_border(web_style_border_); |
+ |
+ SetBorderColorForState(state()); |
+} |
+ |
+gfx::Size WebStyleTextButton::GetPreferredSize() { |
+ gfx::Size prefsize(TextButton::GetPreferredSize()); |
+ prefsize.set_width(std::max(prefsize.height(), kMinWidth)); |
+ prefsize.set_height(std::max(prefsize.height(), kMinHeight)); |
+ |
+ return prefsize; |
+} |
+ |
+void WebStyleTextButton::OnPaintFocusBorder(gfx::Canvas* canvas) { |
+ if (HasFocus() && (focusable() || IsAccessibilityFocusable())) { |
+ gfx::Rect rect(GetLocalBounds()); |
+ SkScalar inset = GetButtonInset() - kFocusRingWidth / 2.0f; |
+ rect.Inset(inset, inset); |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ paint.setStrokeWidth(SkScalar(kFocusRingWidth)); |
+ paint.setColor(kFocusRingColor); |
+ canvas->DrawRoundRect(rect, SkScalar(kFocusRingRadius), paint); |
+ } |
+} |
+ |
+void WebStyleTextButton::StateChanged() { |
+ TextButton::StateChanged(); |
+ |
+ SetBackgroundForState(state()); |
+ |
+ // Update text shadow when transitioning to/from pushed state. |
+ if (state() == BS_PUSHED || prior_state_ == BS_PUSHED) { |
+ SetShadowForState(state()); |
+ } |
+ |
+ // Update border color. We need to change it in all cases except hot |
+ // followed by pushed. |
+ if (!(state() == BS_PUSHED && prior_state_ == BS_HOT)) { |
+ SetBorderColorForState(state()); |
+ } |
+ |
+ prior_state_ = state(); |
+} |
+ |
+std::string WebStyleTextButton::GetClassName() const { |
+ return kViewClassName; |
+} |
+ |
+void WebStyleTextButton::SetBackgroundForState(ButtonState state) { |
+ SkColor top; |
+ SkColor bottom; |
+ |
+ switch (state) { |
+ case BS_NORMAL: |
+ top = kNormalBackgroundTopColor; |
+ bottom = kNormalBackgroundBottomColor; |
+ break; |
+ |
+ case BS_HOT: |
+ top = kHotBackgroundTopColor; |
+ bottom = kHotBackgroundBottomColor; |
+ break; |
+ |
+ case BS_PUSHED: |
+ top = kPushedBackgroundTopColor; |
+ bottom = kPushedBackgroundBottomColor; |
+ break; |
+ |
+ case BS_DISABLED: |
+ top = kDisabledBackgroundTopColor; |
+ bottom = kDisabledBackgroundBottomColor; |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ web_style_background_->SetColors(top, bottom); |
+} |
+ |
+void WebStyleTextButton::SetShadowForState(ButtonState state) { |
+ if (state == BS_PUSHED) { |
+ // Turn off text shadow. |
+ ClearEmbellishing(); |
+ } else { |
+ SetTextShadowColors(kTextShadowColor, kTextShadowColor); |
+ SetTextShadowOffset(kTextShadowOffsetX, kTextShadowOffsetY); |
+ } |
+} |
+ |
+void WebStyleTextButton::SetBorderColorForState(ButtonState state) { |
+ SkColor border_color; |
+ |
+ switch (state) { |
+ case BS_NORMAL: |
+ border_color = kBorderNormalColor; |
+ break; |
+ |
+ case BS_HOT: |
+ case BS_PUSHED: |
+ border_color = kBorderActiveColor; |
+ break; |
+ |
+ case BS_DISABLED: |
+ border_color = kBorderDisabledColor; |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ web_style_border_->SetColor(border_color); |
+} |
+ |
+} // namespace views |