Index: ui/views/animation/ink_drop_animation.cc |
diff --git a/ui/views/animation/ink_drop_animation.cc b/ui/views/animation/ink_drop_animation.cc |
index d5ce3ca9d524b6984d00343092ef49a3c44e566c..0b5e65e88afc3691eda2d8d80e924d1d362e8f7f 100644 |
--- a/ui/views/animation/ink_drop_animation.cc |
+++ b/ui/views/animation/ink_drop_animation.cc |
@@ -11,13 +11,14 @@ |
#include "third_party/skia/include/core/SkColor.h" |
#include "third_party/skia/include/core/SkPaint.h" |
#include "ui/base/ui_base_switches.h" |
+#include "ui/compositor/callback_layer_animation_observer.h" |
#include "ui/compositor/layer.h" |
-#include "ui/compositor/layer_animation_observer.h" |
#include "ui/compositor/layer_animation_sequence.h" |
#include "ui/compositor/paint_recorder.h" |
#include "ui/compositor/scoped_layer_animation_settings.h" |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/transform_util.h" |
+#include "ui/views/animation/ink_drop_animation_observer.h" |
#include "ui/views/view.h" |
namespace { |
@@ -253,75 +254,103 @@ InkDropAnimation::InkDropAnimation(const gfx::Size& large_size, |
root_layer_->SetMasksToBounds(false); |
root_layer_->SetBounds(gfx::Rect(large_size_)); |
- ResetTransformsToMinSize(); |
+ SetStateToHidden(); |
+} |
- SetOpacity(kHiddenOpacity); |
+InkDropAnimation::~InkDropAnimation() { |
+ // Explicitly aborting all the animations ensures all callbacks are invoked |
+ // while this instance still exists. |
+ AbortAllAnimations(); |
} |
-InkDropAnimation::~InkDropAnimation() {} |
+void InkDropAnimation::AddObserver(InkDropAnimationObserver* observer) { |
+ if (!observers_.HasObserver(observer)) |
varkha
2015/10/06 20:58:38
When is this the case? Do we need this?
sadrul
2015/10/08 01:06:01
+1 Let's remove this.
bruthig
2015/10/08 21:42:55
It was originally intended as a safe-guard to ensu
|
+ observers_.AddObserver(observer); |
+} |
+ |
+void InkDropAnimation::RemoveObserver(InkDropAnimationObserver* observer) { |
+ observers_.RemoveObserver(observer); |
+} |
void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) { |
- if (ink_drop_state_ == ink_drop_state) |
- return; |
+ // |animation_observer| will be deleted when AnimationEndedCallback() returns |
+ // true. |
+ ui::CallbackLayerAnimationObserver* animation_observer = |
+ new ui::CallbackLayerAnimationObserver( |
+ base::Bind(&InkDropAnimation::AnimationStartedCallback, |
+ base::Unretained(this), ink_drop_state), |
+ base::Bind(&InkDropAnimation::AnimationEndedCallback, |
+ base::Unretained(this), ink_drop_state)); |
+ AnimateToStateInternal(ink_drop_state, animation_observer); |
+ animation_observer->SetActive(); |
+} |
+ |
+void InkDropAnimation::AnimateToStateInternal( |
+ InkDropState ink_drop_state, |
+ ui::LayerAnimationObserver* animation_observer) { |
+ ink_drop_state_ = ink_drop_state; |
if (ink_drop_state_ == InkDropState::HIDDEN) { |
- ResetTransformsToMinSize(); |
- SetOpacity(kVisibleOpacity); |
+ // Animating to the HIDDEN state doesn't actually use any |
+ // LayerAnimationSequences so we need to explicitly abort any running ones |
+ // so that observers receive an InkDropAnimationEnded() event for the |
+ // running animation prior to receiving an InkDropAnimationStarted() event |
+ // for the HIDDEN 'animation'. |
+ AbortAllAnimations(); |
+ root_layer_->SetVisible(false); |
+ SetStateToHidden(); |
+ return; |
} |
InkDropTransforms transforms; |
- |
- // Must set the |ink_drop_state_| before handling the state change because |
- // some state changes make recursive calls to AnimateToState() and the last |
- // call should 'win'. |
- ink_drop_state_ = ink_drop_state; |
+ root_layer_->SetVisible(true); |
switch (ink_drop_state_) { |
case InkDropState::HIDDEN: |
- GetCurrentTansforms(&transforms); |
- AnimateToTransforms(transforms, kHiddenOpacity, |
- GetAnimationDuration(InkDropState::HIDDEN), |
- ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); |
+ // This case is handled above in a short circuit return. |
break; |
case InkDropState::ACTION_PENDING: |
CalculateCircleTransforms(large_size_, &transforms); |
AnimateToTransforms(transforms, kVisibleOpacity, |
GetAnimationDuration(InkDropState::ACTION_PENDING), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::QUICK_ACTION: |
CalculateCircleTransforms(large_size_, &transforms); |
AnimateToTransforms(transforms, kHiddenOpacity, |
GetAnimationDuration(InkDropState::QUICK_ACTION), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
- AnimateToState(InkDropState::HIDDEN); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::SLOW_ACTION_PENDING: |
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
AnimateToTransforms( |
transforms, kVisibleOpacity, |
GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::SLOW_ACTION: |
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
AnimateToTransforms(transforms, kHiddenOpacity, |
GetAnimationDuration(InkDropState::SLOW_ACTION), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
- AnimateToState(InkDropState::HIDDEN); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::ACTIVATED: |
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
AnimateToTransforms(transforms, kVisibleOpacity, |
GetAnimationDuration(InkDropState::ACTIVATED), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::DEACTIVATED: |
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
AnimateToTransforms(transforms, kHiddenOpacity, |
GetAnimationDuration(InkDropState::DEACTIVATED), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
- AnimateToState(InkDropState::HIDDEN); |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
} |
} |
@@ -330,7 +359,8 @@ void InkDropAnimation::AnimateToTransforms( |
const InkDropTransforms transforms, |
float opacity, |
base::TimeDelta duration, |
- ui::LayerAnimator::PreemptionStrategy preemption_strategy) { |
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy, |
+ ui::LayerAnimationObserver* animation_observer) { |
ui::LayerAnimator* root_animator = root_layer_->GetAnimator(); |
ui::ScopedLayerAnimationSettings root_animation(root_animator); |
root_animation.SetPreemptionStrategy(preemption_strategy); |
@@ -338,6 +368,10 @@ void InkDropAnimation::AnimateToTransforms( |
ui::LayerAnimationElement::CreateOpacityElement(opacity, duration); |
ui::LayerAnimationSequence* root_sequence = |
new ui::LayerAnimationSequence(root_element); |
+ |
+ if (animation_observer) |
+ root_sequence->AddObserver(animation_observer); |
+ |
root_animator->StartAnimation(root_sequence); |
for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) { |
@@ -349,15 +383,20 @@ void InkDropAnimation::AnimateToTransforms( |
duration); |
ui::LayerAnimationSequence* sequence = |
new ui::LayerAnimationSequence(element); |
+ |
+ if (animation_observer) |
+ sequence->AddObserver(animation_observer); |
+ |
animator->StartAnimation(sequence); |
} |
} |
-void InkDropAnimation::ResetTransformsToMinSize() { |
+void InkDropAnimation::SetStateToHidden() { |
InkDropTransforms transforms; |
// Using a size of 0x0 creates visual anomalies. |
CalculateCircleTransforms(gfx::Size(1, 1), &transforms); |
SetTransforms(transforms); |
+ SetOpacity(kHiddenOpacity); |
} |
void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) { |
@@ -473,4 +512,29 @@ void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) { |
painted_layers_[painted_shape].reset(layer); |
} |
+void InkDropAnimation::AbortAllAnimations() { |
+ root_layer_->GetAnimator()->AbortAllAnimations(); |
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
varkha
2015/10/06 20:58:38
Will range syntax work here (and in SetTransforms
bruthig
2015/10/08 21:42:55
It appears there isn't built in support for range
|
+ painted_layers_[i]->GetAnimator()->AbortAllAnimations(); |
+} |
+ |
+void InkDropAnimation::AnimationStartedCallback( |
+ InkDropState ink_drop_state, |
+ const ui::CallbackLayerAnimationObserver& observer) { |
+ FOR_EACH_OBSERVER(InkDropAnimationObserver, observers_, |
+ InkDropAnimationStarted(ink_drop_state)); |
+} |
+ |
+bool InkDropAnimation::AnimationEndedCallback( |
+ InkDropState ink_drop_state, |
+ const ui::CallbackLayerAnimationObserver& observer) { |
+ FOR_EACH_OBSERVER( |
+ InkDropAnimationObserver, observers_, |
+ InkDropAnimationEnded(ink_drop_state, |
+ observer.aborted_count() |
sadrul
2015/10/08 01:06:01
Is this the only reason to send the observer back
bruthig
2015/10/08 21:42:55
In the current use case yes, this is the only data
sadrul
2015/10/09 20:36:26
Simplicity. It's not complex as it is now, so that
|
+ ? InkDropAnimationObserver::PRE_EMPTED |
+ : InkDropAnimationObserver::SUCCESS)); |
+ return true; |
+} |
+ |
} // namespace views |