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

Side by Side Diff: ui/views/animation/ink_drop_animation.cc

Issue 1298513003: Implemented prototype for new ink drop specs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Working prototype. Created 5 years, 4 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/animation/ink_drop_animation.h" 5 #include "ui/views/animation/ink_drop_animation.h"
6 6
7 #include <algorithm>
8
7 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "third_party/skia/include/core/SkColor.h"
11 #include "third_party/skia/include/core/SkPaint.h"
8 #include "ui/base/ui_base_switches.h" 12 #include "ui/base/ui_base_switches.h"
9 #include "ui/compositor/layer.h" 13 #include "ui/compositor/layer.h"
10 #include "ui/compositor/layer_animation_observer.h" 14 #include "ui/compositor/layer_animation_observer.h"
11 #include "ui/compositor/layer_animation_sequence.h" 15 #include "ui/compositor/layer_animation_sequence.h"
12 #include "ui/compositor/paint_recorder.h" 16 #include "ui/compositor/paint_recorder.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h" 17 #include "ui/compositor/scoped_layer_animation_settings.h"
14 #include "ui/gfx/canvas.h" 18 #include "ui/gfx/canvas.h"
15 #include "ui/gfx/geometry/size.h" 19 #include "ui/gfx/transform_util.h"
16 #include "ui/views/animation/ink_drop_delegate.h"
17 #include "ui/views/view.h" 20 #include "ui/views/view.h"
18 21
19 namespace { 22 namespace {
20 23
21 // Animation constants 24 // The minimum scale factor to use when scaling rectangle layers. Smaller values
22 const float kMinimumScale = 0.1f; 25 // were causing visual anomalies.
23 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f; 26 const float kMinimumRectScale = 0.0001f;
24 27
25 const int kHideAnimationDurationFastMs = 100; 28 // The minimum scale factor to use when scaling circle layers. Smaller values
26 const int kHideAnimationDurationSlowMs = 1000; 29 // were causing visual anomalies.
30 const float kMinimumCircleScale = 0.001f;
27 31
28 const int kShowInkDropAnimationDurationFastMs = 250; 32 // The ink drop color.
29 const int kShowInkDropAnimationDurationSlowMs = 750; 33 const SkColor kInkDropColor = SK_ColorBLACK;
jonross 2015/08/19 22:13:36 Testing?
bruthig 2015/08/20 20:35:35 Not 100% sure what you mean here. Assuming you are
jonross 2015/08/21 15:14:48 Ah, yeah the current spec does want the alpha blac
30 34
31 const int kShowLongPressAnimationDurationFastMs = 250; 35 // The opacity of the ink drop when it is visible.
32 const int kShowLongPressAnimationDurationSlowMs = 2500; 36 const float kVisibleOpacity = 0.12f;
33 37
34 const int kRoundedRectCorners = 5; 38 // The opacity of the ink drop when it is not visible.
35 const int kCircleRadius = 30; 39 const float kHiddenOpacity = 0.0f;
36 40
37 const SkColor kInkDropColor = SK_ColorLTGRAY; 41 // The duration for the different InkDropState animations in milliseconds.
38 const SkColor kLongPressColor = SkColorSetRGB(182, 182, 182); 42 const int kAnimationDurationsMs[static_cast<int>(views::InkDropState::COUNT)] =
43 {
44 1, // InkDropState::HIDDEN
jonross 2015/08/19 22:13:36 Consider each of these being a const, then having
bruthig 2015/08/20 20:35:35 I've replaced the array with a switch statement.
45 500, // InkDropState::ACTION_PENDING
46 250, // InkDropState::QUICK_ACTION
47 500, // InkDropState::SLOW_ACTION_PENDING
48 250, // InkDropState::SLOW_ACTION
49 250, // InkDropState::ACTIVATED
50 250, // InkDropState::DEACTIVATED
51 };
39 52
40 // Checks CommandLine switches to determine if the visual feedback should be 53 // A multiplicative factor used to slow down InkDropState animations.
41 // circular. 54 const int kSlowAnimationDurationFactor = 3;
42 bool UseCircularFeedback() {
43 static bool circular =
44 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
45 (::switches::kMaterialDesignInkDrop)) !=
46 ::switches::kMaterialDesignInkDropSquare;
47 return circular;
48 }
49 55
50 // Checks CommandLine switches to determine if the visual feedback should have 56 // Checks CommandLine switches to determine if the visual feedback should have
51 // a fast animations speed. 57 // a fast animations speed.
52 bool UseFastAnimations() { 58 bool UseFastAnimations() {
53 static bool fast = 59 static bool fast =
54 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 60 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
55 (::switches::kMaterialDesignInkDropAnimationSpeed)) != 61 (::switches::kMaterialDesignInkDropAnimationSpeed)) !=
56 ::switches::kMaterialDesignInkDropAnimationSpeedSlow; 62 ::switches::kMaterialDesignInkDropAnimationSpeedSlow;
57 return fast; 63 return fast;
58 } 64 }
59 65
66 // Returns the InkDropState animation duration for the given |state|.
67 base::TimeDelta GetAnimationDuration(views::InkDropState state) {
68 return base::TimeDelta::FromMilliseconds(
69 (UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) *
70 kAnimationDurationsMs[static_cast<int>(state)]);
71 }
72
60 } // namespace 73 } // namespace
61 74
62 namespace views { 75 namespace views {
63 76
64 // An animation observer that should be set on animations of the provided 77 // A simple ui::LayerDelegate that paints a circle of the specified color and
65 // ui::Layer. Can be used to either start a hide animation, or to trigger one 78 // radius.
66 // upon completion of the current animation. 79 class CircleLayerDelegate : public ui::LayerDelegate {
67 //
68 // Sequential animations with PreemptionStrategy::ENQUEUE_NEW_ANIMATION cannot
69 // be used as the observed animation can complete before user input is received
70 // which determines if the hide animation should run.
71 class AppearAnimationObserver : public ui::LayerAnimationObserver {
72 public: 80 public:
73 // Will automatically start a hide animation of |layer| if |hide| is true. 81 CircleLayerDelegate(SkColor color, int radius);
74 // Otherwise StartHideAnimation() or HideNowIfDoneOrOnceCompleted() must be 82 ~CircleLayerDelegate() override;
75 // called.
76 AppearAnimationObserver(ui::Layer* layer, bool hide);
77 ~AppearAnimationObserver() override;
78 83
79 // Returns true during both the appearing animation, and the hiding animation. 84 SkColor color() const { return color_; }
jonross 2015/08/19 22:13:36 Needed?
bruthig 2015/08/20 20:35:35 Removed, but required by the base class now.
jonross 2015/08/21 15:14:48 Acknowledged.
80 bool IsAnimationActive(); 85 void set_color(SkColor color) { color_ = color; }
81 86
82 // Starts a hide animation, preempting any current animations on |layer_|. 87 int radius() const { return radius_; }
83 void StartHideAnimation();
84 88
85 // Starts a hide animation if |layer_| is no longer animating. Otherwise the 89 // ui::LayerDelegate:
86 // hide animation will be started once the current animation is completed. 90 void OnPaintLayer(const ui::PaintContext& context) override;
87 void HideNowIfDoneOrOnceCompleted(); 91 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
88 92 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
89 // Hides |background_layer| (without animation) after the current animation 93 base::Closure PrepareForLayerBoundsChange() override;
90 // completes.
91 void SetBackgroundToHide(ui::Layer* background_layer);
92 94
93 private: 95 private:
94 // ui::ImplicitAnimationObserver: 96 // The color to paint.
95 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; 97 SkColor color_;
96 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
97 void OnLayerAnimationScheduled(
98 ui::LayerAnimationSequence* sequence) override {}
99 98
100 bool RequiresNotificationWhenAnimatorDestroyed() const override; 99 // The radius of the circle.
100 int radius_;
101 101
102 // The ui::Layer being observed, which hide animations will be set on. 102 DISALLOW_COPY_AND_ASSIGN(CircleLayerDelegate);
103 ui::Layer* layer_;
104
105 // Optional ui::Layer which will be hidden upon the completion of animating
106 // |layer_|
107 ui::Layer* background_layer_;
108
109 // If true the hide animation will immediately be scheduled upon completion of
110 // the observed animation.
111 bool hide_;
112
113 DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver);
114 }; 103 };
115 104
116 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide) 105 CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
117 : layer_(layer), background_layer_(nullptr), hide_(hide) {} 106 : color_(color), radius_(radius) {}
118 107
119 AppearAnimationObserver::~AppearAnimationObserver() { 108 CircleLayerDelegate::~CircleLayerDelegate() {}
120 StopObserving(); 109
110 void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
111 SkPaint paint;
112 paint.setColor(color_);
113 paint.setFlags(SkPaint::kAntiAlias_Flag);
114 paint.setStyle(SkPaint::kFill_Style);
115
116 ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
117 gfx::Canvas* canvas = recorder.canvas();
118
119 gfx::Point center_point = gfx::Point(radius_, radius_);
120 canvas->DrawCircle(center_point, radius_, paint);
121 } 121 }
122 122
123 bool AppearAnimationObserver::IsAnimationActive() { 123 void CircleLayerDelegate::OnDelegatedFrameDamage(
124 // Initial animation ongoing 124 const gfx::Rect& damage_rect_in_dip) {}
125 if (!attached_sequences().empty())
126 return true;
127 // Maintain the animation until told to hide.
128 if (!hide_)
129 return true;
130 125
131 // Check the state of the triggered hide animation 126 void CircleLayerDelegate::OnDeviceScaleFactorChanged(
132 return layer_->GetAnimator()->IsAnimatingProperty( 127 float device_scale_factor) {}
133 ui::LayerAnimationElement::OPACITY) && 128
134 layer_->GetTargetOpacity() == 0.0f && 129 base::Closure CircleLayerDelegate::PrepareForLayerBoundsChange() {
135 layer_->GetAnimator()->IsAnimatingProperty( 130 return base::Closure();
136 ui::LayerAnimationElement::VISIBILITY) &&
137 !layer_->GetTargetVisibility();
138 } 131 }
139 132
140 void AppearAnimationObserver::StartHideAnimation() { 133 // A simple ui::LayerDelegate that paints a rectangle of the specified color and
141 if (background_layer_) 134 // size.
142 background_layer_->SetVisible(false); 135 class RectangleLayerDelegate : public ui::LayerDelegate {
jonross 2015/08/19 22:13:36 Mostly duplicate code. Consider making a parent of
bruthig 2015/08/20 20:35:35 Done.
143 if (!layer_->GetTargetVisibility()) 136 public:
144 return; 137 RectangleLayerDelegate(SkColor color, gfx::Size size);
138 ~RectangleLayerDelegate() override;
145 139
146 ui::ScopedLayerAnimationSettings animation(layer_->GetAnimator()); 140 SkColor color() const { return color_; }
147 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 141 void set_color(SkColor color) { color_ = color; }
148 UseFastAnimations() ? kHideAnimationDurationFastMs 142
149 : kHideAnimationDurationSlowMs)); 143 gfx::Size size() const { return size_; }
150 animation.SetPreemptionStrategy( 144
151 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 145 // ui::LayerDelegate:
152 layer_->SetOpacity(0.0f); 146 void OnPaintLayer(const ui::PaintContext& context) override;
153 layer_->SetVisible(false); 147 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
148 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
149 base::Closure PrepareForLayerBoundsChange() override;
150
151 private:
152 // The color to paint.
153 SkColor color_;
154
155 // The size of the rectangle.
156 gfx::Size size_;
157
158 DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
159 };
160
161 RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size)
162 : color_(color), size_(size) {}
163
164 RectangleLayerDelegate::~RectangleLayerDelegate() {}
165
166 void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
167 SkPaint paint;
168 paint.setColor(color_);
169 paint.setFlags(SkPaint::kAntiAlias_Flag);
170 paint.setStyle(SkPaint::kFill_Style);
171
172 ui::PaintRecorder recorder(context, size_);
173 gfx::Canvas* canvas = recorder.canvas();
174 canvas->DrawRect(gfx::Rect(0, 0, size_.width(), size_.height()), paint);
154 } 175 }
155 176
156 void AppearAnimationObserver::HideNowIfDoneOrOnceCompleted() { 177 void RectangleLayerDelegate::OnDelegatedFrameDamage(
157 hide_ = true; 178 const gfx::Rect& damage_rect_in_dip) {}
158 if (attached_sequences().empty()) 179
159 StartHideAnimation(); 180 void RectangleLayerDelegate::OnDeviceScaleFactorChanged(
181 float device_scale_factor) {}
182
183 base::Closure RectangleLayerDelegate::PrepareForLayerBoundsChange() {
184 return base::Closure();
160 } 185 }
161 186
162 void AppearAnimationObserver::SetBackgroundToHide(ui::Layer* background_layer) { 187 InkDropAnimation::InkDropTransforms::InkDropTransforms() {}
163 background_layer_ = background_layer;
164 }
165 188
166 void AppearAnimationObserver::OnLayerAnimationEnded( 189 InkDropAnimation::InkDropTransforms::~InkDropTransforms() {}
167 ui::LayerAnimationSequence* sequence) {
168 if (hide_)
169 StartHideAnimation();
170 }
171 190
172 void AppearAnimationObserver::OnLayerAnimationAborted( 191 InkDropAnimation::InkDropAnimation(const gfx::Size& large_size,
173 ui::LayerAnimationSequence* sequence) { 192 int large_corner_radius,
174 if (hide_) 193 const gfx::Size& small_size,
175 StartHideAnimation(); 194 int small_corner_radius)
176 } 195 : large_size_(large_size),
196 large_corner_radius_(large_corner_radius),
197 small_size_(small_size),
198 small_corner_radius_(small_corner_radius),
199 circle_layer_delegate_(new CircleLayerDelegate(
200 kInkDropColor,
201 std::min(large_size_.width(), large_size_.height()) / 2)),
202 rect_layer_delegate_(
203 new RectangleLayerDelegate(kInkDropColor, large_size_)),
204 root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
205 top_left_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
tdanderson 2015/08/19 22:11:18 I may have already asked before (can't remember),
bruthig 2015/08/20 20:35:35 You are correct, it is not necessary to keep the l
206 top_right_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
207 bottom_right_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
208 bottom_left_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
209 horizontal_rect_layer_(AddPaintLayer(rect_layer_delegate_.get())),
210 vertical_rect_layer_(AddPaintLayer(rect_layer_delegate_.get())),
211 ink_drop_state_(InkDropState::HIDDEN) {
212 root_layer_->SetMasksToBounds(false);
213 root_layer_->SetBounds(gfx::Rect(large_size_));
177 214
178 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() 215 ResetTransformsToMinSize();
179 const {
180 // Ensures that OnImplicitAnimationsCompleted is called even if the observed
181 // animation is deleted. Allows for setting the proper state on |layer_|.
182 return true;
183 }
184 216
185 InkDropAnimation::InkDropAnimation() 217 SetOpacity(kHiddenOpacity);
186 : root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
187 ink_drop_layer_(new ui::Layer()),
188 appear_animation_observer_(nullptr),
189 long_press_layer_(new ui::Layer()),
190 long_press_animation_observer_(nullptr),
191 ink_drop_bounds_(0, 0, 0, 0) {
192 ink_drop_delegate_.reset(new InkDropDelegate(ink_drop_layer_.get(),
193 kInkDropColor, kCircleRadius,
194 kRoundedRectCorners));
195 long_press_delegate_.reset(new InkDropDelegate(long_press_layer_.get(),
196 kLongPressColor, kCircleRadius,
197 kRoundedRectCorners));
198
199 SetupAnimationLayer(long_press_layer_.get(), long_press_delegate_.get());
200 SetupAnimationLayer(ink_drop_layer_.get(), ink_drop_delegate_.get());
201
202 root_layer_->Add(ink_drop_layer_.get());
203 root_layer_->Add(long_press_layer_.get());
204 } 218 }
205 219
206 InkDropAnimation::~InkDropAnimation() {} 220 InkDropAnimation::~InkDropAnimation() {}
207 221
208 ui::Layer* InkDropAnimation::GetRootLayer() { 222 ui::Layer* InkDropAnimation::GetRootLayer() {
209 return root_layer_.get(); 223 return root_layer_.get();
210 } 224 }
211 225
212 void InkDropAnimation::AnimateToState(InkDropState state) { 226 void InkDropAnimation::AnimateToState(InkDropState state) {
213 // TODO(bruthig): Do not transition if we are already in |state| and restrict 227 if (ink_drop_state_ == state)
214 // any state transition that don't make sense or wouldn't look visually 228 return;
215 // appealing. 229
230 if (ink_drop_state_ == InkDropState::HIDDEN &&
231 state != InkDropState::HIDDEN) {
232 ResetTransformsToMinSize();
233 SetOpacity(kVisibleOpacity);
234 }
235
216 switch (state) { 236 switch (state) {
217 case InkDropState::HIDDEN: 237 case InkDropState::HIDDEN:
218 AnimateHide(); 238 ink_drop_state_ = state;
tdanderson 2015/08/19 22:11:18 You should be able to factor this line out to afte
jonross 2015/08/19 22:13:36 Move these out of the switch.
bruthig 2015/08/20 20:35:35 I can't set the |ink_drop_state_| after the switc
jonross 2015/08/21 15:14:48 That sounds dangerous. However I was thinking ove
bruthig 2015/09/03 21:21:04 I've moved it to before the switch statement, adde
239 AnimateToTransforms(GetCurrentTansforms(), kHiddenOpacity,
240 GetAnimationDuration(InkDropState::HIDDEN),
241 ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
219 break; 242 break;
220 case InkDropState::ACTION_PENDING: 243 case InkDropState::ACTION_PENDING:
221 AnimateTapDown(); 244 ink_drop_state_ = state;
245 AnimateToTransforms(CalculateCircleTransforms(large_size_),
246 kVisibleOpacity,
247 GetAnimationDuration(InkDropState::ACTION_PENDING),
248 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
222 break; 249 break;
223 case InkDropState::QUICK_ACTION: 250 case InkDropState::QUICK_ACTION:
224 AnimateTapDown(); 251 ink_drop_state_ = state;
225 AnimateHide(); 252 AnimateToTransforms(CalculateCircleTransforms(large_size_),
253 kHiddenOpacity,
254 GetAnimationDuration(InkDropState::QUICK_ACTION),
255 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
256 AnimateToState(InkDropState::HIDDEN);
257 break;
258 case InkDropState::SLOW_ACTION_PENDING:
259 ink_drop_state_ = state;
260 AnimateToTransforms(
261 CalculateRectTransforms(small_size_, small_corner_radius_),
262 kVisibleOpacity,
263 GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING),
264 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
226 break; 265 break;
227 case InkDropState::SLOW_ACTION: 266 case InkDropState::SLOW_ACTION:
228 AnimateLongPress(); 267 ink_drop_state_ = state;
268 AnimateToTransforms(
269 CalculateRectTransforms(large_size_, large_corner_radius_),
270 kHiddenOpacity, GetAnimationDuration(InkDropState::SLOW_ACTION),
271 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
272 AnimateToState(InkDropState::HIDDEN);
229 break; 273 break;
230 case InkDropState::ACTIVATED: 274 case InkDropState::ACTIVATED:
231 AnimateLongPress(); 275 ink_drop_state_ = state;
232 break; 276 AnimateToTransforms(
277 CalculateRectTransforms(small_size_, small_corner_radius_),
278 kVisibleOpacity, GetAnimationDuration(InkDropState::ACTIVATED),
279 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
280 break;
281 case InkDropState::DEACTIVATED:
282 ink_drop_state_ = state;
283 AnimateToTransforms(
284 CalculateRectTransforms(large_size_, large_corner_radius_),
285 kHiddenOpacity, GetAnimationDuration(InkDropState::DEACTIVATED),
286 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
287 AnimateToState(InkDropState::HIDDEN);
288 break;
289 default:
290 DCHECK(false) << "Unhandled InkDropState=" << static_cast<int>(state);
tdanderson 2015/08/19 22:11:18 Probably use NOTREACHED instead here?
bruthig 2015/08/20 20:35:35 Removed, no longer needed.
291 AnimateToState(InkDropState::HIDDEN);
292 return;
233 } 293 }
234 } 294 }
235 295
236 void InkDropAnimation::SetInkDropSize(const gfx::Size& size) { 296 void InkDropAnimation::AnimateToTransforms(
237 SetInkDropBounds(gfx::Rect(ink_drop_bounds_.origin(), size)); 297 const InkDropTransforms& transforms,
238 } 298 float opacity,
239 299 base::TimeDelta duration,
240 gfx::Rect InkDropAnimation::GetInkDropBounds() const { 300 ui::LayerAnimator::PreemptionStrategy preemption_strategy) {
241 return ink_drop_bounds_; 301 ui::LayerAnimator* root_animator = root_layer_->GetAnimator();
242 } 302 ui::ScopedLayerAnimationSettings root_animation(root_animator);
243 303 root_animation.SetPreemptionStrategy(preemption_strategy);
244 void InkDropAnimation::SetInkDropBounds(const gfx::Rect& bounds) { 304 ui::LayerAnimationElement* root_element =
245 ink_drop_bounds_ = bounds; 305 ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
246 SetLayerBounds(ink_drop_layer_.get()); 306 ui::LayerAnimationSequence* root_sequence =
247 SetLayerBounds(long_press_layer_.get()); 307 new ui::LayerAnimationSequence(root_element);
248 } 308 root_animator->StartAnimation(root_sequence);
249 309
250 void InkDropAnimation::AnimateTapDown() { 310 AnimateToTransform(top_left_circle_layer_.get(), transforms.top_left_circle,
tdanderson 2015/08/19 22:11:19 Does the order of these function calls matter? (if
bruthig 2015/08/20 20:35:35 The order doesn't matter.
251 if ((appear_animation_observer_ && 311 duration, preemption_strategy);
jonross 2015/08/19 22:13:36 We are starting to get duplication from the number
bruthig 2015/08/20 20:35:35 Done.
252 appear_animation_observer_->IsAnimationActive()) || 312 AnimateToTransform(top_right_circle_layer_.get(), transforms.top_right_circle,
253 (long_press_animation_observer_ && 313 duration, preemption_strategy);
254 long_press_animation_observer_->IsAnimationActive())) { 314 AnimateToTransform(bottom_right_circle_layer_.get(),
255 // Only one animation at a time. Subsequent tap downs are ignored until the 315 transforms.bottom_right_circle, duration,
256 // current animation completes. 316 preemption_strategy);
257 return; 317 AnimateToTransform(bottom_left_circle_layer_.get(),
258 } 318 transforms.bottom_left_circle, duration,
259 appear_animation_observer_.reset( 319 preemption_strategy);
260 new AppearAnimationObserver(ink_drop_layer_.get(), false)); 320 AnimateToTransform(horizontal_rect_layer_.get(), transforms.horizontal_rect,
261 AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(), 321 duration, preemption_strategy);
262 base::TimeDelta::FromMilliseconds( 322 AnimateToTransform(vertical_rect_layer_.get(), transforms.vertical_rect,
263 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs 323 duration, preemption_strategy);
264 : kShowInkDropAnimationDurationSlowMs))); 324 }
265 } 325
266 326 void InkDropAnimation::AnimateToTransform(
267 void InkDropAnimation::AnimateHide() { 327 ui::Layer* layer,
268 if (appear_animation_observer_ && 328 const gfx::Transform& target_transform,
269 appear_animation_observer_->IsAnimationActive()) { 329 base::TimeDelta duration,
270 appear_animation_observer_->HideNowIfDoneOrOnceCompleted(); 330 ui::LayerAnimator::PreemptionStrategy preemption_strategy) {
271 } else if (long_press_animation_observer_) {
272 long_press_animation_observer_->HideNowIfDoneOrOnceCompleted();
273 }
274 }
275
276 void InkDropAnimation::AnimateLongPress() {
277 // Only one animation at a time. Subsequent long presses are ignored until the
278 // current animation completes.
279 if (long_press_animation_observer_ &&
280 long_press_animation_observer_->IsAnimationActive()) {
281 return;
282 }
283 appear_animation_observer_.reset();
284 long_press_animation_observer_.reset(
285 new AppearAnimationObserver(long_press_layer_.get(), false));
286 long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get());
287 AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(),
288 base::TimeDelta::FromMilliseconds(
289 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs
290 : kShowLongPressAnimationDurationSlowMs));
291 }
292
293 void InkDropAnimation::AnimateShow(ui::Layer* layer,
294 AppearAnimationObserver* observer,
295 base::TimeDelta duration) {
296 layer->SetVisible(true);
297 layer->SetOpacity(1.0f);
298
299 float start_x = ink_drop_bounds_.x() +
300 layer->bounds().width() * kMinimumScaleCenteringOffset;
301 float start_y = ink_drop_bounds_.y() +
302 layer->bounds().height() * kMinimumScaleCenteringOffset;
303
304 gfx::Transform initial_transform;
305 initial_transform.Translate(start_x, start_y);
306 initial_transform.Scale(kMinimumScale, kMinimumScale);
307 layer->SetTransform(initial_transform);
308
309 ui::LayerAnimator* animator = layer->GetAnimator(); 331 ui::LayerAnimator* animator = layer->GetAnimator();
310 ui::ScopedLayerAnimationSettings animation(animator); 332 ui::ScopedLayerAnimationSettings animation(animator);
311 animation.SetPreemptionStrategy( 333 animation.SetPreemptionStrategy(preemption_strategy);
312 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
313
314 gfx::Transform target_transform;
315 target_transform.Translate(ink_drop_bounds_.x(), ink_drop_bounds_.y());
316 ui::LayerAnimationElement* element = 334 ui::LayerAnimationElement* element =
317 ui::LayerAnimationElement::CreateTransformElement(target_transform, 335 ui::LayerAnimationElement::CreateTransformElement(target_transform,
318 duration); 336 duration);
319 ui::LayerAnimationSequence* sequence = 337 ui::LayerAnimationSequence* sequence =
320 new ui::LayerAnimationSequence(element); 338 new ui::LayerAnimationSequence(element);
321 sequence->AddObserver(observer);
322 animator->StartAnimation(sequence); 339 animator->StartAnimation(sequence);
323 } 340 }
324 341
325 void InkDropAnimation::SetLayerBounds(ui::Layer* layer) { 342 void InkDropAnimation::ResetTransformsToMinSize() {
326 bool circle = UseCircularFeedback(); 343 // Using a size of 0x0 creates visual anomalies.
327 gfx::Size size = ink_drop_bounds_.size(); 344 SetTransforms(CalculateCircleTransforms(gfx::Size(1, 1)));
jonross 2015/08/19 22:13:36 Does this do enough to warrant it being a standalo
bruthig 2015/08/20 20:35:35 The purpose of making this a standalone method is
jonross 2015/08/21 15:14:48 Acknowledged.
328 float circle_width = circle ? 2.0f * kCircleRadius : size.width(); 345 }
329 float circle_height = circle ? 2.0f * kCircleRadius : size.height(); 346
330 float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0; 347 void InkDropAnimation::SetTransforms(const InkDropTransforms& transforms) {
331 float circle_y = circle ? (size.height() - circle_height) * 0.5f : 0; 348 top_left_circle_layer_->SetTransform(transforms.top_left_circle);
332 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height)); 349 top_right_circle_layer_->SetTransform(transforms.top_right_circle);
333 } 350 bottom_right_circle_layer_->SetTransform(transforms.bottom_right_circle);
334 351 bottom_left_circle_layer_->SetTransform(transforms.bottom_left_circle);
335 void InkDropAnimation::SetupAnimationLayer(ui::Layer* layer, 352 horizontal_rect_layer_->SetTransform(transforms.vertical_rect);
336 InkDropDelegate* delegate) { 353 vertical_rect_layer_->SetTransform(transforms.horizontal_rect);
354 }
355
356 void InkDropAnimation::SetOpacity(float opacity) {
357 root_layer_->SetOpacity(opacity);
358 }
359
360 InkDropAnimation::InkDropTransforms InkDropAnimation::CalculateCircleTransforms(
361 const gfx::SizeF size) const {
362 return CalculateRectTransforms(size,
363 std::min(size.width(), size.height()) / 2.0f);
364 }
365
366 InkDropAnimation::InkDropTransforms InkDropAnimation::CalculateRectTransforms(
367 const gfx::SizeF size,
368 float corner_radius) const {
369 InkDropTransforms transforms;
370
371 const float circle_radius = circle_layer_delegate_->radius();
tdanderson 2015/08/19 22:11:19 Probably already on your to-do list, but some inli
bruthig 2015/09/03 21:21:04 I've tried to address this with some refactoring a
372 const float corner_scale =
373 std::max(kMinimumCircleScale, corner_radius / circle_radius);
374 const float corner_circle_x_offset = size.width() / 2.0f - corner_radius;
375 const float corner_circle_y_offset = size.height() / 2.0f - corner_radius;
376
377 transforms.top_left_circle.Translate(circle_radius - corner_circle_x_offset,
378 circle_radius - corner_circle_y_offset);
379 transforms.top_left_circle.Scale(corner_scale, corner_scale);
380 transforms.top_left_circle.Translate(-circle_radius, -circle_radius);
381
382 transforms.top_right_circle.Translate(circle_radius + corner_circle_x_offset,
383 circle_radius - corner_circle_y_offset);
384 transforms.top_right_circle.Scale(corner_scale, corner_scale);
385 transforms.top_right_circle.Translate(-circle_radius, -circle_radius);
386
387 transforms.bottom_right_circle.Translate(
388 circle_radius + corner_circle_x_offset,
389 circle_radius + corner_circle_y_offset);
390 transforms.bottom_right_circle.Scale(corner_scale, corner_scale);
391 transforms.bottom_right_circle.Translate(-circle_radius, -circle_radius);
392
393 transforms.bottom_left_circle.Translate(
394 circle_radius - corner_circle_x_offset,
395 circle_radius + corner_circle_y_offset);
396 transforms.bottom_left_circle.Scale(corner_scale, corner_scale);
397 transforms.bottom_left_circle.Translate(-circle_radius, -circle_radius);
398
399 const float rect_delegate_width =
400 static_cast<float>(rect_layer_delegate_->size().width());
401 const float rect_delegate_height =
402 static_cast<float>(rect_layer_delegate_->size().height());
403
404 const float horizontal_rect_x_scale =
405 std::max(kMinimumRectScale, size.width() / rect_delegate_width);
406 const float horizontal_rect_y_scale =
407 std::max(kMinimumRectScale,
408 (size.height() - 2.0f * corner_radius) / rect_delegate_height);
409
410 transforms.horizontal_rect.Scale(horizontal_rect_x_scale,
411 horizontal_rect_y_scale);
412 transforms.horizontal_rect =
413 TransformAboutPivot(horizontal_rect_layer_->bounds().CenterPoint(),
414 transforms.horizontal_rect);
415
416 const float vertical_rect_x_scale =
417 std::max(kMinimumRectScale,
418 (size.width() - 2.0f * corner_radius) / rect_delegate_width);
419 const float vertical_rect_y_scale =
420 std::max(kMinimumRectScale, size.height() / rect_delegate_height);
421
422 transforms.vertical_rect.Scale(vertical_rect_x_scale, vertical_rect_y_scale);
423 transforms.vertical_rect = TransformAboutPivot(
424 vertical_rect_layer_->bounds().CenterPoint(), transforms.vertical_rect);
425
426 return transforms;
jonross 2015/08/19 22:13:36 Is this performing a move?
bruthig 2015/08/20 20:35:35 Doesn't exist anymore.
427 }
428
429 InkDropAnimation::InkDropTransforms InkDropAnimation::GetCurrentTansforms()
430 const {
431 InkDropTransforms transforms;
432
433 transforms.top_left_circle = top_left_circle_layer_->GetTargetTransform();
434 transforms.top_right_circle = top_right_circle_layer_->GetTargetTransform();
435 transforms.bottom_right_circle =
436 bottom_right_circle_layer_->GetTargetTransform();
437 transforms.bottom_left_circle =
438 bottom_left_circle_layer_->GetTargetTransform();
439 transforms.horizontal_rect = horizontal_rect_layer_->GetTargetTransform();
440 transforms.vertical_rect = vertical_rect_layer_->GetTargetTransform();
441
442 return transforms;
443 }
444
445 void InkDropAnimation::SetOrigin(const gfx::Point& origin) {
446 gfx::Rect bounds = root_layer_->bounds();
447 bounds.set_origin(origin);
448 root_layer_->SetBounds(bounds);
449 }
450
451 ui::Layer* InkDropAnimation::AddPaintLayer(ui::LayerDelegate* delegate) {
452 ui::Layer* layer = new ui::Layer();
453 root_layer_->Add(layer);
454
455 layer->SetBounds(gfx::Rect(large_size_));
337 layer->SetFillsBoundsOpaquely(false); 456 layer->SetFillsBoundsOpaquely(false);
338 layer->set_delegate(delegate); 457 layer->set_delegate(delegate);
339 layer->SetVisible(false); 458 layer->SetVisible(true);
340 layer->SetBounds(gfx::Rect()); 459 layer->SetOpacity(1.0);
341 delegate->set_should_render_circle(UseCircularFeedback()); 460 layer->SetMasksToBounds(false);
461
462 return layer;
342 } 463 }
343 464
344 } // namespace views 465 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698