OLD | NEW |
---|---|
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 14 matching lines...) Expand all Loading... | |
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. Note that the thumb |
26 // margins must be sufficiently large to allow space for the shadow. | 26 // margins must be sufficiently large to allow space for the shadow. |
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 // Paints the circular thumb at |bounds| on |canvas|. The thumb color is set | |
36 // between white and |thumb_on_color| mixed with |ratio|. This utility function | |
37 // is used both whether the thumb is animating or not. | |
38 void PaintThumb(gfx::Canvas* canvas, gfx::Rect bounds, double value, | |
39 SkColor thumb_on_color) { | |
40 std::vector<gfx::ShadowValue> shadows; | |
41 shadows.emplace_back(gfx::Vector2d(0, 1), 4.f, | |
42 SkColorSetA(SK_ColorBLACK, 0x99)); | |
43 SkPaint thumb_paint; | |
44 thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows)); | |
45 thumb_paint.setStyle(SkPaint::kFill_Style); | |
46 thumb_paint.setAntiAlias(true); | |
47 // TODO(estade): get this color from the theme? | |
48 const SkColor thumb_off_color = SK_ColorWHITE; | |
49 const SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * value); | |
50 thumb_paint.setColor( | |
51 color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend)); | |
52 canvas->DrawCircle(gfx::RectF(bounds).CenterPoint(), | |
53 bounds.height() / 2.f, thumb_paint); | |
54 } | |
55 | |
35 } // namespace | 56 } // namespace |
36 | 57 |
58 // Class representing the thumb when ink drop animation is active. In static | |
59 // case the thumb is painted by the ToggleButton. When the thumb is clicked it | |
60 // is separated into its own layer and the ink drop layer is made a child of | |
61 // the thumb layer allowing the two to animate in sync. | |
62 class ToggleButton::ThumbView : public views::View { | |
63 public: | |
64 ThumbView(ui::Layer* ink_drop_layer, double value) : value_(value) { | |
65 SetPaintToLayer(true); | |
66 layer()->SetFillsBoundsOpaquely(false); | |
67 layer()->Add(ink_drop_layer); | |
68 } | |
69 ~ThumbView() override {} | |
70 | |
71 void Update(const gfx::Rect& bounds, double value) { | |
72 SetBoundsRect(bounds); | |
73 value_ = value; | |
74 SchedulePaint(); | |
75 } | |
76 | |
77 private: | |
78 // views::View: | |
79 void OnPaint(gfx::Canvas* canvas) override { | |
80 gfx::Rect thumb_bounds = GetLocalBounds(); | |
81 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin)); | |
82 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor( | |
83 ui::NativeTheme::kColorId_ProminentButtonColor); | |
84 PaintThumb(canvas, thumb_bounds, value_, thumb_on_color); | |
85 } | |
86 | |
87 // Value between 0 and 1 that controls the thumb color. | |
88 double value_; | |
89 | |
90 DISALLOW_COPY_AND_ASSIGN(ThumbView); | |
91 }; | |
92 | |
37 ToggleButton::ToggleButton(ButtonListener* listener) | 93 ToggleButton::ToggleButton(ButtonListener* listener) |
38 : CustomButton(listener), is_on_(false), slide_animation_(this) { | 94 : CustomButton(listener), is_on_(false), slide_animation_(this) { |
39 slide_animation_.SetSlideDuration(80 /* ms */); | 95 slide_animation_.SetSlideDuration(80 /* ms */); |
40 slide_animation_.SetTweenType(gfx::Tween::LINEAR); | 96 slide_animation_.SetTweenType(gfx::Tween::LINEAR); |
41 SetBorder(Border::CreateEmptyBorder( | 97 SetBorder(Border::CreateEmptyBorder( |
42 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin))); | 98 gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin))); |
43 SetInkDropMode(InkDropMode::ON); | 99 SetInkDropMode(InkDropMode::ON); |
44 set_has_ink_drop_action_on_click(true); | 100 set_has_ink_drop_action_on_click(true); |
45 } | 101 } |
46 | 102 |
(...skipping 13 matching lines...) Expand all Loading... | |
60 } | 116 } |
61 | 117 |
62 gfx::Size ToggleButton::GetPreferredSize() const { | 118 gfx::Size ToggleButton::GetPreferredSize() const { |
63 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight); | 119 gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight); |
64 if (border()) | 120 if (border()) |
65 rect.Inset(-border()->GetInsets()); | 121 rect.Inset(-border()->GetInsets()); |
66 return rect.size(); | 122 return rect.size(); |
67 } | 123 } |
68 | 124 |
69 void ToggleButton::OnPaint(gfx::Canvas* canvas) { | 125 void ToggleButton::OnPaint(gfx::Canvas* canvas) { |
70 SkAlpha blend = | 126 const double value = slide_animation_.GetCurrentValue(); |
71 static_cast<SkAlpha>(SK_AlphaOPAQUE * slide_animation_.GetCurrentValue()); | 127 SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * value); |
72 | 128 |
73 // Track. | 129 // Track. |
74 gfx::RectF track_rect(GetContentsBounds()); | 130 gfx::RectF track_rect(GetContentsBounds()); |
75 SkPaint track_paint; | 131 SkPaint track_paint; |
76 track_paint.setAntiAlias(true); | 132 track_paint.setAntiAlias(true); |
77 const SkColor track_on_color = | 133 const SkColor track_on_color = |
78 SkColorSetA(GetNativeTheme()->GetSystemColor( | 134 SkColorSetA(GetNativeTheme()->GetSystemColor( |
79 ui::NativeTheme::kColorId_ProminentButtonColor), | 135 ui::NativeTheme::kColorId_ProminentButtonColor), |
80 0xFF / 2); | 136 0xFF / 2); |
81 track_paint.setColor( | 137 track_paint.setColor( |
82 color_utils::AlphaBlend(track_on_color, kTrackOffColor, blend)); | 138 color_utils::AlphaBlend(track_on_color, kTrackOffColor, blend)); |
83 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint); | 139 canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint); |
84 | 140 |
85 // Thumb. | 141 if (thumb_view_) |
142 return; | |
143 | |
144 // Paint thumb when not animating. | |
86 gfx::Rect thumb_bounds = GetThumbBounds(); | 145 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( | 146 const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor( |
95 ui::NativeTheme::kColorId_ProminentButtonColor); | 147 ui::NativeTheme::kColorId_ProminentButtonColor); |
96 // TODO(estade): get this color from the theme? | 148 PaintThumb(canvas, thumb_bounds, value, thumb_on_color); |
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 } | 149 } |
103 | 150 |
104 void ToggleButton::NotifyClick(const ui::Event& event) { | 151 void ToggleButton::NotifyClick(const ui::Event& event) { |
105 SetIsOn(!is_on(), true); | 152 SetIsOn(!is_on(), true); |
106 CustomButton::NotifyClick(event); | 153 CustomButton::NotifyClick(event); |
107 } | 154 } |
108 | 155 |
109 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { | 156 void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { |
110 SchedulePaint(); | 157 SchedulePaint(); |
111 } | 158 } |
112 | 159 |
160 void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) { | |
161 CustomButton::AddInkDropLayer(ink_drop_layer); | |
162 thumb_view_.reset( | |
163 new ToggleButton::ThumbView(ink_drop_layer, | |
Evan Stade
2016/10/12 00:46:55
I was kind of expecting the thumb to just always b
varkha
2016/10/12 01:52:41
Done.
| |
164 slide_animation_.GetCurrentValue())); | |
165 AddChildView(thumb_view_.get()); | |
166 gfx::Rect thumb_bounds = GetThumbBounds(); | |
167 thumb_bounds.Inset(gfx::Insets(-kThumbVerticalMargin)); | |
168 thumb_view_->SetBoundsRect(thumb_bounds); | |
169 } | |
170 | |
171 void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) { | |
172 thumb_view_->layer()->Remove(ink_drop_layer); | |
173 thumb_view_.reset(); | |
174 SchedulePaint(); | |
175 } | |
176 | |
113 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const { | 177 std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const { |
114 return CreateDefaultInkDropRipple(GetThumbBounds().CenterPoint()); | 178 const int radius = (kTrackHeight + kTrackVerticalMargin * 2) / 2; |
179 return CreateDefaultInkDropRipple(gfx::Point(radius, radius)); | |
115 } | 180 } |
116 | 181 |
117 SkColor ToggleButton::GetInkDropBaseColor() const { | 182 SkColor ToggleButton::GetInkDropBaseColor() const { |
118 return is_on() | 183 return is_on() |
119 ? GetNativeTheme()->GetSystemColor( | 184 ? GetNativeTheme()->GetSystemColor( |
120 ui::NativeTheme::kColorId_ProminentButtonColor) | 185 ui::NativeTheme::kColorId_ProminentButtonColor) |
121 : kTrackOffColor; | 186 : kTrackOffColor; |
122 } | 187 } |
123 | 188 |
124 bool ToggleButton::ShouldShowInkDropHighlight() const { | 189 bool ToggleButton::ShouldShowInkDropHighlight() const { |
125 return false; | 190 return false; |
126 } | 191 } |
127 | 192 |
128 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) { | 193 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) { |
129 if (animation == &slide_animation_) | 194 if (animation == &slide_animation_) { |
195 if (thumb_view_) { | |
196 gfx::Rect thumb_bounds = GetThumbBounds(); | |
197 thumb_bounds.Inset(gfx::Insets(-kThumbVerticalMargin)); | |
198 thumb_view_->Update(thumb_bounds, slide_animation_.GetCurrentValue()); | |
199 } | |
130 SchedulePaint(); | 200 SchedulePaint(); |
131 else | 201 } else { |
132 CustomButton::AnimationProgressed(animation); | 202 CustomButton::AnimationProgressed(animation); |
203 } | |
133 } | 204 } |
134 | 205 |
135 gfx::Rect ToggleButton::GetThumbBounds() const { | 206 gfx::Rect ToggleButton::GetThumbBounds() const { |
136 gfx::Rect thumb_bounds = GetLocalBounds(); | 207 gfx::Rect thumb_bounds = GetLocalBounds(); |
137 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin)); | 208 thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin)); |
138 thumb_bounds.set_x(thumb_bounds.x() + | 209 thumb_bounds.set_x(thumb_bounds.x() + |
139 slide_animation_.GetCurrentValue() * | 210 slide_animation_.GetCurrentValue() * |
140 (thumb_bounds.width() - thumb_bounds.height())); | 211 (thumb_bounds.width() - thumb_bounds.height())); |
141 // The thumb is a circle, so the width should match the height. | 212 // The thumb is a circle, so the width should match the height. |
142 thumb_bounds.set_width(thumb_bounds.height()); | 213 thumb_bounds.set_width(thumb_bounds.height()); |
143 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds)); | 214 thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds)); |
144 return thumb_bounds; | 215 return thumb_bounds; |
145 } | 216 } |
146 | 217 |
147 } // namespace views | 218 } // namespace views |
OLD | NEW |