Chromium Code Reviews| 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 e7c656b641bfaaeb7eee4fe06c47f89abc99c3ea..8685cffa6160d53160d434d1b70c35ca19191946 100644 |
| --- a/ui/views/controls/button/toggle_button.cc |
| +++ b/ui/views/controls/button/toggle_button.cc |
| @@ -28,38 +28,30 @@ const int kThumbHorizontalMargin = 4; |
| // Margin from top/bottom edge of thumb to top/bottom edge of view. |
| const int kThumbVerticalMargin = 3; |
| -// TODO(estade): get the base color (black) from the theme? |
| -const SkColor kTrackOffColor = |
| - SkColorSetA(SK_ColorBLACK, gfx::kDisabledControlAlpha); |
| - |
| } // 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 { |
| +// Class representing the thumb (the circle that slides horizontally). |
| +class ToggleButton::ThumbView : public InkDropHostView { |
| public: |
| ThumbView() : color_ratio_(0.) {} |
| ~ThumbView() override {} |
| - void AddInkDropLayer(ui::Layer* ink_drop_layer) { |
| - 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(); |
| } |
| + static gfx::Insets GetShadowInsets() { |
| + return gfx::Insets(kShadowBlur) + |
| + gfx::Vector2d(kShadowOffsetX, kShadowOffsetY); |
| + } |
| + |
| private: |
| + static const int kShadowOffsetX = 0; |
| + static const int kShadowOffsetY = 1; |
| + static const int kShadowBlur = 2; |
| + |
| // views::View: |
| const char* GetClassName() const override { |
| return "ToggleButton::ThumbView"; |
| @@ -67,23 +59,34 @@ class ToggleButton::ThumbView : public views::View { |
| void OnPaint(gfx::Canvas* canvas) override { |
| std::vector<gfx::ShadowValue> shadows; |
| - shadows.emplace_back(gfx::Vector2d(0, 1), 4.f, |
| - SkColorSetA(SK_ColorBLACK, 0x99)); |
| + shadows.emplace_back( |
| + gfx::Vector2d(kShadowOffsetX, kShadowOffsetY), 2 * kShadowBlur, |
| + SkColorSetA(GetNativeTheme()->GetSystemColor( |
| + ui::NativeTheme::kColorId_LabelEnabledColor), |
| + 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 SkColor thumb_off_color = GetNativeTheme()->GetSystemColor( |
| + ui::NativeTheme::kColorId_DialogBackground); |
| 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); |
| + |
| + gfx::RectF thumb_bounds(GetLocalBounds()); |
| + thumb_bounds.Inset(GetShadowInsets()); |
| + thumb_bounds.Inset(gfx::InsetsF(0.5f)); |
| + gfx::RectF bounds_in_px = thumb_bounds; |
| + // We want the circle to have an integer pixel diameter and to be aligned |
| + // with pixel boundaries, so we scale dip bounds to pixel bounds, round, and |
| + // unscale back to dip bounds. |
|
sadrul
2016/10/28 02:58:14
This is pretty weird. Can you use Canvas::UndoDevi
Evan Stade
2016/10/28 17:49:39
That makes it harder to deal with the shadows, whi
danakj
2016/10/28 18:44:59
UndoDSF() mostly lets you round to physical pixels
Evan Stade
2016/10/28 19:22:03
I don't think that addresses the problem with shad
sadrul
2016/10/31 18:28:50
We avoid going pixel -> dip (and possibly avoid mo
sadrul
2016/10/31 18:28:50
Can you clarify why scaling the shadow values is h
Evan Stade
2016/11/01 16:26:22
mainly because of a lack of awareness of ShadowVal
Evan Stade
2016/11/01 16:26:22
Done.
|
| + bounds_in_px.Scale(canvas->image_scale()); |
| + gfx::RectF bounds_in_dip(gfx::ToEnclosingRect(bounds_in_px)); |
| + bounds_in_dip.Scale(1.f / canvas->image_scale()); |
| + canvas->DrawCircle(bounds_in_dip.CenterPoint(), |
| + bounds_in_dip.height() / 2.f, thumb_paint); |
| } |
| // Color ratio between 0 and 1 that controls the thumb color. |
| @@ -99,12 +102,12 @@ ToggleButton::ToggleButton(ButtonListener* listener) |
| : CustomButton(listener), |
| is_on_(false), |
| slide_animation_(this), |
| - thumb_view_(new ToggleButton::ThumbView()) { |
| + thumb_view_(new ThumbView()) { |
| slide_animation_.SetSlideDuration(80 /* ms */); |
| slide_animation_.SetTweenType(gfx::Tween::LINEAR); |
| SetBorder(Border::CreateEmptyBorder( |
| gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin))); |
| - AddChildView(thumb_view_.get()); |
| + AddChildView(thumb_view_); |
| SetInkDropMode(InkDropMode::ON); |
| set_has_ink_drop_action_on_click(true); |
| } |
| @@ -136,13 +139,22 @@ gfx::Rect ToggleButton::GetThumbBounds() const { |
| // 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)); |
| + thumb_bounds.Inset(-ThumbView::GetShadowInsets()); |
| 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()); |
| + thumb_view_->Update(GetThumbBounds(), slide_animation_.GetCurrentValue()); |
| +} |
| + |
| +SkColor ToggleButton::GetTrackColor(bool is_on) const { |
| + const SkAlpha kOffTrackAlpha = 0x29; |
| + const SkAlpha kOnTrackAlpha = kOffTrackAlpha * 2; |
| + ui::NativeTheme::ColorId color_id = |
| + is_on ? ui::NativeTheme::kColorId_ProminentButtonColor |
| + : ui::NativeTheme::kColorId_LabelEnabledColor; |
| + return SkColorSetA(GetNativeTheme()->GetSystemColor(color_id), |
| + is_on ? kOnTrackAlpha : kOffTrackAlpha); |
| } |
| gfx::Size ToggleButton::GetPreferredSize() const { |
| @@ -161,13 +173,9 @@ void ToggleButton::OnPaint(gfx::Canvas* canvas) { |
| gfx::RectF track_rect(GetContentsBounds()); |
| SkPaint track_paint; |
| track_paint.setAntiAlias(true); |
| - const SkColor track_on_color = |
| - SkColorSetA(GetNativeTheme()->GetSystemColor( |
| - ui::NativeTheme::kColorId_ProminentButtonColor), |
| - 0xFF / 2); |
| const double color_ratio = slide_animation_.GetCurrentValue(); |
| track_paint.setColor(color_utils::AlphaBlend( |
| - track_on_color, kTrackOffColor, |
| + GetTrackColor(true), GetTrackColor(false), |
| static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio))); |
| canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint); |
| } |
| @@ -202,10 +210,7 @@ std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const { |
| } |
| SkColor ToggleButton::GetInkDropBaseColor() const { |
| - return is_on() |
| - ? GetNativeTheme()->GetSystemColor( |
| - ui::NativeTheme::kColorId_ProminentButtonColor) |
| - : kTrackOffColor; |
| + return GetTrackColor(is_on()); |
| } |
| bool ToggleButton::ShouldShowInkDropHighlight() const { |