Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: ui/views/style/mac/dialog_button_border_mac.cc

Issue 1569113002: MacViews: Style BUTTON_STYLE buttons using the "modern" UI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: respond to comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/style/mac/dialog_button_border_mac.h ('k') | ui/views/style/platform_style.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/style/mac/dialog_button_border_mac.h" 5 #include "ui/views/style/mac/dialog_button_border_mac.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "skia/ext/refptr.h" 8 #include "skia/ext/refptr.h"
9 #include "third_party/skia/include/core/SkCanvas.h" 9 #include "third_party/skia/include/core/SkCanvas.h"
10 #include "third_party/skia/include/core/SkDrawLooper.h" 10 #include "third_party/skia/include/core/SkDrawLooper.h"
11 #include "third_party/skia/include/core/SkPaint.h" 11 #include "third_party/skia/include/core/SkPaint.h"
12 #include "third_party/skia/include/core/SkPath.h" 12 #include "third_party/skia/include/core/SkPath.h"
13 #include "third_party/skia/include/effects/SkGradientShader.h" 13 #include "third_party/skia/include/effects/SkGradientShader.h"
14 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
15 #include "ui/native_theme/native_theme_mac.h"
15 #include "ui/views/border.h" 16 #include "ui/views/border.h"
16 #include "ui/views/controls/button/custom_button.h" 17 #include "ui/views/controls/button/custom_button.h"
18 #include "ui/views/controls/button/label_button.h"
19
20 using ui::NativeThemeMac;
17 21
18 namespace views { 22 namespace views {
19 namespace { 23 namespace {
20 24
21 // Type to map button states to a corresponding SkColor.
22 typedef const SkColor ColorByState[Button::STATE_COUNT];
23
24 // If a state is added, ColorByState will silently fill with zeros, so assert.
25 static_assert(Button::STATE_COUNT == 4,
26 "DialogButtonBorderMac assumes 4 button states.");
27
28 // Corner radius of rounded rectangles. 25 // Corner radius of rounded rectangles.
29 const SkScalar kCornerRadius = 2; 26 const SkScalar kCornerRadius = 2;
27 const SkScalar kFocusCornerRadius = 4;
28 const SkScalar kFocusRingThickness = 3;
30 29
31 // Vertical offset of the drop shadow and the inner highlight shadow. 30 const SkColor kDefaultBorderColor = SkColorSetARGB(0xF2, 0xBA, 0xBA, 0xBA);
32 const SkScalar kShadowOffsetY = 1; 31 const SkColor kHighlightedBorderColor = SkColorSetARGB(0xFF, 0x52, 0x76, 0xFF);
33 32 const SkColor kFocusRingColor = SkColorSetARGB(0x80, 0x3B, 0x9A, 0xFC);
34 // Shadow blur radius of the inner highlight shadow.
35 const double kInnerShadowBlurRadius = 2.0;
36 33
37 // Default border insets, to provide text padding. 34 // Default border insets, to provide text padding.
38 const int kPaddingX = 14; 35 const int kPaddingX = 19;
39 const int kPaddingY = 4; 36 const int kPaddingY = 7;
40 37
41 sk_sp<SkShader> CreateButtonGradient(int height, 38 void DrawDialogButtonBackground(const SkRect& button_rect,
42 Button::ButtonState state) { 39 SkCanvas* canvas,
43 ColorByState start = {0xFFF0F0F0, 0xFFF4F4F4, 0xFFEBEBEB, 0xFFEDEDED}; 40 const LabelButton& button) {
44 ColorByState end = {0xFFE0E0E0, 0xFFE4E4E4, 0xFFDBDBDB, 0xFFDEDEDE};
45
46 SkPoint gradient_points[2];
47 gradient_points[0].iset(0, 0);
48 gradient_points[1].iset(0, height);
49
50 SkColor gradient_colors[] = {start[state], start[state], end[state]};
51 SkScalar gradient_positions[] = {0.0, 0.38, 1.0};
52
53 return SkGradientShader::MakeLinear(
54 gradient_points, gradient_colors, gradient_positions, 3,
55 SkShader::kClamp_TileMode);
56 }
57
58 void DrawConstrainedButtonBackground(const SkRect& button_rect,
59 SkCanvas* canvas,
60 Button::ButtonState button_state) {
61 // Extend the size of the SkRect so the border stroke is drawn over it on all 41 // Extend the size of the SkRect so the border stroke is drawn over it on all
62 // sides. 42 // sides.
63 SkRect rect(button_rect); 43 SkRect rect(button_rect);
64 rect.fRight += 1; 44 rect.fRight += 1;
65 rect.fBottom += 1; 45 rect.fBottom += 1;
66 46
67 SkPaint paint; 47 NativeThemeMac::ButtonBackgroundType type =
68 48 NativeThemeMac::ButtonBackgroundType::NORMAL;
69 // Drop Shadow. 49 if (!button.enabled() || button.state() == Button::STATE_DISABLED)
70 ColorByState shadow = {0x14000000, 0x1F000000, 0x00000000, 0x00000000}; 50 type = NativeThemeMac::ButtonBackgroundType::DISABLED;
71 const double blur = 0.0; 51 else if (button.state() == Button::STATE_PRESSED)
72 std::vector<gfx::ShadowValue> shadows( 52 type = NativeThemeMac::ButtonBackgroundType::PRESSED;
73 1, gfx::ShadowValue(gfx::Vector2d(0, kShadowOffsetY), blur, 53 else if (DialogButtonBorderMac::ShouldRenderDefault(button))
74 shadow[button_state])); 54 type = NativeThemeMac::ButtonBackgroundType::HIGHLIGHTED;
75 paint.setLooper(gfx::CreateShadowDrawLooper(shadows));
76 55
77 // Background. 56 // Background.
78 paint.setShader(CreateButtonGradient(rect.height(), button_state)); 57 SkPaint paint;
58 paint.setShader(
59 NativeThemeMac::GetButtonBackgroundShader(type, rect.height()));
79 paint.setStyle(SkPaint::kFill_Style); 60 paint.setStyle(SkPaint::kFill_Style);
80 paint.setFlags(SkPaint::kAntiAlias_Flag); 61 paint.setFlags(SkPaint::kAntiAlias_Flag);
81 canvas->drawRoundRect(rect, kCornerRadius, kCornerRadius, paint); 62 canvas->drawRoundRect(rect, kCornerRadius, kCornerRadius, paint);
82 } 63 }
83 64
84 // Draws an inner box shadow inside a rounded rectangle of size |rect|. The
85 // technique: draw a black "ring" around the outside of the button cell. Then
86 // clip out everything except the shadow it casts. Works similar to Blink's
87 // GraphicsContext::drawInnerShadow().
88 void DrawRoundRectInnerShadow(const SkRect& rect,
89 SkCanvas* canvas,
90 SkColor shadow_color) {
91 const gfx::Vector2d shadow_offset(0, kShadowOffsetY);
92 SkRect outer(rect);
93 outer.outset(abs(shadow_offset.x()) + kInnerShadowBlurRadius,
94 abs(shadow_offset.y()) + kInnerShadowBlurRadius);
95
96 SkPath path;
97 path.addRect(outer);
98 path.setFillType(SkPath::kEvenOdd_FillType);
99 path.addRoundRect(rect, kCornerRadius, kCornerRadius); // Poke a hole.
100
101 // Inset the clip to cater for the border stroke.
102 SkPath clip;
103 clip.addRoundRect(rect.makeInset(0.5, 0.5), kCornerRadius, kCornerRadius);
104
105 SkPaint paint;
106 std::vector<gfx::ShadowValue> shadows(
107 1, gfx::ShadowValue(shadow_offset, kInnerShadowBlurRadius, shadow_color));
108 paint.setLooper(gfx::CreateShadowDrawLooper(shadows));
109 paint.setStyle(SkPaint::kFill_Style);
110 paint.setColor(SK_ColorBLACK); // Note: Entirely clipped.
111
112 canvas->save();
113 canvas->clipPath(clip, SkRegion::kIntersect_Op, true /* antialias */);
114 canvas->drawPath(path, paint);
115 canvas->restore();
116 }
117
118 } // namespace 65 } // namespace
119 66
120 DialogButtonBorderMac::DialogButtonBorderMac() { 67 DialogButtonBorderMac::DialogButtonBorderMac() {
121 set_insets(gfx::Insets(kPaddingY, kPaddingX, kPaddingY, kPaddingX)); 68 set_insets(gfx::Insets(kPaddingY, kPaddingX, kPaddingY, kPaddingX));
122 } 69 }
123 70
124 DialogButtonBorderMac::~DialogButtonBorderMac() {} 71 DialogButtonBorderMac::~DialogButtonBorderMac() {}
125 72
73 // static
74 bool DialogButtonBorderMac::ShouldRenderDefault(const LabelButton& button) {
75 // TODO(tapted): Check whether the Widget is active, and only return true here
76 // if it is. Plumbing this requires default buttons to also observe Widget
77 // activations to ensure text and background colors are properly invalidated.
78 return button.is_default();
79 }
80
126 void DialogButtonBorderMac::Paint(const View& view, gfx::Canvas* canvas) { 81 void DialogButtonBorderMac::Paint(const View& view, gfx::Canvas* canvas) {
82 // Actually, |view| should be a LabelButton as well, but don't rely too much
83 // on RTTI.
127 DCHECK(CustomButton::AsCustomButton(&view)); 84 DCHECK(CustomButton::AsCustomButton(&view));
128 const CustomButton& button = static_cast<const CustomButton&>(view); 85 const LabelButton& button = static_cast<const LabelButton&>(view);
129 SkCanvas* canvas_skia = canvas->sk_canvas(); 86 SkCanvas* canvas_skia = canvas->sk_canvas();
130 87
131 // Inset all sides for the rounded rectangle stroke. Inset again to make room 88 // Inset all sides for the rounded rectangle stroke. Inset again to make room
132 // for the shadows (while keeping the text centered). 89 // for the shadows and static focus ring (while keeping the text centered).
133 SkRect sk_rect = gfx::RectToSkRect(view.GetLocalBounds()); 90 SkRect sk_rect = gfx::RectToSkRect(view.GetLocalBounds());
134 sk_rect.inset(2.0, 2.0); 91 sk_rect.inset(kFocusRingThickness, kFocusRingThickness);
135 92
136 DrawConstrainedButtonBackground(sk_rect, canvas_skia, button.state()); 93 DrawDialogButtonBackground(sk_rect, canvas_skia, button);
137 94
138 // Offset so that strokes are contained within the pixel boundary. 95 // Offset so that strokes are contained within the pixel boundary.
139 sk_rect.offset(0.5, 0.5); 96 sk_rect.offset(0.5, 0.5);
140 ColorByState highlight = {0xBFFFFFFF, 0xF2FFFFFF, 0x24000000, 0x00000000};
141 DrawRoundRectInnerShadow(sk_rect, canvas_skia, highlight[button.state()]);
142 97
143 // Border or focus ring. 98 // Border and focus ring.
99 SkColor border_color = kDefaultBorderColor;
100 if (button.state() == Button::STATE_PRESSED || ShouldRenderDefault(button))
101 border_color = kHighlightedBorderColor;
102
144 SkPaint paint; 103 SkPaint paint;
145 ColorByState border = {0x40000000, 0x4D000000, 0x4D000000, 0x1F000000};
146 const SkColor focus_border = {0xFF5DA5FF};
147 paint.setStrokeWidth(1);
148 paint.setStyle(SkPaint::kStroke_Style); 104 paint.setStyle(SkPaint::kStroke_Style);
149 paint.setFlags(SkPaint::kAntiAlias_Flag); 105 paint.setFlags(SkPaint::kAntiAlias_Flag);
150 if (button.HasFocus() && button.state() != Button::STATE_PRESSED) 106 paint.setStrokeWidth(1);
151 paint.setColor(focus_border); 107 paint.setColor(border_color);
152 else
153 paint.setColor(border[button.state()]);
154 canvas_skia->drawRoundRect(sk_rect, kCornerRadius, kCornerRadius, paint); 108 canvas_skia->drawRoundRect(sk_rect, kCornerRadius, kCornerRadius, paint);
109
110 if (button.HasFocus()) {
111 paint.setStrokeWidth(kFocusRingThickness);
112 paint.setColor(kFocusRingColor);
113 sk_rect.inset(-1, -1);
114 canvas_skia->drawRoundRect(sk_rect, kFocusCornerRadius, kFocusCornerRadius,
115 paint);
116 }
155 } 117 }
156 118
157 gfx::Size DialogButtonBorderMac::GetMinimumSize() const { 119 gfx::Size DialogButtonBorderMac::GetMinimumSize() const {
158 return gfx::Size(100, 30); 120 return gfx::Size(28, 4);
159 } 121 }
160 122
161 } // namespace views 123 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/style/mac/dialog_button_border_mac.h ('k') | ui/views/style/platform_style.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698