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

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

Issue 2396133005: [ash-md] Animates ToggleButton highlight to move it in sync with the thumb (Closed)
Patch Set: [ash-md] Animates ToggleButton highlight to move it in sync with the thumb (thumb view always exist… 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
« no previous file with comments | « ui/views/controls/button/toggle_button.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 16 matching lines...) Expand all
27 const int kThumbHorizontalMargin = 4; 27 const int kThumbHorizontalMargin = 4;
28 // Margin from top/bottom edge of thumb to top/bottom edge of view. 28 // Margin from top/bottom edge of thumb to top/bottom edge of view.
29 const int kThumbVerticalMargin = 3; 29 const int kThumbVerticalMargin = 3;
30 30
31 // TODO(estade): get the base color (black) from the theme? 31 // TODO(estade): get the base color (black) from the theme?
32 const SkColor kTrackOffColor = 32 const SkColor kTrackOffColor =
33 SkColorSetA(SK_ColorBLACK, gfx::kDisabledControlAlpha); 33 SkColorSetA(SK_ColorBLACK, gfx::kDisabledControlAlpha);
34 34
35 } // namespace 35 } // namespace
36 36
37 // Class representing the thumb. When the thumb is clicked it is separated into
38 // its own layer and the ink drop layer is made a child of the thumb layer
39 // allowing the two to animate in sync.
40 class ToggleButton::ThumbView : public views::View {
41 public:
42 ThumbView(views::View* parent) : color_ratio_(0.) {
43 parent->AddChildView(this);
44 }
45 ~ThumbView() override {}
46
47 void AddInkDropLayer(ui::Layer* ink_drop_layer) {
48 SetPaintToLayer(true);
49 layer()->SetFillsBoundsOpaquely(false);
50 layer()->Add(ink_drop_layer);
51 }
52
53 void RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
54 layer()->Remove(ink_drop_layer);
55 SetPaintToLayer(false);
56 }
57
58 void Update(const gfx::Rect& bounds, double color_ratio) {
59 SetBoundsRect(bounds);
60 color_ratio_ = color_ratio;
61 SchedulePaint();
62 }
63
64 private:
65 // views::View:
66 const char* GetClassName() const override {
67 return "ToggleButton::ThumbView";
68 }
69
70 void OnPaint(gfx::Canvas* canvas) override {
71 std::vector<gfx::ShadowValue> shadows;
72 shadows.emplace_back(gfx::Vector2d(0, 1), 4.f,
73 SkColorSetA(SK_ColorBLACK, 0x99));
74 SkPaint thumb_paint;
75 thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
76 thumb_paint.setStyle(SkPaint::kFill_Style);
77 thumb_paint.setAntiAlias(true);
78 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
79 ui::NativeTheme::kColorId_ProminentButtonColor);
80 // TODO(estade): get this color from the theme?
81 const SkColor thumb_off_color = SK_ColorWHITE;
82 const SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio_);
83 thumb_paint.setColor(
84 color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
85 gfx::Rect thumb_bounds = GetLocalBounds();
86 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin));
87 canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(),
88 thumb_bounds.height() / 2.f, thumb_paint);
89 }
90
91 // Color ratio between 0 and 1 that controls the thumb color.
92 double color_ratio_;
93
94 DISALLOW_COPY_AND_ASSIGN(ThumbView);
95 };
96
37 ToggleButton::ToggleButton(ButtonListener* listener) 97 ToggleButton::ToggleButton(ButtonListener* listener)
38 : CustomButton(listener), is_on_(false), slide_animation_(this) { 98 : CustomButton(listener),
99 is_on_(false),
100 slide_animation_(this),
101 thumb_view_(new ToggleButton::ThumbView(this)) {
39 slide_animation_.SetSlideDuration(80 /* ms */); 102 slide_animation_.SetSlideDuration(80 /* ms */);
40 slide_animation_.SetTweenType(gfx::Tween::LINEAR); 103 slide_animation_.SetTweenType(gfx::Tween::LINEAR);
41 SetBorder(Border::CreateEmptyBorder( 104 SetBorder(Border::CreateEmptyBorder(
42 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin))); 105 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin)));
43 SetInkDropMode(InkDropMode::ON); 106 SetInkDropMode(InkDropMode::ON);
44 set_has_ink_drop_action_on_click(true); 107 set_has_ink_drop_action_on_click(true);
45 } 108 }
46 109
47 ToggleButton::~ToggleButton() {} 110 ToggleButton::~ToggleButton() {
111 thumb_view_.reset();
112 }
48 113
49 void ToggleButton::SetIsOn(bool is_on, bool animate) { 114 void ToggleButton::SetIsOn(bool is_on, bool animate) {
50 if (is_on_ == is_on) 115 if (is_on_ == is_on)
51 return; 116 return;
52 117
53 is_on_ = is_on; 118 is_on_ = is_on;
54 if (!animate) 119 if (!animate)
55 slide_animation_.Reset(is_on_ ? 1.0 : 0.0); 120 slide_animation_.Reset(is_on_ ? 1.0 : 0.0);
56 else if (is_on_) 121 else if (is_on_)
57 slide_animation_.Show(); 122 slide_animation_.Show();
58 else 123 else
59 slide_animation_.Hide(); 124 slide_animation_.Hide();
60 } 125 }
61 126
62 gfx::Size ToggleButton::GetPreferredSize() const { 127 gfx::Size ToggleButton::GetPreferredSize() const {
63 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight); 128 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight);
64 if (border()) 129 if (border())
65 rect.Inset(-border()->GetInsets()); 130 rect.Inset(-border()->GetInsets());
66 return rect.size(); 131 return rect.size();
67 } 132 }
68 133
134 const char* ToggleButton::GetClassName() const {
135 return "ToggleButton";
136 }
137
69 void ToggleButton::OnPaint(gfx::Canvas* canvas) { 138 void ToggleButton::OnPaint(gfx::Canvas* canvas) {
70 SkAlpha blend = 139 const double color_ratio = slide_animation_.GetCurrentValue();
71 static_cast<SkAlpha>(SK_AlphaOPAQUE * slide_animation_.GetCurrentValue()); 140 SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio);
72 141
73 // Track. 142 // Track.
74 gfx::RectF track_rect(GetContentsBounds()); 143 gfx::RectF track_rect(GetContentsBounds());
75 SkPaint track_paint; 144 SkPaint track_paint;
76 track_paint.setAntiAlias(true); 145 track_paint.setAntiAlias(true);
77 const SkColor track_on_color = 146 const SkColor track_on_color =
78 SkColorSetA(GetNativeTheme()->GetSystemColor( 147 SkColorSetA(GetNativeTheme()->GetSystemColor(
79 ui::NativeTheme::kColorId_ProminentButtonColor), 148 ui::NativeTheme::kColorId_ProminentButtonColor),
80 0xFF / 2); 149 0xFF / 2);
81 track_paint.setColor( 150 track_paint.setColor(
82 color_utils::AlphaBlend(track_on_color, kTrackOffColor, blend)); 151 color_utils::AlphaBlend(track_on_color, kTrackOffColor, blend));
83 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint); 152 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint);
84
85 // Thumb.
86 gfx::Rect thumb_bounds = GetThumbBounds();
87 SkPaint thumb_paint;
88 std::vector<gfx::ShadowValue> shadows;
89 shadows.emplace_back(gfx::Vector2d(0, 1), 4.f,
90 SkColorSetA(SK_ColorBLACK, 0x99));
91 thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
92 thumb_paint.setStyle(SkPaint::kFill_Style);
93 thumb_paint.setAntiAlias(true);
94 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
95 ui::NativeTheme::kColorId_ProminentButtonColor);
96 // TODO(estade): get this color from the theme?
97 const SkColor thumb_off_color = SK_ColorWHITE;
98 thumb_paint.setColor(
99 color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
100 canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(),
101 thumb_bounds.height() / 2.f, thumb_paint);
102 } 153 }
103 154
104 void ToggleButton::NotifyClick(const ui::Event& event) { 155 void ToggleButton::NotifyClick(const ui::Event& event) {
105 SetIsOn(!is_on(), true); 156 SetIsOn(!is_on(), true);
106 CustomButton::NotifyClick(event); 157 CustomButton::NotifyClick(event);
107 } 158 }
108 159
160 void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
161 UpdateThumb();
162 }
163
109 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { 164 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
110 SchedulePaint(); 165 SchedulePaint();
111 } 166 }
112 167
168 void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
169 CustomButton::AddInkDropLayer(ink_drop_layer);
bruthig 2016/10/12 13:38:09 You shouldn't need to call into the parent here si
varkha 2016/10/12 14:45:24 Done.
170 thumb_view_->AddInkDropLayer(ink_drop_layer);
171 UpdateThumb();
172 SchedulePaint();
173 }
174
175 void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
176 thumb_view_->RemoveInkDropLayer(ink_drop_layer);
bruthig 2016/10/12 13:38:09 You should maybe check that |thumb_view_| isn't nu
varkha 2016/10/12 14:45:24 I think this gets handled auto-magically. When a i
bruthig 2016/10/13 17:09:46 The |thumb_view_| is being destroyed in ~ToggleBut
varkha 2016/10/13 23:07:35 Good call. So the test doesn't crash because the v
177 SchedulePaint();
178 }
179
113 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const { 180 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const {
114 return CreateDefaultInkDropRipple(GetThumbBounds().CenterPoint()); 181 const int radius = (kTrackHeight + kTrackVerticalMargin * 2) / 2;
182 return CreateDefaultInkDropRipple(gfx::Point(radius, radius));
115 } 183 }
116 184
117 SkColor ToggleButton::GetInkDropBaseColor() const { 185 SkColor ToggleButton::GetInkDropBaseColor() const {
118 return is_on() 186 return is_on()
119 ? GetNativeTheme()->GetSystemColor( 187 ? GetNativeTheme()->GetSystemColor(
120 ui::NativeTheme::kColorId_ProminentButtonColor) 188 ui::NativeTheme::kColorId_ProminentButtonColor)
121 : kTrackOffColor; 189 : kTrackOffColor;
122 } 190 }
123 191
124 bool ToggleButton::ShouldShowInkDropHighlight() const { 192 bool ToggleButton::ShouldShowInkDropHighlight() const {
125 return false; 193 return false;
126 } 194 }
127 195
128 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) { 196 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
129 if (animation == &slide_animation_) 197 if (animation == &slide_animation_) {
198 UpdateThumb();
130 SchedulePaint(); 199 SchedulePaint();
131 else 200 return;
132 CustomButton::AnimationProgressed(animation); 201 }
202 CustomButton::AnimationProgressed(animation);
133 } 203 }
134 204
135 gfx::Rect ToggleButton::GetThumbBounds() const { 205 gfx::Rect ToggleButton::GetThumbBounds() const {
136 gfx::Rect thumb_bounds = GetLocalBounds(); 206 gfx::Rect thumb_bounds = GetLocalBounds();
137 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin)); 207 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
138 thumb_bounds.set_x(thumb_bounds.x() + 208 thumb_bounds.set_x(thumb_bounds.x() +
139 slide_animation_.GetCurrentValue() * 209 slide_animation_.GetCurrentValue() *
140 (thumb_bounds.width() - thumb_bounds.height())); 210 (thumb_bounds.width() - thumb_bounds.height()));
141 // The thumb is a circle, so the width should match the height. 211 // The thumb is a circle, so the width should match the height.
142 thumb_bounds.set_width(thumb_bounds.height()); 212 thumb_bounds.set_width(thumb_bounds.height());
143 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds)); 213 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds));
144 return thumb_bounds; 214 return thumb_bounds;
145 } 215 }
146 216
217 void ToggleButton::UpdateThumb() {
218 gfx::Rect thumb_bounds = GetThumbBounds();
219 thumb_bounds.Inset(gfx::Insets(-kThumbVerticalMargin));
220 thumb_view_->Update(thumb_bounds, slide_animation_.GetCurrentValue());
221 }
222
147 } // namespace views 223 } // namespace views
OLDNEW
« no previous file with comments | « 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