1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/wm/splitview/split_view_divider_handler_view.h"
6
7 #include "ash/display/screen_orientation_controller.h"
8 #include "ash/shell.h"
9 #include "ash/style/ash_color_provider.h"
10 #include "ash/wm/splitview/split_view_constants.h"
11 #include "ash/wm/splitview/split_view_utils.h"
12 #include "base/timer/timer.h"
13 #include "ui/gfx/animation/animation_delegate.h"
14 #include "ui/gfx/animation/slide_animation.h"
15 #include "ui/views/background.h"
16
17 namespace ash {
18
19 namespace {
20
GetBackgroundColor()21 SkColor GetBackgroundColor() {
22 return AshColorProvider::Get()->GetContentLayerColor(
23 AshColorProvider::ContentLayerType::kIconColorPrimary);
24 }
25
26 } // namespace
27
28 class SplitViewDividerHandlerView::SelectionAnimation
29 : public gfx::SlideAnimation,
30 public gfx::AnimationDelegate {
31 public:
SelectionAnimation(SplitViewDividerHandlerView * white_handler_view)32 SelectionAnimation(SplitViewDividerHandlerView* white_handler_view)
33 : gfx::SlideAnimation(this), white_handler_view_(white_handler_view) {
34 SetSlideDuration(kSplitviewDividerSelectionStatusChangeDuration);
35 SetTweenType(gfx::Tween::EASE_IN);
36 }
37
38 ~SelectionAnimation() override = default;
39
UpdateWhiteHandlerBounds()40 void UpdateWhiteHandlerBounds() {
41 white_handler_view_->SetBounds(
42 CurrentValueBetween(kSplitviewWhiteBarShortSideLength,
43 kSplitviewWhiteBarRadius * 2),
44 CurrentValueBetween(kSplitviewWhiteBarLongSideLength,
45 kSplitviewWhiteBarRadius * 2),
46 /*signed_offset=*/0);
47 }
48
49 private:
50 // gfx::AnimationDelegate:
AnimationProgressed(const gfx::Animation * animation)51 void AnimationProgressed(const gfx::Animation* animation) override {
52 UpdateWhiteHandlerBounds();
53 white_handler_view_->UpdateCornerRadius(CurrentValueBetween(
54 kSplitviewWhiteBarCornerRadius, kSplitviewWhiteBarRadius));
55 }
56
57 SplitViewDividerHandlerView* white_handler_view_;
58
59 DISALLOW_COPY_AND_ASSIGN(SelectionAnimation);
60 };
61
62 class SplitViewDividerHandlerView::SpawningAnimation
63 : public gfx::SlideAnimation,
64 public gfx::AnimationDelegate {
65 public:
SpawningAnimation(SplitViewDividerHandlerView * white_handler_view,int divider_signed_offset)66 SpawningAnimation(SplitViewDividerHandlerView* white_handler_view,
67 int divider_signed_offset)
68 : gfx::SlideAnimation(this),
69 white_handler_view_(white_handler_view),
70 spawn_signed_offset_(divider_signed_offset +
71 (divider_signed_offset > 0
72 ? kSplitviewWhiteBarSpawnUnsignedOffset
73 : -kSplitviewWhiteBarSpawnUnsignedOffset)) {
74 SetSlideDuration(kSplitviewDividerSpawnDuration);
75 SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
76 }
77
78 ~SpawningAnimation() override = default;
79
Activate()80 void Activate() {
81 white_handler_view_->SetVisible(false);
82 delay_timer_.Start(FROM_HERE, kSplitviewDividerSpawnDelay, this,
83 &SpawningAnimation::StartAnimation);
84 }
85
IsActive() const86 bool IsActive() const { return delay_timer_.IsRunning() || is_animating(); }
87
UpdateWhiteHandlerBounds()88 void UpdateWhiteHandlerBounds() {
89 DCHECK(IsActive());
90 white_handler_view_->SetBounds(
91 kSplitviewWhiteBarShortSideLength,
92 CurrentValueBetween(kSplitviewWhiteBarSpawnLongSideLength,
93 kSplitviewWhiteBarLongSideLength),
94 CurrentValueBetween(spawn_signed_offset_, 0));
95 }
96
97 private:
StartAnimation()98 void StartAnimation() {
99 DCHECK(!white_handler_view_->GetVisible());
100 white_handler_view_->SetVisible(true);
101 DCHECK(!is_animating());
102 Show();
103 DCHECK_EQ(0.0, GetCurrentValue());
104 UpdateWhiteHandlerBounds();
105 }
106
107 // gfx::AnimationDelegate:
AnimationProgressed(const gfx::Animation * animation)108 void AnimationProgressed(const gfx::Animation* animation) override {
109 UpdateWhiteHandlerBounds();
110 }
111
112 SplitViewDividerHandlerView* white_handler_view_;
113 int spawn_signed_offset_;
114 base::OneShotTimer delay_timer_;
115
116 DISALLOW_COPY_AND_ASSIGN(SpawningAnimation);
117 };
118
SplitViewDividerHandlerView()119 SplitViewDividerHandlerView::SplitViewDividerHandlerView()
120 : selection_animation_(std::make_unique<SelectionAnimation>(this)) {
121 SetPaintToLayer();
122 SetBackground(views::CreateRoundedRectBackground(
123 GetBackgroundColor(), kSplitviewWhiteBarCornerRadius));
124 }
125
126 SplitViewDividerHandlerView::~SplitViewDividerHandlerView() = default;
127
DoSpawningAnimation(int divider_signed_offset)128 void SplitViewDividerHandlerView::DoSpawningAnimation(
129 int divider_signed_offset) {
130 spawning_animation_ =
131 std::make_unique<SpawningAnimation>(this, divider_signed_offset);
132 spawning_animation_->Activate();
133 }
134
Refresh(bool is_resizing)135 void SplitViewDividerHandlerView::Refresh(bool is_resizing) {
136 spawning_animation_.reset();
137 SetVisible(true);
138 selection_animation_->UpdateWhiteHandlerBounds();
139 if (is_resizing)
140 selection_animation_->Show();
141 else
142 selection_animation_->Hide();
143 }
144
UpdateCornerRadius(int radius)145 void SplitViewDividerHandlerView::UpdateCornerRadius(int radius) {
146 layer()->SetRoundedCornerRadius(gfx::RoundedCornersF{radius});
147 }
148
SetBounds(int short_length,int long_length,int signed_offset)149 void SplitViewDividerHandlerView::SetBounds(int short_length,
150 int long_length,
151 int signed_offset) {
152 const bool landscape = IsCurrentScreenOrientationLandscape();
153 gfx::Rect bounds = landscape ? gfx::Rect(short_length, long_length)
154 : gfx::Rect(long_length, short_length);
155 bounds.Offset(parent()->GetLocalBounds().CenterPoint() -
156 bounds.CenterPoint() +
157 (landscape ? gfx::Vector2d(signed_offset, 0)
158 : gfx::Vector2d(0, signed_offset)));
159 SetBoundsRect(bounds);
160 }
161
OnPaint(gfx::Canvas * canvas)162 void SplitViewDividerHandlerView::OnPaint(gfx::Canvas* canvas) {
163 views::View::OnPaint(canvas);
164 // It's needed to avoid artifacts when tapping on the divider quickly.
165 canvas->DrawColor(SK_ColorTRANSPARENT, SkBlendMode::kSrc);
166 views::View::OnPaint(canvas);
167 }
168
OnThemeChanged()169 void SplitViewDividerHandlerView::OnThemeChanged() {
170 views::View::OnThemeChanged();
171 background()->SetNativeControlColor(GetBackgroundColor());
172 SchedulePaint();
173 }
174
175 } // namespace ash
176