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

Unified 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: Addressed comments from patch set 10. Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/animation/ink_drop_animation.h ('k') | ui/views/animation/ink_drop_animation_controller.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 b02fcd6cbf65fa13709c441b3127cae1c19c0f2c..232ef6a92f85fef02b4b3e7714802a943a7bdcbd 100644
--- a/ui/views/animation/ink_drop_animation.cc
+++ b/ui/views/animation/ink_drop_animation.cc
@@ -4,7 +4,12 @@
#include "ui/views/animation/ink_drop_animation.h"
+#include <algorithm>
+
#include "base/command_line.h"
+#include "base/logging.h"
+#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/layer.h"
#include "ui/compositor/layer_animation_observer.h"
@@ -12,40 +17,39 @@
#include "ui/compositor/paint_recorder.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/views/animation/ink_drop_delegate.h"
+#include "ui/gfx/transform_util.h"
#include "ui/views/view.h"
namespace {
-// Animation constants
-const float kMinimumScale = 0.1f;
-const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f;
+// The minimum scale factor to use when scaling rectangle layers. Smaller values
+// were causing visual anomalies.
+const float kMinimumRectScale = 0.0001f;
-const int kHideAnimationDurationFastMs = 100;
-const int kHideAnimationDurationSlowMs = 1000;
+// The minimum scale factor to use when scaling circle layers. Smaller values
+// were causing visual anomalies.
+const float kMinimumCircleScale = 0.001f;
-const int kShowInkDropAnimationDurationFastMs = 250;
-const int kShowInkDropAnimationDurationSlowMs = 750;
+// The ink drop color.
+const SkColor kInkDropColor = SK_ColorBLACK;
-const int kShowLongPressAnimationDurationFastMs = 250;
-const int kShowLongPressAnimationDurationSlowMs = 2500;
+// The opacity of the ink drop when it is visible.
+const float kVisibleOpacity = 0.12f;
-const int kRoundedRectCorners = 5;
-const int kCircleRadius = 30;
+// The opacity of the ink drop when it is not visible.
+const float kHiddenOpacity = 0.0f;
-const SkColor kInkDropColor = SK_ColorLTGRAY;
-const SkColor kLongPressColor = SkColorSetRGB(182, 182, 182);
+// 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 = 250;
+const int kDeactivatedStateAnimationDurationMs = 250;
-// Checks CommandLine switches to determine if the visual feedback should be
-// circular.
-bool UseCircularFeedback() {
- static bool circular =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- (::switches::kMaterialDesignInkDrop)) !=
- ::switches::kMaterialDesignInkDropSquare;
- return circular;
-}
+// A multiplicative factor used to slow down InkDropState animations.
+const int kSlowAnimationDurationFactor = 3;
// Checks CommandLine switches to determine if the visual feedback should have
// a fast animations speed.
@@ -57,284 +61,416 @@ 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
namespace views {
-// An animation observer that should be set on animations of the provided
-// ui::Layer. Can be used to either start a hide animation, or to trigger one
-// upon completion of the current animation.
-//
-// Sequential animations with PreemptionStrategy::ENQUEUE_NEW_ANIMATION cannot
-// be used as the observed animation can complete before user input is received
-// which determines if the hide animation should run.
-class AppearAnimationObserver : public ui::LayerAnimationObserver {
+// Base ui::LayerDelegate stub that can be extended to paint shapes of a
+// specific color.
+class BasePaintedLayerDelegate : public ui::LayerDelegate {
public:
- // Will automatically start a hide animation of |layer| if |hide| is true.
- // Otherwise StartHideAnimation() or HideNowIfDoneOrOnceCompleted() must be
- // called.
- AppearAnimationObserver(ui::Layer* layer, bool hide);
- ~AppearAnimationObserver() override;
-
- // Returns true during both the appearing animation, and the hiding animation.
- bool IsAnimationActive();
+ ~BasePaintedLayerDelegate() override;
- // Starts a hide animation, preempting any current animations on |layer_|.
- void StartHideAnimation();
+ SkColor color() const { return color_; }
- // Starts a hide animation if |layer_| is no longer animating. Otherwise the
- // hide animation will be started once the current animation is completed.
- void HideNowIfDoneOrOnceCompleted();
+ // ui::LayerDelegate:
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ base::Closure PrepareForLayerBoundsChange() override;
- // Hides |background_layer| (without animation) after the current animation
- // completes.
- void SetBackgroundToHide(ui::Layer* background_layer);
+ protected:
+ explicit BasePaintedLayerDelegate(SkColor color);
private:
- // ui::ImplicitAnimationObserver:
- void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
- void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
- void OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* sequence) override {}
+ // The color to paint.
+ SkColor color_;
+
+ DISALLOW_COPY_AND_ASSIGN(BasePaintedLayerDelegate);
+};
- bool RequiresNotificationWhenAnimatorDestroyed() const override;
+BasePaintedLayerDelegate::BasePaintedLayerDelegate(SkColor color)
+ : color_(color) {}
- // The ui::Layer being observed, which hide animations will be set on.
- ui::Layer* layer_;
+BasePaintedLayerDelegate::~BasePaintedLayerDelegate() {}
- // Optional ui::Layer which will be hidden upon the completion of animating
- // |layer_|
- ui::Layer* background_layer_;
+void BasePaintedLayerDelegate::OnDelegatedFrameDamage(
+ const gfx::Rect& damage_rect_in_dip) {}
- // If true the hide animation will immediately be scheduled upon completion of
- // the observed animation.
- bool hide_;
+void BasePaintedLayerDelegate::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {}
+
+base::Closure BasePaintedLayerDelegate::PrepareForLayerBoundsChange() {
+ return base::Closure();
+}
+
+// A BasePaintedLayerDelegate that paints a circle of a specified color and
+// radius.
+class CircleLayerDelegate : public BasePaintedLayerDelegate {
+ public:
+ CircleLayerDelegate(SkColor color, int radius);
+ ~CircleLayerDelegate() override;
- DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver);
+ int radius() const { return radius_; }
+
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+
+ private:
+ // The radius of the circle.
+ int radius_;
+
+ DISALLOW_COPY_AND_ASSIGN(CircleLayerDelegate);
};
-AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide)
- : layer_(layer), background_layer_(nullptr), hide_(hide) {}
+CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
+ : BasePaintedLayerDelegate(color), radius_(radius) {}
-AppearAnimationObserver::~AppearAnimationObserver() {
- StopObserving();
-}
+CircleLayerDelegate::~CircleLayerDelegate() {}
-bool AppearAnimationObserver::IsAnimationActive() {
- // Initial animation ongoing
- if (!attached_sequences().empty())
- return true;
- // Maintain the animation until told to hide.
- if (!hide_)
- return true;
-
- // Check the state of the triggered hide animation
- return layer_->GetAnimator()->IsAnimatingProperty(
- ui::LayerAnimationElement::OPACITY) &&
- layer_->GetTargetOpacity() == 0.0f &&
- layer_->GetAnimator()->IsAnimatingProperty(
- ui::LayerAnimationElement::VISIBILITY) &&
- !layer_->GetTargetVisibility();
-}
+void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
+ SkPaint paint;
+ paint.setColor(color());
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setStyle(SkPaint::kFill_Style);
-void AppearAnimationObserver::StartHideAnimation() {
- if (background_layer_)
- background_layer_->SetVisible(false);
- if (!layer_->GetTargetVisibility())
- return;
+ ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
+ gfx::Canvas* canvas = recorder.canvas();
- ui::ScopedLayerAnimationSettings animation(layer_->GetAnimator());
- animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
- UseFastAnimations() ? kHideAnimationDurationFastMs
- : kHideAnimationDurationSlowMs));
- animation.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- layer_->SetOpacity(0.0f);
- layer_->SetVisible(false);
+ gfx::Point center_point = gfx::Point(radius_, radius_);
+ canvas->DrawCircle(center_point, radius_, paint);
}
-void AppearAnimationObserver::HideNowIfDoneOrOnceCompleted() {
- hide_ = true;
- if (attached_sequences().empty())
- StartHideAnimation();
-}
+// A BasePaintedLayerDelegate that paints a rectangle of a specified color and
+// size.
+class RectangleLayerDelegate : public BasePaintedLayerDelegate {
+ public:
+ RectangleLayerDelegate(SkColor color, gfx::Size size);
+ ~RectangleLayerDelegate() override;
-void AppearAnimationObserver::SetBackgroundToHide(ui::Layer* background_layer) {
- background_layer_ = background_layer;
-}
+ const gfx::Size& size() const { return size_; }
-void AppearAnimationObserver::OnLayerAnimationEnded(
- ui::LayerAnimationSequence* sequence) {
- if (hide_)
- StartHideAnimation();
-}
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
-void AppearAnimationObserver::OnLayerAnimationAborted(
- ui::LayerAnimationSequence* sequence) {
- if (hide_)
- StartHideAnimation();
-}
+ private:
+ // The size of the rectangle.
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
+};
+
+RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size)
+ : BasePaintedLayerDelegate(color), size_(size) {}
+
+RectangleLayerDelegate::~RectangleLayerDelegate() {}
-bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed()
- const {
- // Ensures that OnImplicitAnimationsCompleted is called even if the observed
- // animation is deleted. Allows for setting the proper state on |layer_|.
- return true;
+void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
+ SkPaint paint;
+ paint.setColor(color());
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ ui::PaintRecorder recorder(context, size_);
+ gfx::Canvas* canvas = recorder.canvas();
+ canvas->DrawRect(gfx::Rect(size_), paint);
}
-InkDropAnimation::InkDropAnimation()
- : root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
- ink_drop_layer_(new ui::Layer()),
- appear_animation_observer_(nullptr),
- long_press_layer_(new ui::Layer()),
- long_press_animation_observer_(nullptr),
- ink_drop_bounds_(0, 0, 0, 0) {
- ink_drop_delegate_.reset(new InkDropDelegate(ink_drop_layer_.get(),
- kInkDropColor, kCircleRadius,
- kRoundedRectCorners));
- long_press_delegate_.reset(new InkDropDelegate(long_press_layer_.get(),
- kLongPressColor, kCircleRadius,
- kRoundedRectCorners));
-
- SetupAnimationLayer(long_press_layer_.get(), long_press_delegate_.get());
- SetupAnimationLayer(ink_drop_layer_.get(), ink_drop_delegate_.get());
-
- root_layer_->Add(ink_drop_layer_.get());
- root_layer_->Add(long_press_layer_.get());
+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) {
+ 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_));
+
+ ResetTransformsToMinSize();
+
+ SetOpacity(kHiddenOpacity);
}
InkDropAnimation::~InkDropAnimation() {}
-void InkDropAnimation::AnimateToState(InkDropState state) {
- // TODO(bruthig): Do not transition if we are already in |state| and restrict
- // any state transition that don't make sense or wouldn't look visually
- // appealing.
- switch (state) {
+void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) {
+ if (ink_drop_state_ == ink_drop_state)
+ return;
+
+ if (ink_drop_state_ == InkDropState::HIDDEN) {
+ ResetTransformsToMinSize();
+ SetOpacity(kVisibleOpacity);
+ }
+
+ 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;
+
+ switch (ink_drop_state_) {
case InkDropState::HIDDEN:
- AnimateHide();
+ GetCurrentTansforms(&transforms);
+ AnimateToTransforms(transforms, kHiddenOpacity,
+ GetAnimationDuration(InkDropState::HIDDEN),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
break;
case InkDropState::ACTION_PENDING:
- AnimateTapDown();
+ CalculateCircleTransforms(large_size_, &transforms);
+ AnimateToTransforms(transforms, kVisibleOpacity,
+ GetAnimationDuration(InkDropState::ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
case InkDropState::QUICK_ACTION:
- AnimateTapDown();
- AnimateHide();
+ CalculateCircleTransforms(large_size_, &transforms);
+ AnimateToTransforms(transforms, kHiddenOpacity,
+ GetAnimationDuration(InkDropState::QUICK_ACTION),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ AnimateToState(InkDropState::HIDDEN);
+ 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);
break;
case InkDropState::SLOW_ACTION:
- AnimateLongPress();
+ CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
+ AnimateToTransforms(transforms, kHiddenOpacity,
+ GetAnimationDuration(InkDropState::SLOW_ACTION),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ AnimateToState(InkDropState::HIDDEN);
break;
case InkDropState::ACTIVATED:
- AnimateLongPress();
+ CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
+ AnimateToTransforms(transforms, kVisibleOpacity,
+ GetAnimationDuration(InkDropState::ACTIVATED),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ 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);
break;
}
}
-void InkDropAnimation::SetInkDropSize(const gfx::Size& size) {
- SetInkDropBounds(gfx::Rect(ink_drop_bounds_.origin(), size));
+void InkDropAnimation::AnimateToTransforms(
+ const InkDropTransforms transforms,
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy) {
+ 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);
+ 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);
+ animator->StartAnimation(sequence);
+ }
}
-gfx::Rect InkDropAnimation::GetInkDropBounds() const {
- return ink_drop_bounds_;
+void InkDropAnimation::ResetTransformsToMinSize() {
+ InkDropTransforms transforms;
+ // Using a size of 0x0 creates visual anomalies.
+ CalculateCircleTransforms(gfx::Size(1, 1), &transforms);
+ SetTransforms(transforms);
}
-void InkDropAnimation::SetInkDropBounds(const gfx::Rect& bounds) {
- ink_drop_bounds_ = bounds;
- SetLayerBounds(ink_drop_layer_.get());
- SetLayerBounds(long_press_layer_.get());
+void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) {
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
+ painted_layers_[i]->SetTransform(transforms[i]);
}
-void InkDropAnimation::AnimateTapDown() {
- if ((appear_animation_observer_ &&
- appear_animation_observer_->IsAnimationActive()) ||
- (long_press_animation_observer_ &&
- long_press_animation_observer_->IsAnimationActive())) {
- // Only one animation at a time. Subsequent tap downs are ignored until the
- // current animation completes.
- return;
- }
- appear_animation_observer_.reset(
- new AppearAnimationObserver(ink_drop_layer_.get(), false));
- AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(),
- base::TimeDelta::FromMilliseconds(
- (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs
- : kShowInkDropAnimationDurationSlowMs)));
+void InkDropAnimation::SetOpacity(float opacity) {
+ root_layer_->SetOpacity(opacity);
}
-void InkDropAnimation::AnimateHide() {
- if (appear_animation_observer_ &&
- appear_animation_observer_->IsAnimationActive()) {
- appear_animation_observer_->HideNowIfDoneOrOnceCompleted();
- } else if (long_press_animation_observer_) {
- long_press_animation_observer_->HideNowIfDoneOrOnceCompleted();
- }
+void InkDropAnimation::CalculateCircleTransforms(
+ const gfx::SizeF& size,
+ InkDropTransforms* transforms_out) const {
+ CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f,
+ transforms_out);
}
-void InkDropAnimation::AnimateLongPress() {
- // Only one animation at a time. Subsequent long presses are ignored until the
- // current animation completes.
- if (long_press_animation_observer_ &&
- long_press_animation_observer_->IsAnimationActive()) {
- return;
- }
- appear_animation_observer_.reset();
- long_press_animation_observer_.reset(
- new AppearAnimationObserver(long_press_layer_.get(), false));
- long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get());
- AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(),
- base::TimeDelta::FromMilliseconds(
- UseFastAnimations() ? kShowLongPressAnimationDurationFastMs
- : kShowLongPressAnimationDurationSlowMs));
+void InkDropAnimation::CalculateRectTransforms(
+ const gfx::SizeF& 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(
+ painted_layers_[TOP_LEFT_CIRCLE]->bounds().CenterPoint(), circle_scale,
+ -circle_target_x_offset, -circle_target_y_offset);
+
+ (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform(
+ painted_layers_[TOP_RIGHT_CIRCLE]->bounds().CenterPoint(), circle_scale,
+ circle_target_x_offset, -circle_target_y_offset);
+
+ (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform(
+ painted_layers_[BOTTOM_RIGHT_CIRCLE]->bounds().CenterPoint(),
+ circle_scale, circle_target_x_offset, circle_target_y_offset);
+
+ (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform(
+ painted_layers_[BOTTOM_LEFT_CIRCLE]->bounds().CenterPoint(), 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(
+ painted_layers_[HORIZONTAL_RECT]->bounds().CenterPoint(),
+ 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(
+ painted_layers_[VERTICAL_RECT]->bounds().CenterPoint(),
+ std::max(kMinimumRectScale,
+ (size.width() - 2.0f * corner_radius) / rect_delegate_width),
+ std::max(kMinimumRectScale, size.height() / rect_delegate_height));
}
-void InkDropAnimation::AnimateShow(ui::Layer* layer,
- AppearAnimationObserver* observer,
- base::TimeDelta duration) {
- layer->SetVisible(true);
- layer->SetOpacity(1.0f);
-
- float start_x = ink_drop_bounds_.x() +
- layer->bounds().width() * kMinimumScaleCenteringOffset;
- float start_y = ink_drop_bounds_.y() +
- layer->bounds().height() * kMinimumScaleCenteringOffset;
-
- gfx::Transform initial_transform;
- initial_transform.Translate(start_x, start_y);
- initial_transform.Scale(kMinimumScale, kMinimumScale);
- layer->SetTransform(initial_transform);
-
- ui::LayerAnimator* animator = layer->GetAnimator();
- ui::ScopedLayerAnimationSettings animation(animator);
- animation.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-
- gfx::Transform target_transform;
- target_transform.Translate(ink_drop_bounds_.x(), ink_drop_bounds_.y());
- ui::LayerAnimationElement* element =
- ui::LayerAnimationElement::CreateTransformElement(target_transform,
- duration);
- ui::LayerAnimationSequence* sequence =
- new ui::LayerAnimationSequence(element);
- sequence->AddObserver(observer);
- animator->StartAnimation(sequence);
+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::SetLayerBounds(ui::Layer* layer) {
- bool circle = UseCircularFeedback();
- gfx::Size size = ink_drop_bounds_.size();
- float circle_width = circle ? 2.0f * kCircleRadius : size.width();
- float circle_height = circle ? 2.0f * kCircleRadius : size.height();
- float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0;
- float circle_y = circle ? (size.height() - circle_height) * 0.5f : 0;
- layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height));
+void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) {
+ gfx::Transform transform;
+ transform.Translate(center_point.x(), center_point.y());
+ root_layer_->SetTransform(transform);
}
-void InkDropAnimation::SetupAnimationLayer(ui::Layer* layer,
- InkDropDelegate* delegate) {
+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(false);
- layer->SetBounds(gfx::Rect());
- delegate->set_should_render_circle(UseCircularFeedback());
+ layer->SetVisible(true);
+ layer->SetOpacity(1.0);
+ layer->SetMasksToBounds(false);
+
+ painted_layers_[painted_shape].reset(layer);
}
} // namespace views
« no previous file with comments | « ui/views/animation/ink_drop_animation.h ('k') | ui/views/animation/ink_drop_animation_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698