summaryrefslogtreecommitdiff
path: root/chromium/ui/views/animation/ink_drop_animation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/views/animation/ink_drop_animation.cc')
-rw-r--r--chromium/ui/views/animation/ink_drop_animation.cc455
1 files changed, 60 insertions, 395 deletions
diff --git a/chromium/ui/views/animation/ink_drop_animation.cc b/chromium/ui/views/animation/ink_drop_animation.cc
index cf0c705e7ba..214716da23a 100644
--- a/chromium/ui/views/animation/ink_drop_animation.cc
+++ b/chromium/ui/views/animation/ink_drop_animation.cc
@@ -4,56 +4,18 @@
#include "ui/views/animation/ink_drop_animation.h"
-#include <algorithm>
-
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
-#include "base/logging.h"
-#include "third_party/skia/include/core/SkColor.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_sequence.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/transform_util.h"
-#include "ui/views/animation/ink_drop_animation_observer.h"
-#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
-#include "ui/views/view.h"
-
-namespace {
-
-// The minimum scale factor to use when scaling rectangle layers. Smaller values
-// were causing visual anomalies.
-const float kMinimumRectScale = 0.0001f;
-
-// The minimum scale factor to use when scaling circle layers. Smaller values
-// were causing visual anomalies.
-const float kMinimumCircleScale = 0.001f;
-
-// The ink drop color.
-const SkColor kInkDropColor = SK_ColorBLACK;
-
-// The opacity of the ink drop when it is visible.
-const float kVisibleOpacity = 0.14f;
-// The opacity of the ink drop when it is not visible.
-const float kHiddenOpacity = 0.0f;
-
-// Durations for the different InkDropState animations in milliseconds.
-const int kHiddenStateAnimationDurationMs = 1;
-const int kActionPendingStateAnimationDurationMs = 500;
-const int kQuickActionStateAnimationDurationMs = 250;
-const int kSlowActionPendingStateAnimationDurationMs = 500;
-const int kSlowActionStateAnimationDurationMs = 250;
-const int kActivatedStateAnimationDurationMs = 125;
-const int kDeactivatedStateAnimationDurationMs = 250;
+namespace views {
-// A multiplicative factor used to slow down InkDropState animations.
-const int kSlowAnimationDurationFactor = 3;
+const double InkDropAnimation::kSlowAnimationDurationFactor = 3.0;
-// Checks CommandLine switches to determine if the visual feedback should have
-// a fast animations speed.
-bool UseFastAnimations() {
+bool InkDropAnimation::UseFastAnimations() {
static bool fast =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
(::switches::kMaterialDesignInkDropAnimationSpeed)) !=
@@ -61,391 +23,94 @@ bool UseFastAnimations() {
return fast;
}
-// Returns the InkDropState animation duration for the given |state|.
-base::TimeDelta GetAnimationDuration(views::InkDropState state) {
- int duration = 0;
- switch (state) {
- case views::InkDropState::HIDDEN:
- duration = kHiddenStateAnimationDurationMs;
- break;
- case views::InkDropState::ACTION_PENDING:
- duration = kActionPendingStateAnimationDurationMs;
- break;
- case views::InkDropState::QUICK_ACTION:
- duration = kQuickActionStateAnimationDurationMs;
- break;
- case views::InkDropState::SLOW_ACTION_PENDING:
- duration = kSlowActionPendingStateAnimationDurationMs;
- break;
- case views::InkDropState::SLOW_ACTION:
- duration = kSlowActionStateAnimationDurationMs;
- break;
- case views::InkDropState::ACTIVATED:
- duration = kActivatedStateAnimationDurationMs;
- break;
- case views::InkDropState::DEACTIVATED:
- duration = kDeactivatedStateAnimationDurationMs;
- break;
- }
-
- return base::TimeDelta::FromMilliseconds(
- (UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) * duration);
-}
-
-// Calculates a Transform for a circle layer. The transform will be set up to
-// translate the |drawn_center_point| to the origin, scale, and then translate
-// to the target point defined by |target_center_x| and |target_center_y|.
-gfx::Transform CalculateCircleTransform(const gfx::Point& drawn_center_point,
- float scale,
- float target_center_x,
- float target_center_y) {
- gfx::Transform transform;
- transform.Translate(target_center_x, target_center_y);
- transform.Scale(scale, scale);
- transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
- return transform;
-}
-
-// Calculates a Transform for a rectangle layer. The transform will be set up to
-// translate the |drawn_center_point| to the origin and then scale by the
-// |x_scale| and |y_scale| factors.
-gfx::Transform CalculateRectTransform(const gfx::Point& drawn_center_point,
- float x_scale,
- float y_scale) {
- gfx::Transform transform;
- transform.Scale(x_scale, y_scale);
- transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
- return transform;
-}
-
-} // namespace
+const float InkDropAnimation::kHiddenOpacity = 0.f;
+const float InkDropAnimation::kVisibleOpacity = 0.175f;
-namespace views {
+InkDropAnimation::InkDropAnimation()
+ : target_ink_drop_state_(InkDropState::HIDDEN), observer_(nullptr) {}
-InkDropAnimation::InkDropAnimation(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius)
- : large_size_(large_size),
- large_corner_radius_(large_corner_radius),
- small_size_(small_size),
- small_corner_radius_(small_corner_radius),
- circle_layer_delegate_(new CircleLayerDelegate(
- kInkDropColor,
- std::min(large_size_.width(), large_size_.height()) / 2)),
- rect_layer_delegate_(
- new RectangleLayerDelegate(kInkDropColor, large_size_)),
- root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
- ink_drop_state_(InkDropState::HIDDEN) {
- root_layer_->set_name("InkDropAnimation:ROOT_LAYER");
-
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- AddPaintLayer(static_cast<PaintedShape>(i));
-
- root_layer_->SetMasksToBounds(false);
- root_layer_->SetBounds(gfx::Rect(large_size_));
-
- SetStateToHidden();
-}
-
-InkDropAnimation::~InkDropAnimation() {
- // Explicitly aborting all the animations ensures all callbacks are invoked
- // while this instance still exists.
- AbortAllAnimations();
-}
-
-void InkDropAnimation::AddObserver(InkDropAnimationObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void InkDropAnimation::RemoveObserver(InkDropAnimationObserver* observer) {
- observers_.RemoveObserver(observer);
-}
+InkDropAnimation::~InkDropAnimation() {}
void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) {
+ // Does not return early if |target_ink_drop_state_| == |ink_drop_state| for
+ // two reasons.
+ // 1. The attached observers must be notified of all animations started and
+ // ended.
+ // 2. Not all state transitions is are valid, especially no-op transitions,
+ // and these should be detected by DCHECKs in AnimateStateChange().
+
// |animation_observer| will be deleted when AnimationEndedCallback() returns
// true.
+ // TODO(bruthig): Implement a safer ownership model for the
+ // |animation_observer|.
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::SetCenterPoint(const gfx::Point& center_point) {
- gfx::Transform transform;
- transform.Translate(center_point.x(), center_point.y());
- root_layer_->SetTransform(transform);
-}
+ InkDropState old_ink_drop_state = target_ink_drop_state_;
+ // Assign to |target_ink_drop_state_| before calling AnimateStateChange() so
+ // that any observers notified as a side effect of the AnimateStateChange()
+ // will get the target InkDropState when calling GetInkDropState().
+ target_ink_drop_state_ = ink_drop_state;
-std::string InkDropAnimation::ToLayerName(PaintedShape painted_shape) {
- switch (painted_shape) {
- case TOP_LEFT_CIRCLE:
- return "TOP_LEFT_CIRCLE";
- case TOP_RIGHT_CIRCLE:
- return "TOP_RIGHT_CIRCLE";
- case BOTTOM_RIGHT_CIRCLE:
- return "BOTTOM_RIGHT_CIRCLE";
- case BOTTOM_LEFT_CIRCLE:
- return "BOTTOM_LEFT_CIRCLE";
- case HORIZONTAL_RECT:
- return "HORIZONTAL_RECT";
- case VERTICAL_RECT:
- return "VERTICAL_RECT";
- case PAINTED_SHAPE_COUNT:
- NOTREACHED() << "The PAINTED_SHAPE_COUNT value should never be used.";
- return "PAINTED_SHAPE_COUNT";
+ if (old_ink_drop_state == InkDropState::HIDDEN &&
+ target_ink_drop_state_ != InkDropState::HIDDEN) {
+ GetRootLayer()->SetVisible(true);
}
- return "UNKNOWN";
-}
-
-void InkDropAnimation::AnimateToStateInternal(
- InkDropState ink_drop_state,
- ui::LayerAnimationObserver* animation_observer) {
- ink_drop_state_ = ink_drop_state;
-
- if (ink_drop_state_ == InkDropState::HIDDEN) {
- // 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;
- root_layer_->SetVisible(true);
-
- switch (ink_drop_state_) {
- case InkDropState::HIDDEN:
- // 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,
- 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,
- 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,
- 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,
- 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,
- 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,
- animation_observer);
- break;
- }
-}
-void InkDropAnimation::AnimateToTransforms(
- const InkDropTransforms transforms,
- float opacity,
- base::TimeDelta duration,
- 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);
- ui::LayerAnimationElement* root_element =
- 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) {
- ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator();
- ui::ScopedLayerAnimationSettings animation(animator);
- animation.SetPreemptionStrategy(preemption_strategy);
- ui::LayerAnimationElement* element =
- ui::LayerAnimationElement::CreateTransformElement(transforms[i],
- duration);
- ui::LayerAnimationSequence* sequence =
- new ui::LayerAnimationSequence(element);
-
- if (animation_observer)
- sequence->AddObserver(animation_observer);
-
- animator->StartAnimation(sequence);
- }
-}
-
-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) {
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- painted_layers_[i]->SetTransform(transforms[i]);
-}
-
-void InkDropAnimation::SetOpacity(float opacity) {
- root_layer_->SetOpacity(opacity);
-}
-
-void InkDropAnimation::CalculateCircleTransforms(
- const gfx::Size& size,
- InkDropTransforms* transforms_out) const {
- CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f,
- transforms_out);
-}
-
-void InkDropAnimation::CalculateRectTransforms(
- const gfx::Size& size,
- float corner_radius,
- InkDropTransforms* transforms_out) const {
- DCHECK_GE(size.width() / 2.0f, corner_radius)
- << "The circle's diameter should not be greater than the total width.";
- DCHECK_GE(size.height() / 2.0f, corner_radius)
- << "The circle's diameter should not be greater than the total height.";
-
- // The shapes are drawn such that their center points are not at the origin.
- // Thus we use the CalculateCircleTransform() and CalculateRectTransform()
- // methods to calculate the complex Transforms.
-
- const float circle_scale = std::max(
- kMinimumCircleScale,
- corner_radius / static_cast<float>(circle_layer_delegate_->radius()));
-
- const float circle_target_x_offset = size.width() / 2.0f - corner_radius;
- const float circle_target_y_offset = size.height() / 2.0f - corner_radius;
-
- (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- -circle_target_x_offset, -circle_target_y_offset);
-
- (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- circle_target_x_offset, -circle_target_y_offset);
-
- (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- circle_target_x_offset, circle_target_y_offset);
-
- (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- -circle_target_x_offset, circle_target_y_offset);
-
- const float rect_delegate_width =
- static_cast<float>(rect_layer_delegate_->size().width());
- const float rect_delegate_height =
- static_cast<float>(rect_layer_delegate_->size().height());
-
- (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform(
- ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
- std::max(kMinimumRectScale, size.width() / rect_delegate_width),
- std::max(kMinimumRectScale,
- (size.height() - 2.0f * corner_radius) / rect_delegate_height));
-
- (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform(
- ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
- std::max(kMinimumRectScale,
- (size.width() - 2.0f * corner_radius) / rect_delegate_width),
- std::max(kMinimumRectScale, size.height() / rect_delegate_height));
+ AnimateStateChange(old_ink_drop_state, target_ink_drop_state_,
+ animation_observer);
+ animation_observer->SetActive();
+ // |this| may be deleted! |animation_observer| might synchronously call
+ // AnimationEndedCallback which can delete |this|.
}
-void InkDropAnimation::GetCurrentTansforms(
- InkDropTransforms* transforms_out) const {
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform();
+void InkDropAnimation::SnapToActivated() {
+ AbortAllAnimations();
+ // |animation_observer| will be deleted when AnimationEndedCallback() returns
+ // true.
+ // TODO(bruthig): Implement a safer ownership model for the
+ // |animation_observer|.
+ ui::CallbackLayerAnimationObserver* animation_observer =
+ new ui::CallbackLayerAnimationObserver(
+ base::Bind(&InkDropAnimation::AnimationStartedCallback,
+ base::Unretained(this), InkDropState::ACTIVATED),
+ base::Bind(&InkDropAnimation::AnimationEndedCallback,
+ base::Unretained(this), InkDropState::ACTIVATED));
+ GetRootLayer()->SetVisible(true);
+ target_ink_drop_state_ = InkDropState::ACTIVATED;
+ animation_observer->SetActive();
}
-void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) {
- ui::LayerDelegate* delegate = nullptr;
- switch (painted_shape) {
- case TOP_LEFT_CIRCLE:
- case TOP_RIGHT_CIRCLE:
- case BOTTOM_RIGHT_CIRCLE:
- case BOTTOM_LEFT_CIRCLE:
- delegate = circle_layer_delegate_.get();
- break;
- case HORIZONTAL_RECT:
- case VERTICAL_RECT:
- delegate = rect_layer_delegate_.get();
- break;
- case PAINTED_SHAPE_COUNT:
- NOTREACHED() << "PAINTED_SHAPE_COUNT is not an actual shape type.";
- break;
- }
-
- ui::Layer* layer = new ui::Layer();
- root_layer_->Add(layer);
-
- layer->SetBounds(gfx::Rect(large_size_));
- layer->SetFillsBoundsOpaquely(false);
- layer->set_delegate(delegate);
- layer->SetVisible(true);
- layer->SetOpacity(1.0);
- layer->SetMasksToBounds(false);
- layer->set_name("PAINTED_SHAPE_COUNT:" + ToLayerName(painted_shape));
-
- painted_layers_[painted_shape].reset(layer);
+void InkDropAnimation::HideImmediately() {
+ AbortAllAnimations();
+ SetStateToHidden();
+ target_ink_drop_state_ = InkDropState::HIDDEN;
}
-void InkDropAnimation::AbortAllAnimations() {
- root_layer_->GetAnimator()->AbortAllAnimations();
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- painted_layers_[i]->GetAnimator()->AbortAllAnimations();
+test::InkDropAnimationTestApi* InkDropAnimation::GetTestApi() {
+ return nullptr;
}
void InkDropAnimation::AnimationStartedCallback(
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer) {
- FOR_EACH_OBSERVER(InkDropAnimationObserver, observers_,
- InkDropAnimationStarted(ink_drop_state));
+ observer_->AnimationStarted(ink_drop_state);
}
bool InkDropAnimation::AnimationEndedCallback(
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer) {
- FOR_EACH_OBSERVER(
- InkDropAnimationObserver, observers_,
- InkDropAnimationEnded(ink_drop_state,
+ if (ink_drop_state == InkDropState::HIDDEN)
+ SetStateToHidden();
+ observer_->AnimationEnded(ink_drop_state,
observer.aborted_count()
- ? InkDropAnimationObserver::PRE_EMPTED
- : InkDropAnimationObserver::SUCCESS));
+ ? InkDropAnimationEndedReason::PRE_EMPTED
+ : InkDropAnimationEndedReason::SUCCESS);
+ // |this| may be deleted!
return true;
}