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

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

Issue 1280953003: Enhance the material design ripple API so the ripple's state can be controlled by it's owning View. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments from patch set 15. 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_controller.h" 5 #include "ui/views/animation/ink_drop_animation_controller_impl.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "ui/base/ui_base_switches.h" 8 #include "ui/base/ui_base_switches.h"
9 #include "ui/compositor/layer.h" 9 #include "ui/compositor/layer.h"
10 #include "ui/compositor/layer_animation_observer.h" 10 #include "ui/compositor/layer_animation_observer.h"
11 #include "ui/compositor/layer_animation_sequence.h" 11 #include "ui/compositor/layer_animation_sequence.h"
12 #include "ui/compositor/paint_recorder.h" 12 #include "ui/compositor/paint_recorder.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h" 13 #include "ui/compositor/scoped_layer_animation_settings.h"
14 #include "ui/events/event.h" 14 #include "ui/events/event.h"
15 #include "ui/gfx/canvas.h" 15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/geometry/size.h"
17 #include "ui/views/animation/ink_drop_delegate.h"
18 #include "ui/views/animation/ink_drop_host.h"
16 #include "ui/views/view.h" 19 #include "ui/views/view.h"
17 20
18 namespace { 21 namespace {
19 22
20 // Animation constants 23 // Animation constants
21 const float kMinimumScale = 0.1f; 24 const float kMinimumScale = 0.1f;
22 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f; 25 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f;
23 26
24 const int kHideAnimationDurationFastMs = 100; 27 const int kHideAnimationDurationFastMs = 100;
25 const int kHideAnimationDurationSlowMs = 1000; 28 const int kHideAnimationDurationSlowMs = 1000;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 ui::Layer* background_layer_; 109 ui::Layer* background_layer_;
107 110
108 // If true the hide animation will immediately be scheduled upon completion of 111 // If true the hide animation will immediately be scheduled upon completion of
109 // the observed animation. 112 // the observed animation.
110 bool hide_; 113 bool hide_;
111 114
112 DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver); 115 DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver);
113 }; 116 };
114 117
115 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide) 118 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide)
116 : layer_(layer), background_layer_(nullptr), hide_(hide) { 119 : layer_(layer), background_layer_(nullptr), hide_(hide) {}
117 }
118 120
119 AppearAnimationObserver::~AppearAnimationObserver() { 121 AppearAnimationObserver::~AppearAnimationObserver() {
120 StopObserving(); 122 StopObserving();
121 } 123 }
122 124
123 bool AppearAnimationObserver::IsAnimationActive() { 125 bool AppearAnimationObserver::IsAnimationActive() {
124 // Initial animation ongoing 126 // Initial animation ongoing
125 if (!attached_sequences().empty()) 127 if (!attached_sequences().empty())
126 return true; 128 return true;
127 // Maintain the animation until told to hide. 129 // Maintain the animation until told to hide.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 StartHideAnimation(); 177 StartHideAnimation();
176 } 178 }
177 179
178 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() 180 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed()
179 const { 181 const {
180 // Ensures that OnImplicitAnimationsCompleted is called even if the observed 182 // Ensures that OnImplicitAnimationsCompleted is called even if the observed
181 // animation is deleted. Allows for setting the proper state on |layer_|. 183 // animation is deleted. Allows for setting the proper state on |layer_|.
182 return true; 184 return true;
183 } 185 }
184 186
185 // Renders the visual feedback. Will render a circle if |circle_| is true, 187 InkDropAnimationControllerImpl::InkDropAnimationControllerImpl(
186 // otherwise renders a rounded rectangle. 188 InkDropHost* ink_drop_host)
187 class InkDropDelegate : public ui::LayerDelegate { 189 : ink_drop_host_(ink_drop_host),
188 public: 190 appear_animation_observer_(nullptr),
189 InkDropDelegate(ui::Layer* layer, SkColor color); 191 long_press_animation_observer_(nullptr),
190 ~InkDropDelegate() override; 192 ink_drop_bounds_(0, 0, 0, 0) {
193 root_layer_owner_.SetLayer(new ui::Layer(ui::LAYER_NOT_DRAWN));
194 ink_drop_layer_owner_.SetLayer(new ui::Layer());
195 long_press_layer_owner_.SetLayer(new ui::Layer());
191 196
192 // Sets the visual style of the feedback. 197 ink_drop_delegate_.reset(new InkDropDelegate(ink_drop_layer_owner_.layer(),
193 void set_should_render_circle(bool should_render_circle) { 198 kInkDropColor, kCircleRadius,
194 should_render_circle_ = should_render_circle; 199 kRoundedRectCorners));
195 } 200 long_press_delegate_.reset(
201 new InkDropDelegate(long_press_layer_owner_.layer(), kLongPressColor,
202 kCircleRadius, kRoundedRectCorners));
196 203
197 // ui::LayerDelegate: 204 SetupAnimationLayer(long_press_layer_owner_.layer(),
198 void OnPaintLayer(const ui::PaintContext& context) override; 205 long_press_delegate_.get());
199 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; 206 SetupAnimationLayer(ink_drop_layer_owner_.layer(), ink_drop_delegate_.get());
200 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
201 base::Closure PrepareForLayerBoundsChange() override;
202 207
203 private: 208 root_layer_owner_.layer()->Add(ink_drop_layer_owner_.layer());
204 // The ui::Layer being rendered to. 209 root_layer_owner_.layer()->Add(long_press_layer_owner_.layer());
205 ui::Layer* layer_;
206 210
207 // The color to paint. 211 ink_drop_host_->AddInkDropLayer(root_layer_owner_.layer());
sadrul 2015/08/18 19:52:39 Add a TODO and refer to 522175
bruthig 2015/08/18 20:58:04 Done.
208 SkColor color_;
209
210 // When true renders a circle, otherwise renders a rounded rectangle.
211 bool should_render_circle_;
212
213 DISALLOW_COPY_AND_ASSIGN(InkDropDelegate);
214 };
215
216 InkDropDelegate::InkDropDelegate(ui::Layer* layer, SkColor color)
217 : layer_(layer), color_(color), should_render_circle_(true) {
218 } 212 }
219 213
220 InkDropDelegate::~InkDropDelegate() { 214 InkDropAnimationControllerImpl::~InkDropAnimationControllerImpl() {
215 // TODO(bruthig): Change this to be called when the ink drop becomes hidden.
216 // See www.crbug.com/522175.
217 ink_drop_host_->RemoveInkDropLayer(root_layer_owner_.layer());
221 } 218 }
222 219
223 void InkDropDelegate::OnPaintLayer(const ui::PaintContext& context) { 220 void InkDropAnimationControllerImpl::AnimateToState(InkDropState state) {
224 SkPaint paint; 221 // TODO(bruthig): Do not transition if we are already in |state| and restrict
225 paint.setColor(color_); 222 // any state transition that don't make sense or wouldn't look visually
226 paint.setFlags(SkPaint::kAntiAlias_Flag); 223 // appealing.
227 paint.setStyle(SkPaint::kFill_Style); 224 switch (state) {
228 225 case InkDropState::HIDDEN:
229 gfx::Rect bounds = layer_->bounds(); 226 AnimateHide();
230 227 break;
231 ui::PaintRecorder recorder(context, layer_->size()); 228 case InkDropState::ACTION_PENDING:
232 gfx::Canvas* canvas = recorder.canvas(); 229 AnimateTapDown();
233 if (should_render_circle_) { 230 break;
234 gfx::Point midpoint(bounds.width() * 0.5f, bounds.height() * 0.5f); 231 case InkDropState::QUICK_ACTION:
235 canvas->DrawCircle(midpoint, kCircleRadius, paint); 232 AnimateTapDown();
236 } else { 233 AnimateHide();
237 canvas->DrawRoundRect(bounds, kRoundedRectCorners, paint); 234 break;
235 case InkDropState::SLOW_ACTION:
236 AnimateLongPress();
237 break;
238 case InkDropState::ACTIVATED:
239 AnimateLongPress();
240 break;
238 } 241 }
239 } 242 }
240 243
241 void InkDropDelegate::OnDelegatedFrameDamage( 244 void InkDropAnimationControllerImpl::SetInkDropSize(const gfx::Size& size) {
242 const gfx::Rect& damage_rect_in_dip) { 245 SetInkDropBounds(gfx::Rect(ink_drop_bounds_.origin(), size));
243 } 246 }
244 247
245 void InkDropDelegate::OnDeviceScaleFactorChanged(float device_scale_factor) { 248 gfx::Rect InkDropAnimationControllerImpl::GetInkDropBounds() const {
249 return ink_drop_bounds_;
246 } 250 }
247 251
248 base::Closure InkDropDelegate::PrepareForLayerBoundsChange() { 252 void InkDropAnimationControllerImpl::SetInkDropBounds(const gfx::Rect& bounds) {
249 return base::Closure(); 253 ink_drop_bounds_ = bounds;
254 SetLayerBounds(ink_drop_layer_owner_.layer());
255 SetLayerBounds(long_press_layer_owner_.layer());
250 } 256 }
251 257
252 InkDropAnimationController::InkDropAnimationController(views::View* view) 258 void InkDropAnimationControllerImpl::AnimateTapDown() {
253 : ink_drop_layer_(new ui::Layer()),
254 ink_drop_delegate_(
255 new InkDropDelegate(ink_drop_layer_.get(), kInkDropColor)),
256 appear_animation_observer_(nullptr),
257 long_press_layer_(new ui::Layer()),
258 long_press_delegate_(
259 new InkDropDelegate(long_press_layer_.get(), kLongPressColor)),
260 long_press_animation_observer_(nullptr),
261 view_(view) {
262 view_->SetPaintToLayer(true);
263 view_->AddPreTargetHandler(this);
264 ui::Layer* layer = view_->layer();
265 layer->SetMasksToBounds(!UseCircularFeedback());
266 SetupAnimationLayer(layer, long_press_layer_.get(),
267 long_press_delegate_.get());
268 SetupAnimationLayer(layer, ink_drop_layer_.get(), ink_drop_delegate_.get());
269 ink_drop_delegate_->set_should_render_circle(UseCircularFeedback());
270 }
271
272 InkDropAnimationController::~InkDropAnimationController() {
273 view_->RemovePreTargetHandler(this);
274 }
275
276 void InkDropAnimationController::AnimateTapDown() {
277 if ((appear_animation_observer_ && 259 if ((appear_animation_observer_ &&
278 appear_animation_observer_->IsAnimationActive()) || 260 appear_animation_observer_->IsAnimationActive()) ||
279 (long_press_animation_observer_ && 261 (long_press_animation_observer_ &&
280 long_press_animation_observer_->IsAnimationActive())) { 262 long_press_animation_observer_->IsAnimationActive())) {
281 // Only one animation at a time. Subsequent tap downs are ignored until the 263 // Only one animation at a time. Subsequent tap downs are ignored until the
282 // current animation completes. 264 // current animation completes.
283 return; 265 return;
284 } 266 }
285 appear_animation_observer_.reset( 267 appear_animation_observer_.reset(
286 new AppearAnimationObserver(ink_drop_layer_.get(), false)); 268 new AppearAnimationObserver(ink_drop_layer_owner_.layer(), false));
287 AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(), 269 AnimateShow(ink_drop_layer_owner_.layer(), appear_animation_observer_.get(),
288 UseCircularFeedback(),
289 base::TimeDelta::FromMilliseconds( 270 base::TimeDelta::FromMilliseconds(
290 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs 271 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs
291 : kShowInkDropAnimationDurationSlowMs))); 272 : kShowInkDropAnimationDurationSlowMs)));
292 } 273 }
293 274
294 void InkDropAnimationController::AnimateHide() { 275 void InkDropAnimationControllerImpl::AnimateHide() {
295 if (appear_animation_observer_) 276 if (appear_animation_observer_ &&
277 appear_animation_observer_->IsAnimationActive()) {
296 appear_animation_observer_->HideNowIfDoneOrOnceCompleted(); 278 appear_animation_observer_->HideNowIfDoneOrOnceCompleted();
279 } else if (long_press_animation_observer_) {
280 long_press_animation_observer_->HideNowIfDoneOrOnceCompleted();
281 }
297 } 282 }
298 283
299 void InkDropAnimationController::AnimateLongPress() { 284 void InkDropAnimationControllerImpl::AnimateLongPress() {
300 // Only one animation at a time. Subsequent long presses are ignored until the 285 // Only one animation at a time. Subsequent long presses are ignored until the
301 // current animation completes. 286 // current animation completes.
302 if (long_press_animation_observer_ && 287 if (long_press_animation_observer_ &&
303 long_press_animation_observer_->IsAnimationActive()) { 288 long_press_animation_observer_->IsAnimationActive()) {
304 return; 289 return;
305 } 290 }
306 appear_animation_observer_.reset(); 291 appear_animation_observer_.reset();
307 long_press_animation_observer_.reset( 292 long_press_animation_observer_.reset(
308 new AppearAnimationObserver(long_press_layer_.get(), true)); 293 new AppearAnimationObserver(long_press_layer_owner_.layer(), false));
309 long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get()); 294 long_press_animation_observer_->SetBackgroundToHide(
310 AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(), 295 ink_drop_layer_owner_.layer());
311 true, 296 AnimateShow(long_press_layer_owner_.layer(),
297 long_press_animation_observer_.get(),
312 base::TimeDelta::FromMilliseconds( 298 base::TimeDelta::FromMilliseconds(
313 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs 299 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs
314 : kShowLongPressAnimationDurationSlowMs)); 300 : kShowLongPressAnimationDurationSlowMs));
315 } 301 }
316 302
317 void InkDropAnimationController::AnimateShow(ui::Layer* layer, 303 void InkDropAnimationControllerImpl::AnimateShow(
318 AppearAnimationObserver* observer, 304 ui::Layer* layer,
319 bool circle, 305 AppearAnimationObserver* observer,
320 base::TimeDelta duration) { 306 base::TimeDelta duration) {
321 SetLayerBounds(layer, circle, view_->width(), view_->height());
322 layer->SetVisible(true); 307 layer->SetVisible(true);
323 layer->SetOpacity(1.0f); 308 layer->SetOpacity(1.0f);
324 309
325 float start_x = layer->bounds().width() * kMinimumScaleCenteringOffset; 310 float start_x = ink_drop_bounds_.x() +
326 float start_y = layer->bounds().height() * kMinimumScaleCenteringOffset; 311 layer->bounds().width() * kMinimumScaleCenteringOffset;
312 float start_y = ink_drop_bounds_.y() +
313 layer->bounds().height() * kMinimumScaleCenteringOffset;
327 314
328 gfx::Transform initial_transform; 315 gfx::Transform initial_transform;
329 initial_transform.Translate(start_x, start_y); 316 initial_transform.Translate(start_x, start_y);
330 initial_transform.Scale(kMinimumScale, kMinimumScale); 317 initial_transform.Scale(kMinimumScale, kMinimumScale);
331 layer->SetTransform(initial_transform); 318 layer->SetTransform(initial_transform);
332 319
333 ui::LayerAnimator* animator = layer->GetAnimator(); 320 ui::LayerAnimator* animator = layer->GetAnimator();
334 ui::ScopedLayerAnimationSettings animation(animator); 321 ui::ScopedLayerAnimationSettings animation(animator);
335 animation.SetPreemptionStrategy( 322 animation.SetPreemptionStrategy(
336 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 323 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
337 324
338 gfx::Transform identity_transform; 325 gfx::Transform target_transform;
326 target_transform.Translate(ink_drop_bounds_.x(), ink_drop_bounds_.y());
339 ui::LayerAnimationElement* element = 327 ui::LayerAnimationElement* element =
340 ui::LayerAnimationElement::CreateTransformElement(identity_transform, 328 ui::LayerAnimationElement::CreateTransformElement(target_transform,
341 duration); 329 duration);
342 ui::LayerAnimationSequence* sequence = 330 ui::LayerAnimationSequence* sequence =
343 new ui::LayerAnimationSequence(element); 331 new ui::LayerAnimationSequence(element);
344 sequence->AddObserver(observer); 332 sequence->AddObserver(observer);
345 animator->StartAnimation(sequence); 333 animator->StartAnimation(sequence);
346 } 334 }
347 335
348 void InkDropAnimationController::SetLayerBounds(ui::Layer* layer, 336 void InkDropAnimationControllerImpl::SetLayerBounds(ui::Layer* layer) {
349 bool circle, 337 bool circle = UseCircularFeedback();
350 int width, 338 gfx::Size size = ink_drop_bounds_.size();
351 int height) { 339 float circle_width = circle ? 2.0f * kCircleRadius : size.width();
352 float circle_width = circle ? 2.0f * kCircleRadius : width; 340 float circle_height = circle ? 2.0f * kCircleRadius : size.height();
353 float circle_height = circle ? 2.0f * kCircleRadius : height; 341 float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0;
354 float circle_x = circle ? (width - circle_width) * 0.5f : 0; 342 float circle_y = circle ? (size.height() - circle_height) * 0.5f : 0;
355 float circle_y = circle ? (height - circle_height) * 0.5f : 0;
356 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height)); 343 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height));
357 } 344 }
358 345
359 void InkDropAnimationController::SetupAnimationLayer( 346 void InkDropAnimationControllerImpl::SetupAnimationLayer(
360 ui::Layer* parent,
361 ui::Layer* layer, 347 ui::Layer* layer,
362 InkDropDelegate* delegate) { 348 InkDropDelegate* delegate) {
363 layer->SetFillsBoundsOpaquely(false); 349 layer->SetFillsBoundsOpaquely(false);
364 layer->set_delegate(delegate); 350 layer->set_delegate(delegate);
365 layer->SetVisible(false); 351 layer->SetVisible(false);
366 layer->SetBounds(gfx::Rect()); 352 layer->SetBounds(gfx::Rect());
367 parent->Add(layer); 353 delegate->set_should_render_circle(UseCircularFeedback());
368 parent->StackAtBottom(layer);
369 }
370
371 void InkDropAnimationController::OnGestureEvent(ui::GestureEvent* event) {
372 if (event->target() != view_)
373 return;
374
375 switch (event->type()) {
376 case ui::ET_GESTURE_TAP_DOWN:
377 AnimateTapDown();
378 break;
379 case ui::ET_GESTURE_LONG_PRESS:
380 AnimateLongPress();
381 break;
382 case ui::ET_GESTURE_END:
383 case ui::ET_GESTURE_TAP_CANCEL:
384 case ui::ET_GESTURE_TAP:
385 AnimateHide();
386 break;
387 default:
388 break;
389 }
390 } 354 }
391 355
392 } // namespace views 356 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698