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

Unified 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 (better destruction sequ… 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/button/toggle_button.h ('k') | ui/views/controls/button/toggle_button_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/button/toggle_button.cc
diff --git a/ui/views/controls/button/toggle_button.cc b/ui/views/controls/button/toggle_button.cc
index 30bf562a54887ce6a3b62c24af0408b80104c884..e7c656b641bfaaeb7eee4fe06c47f89abc99c3ea 100644
--- a/ui/views/controls/button/toggle_button.cc
+++ b/ui/views/controls/button/toggle_button.cc
@@ -34,17 +34,85 @@ const SkColor kTrackOffColor =
} // namespace
+// Class representing the thumb. When the thumb is clicked it is separated into
+// its own layer and the ink drop layer is made a child of the thumb layer
+// allowing the two to animate in sync.
+class ToggleButton::ThumbView : public views::View {
+ public:
+ ThumbView() : color_ratio_(0.) {}
+ ~ThumbView() override {}
+
+ void AddInkDropLayer(ui::Layer* ink_drop_layer) {
Evan Stade 2016/10/17 15:37:58 if ThumbView were an InkDropHostView could we not
varkha 2016/10/17 16:12:53 Yes, but this would mean we would have to fix the
Evan Stade 2016/10/18 13:13:15 I didn't mean to replace the ToggleButton as the I
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+ layer()->Add(ink_drop_layer);
+ }
+
+ void RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ layer()->Remove(ink_drop_layer);
+ SetPaintToLayer(false);
+ }
+
+ void Update(const gfx::Rect& bounds, double color_ratio) {
+ SetBoundsRect(bounds);
+ color_ratio_ = color_ratio;
+ SchedulePaint();
+ }
+
+ private:
+ // views::View:
+ const char* GetClassName() const override {
+ return "ToggleButton::ThumbView";
+ }
+
+ void OnPaint(gfx::Canvas* canvas) override {
+ std::vector<gfx::ShadowValue> shadows;
+ shadows.emplace_back(gfx::Vector2d(0, 1), 4.f,
+ SkColorSetA(SK_ColorBLACK, 0x99));
+ SkPaint thumb_paint;
+ thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
+ thumb_paint.setStyle(SkPaint::kFill_Style);
+ thumb_paint.setAntiAlias(true);
+ const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_ProminentButtonColor);
+ // TODO(estade): get this color from the theme?
+ const SkColor thumb_off_color = SK_ColorWHITE;
+ const SkAlpha blend = static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio_);
+ thumb_paint.setColor(
+ color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
+ gfx::Rect thumb_bounds = GetLocalBounds();
+ thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin));
+ canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(),
+ thumb_bounds.height() / 2.f, thumb_paint);
+ }
+
+ // Color ratio between 0 and 1 that controls the thumb color.
+ double color_ratio_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThumbView);
+};
+
+// static
+const char ToggleButton::kViewClassName[] = "ToggleButton";
+
ToggleButton::ToggleButton(ButtonListener* listener)
- : CustomButton(listener), is_on_(false), slide_animation_(this) {
+ : CustomButton(listener),
+ is_on_(false),
+ slide_animation_(this),
+ thumb_view_(new ToggleButton::ThumbView()) {
slide_animation_.SetSlideDuration(80 /* ms */);
slide_animation_.SetTweenType(gfx::Tween::LINEAR);
SetBorder(Border::CreateEmptyBorder(
gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin)));
+ AddChildView(thumb_view_.get());
SetInkDropMode(InkDropMode::ON);
set_has_ink_drop_action_on_click(true);
}
-ToggleButton::~ToggleButton() {}
+ToggleButton::~ToggleButton() {
+ // Destroying ink drop early allows ink drop layer to be properly removed,
+ SetInkDropMode(InkDropMode::OFF);
+}
void ToggleButton::SetIsOn(bool is_on, bool animate) {
if (is_on_ == is_on)
@@ -59,6 +127,24 @@ void ToggleButton::SetIsOn(bool is_on, bool animate) {
slide_animation_.Hide();
}
+gfx::Rect ToggleButton::GetThumbBounds() const {
+ gfx::Rect thumb_bounds = GetLocalBounds();
+ thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
+ thumb_bounds.set_x(thumb_bounds.x() +
+ slide_animation_.GetCurrentValue() *
+ (thumb_bounds.width() - thumb_bounds.height()));
+ // The thumb is a circle, so the width should match the height.
+ thumb_bounds.set_width(thumb_bounds.height());
+ thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds));
+ return thumb_bounds;
+}
+
+void ToggleButton::UpdateThumb() {
+ gfx::Rect thumb_bounds = GetThumbBounds();
+ thumb_bounds.Inset(gfx::Insets(-kThumbVerticalMargin));
+ thumb_view_->Update(thumb_bounds, slide_animation_.GetCurrentValue());
+}
+
gfx::Size ToggleButton::GetPreferredSize() const {
gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight);
if (border())
@@ -66,11 +152,12 @@ gfx::Size ToggleButton::GetPreferredSize() const {
return rect.size();
}
-void ToggleButton::OnPaint(gfx::Canvas* canvas) {
- SkAlpha blend =
- static_cast<SkAlpha>(SK_AlphaOPAQUE * slide_animation_.GetCurrentValue());
+const char* ToggleButton::GetClassName() const {
+ return kViewClassName;
+}
- // Track.
+void ToggleButton::OnPaint(gfx::Canvas* canvas) {
+ // Paint the toggle track.
gfx::RectF track_rect(GetContentsBounds());
SkPaint track_paint;
track_paint.setAntiAlias(true);
@@ -78,27 +165,11 @@ void ToggleButton::OnPaint(gfx::Canvas* canvas) {
SkColorSetA(GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor),
0xFF / 2);
- track_paint.setColor(
- color_utils::AlphaBlend(track_on_color, kTrackOffColor, blend));
+ const double color_ratio = slide_animation_.GetCurrentValue();
+ track_paint.setColor(color_utils::AlphaBlend(
+ track_on_color, kTrackOffColor,
+ static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio)));
canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint);
-
- // Thumb.
- gfx::Rect thumb_bounds = GetThumbBounds();
- SkPaint thumb_paint;
- std::vector<gfx::ShadowValue> shadows;
- shadows.emplace_back(gfx::Vector2d(0, 1), 4.f,
- SkColorSetA(SK_ColorBLACK, 0x99));
- thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
- thumb_paint.setStyle(SkPaint::kFill_Style);
- thumb_paint.setAntiAlias(true);
- const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_ProminentButtonColor);
- // TODO(estade): get this color from the theme?
- const SkColor thumb_off_color = SK_ColorWHITE;
- thumb_paint.setColor(
- color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
- canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(),
- thumb_bounds.height() / 2.f, thumb_paint);
}
void ToggleButton::NotifyClick(const ui::Event& event) {
@@ -106,12 +177,28 @@ void ToggleButton::NotifyClick(const ui::Event& event) {
CustomButton::NotifyClick(event);
}
+void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ UpdateThumb();
+}
+
void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
SchedulePaint();
}
+void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+ thumb_view_->AddInkDropLayer(ink_drop_layer);
+ UpdateThumb();
+ SchedulePaint();
+}
+
+void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ thumb_view_->RemoveInkDropLayer(ink_drop_layer);
+ SchedulePaint();
+}
+
std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const {
- return CreateDefaultInkDropRipple(GetThumbBounds().CenterPoint());
+ const int radius = (kTrackHeight + kTrackVerticalMargin * 2) / 2;
+ return CreateDefaultInkDropRipple(gfx::Point(radius, radius));
}
SkColor ToggleButton::GetInkDropBaseColor() const {
@@ -126,22 +213,14 @@ bool ToggleButton::ShouldShowInkDropHighlight() const {
}
void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
- if (animation == &slide_animation_)
+ if (animation == &slide_animation_) {
+ // TODO(varkha, estade): The thumb is using its own view. Investigate if
+ // repainting in every animation step to update colors could be avoided.
Evan Stade 2016/10/17 15:37:58 I don't understand this comment. How can we avoid
varkha 2016/10/17 16:12:53 I think sadrul@ was asking if some layer animation
+ UpdateThumb();
SchedulePaint();
- else
- CustomButton::AnimationProgressed(animation);
-}
-
-gfx::Rect ToggleButton::GetThumbBounds() const {
- gfx::Rect thumb_bounds = GetLocalBounds();
- thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
- thumb_bounds.set_x(thumb_bounds.x() +
- slide_animation_.GetCurrentValue() *
- (thumb_bounds.width() - thumb_bounds.height()));
- // The thumb is a circle, so the width should match the height.
- thumb_bounds.set_width(thumb_bounds.height());
- thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds));
- return thumb_bounds;
+ return;
+ }
+ CustomButton::AnimationProgressed(animation);
}
} // namespace views
« no previous file with comments | « ui/views/controls/button/toggle_button.h ('k') | ui/views/controls/button/toggle_button_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698