OLD | NEW |
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> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "third_party/skia/include/core/SkColor.h" | 11 #include "third_party/skia/include/core/SkColor.h" |
12 #include "third_party/skia/include/core/SkPaint.h" | 12 #include "third_party/skia/include/core/SkPaint.h" |
13 #include "ui/base/ui_base_switches.h" | 13 #include "ui/base/ui_base_switches.h" |
| 14 #include "ui/compositor/callback_layer_animation_observer.h" |
14 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
15 #include "ui/compositor/layer_animation_observer.h" | |
16 #include "ui/compositor/layer_animation_sequence.h" | 16 #include "ui/compositor/layer_animation_sequence.h" |
17 #include "ui/compositor/paint_recorder.h" | 17 #include "ui/compositor/paint_recorder.h" |
18 #include "ui/compositor/scoped_layer_animation_settings.h" | 18 #include "ui/compositor/scoped_layer_animation_settings.h" |
19 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
20 #include "ui/gfx/transform_util.h" | 20 #include "ui/gfx/transform_util.h" |
| 21 #include "ui/views/animation/ink_drop_animation_observer.h" |
21 #include "ui/views/view.h" | 22 #include "ui/views/view.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // The minimum scale factor to use when scaling rectangle layers. Smaller values | 26 // The minimum scale factor to use when scaling rectangle layers. Smaller values |
26 // were causing visual anomalies. | 27 // were causing visual anomalies. |
27 const float kMinimumRectScale = 0.0001f; | 28 const float kMinimumRectScale = 0.0001f; |
28 | 29 |
29 // The minimum scale factor to use when scaling circle layers. Smaller values | 30 // The minimum scale factor to use when scaling circle layers. Smaller values |
30 // were causing visual anomalies. | 31 // were causing visual anomalies. |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 rect_layer_delegate_( | 247 rect_layer_delegate_( |
247 new RectangleLayerDelegate(kInkDropColor, large_size_)), | 248 new RectangleLayerDelegate(kInkDropColor, large_size_)), |
248 root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)), | 249 root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)), |
249 ink_drop_state_(InkDropState::HIDDEN) { | 250 ink_drop_state_(InkDropState::HIDDEN) { |
250 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | 251 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
251 AddPaintLayer(static_cast<PaintedShape>(i)); | 252 AddPaintLayer(static_cast<PaintedShape>(i)); |
252 | 253 |
253 root_layer_->SetMasksToBounds(false); | 254 root_layer_->SetMasksToBounds(false); |
254 root_layer_->SetBounds(gfx::Rect(large_size_)); | 255 root_layer_->SetBounds(gfx::Rect(large_size_)); |
255 | 256 |
256 ResetTransformsToMinSize(); | 257 SetStateToHidden(); |
257 | |
258 SetOpacity(kHiddenOpacity); | |
259 } | 258 } |
260 | 259 |
261 InkDropAnimation::~InkDropAnimation() {} | 260 InkDropAnimation::~InkDropAnimation() { |
| 261 // Explicitly aborting all the animations ensures all callbacks are invoked |
| 262 // while this instance still exists. |
| 263 AbortAllAnimations(); |
| 264 } |
| 265 |
| 266 void InkDropAnimation::AddObserver(InkDropAnimationObserver* observer) { |
| 267 observers_.AddObserver(observer); |
| 268 } |
| 269 |
| 270 void InkDropAnimation::RemoveObserver(InkDropAnimationObserver* observer) { |
| 271 observers_.RemoveObserver(observer); |
| 272 } |
262 | 273 |
263 void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) { | 274 void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) { |
264 if (ink_drop_state_ == ink_drop_state) | 275 // |animation_observer| will be deleted when AnimationEndedCallback() returns |
265 return; | 276 // true. |
| 277 ui::CallbackLayerAnimationObserver* animation_observer = |
| 278 new ui::CallbackLayerAnimationObserver( |
| 279 base::Bind(&InkDropAnimation::AnimationStartedCallback, |
| 280 base::Unretained(this), ink_drop_state), |
| 281 base::Bind(&InkDropAnimation::AnimationEndedCallback, |
| 282 base::Unretained(this), ink_drop_state)); |
| 283 AnimateToStateInternal(ink_drop_state, animation_observer); |
| 284 animation_observer->SetActive(); |
| 285 } |
| 286 |
| 287 void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) { |
| 288 gfx::Transform transform; |
| 289 transform.Translate(center_point.x(), center_point.y()); |
| 290 root_layer_->SetTransform(transform); |
| 291 } |
| 292 |
| 293 void InkDropAnimation::AnimateToStateInternal( |
| 294 InkDropState ink_drop_state, |
| 295 ui::LayerAnimationObserver* animation_observer) { |
| 296 ink_drop_state_ = ink_drop_state; |
266 | 297 |
267 if (ink_drop_state_ == InkDropState::HIDDEN) { | 298 if (ink_drop_state_ == InkDropState::HIDDEN) { |
268 ResetTransformsToMinSize(); | 299 // Animating to the HIDDEN state doesn't actually use any |
269 SetOpacity(kVisibleOpacity); | 300 // LayerAnimationSequences so we need to explicitly abort any running ones |
| 301 // so that observers receive an InkDropAnimationEnded() event for the |
| 302 // running animation prior to receiving an InkDropAnimationStarted() event |
| 303 // for the HIDDEN 'animation'. |
| 304 AbortAllAnimations(); |
| 305 root_layer_->SetVisible(false); |
| 306 SetStateToHidden(); |
| 307 return; |
270 } | 308 } |
271 | 309 |
272 InkDropTransforms transforms; | 310 InkDropTransforms transforms; |
273 | 311 root_layer_->SetVisible(true); |
274 // Must set the |ink_drop_state_| before handling the state change because | |
275 // some state changes make recursive calls to AnimateToState() and the last | |
276 // call should 'win'. | |
277 ink_drop_state_ = ink_drop_state; | |
278 | 312 |
279 switch (ink_drop_state_) { | 313 switch (ink_drop_state_) { |
280 case InkDropState::HIDDEN: | 314 case InkDropState::HIDDEN: |
281 GetCurrentTansforms(&transforms); | 315 // This case is handled above in a short circuit return. |
282 AnimateToTransforms(transforms, kHiddenOpacity, | |
283 GetAnimationDuration(InkDropState::HIDDEN), | |
284 ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); | |
285 break; | 316 break; |
286 case InkDropState::ACTION_PENDING: | 317 case InkDropState::ACTION_PENDING: |
287 CalculateCircleTransforms(large_size_, &transforms); | 318 CalculateCircleTransforms(large_size_, &transforms); |
288 AnimateToTransforms(transforms, kVisibleOpacity, | 319 AnimateToTransforms(transforms, kVisibleOpacity, |
289 GetAnimationDuration(InkDropState::ACTION_PENDING), | 320 GetAnimationDuration(InkDropState::ACTION_PENDING), |
290 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 321 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
| 322 animation_observer); |
291 break; | 323 break; |
292 case InkDropState::QUICK_ACTION: | 324 case InkDropState::QUICK_ACTION: |
293 CalculateCircleTransforms(large_size_, &transforms); | 325 CalculateCircleTransforms(large_size_, &transforms); |
294 AnimateToTransforms(transforms, kHiddenOpacity, | 326 AnimateToTransforms(transforms, kHiddenOpacity, |
295 GetAnimationDuration(InkDropState::QUICK_ACTION), | 327 GetAnimationDuration(InkDropState::QUICK_ACTION), |
296 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 328 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
297 AnimateToState(InkDropState::HIDDEN); | 329 animation_observer); |
298 break; | 330 break; |
299 case InkDropState::SLOW_ACTION_PENDING: | 331 case InkDropState::SLOW_ACTION_PENDING: |
300 CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); | 332 CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
301 AnimateToTransforms( | 333 AnimateToTransforms( |
302 transforms, kVisibleOpacity, | 334 transforms, kVisibleOpacity, |
303 GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING), | 335 GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING), |
304 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 336 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
| 337 animation_observer); |
305 break; | 338 break; |
306 case InkDropState::SLOW_ACTION: | 339 case InkDropState::SLOW_ACTION: |
307 CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); | 340 CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
308 AnimateToTransforms(transforms, kHiddenOpacity, | 341 AnimateToTransforms(transforms, kHiddenOpacity, |
309 GetAnimationDuration(InkDropState::SLOW_ACTION), | 342 GetAnimationDuration(InkDropState::SLOW_ACTION), |
310 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 343 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
311 AnimateToState(InkDropState::HIDDEN); | 344 animation_observer); |
312 break; | 345 break; |
313 case InkDropState::ACTIVATED: | 346 case InkDropState::ACTIVATED: |
314 CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); | 347 CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
315 AnimateToTransforms(transforms, kVisibleOpacity, | 348 AnimateToTransforms(transforms, kVisibleOpacity, |
316 GetAnimationDuration(InkDropState::ACTIVATED), | 349 GetAnimationDuration(InkDropState::ACTIVATED), |
317 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 350 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
| 351 animation_observer); |
318 break; | 352 break; |
319 case InkDropState::DEACTIVATED: | 353 case InkDropState::DEACTIVATED: |
320 CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); | 354 CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
321 AnimateToTransforms(transforms, kHiddenOpacity, | 355 AnimateToTransforms(transforms, kHiddenOpacity, |
322 GetAnimationDuration(InkDropState::DEACTIVATED), | 356 GetAnimationDuration(InkDropState::DEACTIVATED), |
323 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 357 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
324 AnimateToState(InkDropState::HIDDEN); | 358 animation_observer); |
325 break; | 359 break; |
326 } | 360 } |
327 } | 361 } |
328 | 362 |
329 void InkDropAnimation::AnimateToTransforms( | 363 void InkDropAnimation::AnimateToTransforms( |
330 const InkDropTransforms transforms, | 364 const InkDropTransforms transforms, |
331 float opacity, | 365 float opacity, |
332 base::TimeDelta duration, | 366 base::TimeDelta duration, |
333 ui::LayerAnimator::PreemptionStrategy preemption_strategy) { | 367 ui::LayerAnimator::PreemptionStrategy preemption_strategy, |
| 368 ui::LayerAnimationObserver* animation_observer) { |
334 ui::LayerAnimator* root_animator = root_layer_->GetAnimator(); | 369 ui::LayerAnimator* root_animator = root_layer_->GetAnimator(); |
335 ui::ScopedLayerAnimationSettings root_animation(root_animator); | 370 ui::ScopedLayerAnimationSettings root_animation(root_animator); |
336 root_animation.SetPreemptionStrategy(preemption_strategy); | 371 root_animation.SetPreemptionStrategy(preemption_strategy); |
337 ui::LayerAnimationElement* root_element = | 372 ui::LayerAnimationElement* root_element = |
338 ui::LayerAnimationElement::CreateOpacityElement(opacity, duration); | 373 ui::LayerAnimationElement::CreateOpacityElement(opacity, duration); |
339 ui::LayerAnimationSequence* root_sequence = | 374 ui::LayerAnimationSequence* root_sequence = |
340 new ui::LayerAnimationSequence(root_element); | 375 new ui::LayerAnimationSequence(root_element); |
| 376 |
| 377 if (animation_observer) |
| 378 root_sequence->AddObserver(animation_observer); |
| 379 |
341 root_animator->StartAnimation(root_sequence); | 380 root_animator->StartAnimation(root_sequence); |
342 | 381 |
343 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) { | 382 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) { |
344 ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator(); | 383 ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator(); |
345 ui::ScopedLayerAnimationSettings animation(animator); | 384 ui::ScopedLayerAnimationSettings animation(animator); |
346 animation.SetPreemptionStrategy(preemption_strategy); | 385 animation.SetPreemptionStrategy(preemption_strategy); |
347 ui::LayerAnimationElement* element = | 386 ui::LayerAnimationElement* element = |
348 ui::LayerAnimationElement::CreateTransformElement(transforms[i], | 387 ui::LayerAnimationElement::CreateTransformElement(transforms[i], |
349 duration); | 388 duration); |
350 ui::LayerAnimationSequence* sequence = | 389 ui::LayerAnimationSequence* sequence = |
351 new ui::LayerAnimationSequence(element); | 390 new ui::LayerAnimationSequence(element); |
| 391 |
| 392 if (animation_observer) |
| 393 sequence->AddObserver(animation_observer); |
| 394 |
352 animator->StartAnimation(sequence); | 395 animator->StartAnimation(sequence); |
353 } | 396 } |
354 } | 397 } |
355 | 398 |
356 void InkDropAnimation::ResetTransformsToMinSize() { | 399 void InkDropAnimation::SetStateToHidden() { |
357 InkDropTransforms transforms; | 400 InkDropTransforms transforms; |
358 // Using a size of 0x0 creates visual anomalies. | 401 // Using a size of 0x0 creates visual anomalies. |
359 CalculateCircleTransforms(gfx::Size(1, 1), &transforms); | 402 CalculateCircleTransforms(gfx::Size(1, 1), &transforms); |
360 SetTransforms(transforms); | 403 SetTransforms(transforms); |
| 404 SetOpacity(kHiddenOpacity); |
361 } | 405 } |
362 | 406 |
363 void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) { | 407 void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) { |
364 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | 408 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
365 painted_layers_[i]->SetTransform(transforms[i]); | 409 painted_layers_[i]->SetTransform(transforms[i]); |
366 } | 410 } |
367 | 411 |
368 void InkDropAnimation::SetOpacity(float opacity) { | 412 void InkDropAnimation::SetOpacity(float opacity) { |
369 root_layer_->SetOpacity(opacity); | 413 root_layer_->SetOpacity(opacity); |
370 } | 414 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 (size.width() - 2.0f * corner_radius) / rect_delegate_width), | 473 (size.width() - 2.0f * corner_radius) / rect_delegate_width), |
430 std::max(kMinimumRectScale, size.height() / rect_delegate_height)); | 474 std::max(kMinimumRectScale, size.height() / rect_delegate_height)); |
431 } | 475 } |
432 | 476 |
433 void InkDropAnimation::GetCurrentTansforms( | 477 void InkDropAnimation::GetCurrentTansforms( |
434 InkDropTransforms* transforms_out) const { | 478 InkDropTransforms* transforms_out) const { |
435 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | 479 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
436 (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform(); | 480 (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform(); |
437 } | 481 } |
438 | 482 |
439 void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) { | |
440 gfx::Transform transform; | |
441 transform.Translate(center_point.x(), center_point.y()); | |
442 root_layer_->SetTransform(transform); | |
443 } | |
444 | |
445 void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) { | 483 void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) { |
446 ui::LayerDelegate* delegate = nullptr; | 484 ui::LayerDelegate* delegate = nullptr; |
447 switch (painted_shape) { | 485 switch (painted_shape) { |
448 case TOP_LEFT_CIRCLE: | 486 case TOP_LEFT_CIRCLE: |
449 case TOP_RIGHT_CIRCLE: | 487 case TOP_RIGHT_CIRCLE: |
450 case BOTTOM_RIGHT_CIRCLE: | 488 case BOTTOM_RIGHT_CIRCLE: |
451 case BOTTOM_LEFT_CIRCLE: | 489 case BOTTOM_LEFT_CIRCLE: |
452 delegate = circle_layer_delegate_.get(); | 490 delegate = circle_layer_delegate_.get(); |
453 break; | 491 break; |
454 case HORIZONTAL_RECT: | 492 case HORIZONTAL_RECT: |
(...skipping 11 matching lines...) Expand all Loading... |
466 layer->SetBounds(gfx::Rect(large_size_)); | 504 layer->SetBounds(gfx::Rect(large_size_)); |
467 layer->SetFillsBoundsOpaquely(false); | 505 layer->SetFillsBoundsOpaquely(false); |
468 layer->set_delegate(delegate); | 506 layer->set_delegate(delegate); |
469 layer->SetVisible(true); | 507 layer->SetVisible(true); |
470 layer->SetOpacity(1.0); | 508 layer->SetOpacity(1.0); |
471 layer->SetMasksToBounds(false); | 509 layer->SetMasksToBounds(false); |
472 | 510 |
473 painted_layers_[painted_shape].reset(layer); | 511 painted_layers_[painted_shape].reset(layer); |
474 } | 512 } |
475 | 513 |
| 514 void InkDropAnimation::AbortAllAnimations() { |
| 515 root_layer_->GetAnimator()->AbortAllAnimations(); |
| 516 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
| 517 painted_layers_[i]->GetAnimator()->AbortAllAnimations(); |
| 518 } |
| 519 |
| 520 void InkDropAnimation::AnimationStartedCallback( |
| 521 InkDropState ink_drop_state, |
| 522 const ui::CallbackLayerAnimationObserver& observer) { |
| 523 FOR_EACH_OBSERVER(InkDropAnimationObserver, observers_, |
| 524 InkDropAnimationStarted(ink_drop_state)); |
| 525 } |
| 526 |
| 527 bool InkDropAnimation::AnimationEndedCallback( |
| 528 InkDropState ink_drop_state, |
| 529 const ui::CallbackLayerAnimationObserver& observer) { |
| 530 FOR_EACH_OBSERVER( |
| 531 InkDropAnimationObserver, observers_, |
| 532 InkDropAnimationEnded(ink_drop_state, |
| 533 observer.aborted_count() |
| 534 ? InkDropAnimationObserver::PRE_EMPTED |
| 535 : InkDropAnimationObserver::SUCCESS)); |
| 536 return true; |
| 537 } |
| 538 |
476 } // namespace views | 539 } // namespace views |
OLD | NEW |