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

Side by Side Diff: ui/views/controls/button/toggle_button.cc

Issue 2440723003: Tweaks to ToggleButton details. (Closed)
Patch Set: colors Created 4 years, 2 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/toggle_button.h" 5 #include "ui/views/controls/button/toggle_button.h"
6 6
7 #include "third_party/skia/include/core/SkDrawLooper.h" 7 #include "third_party/skia/include/core/SkDrawLooper.h"
8 #include "third_party/skia/include/core/SkPaint.h" 8 #include "third_party/skia/include/core/SkPaint.h"
9 #include "ui/gfx/canvas.h" 9 #include "ui/gfx/canvas.h"
10 #include "ui/gfx/color_palette.h" 10 #include "ui/gfx/color_palette.h"
11 #include "ui/gfx/color_utils.h" 11 #include "ui/gfx/color_utils.h"
12 #include "ui/views/animation/ink_drop_ripple.h" 12 #include "ui/views/animation/ink_drop_ripple.h"
13 #include "ui/views/border.h" 13 #include "ui/views/border.h"
14 14
15 namespace views { 15 namespace views {
16 16
17 namespace { 17 namespace {
18 18
19 // Constants are measured in dip. 19 // Constants are measured in dip.
20 const int kTrackHeight = 12; 20 const int kTrackHeight = 12;
21 const int kTrackWidth = 28; 21 const int kTrackWidth = 28;
22 // Margins from edge of track to edge of view. 22 // Margins from edge of track to edge of view.
23 const int kTrackVerticalMargin = 5; 23 const int kTrackVerticalMargin = 4;
24 const int kTrackHorizontalMargin = 6; 24 const int kTrackHorizontalMargin = 6;
25 // Margin from edge of thumb to closest edge of view. Note that the thumb 25 // Margin from edge of thumb to closest edge of view.
26 // margins must be sufficiently large to allow space for the shadow.
27 const int kThumbHorizontalMargin = 4; 26 const int kThumbHorizontalMargin = 4;
28 // Margin from top/bottom edge of thumb to top/bottom edge of view. 27 // Margin from top/bottom edge of thumb to top/bottom edge of view.
29 const int kThumbVerticalMargin = 3; 28 const int kThumbVerticalMargin = 2;
30
31 // TODO(estade): get the base color (black) from the theme?
32 const SkColor kTrackOffColor =
33 SkColorSetA(SK_ColorBLACK, gfx::kDisabledControlAlpha);
34 29
35 } // namespace 30 } // namespace
36 31
37 // Class representing the thumb. When the thumb is clicked it is separated into 32 // Class representing the thumb (the circle that slides horizontally).
38 // its own layer and the ink drop layer is made a child of the thumb layer 33 class ToggleButton::ThumbView : public InkDropHostView {
39 // allowing the two to animate in sync.
40 class ToggleButton::ThumbView : public views::View {
41 public: 34 public:
42 ThumbView() : color_ratio_(0.) {} 35 ThumbView() : color_ratio_(0.) {
43 ~ThumbView() override {}
44
45 void AddInkDropLayer(ui::Layer* ink_drop_layer) {
46 SetPaintToLayer(true); 36 SetPaintToLayer(true);
varkha 2016/10/21 00:35:18 The old implementation was more lines but it was o
Evan Stade 2016/10/21 17:19:15 It's not clear to me that creating and destroying
varkha 2016/10/21 17:55:36 +bruthig@ and sadrul@ to see if they have stronger
bruthig 2016/10/21 18:36:40 Even though the ThumbView is always painting to a
sadrul 2016/10/24 14:46:12 Always having the layer seem unrelated to the bugs
Evan Stade 2016/10/27 17:12:14 Done.
47 layer()->SetFillsBoundsOpaquely(false); 37 layer()->SetFillsBoundsOpaquely(false);
48 layer()->Add(ink_drop_layer);
49 } 38 }
50 39 ~ThumbView() override {}
51 void RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
52 layer()->Remove(ink_drop_layer);
53 SetPaintToLayer(false);
54 }
55 40
56 void Update(const gfx::Rect& bounds, double color_ratio) { 41 void Update(const gfx::Rect& bounds, double color_ratio) {
57 SetBoundsRect(bounds); 42 SetBoundsRect(bounds);
58 color_ratio_ = color_ratio; 43 color_ratio_ = color_ratio;
59 SchedulePaint(); 44 SchedulePaint();
60 } 45 }
61 46
47 static gfx::Insets GetShadowInsets() {
48 gfx::Insets blur(kShadowBlur);
49 gfx::Insets offset(-kShadowOffsetY, -kShadowOffsetX, kShadowOffsetY,
50 kShadowOffsetX);
51 return blur + offset;
52 }
53
62 private: 54 private:
55 static const int kShadowOffsetX = 0;
56 static const int kShadowOffsetY = 1;
57 static const int kShadowBlur = 2;
58
63 // views::View: 59 // views::View:
64 const char* GetClassName() const override { 60 const char* GetClassName() const override {
65 return "ToggleButton::ThumbView"; 61 return "ToggleButton::ThumbView";
66 } 62 }
67 63
68 void OnPaint(gfx::Canvas* canvas) override { 64 void OnPaint(gfx::Canvas* canvas) override {
69 std::vector<gfx::ShadowValue> shadows; 65 std::vector<gfx::ShadowValue> shadows;
70 shadows.emplace_back(gfx::Vector2d(0, 1), 4.f, 66 shadows.emplace_back(
71 SkColorSetA(SK_ColorBLACK, 0x99)); 67 gfx::Vector2d(kShadowOffsetX, kShadowOffsetY), 2 * kShadowBlur,
68 SkColorSetA(GetNativeTheme()->GetSystemColor(
69 ui::NativeTheme::kColorId_LabelEnabledColor),
70 0x99));
72 SkPaint thumb_paint; 71 SkPaint thumb_paint;
73 thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows)); 72 thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
74 thumb_paint.setStyle(SkPaint::kFill_Style);
75 thumb_paint.setAntiAlias(true); 73 thumb_paint.setAntiAlias(true);
76 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor( 74 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
77 ui::NativeTheme::kColorId_ProminentButtonColor); 75 ui::NativeTheme::kColorId_ProminentButtonColor);
78 // TODO(estade): get this color from the theme? 76 const SkColor thumb_off_color = GetNativeTheme()->GetSystemColor(
79 const SkColor thumb_off_color = SK_ColorWHITE; 77 ui::NativeTheme::kColorId_DialogBackground);
80 const SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio_); 78 const SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio_);
81 thumb_paint.setColor( 79 thumb_paint.setColor(
82 color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend)); 80 color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
83 gfx::Rect thumb_bounds = GetLocalBounds(); 81
84 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin)); 82 gfx::RectF thumb_bounds(GetLocalBounds());
85 canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(), 83 thumb_bounds.Inset(GetShadowInsets());
86 thumb_bounds.height() / 2.f, thumb_paint); 84 thumb_bounds.Inset(gfx::InsetsF(0.5f));
85 gfx::RectF bounds_in_px = thumb_bounds;
86 // We want the circle to have an integer pixel diameter and to be aligned
87 // with pixel boundaries, so we scale dip bounds to pixel bounds, round, and
88 // unscale back to dip bounds.
89 bounds_in_px.Scale(canvas->image_scale());
90 gfx::RectF bounds_in_dip(gfx::ToEnclosingRect(bounds_in_px));
91 bounds_in_dip.Scale(1.f / canvas->image_scale());
92 canvas->DrawCircle(bounds_in_dip.CenterPoint(),
93 bounds_in_dip.height() / 2.f, thumb_paint);
87 } 94 }
88 95
89 // Color ratio between 0 and 1 that controls the thumb color. 96 // Color ratio between 0 and 1 that controls the thumb color.
90 double color_ratio_; 97 double color_ratio_;
91 98
92 DISALLOW_COPY_AND_ASSIGN(ThumbView); 99 DISALLOW_COPY_AND_ASSIGN(ThumbView);
93 }; 100 };
94 101
95 // static 102 // static
96 const char ToggleButton::kViewClassName[] = "ToggleButton"; 103 const char ToggleButton::kViewClassName[] = "ToggleButton";
97 104
98 ToggleButton::ToggleButton(ButtonListener* listener) 105 ToggleButton::ToggleButton(ButtonListener* listener)
99 : CustomButton(listener), 106 : CustomButton(listener),
100 is_on_(false), 107 is_on_(false),
101 slide_animation_(this), 108 slide_animation_(this),
102 thumb_view_(new ToggleButton::ThumbView()) { 109 thumb_view_(new ThumbView()) {
103 slide_animation_.SetSlideDuration(80 /* ms */); 110 slide_animation_.SetSlideDuration(80 /* ms */);
104 slide_animation_.SetTweenType(gfx::Tween::LINEAR); 111 slide_animation_.SetTweenType(gfx::Tween::LINEAR);
105 SetBorder(Border::CreateEmptyBorder( 112 SetBorder(Border::CreateEmptyBorder(
106 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin))); 113 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin)));
107 AddChildView(thumb_view_.get()); 114 AddChildView(thumb_view_);
108 SetInkDropMode(InkDropMode::ON); 115 SetInkDropMode(InkDropMode::ON);
109 set_has_ink_drop_action_on_click(true); 116 set_has_ink_drop_action_on_click(true);
110 } 117 }
111 118
112 ToggleButton::~ToggleButton() { 119 ToggleButton::~ToggleButton() {
113 // Destroying ink drop early allows ink drop layer to be properly removed, 120 // Destroying ink drop early allows ink drop layer to be properly removed,
114 SetInkDropMode(InkDropMode::OFF); 121 SetInkDropMode(InkDropMode::OFF);
115 } 122 }
116 123
117 void ToggleButton::SetIsOn(bool is_on, bool animate) { 124 void ToggleButton::SetIsOn(bool is_on, bool animate) {
(...skipping 11 matching lines...) Expand all
129 136
130 gfx::Rect ToggleButton::GetThumbBounds() const { 137 gfx::Rect ToggleButton::GetThumbBounds() const {
131 gfx::Rect thumb_bounds = GetLocalBounds(); 138 gfx::Rect thumb_bounds = GetLocalBounds();
132 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin)); 139 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
133 thumb_bounds.set_x(thumb_bounds.x() + 140 thumb_bounds.set_x(thumb_bounds.x() +
134 slide_animation_.GetCurrentValue() * 141 slide_animation_.GetCurrentValue() *
135 (thumb_bounds.width() - thumb_bounds.height())); 142 (thumb_bounds.width() - thumb_bounds.height()));
136 // The thumb is a circle, so the width should match the height. 143 // The thumb is a circle, so the width should match the height.
137 thumb_bounds.set_width(thumb_bounds.height()); 144 thumb_bounds.set_width(thumb_bounds.height());
138 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds)); 145 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds));
146 thumb_bounds.Inset(-ThumbView::GetShadowInsets());
varkha 2016/10/21 00:35:18 Thank you!
139 return thumb_bounds; 147 return thumb_bounds;
140 } 148 }
141 149
142 void ToggleButton::UpdateThumb() { 150 void ToggleButton::UpdateThumb() {
143 gfx::Rect thumb_bounds = GetThumbBounds(); 151 thumb_view_->Update(GetThumbBounds(), slide_animation_.GetCurrentValue());
144 thumb_bounds.Inset(gfx::Insets(-kThumbVerticalMargin));
145 thumb_view_->Update(thumb_bounds, slide_animation_.GetCurrentValue());
146 } 152 }
147 153
148 gfx::Size ToggleButton::GetPreferredSize() const { 154 gfx::Size ToggleButton::GetPreferredSize() const {
149 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight); 155 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight);
150 if (border()) 156 if (border())
151 rect.Inset(-border()->GetInsets()); 157 rect.Inset(-border()->GetInsets());
152 return rect.size(); 158 return rect.size();
153 } 159 }
154 160
155 const char* ToggleButton::GetClassName() const { 161 const char* ToggleButton::GetClassName() const {
156 return kViewClassName; 162 return kViewClassName;
157 } 163 }
158 164
159 void ToggleButton::OnPaint(gfx::Canvas* canvas) { 165 void ToggleButton::OnPaint(gfx::Canvas* canvas) {
160 // Paint the toggle track. 166 // Paint the toggle track.
161 gfx::RectF track_rect(GetContentsBounds()); 167 gfx::RectF track_rect(GetContentsBounds());
162 SkPaint track_paint; 168 SkPaint track_paint;
163 track_paint.setAntiAlias(true); 169 track_paint.setAntiAlias(true);
164 const SkColor track_on_color =
165 SkColorSetA(GetNativeTheme()->GetSystemColor(
166 ui::NativeTheme::kColorId_ProminentButtonColor),
167 0xFF / 2);
168 const double color_ratio = slide_animation_.GetCurrentValue(); 170 const double color_ratio = slide_animation_.GetCurrentValue();
169 track_paint.setColor(color_utils::AlphaBlend( 171 track_paint.setColor(color_utils::AlphaBlend(
170 track_on_color, kTrackOffColor, 172 GetTrackColor(true), GetTrackColor(false),
171 static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio))); 173 static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio)));
172 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint); 174 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint);
173 } 175 }
174 176
175 void ToggleButton::NotifyClick(const ui::Event& event) { 177 void ToggleButton::NotifyClick(const ui::Event& event) {
176 SetIsOn(!is_on(), true); 178 SetIsOn(!is_on(), true);
177 CustomButton::NotifyClick(event); 179 CustomButton::NotifyClick(event);
178 } 180 }
179 181
180 void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { 182 void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
181 UpdateThumb(); 183 UpdateThumb();
182 } 184 }
183 185
184 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { 186 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
185 SchedulePaint(); 187 SchedulePaint();
186 } 188 }
187 189
188 void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) { 190 void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
189 thumb_view_->AddInkDropLayer(ink_drop_layer); 191 thumb_view_->AddInkDropLayer(ink_drop_layer);
190 UpdateThumb(); 192 UpdateThumb();
191 SchedulePaint(); 193 SchedulePaint();
bruthig 2016/10/21 18:36:40 varkha@, IF the ThumbView is always painting to a
192 } 194 }
193 195
194 void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) { 196 void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
195 thumb_view_->RemoveInkDropLayer(ink_drop_layer); 197 thumb_view_->RemoveInkDropLayer(ink_drop_layer);
196 SchedulePaint(); 198 SchedulePaint();
197 } 199 }
198 200
199 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const { 201 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const {
200 const int radius = (kTrackHeight + kTrackVerticalMargin * 2) / 2; 202 const int radius = (kTrackHeight + kTrackVerticalMargin * 2) / 2;
201 return CreateDefaultInkDropRipple(gfx::Point(radius, radius)); 203 return CreateDefaultInkDropRipple(gfx::Point(radius, radius));
202 } 204 }
203 205
204 SkColor ToggleButton::GetInkDropBaseColor() const { 206 SkColor ToggleButton::GetInkDropBaseColor() const {
205 return is_on() 207 return GetTrackColor(is_on());
206 ? GetNativeTheme()->GetSystemColor(
207 ui::NativeTheme::kColorId_ProminentButtonColor)
208 : kTrackOffColor;
209 } 208 }
210 209
211 bool ToggleButton::ShouldShowInkDropHighlight() const { 210 bool ToggleButton::ShouldShowInkDropHighlight() const {
212 return false; 211 return false;
213 } 212 }
214 213
215 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) { 214 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
216 if (animation == &slide_animation_) { 215 if (animation == &slide_animation_) {
217 // TODO(varkha, estade): The thumb is using its own view. Investigate if 216 // TODO(varkha, estade): The thumb is using its own view. Investigate if
218 // repainting in every animation step to update colors could be avoided. 217 // repainting in every animation step to update colors could be avoided.
219 UpdateThumb(); 218 UpdateThumb();
220 SchedulePaint(); 219 SchedulePaint();
221 return; 220 return;
222 } 221 }
223 CustomButton::AnimationProgressed(animation); 222 CustomButton::AnimationProgressed(animation);
224 } 223 }
225 224
225 SkColor ToggleButton::GetTrackColor(bool is_on) const {
226 const SkAlpha kOffTrackAlpha = 0x29;
227 const SkAlpha kOnTrackAlpha = kOffTrackAlpha * 2;
228 ui::NativeTheme::ColorId color_id =
229 is_on ? ui::NativeTheme::kColorId_ProminentButtonColor
230 : ui::NativeTheme::kColorId_LabelEnabledColor;
231 return SkColorSetA(GetNativeTheme()->GetSystemColor(color_id),
232 is_on ? kOnTrackAlpha : kOffTrackAlpha);
233 }
234
226 } // namespace views 235 } // namespace views
OLDNEW
« ui/views/controls/button/toggle_button.h ('K') | « ui/views/controls/button/toggle_button.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698