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

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: Working prototype. 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 side-by-side diff with in-line comments
Download patch
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 6d4b3777b1b43d8cc64ad75eed9ebc6e50837c90..aa50c0ce18dcc1465cb4ddaab0bd934ddf4395a2 100644
--- a/ui/views/animation/ink_drop_animation.cc
+++ b/ui/views/animation/ink_drop_animation.cc
@@ -4,7 +4,11 @@
#include "ui/views/animation/ink_drop_animation.h"
+#include <algorithm>
+
#include "base/command_line.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 +16,42 @@
#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;
-
-const int kHideAnimationDurationFastMs = 100;
-const int kHideAnimationDurationSlowMs = 1000;
-
-const int kShowInkDropAnimationDurationFastMs = 250;
-const int kShowInkDropAnimationDurationSlowMs = 750;
-
-const int kShowLongPressAnimationDurationFastMs = 250;
-const int kShowLongPressAnimationDurationSlowMs = 2500;
-
-const int kRoundedRectCorners = 5;
-const int kCircleRadius = 30;
-
-const SkColor kInkDropColor = SK_ColorLTGRAY;
-const SkColor kLongPressColor = SkColorSetRGB(182, 182, 182);
+// 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;
jonross 2015/08/19 22:13:36 Testing?
bruthig 2015/08/20 20:35:35 Not 100% sure what you mean here. Assuming you are
jonross 2015/08/21 15:14:48 Ah, yeah the current spec does want the alpha blac
+
+// The opacity of the ink drop when it is visible.
+const float kVisibleOpacity = 0.12f;
+
+// The opacity of the ink drop when it is not visible.
+const float kHiddenOpacity = 0.0f;
+
+// The duration for the different InkDropState animations in milliseconds.
+const int kAnimationDurationsMs[static_cast<int>(views::InkDropState::COUNT)] =
+ {
+ 1, // InkDropState::HIDDEN
jonross 2015/08/19 22:13:36 Consider each of these being a const, then having
bruthig 2015/08/20 20:35:35 I've replaced the array with a switch statement.
+ 500, // InkDropState::ACTION_PENDING
+ 250, // InkDropState::QUICK_ACTION
+ 500, // InkDropState::SLOW_ACTION_PENDING
+ 250, // InkDropState::SLOW_ACTION
+ 250, // InkDropState::ACTIVATED
+ 250, // InkDropState::DEACTIVATED
+};
-// 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,150 +63,158 @@ bool UseFastAnimations() {
return fast;
}
+// Returns the InkDropState animation duration for the given |state|.
+base::TimeDelta GetAnimationDuration(views::InkDropState state) {
+ return base::TimeDelta::FromMilliseconds(
+ (UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) *
+ kAnimationDurationsMs[static_cast<int>(state)]);
+}
+
} // 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 {
+// A simple ui::LayerDelegate that paints a circle of the specified color and
+// radius.
+class CircleLayerDelegate : 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;
+ CircleLayerDelegate(SkColor color, int radius);
+ ~CircleLayerDelegate() override;
- // Returns true during both the appearing animation, and the hiding animation.
- bool IsAnimationActive();
+ SkColor color() const { return color_; }
jonross 2015/08/19 22:13:36 Needed?
bruthig 2015/08/20 20:35:35 Removed, but required by the base class now.
jonross 2015/08/21 15:14:48 Acknowledged.
+ void set_color(SkColor color) { color_ = color; }
- // Starts a hide animation, preempting any current animations on |layer_|.
- void StartHideAnimation();
+ int radius() const { return radius_; }
- // 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();
-
- // Hides |background_layer| (without animation) after the current animation
- // completes.
- void SetBackgroundToHide(ui::Layer* background_layer);
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ base::Closure PrepareForLayerBoundsChange() override;
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_;
- bool RequiresNotificationWhenAnimatorDestroyed() const override;
+ // The radius of the circle.
+ int radius_;
- // The ui::Layer being observed, which hide animations will be set on.
- ui::Layer* layer_;
+ DISALLOW_COPY_AND_ASSIGN(CircleLayerDelegate);
+};
- // Optional ui::Layer which will be hidden upon the completion of animating
- // |layer_|
- ui::Layer* background_layer_;
+CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
+ : color_(color), radius_(radius) {}
- // If true the hide animation will immediately be scheduled upon completion of
- // the observed animation.
- bool hide_;
+CircleLayerDelegate::~CircleLayerDelegate() {}
- DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver);
-};
+void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
+ SkPaint paint;
+ paint.setColor(color_);
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setStyle(SkPaint::kFill_Style);
-AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide)
- : layer_(layer), background_layer_(nullptr), hide_(hide) {}
+ ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
+ gfx::Canvas* canvas = recorder.canvas();
-AppearAnimationObserver::~AppearAnimationObserver() {
- StopObserving();
+ gfx::Point center_point = gfx::Point(radius_, radius_);
+ canvas->DrawCircle(center_point, radius_, paint);
}
-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::OnDelegatedFrameDamage(
+ const gfx::Rect& damage_rect_in_dip) {}
-void AppearAnimationObserver::StartHideAnimation() {
- if (background_layer_)
- background_layer_->SetVisible(false);
- if (!layer_->GetTargetVisibility())
- return;
+void CircleLayerDelegate::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {}
- 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);
+base::Closure CircleLayerDelegate::PrepareForLayerBoundsChange() {
+ return base::Closure();
}
-void AppearAnimationObserver::HideNowIfDoneOrOnceCompleted() {
- hide_ = true;
- if (attached_sequences().empty())
- StartHideAnimation();
-}
+// A simple ui::LayerDelegate that paints a rectangle of the specified color and
+// size.
+class RectangleLayerDelegate : public ui::LayerDelegate {
jonross 2015/08/19 22:13:36 Mostly duplicate code. Consider making a parent of
bruthig 2015/08/20 20:35:35 Done.
+ public:
+ RectangleLayerDelegate(SkColor color, gfx::Size size);
+ ~RectangleLayerDelegate() override;
-void AppearAnimationObserver::SetBackgroundToHide(ui::Layer* background_layer) {
- background_layer_ = background_layer;
-}
+ SkColor color() const { return color_; }
+ void set_color(SkColor color) { color_ = color; }
-void AppearAnimationObserver::OnLayerAnimationEnded(
- ui::LayerAnimationSequence* sequence) {
- if (hide_)
- StartHideAnimation();
-}
+ gfx::Size size() const { return size_; }
+
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ base::Closure PrepareForLayerBoundsChange() override;
+
+ private:
+ // The color to paint.
+ SkColor color_;
+
+ // The size of the rectangle.
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
+};
-void AppearAnimationObserver::OnLayerAnimationAborted(
- ui::LayerAnimationSequence* sequence) {
- if (hide_)
- StartHideAnimation();
+RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size)
+ : color_(color), size_(size) {}
+
+RectangleLayerDelegate::~RectangleLayerDelegate() {}
+
+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(0, 0, size_.width(), size_.height()), paint);
}
-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::OnDelegatedFrameDamage(
+ const gfx::Rect& damage_rect_in_dip) {}
+
+void RectangleLayerDelegate::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {}
+
+base::Closure RectangleLayerDelegate::PrepareForLayerBoundsChange() {
+ return base::Closure();
}
-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::InkDropTransforms::InkDropTransforms() {}
+
+InkDropAnimation::InkDropTransforms::~InkDropTransforms() {}
+
+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)),
+ top_left_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
tdanderson 2015/08/19 22:11:18 I may have already asked before (can't remember),
bruthig 2015/08/20 20:35:35 You are correct, it is not necessary to keep the l
+ top_right_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
+ bottom_right_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
+ bottom_left_circle_layer_(AddPaintLayer(circle_layer_delegate_.get())),
+ horizontal_rect_layer_(AddPaintLayer(rect_layer_delegate_.get())),
+ vertical_rect_layer_(AddPaintLayer(rect_layer_delegate_.get())),
+ ink_drop_state_(InkDropState::HIDDEN) {
+ root_layer_->SetMasksToBounds(false);
+ root_layer_->SetBounds(gfx::Rect(large_size_));
+
+ ResetTransformsToMinSize();
+
+ SetOpacity(kHiddenOpacity);
}
InkDropAnimation::~InkDropAnimation() {}
@@ -210,135 +224,242 @@ ui::Layer* InkDropAnimation::GetRootLayer() {
}
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.
+ if (ink_drop_state_ == state)
+ return;
+
+ if (ink_drop_state_ == InkDropState::HIDDEN &&
+ state != InkDropState::HIDDEN) {
+ ResetTransformsToMinSize();
+ SetOpacity(kVisibleOpacity);
+ }
+
switch (state) {
case InkDropState::HIDDEN:
- AnimateHide();
+ ink_drop_state_ = state;
tdanderson 2015/08/19 22:11:18 You should be able to factor this line out to afte
jonross 2015/08/19 22:13:36 Move these out of the switch.
bruthig 2015/08/20 20:35:35 I can't set the |ink_drop_state_| after the switc
jonross 2015/08/21 15:14:48 That sounds dangerous. However I was thinking ove
bruthig 2015/09/03 21:21:04 I've moved it to before the switch statement, adde
+ AnimateToTransforms(GetCurrentTansforms(), kHiddenOpacity,
+ GetAnimationDuration(InkDropState::HIDDEN),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
break;
case InkDropState::ACTION_PENDING:
- AnimateTapDown();
+ ink_drop_state_ = state;
+ AnimateToTransforms(CalculateCircleTransforms(large_size_),
+ kVisibleOpacity,
+ GetAnimationDuration(InkDropState::ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
case InkDropState::QUICK_ACTION:
- AnimateTapDown();
- AnimateHide();
+ ink_drop_state_ = state;
+ AnimateToTransforms(CalculateCircleTransforms(large_size_),
+ kHiddenOpacity,
+ GetAnimationDuration(InkDropState::QUICK_ACTION),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ AnimateToState(InkDropState::HIDDEN);
+ break;
+ case InkDropState::SLOW_ACTION_PENDING:
+ ink_drop_state_ = state;
+ AnimateToTransforms(
+ CalculateRectTransforms(small_size_, small_corner_radius_),
+ kVisibleOpacity,
+ GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
case InkDropState::SLOW_ACTION:
- AnimateLongPress();
+ ink_drop_state_ = state;
+ AnimateToTransforms(
+ CalculateRectTransforms(large_size_, large_corner_radius_),
+ kHiddenOpacity, GetAnimationDuration(InkDropState::SLOW_ACTION),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ AnimateToState(InkDropState::HIDDEN);
break;
case InkDropState::ACTIVATED:
- AnimateLongPress();
+ ink_drop_state_ = state;
+ AnimateToTransforms(
+ CalculateRectTransforms(small_size_, small_corner_radius_),
+ kVisibleOpacity, GetAnimationDuration(InkDropState::ACTIVATED),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
+ case InkDropState::DEACTIVATED:
+ ink_drop_state_ = state;
+ AnimateToTransforms(
+ CalculateRectTransforms(large_size_, large_corner_radius_),
+ kHiddenOpacity, GetAnimationDuration(InkDropState::DEACTIVATED),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ AnimateToState(InkDropState::HIDDEN);
+ break;
+ default:
+ DCHECK(false) << "Unhandled InkDropState=" << static_cast<int>(state);
tdanderson 2015/08/19 22:11:18 Probably use NOTREACHED instead here?
bruthig 2015/08/20 20:35:35 Removed, no longer needed.
+ AnimateToState(InkDropState::HIDDEN);
+ return;
}
}
-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);
+
+ AnimateToTransform(top_left_circle_layer_.get(), transforms.top_left_circle,
tdanderson 2015/08/19 22:11:19 Does the order of these function calls matter? (if
bruthig 2015/08/20 20:35:35 The order doesn't matter.
+ duration, preemption_strategy);
jonross 2015/08/19 22:13:36 We are starting to get duplication from the number
bruthig 2015/08/20 20:35:35 Done.
+ AnimateToTransform(top_right_circle_layer_.get(), transforms.top_right_circle,
+ duration, preemption_strategy);
+ AnimateToTransform(bottom_right_circle_layer_.get(),
+ transforms.bottom_right_circle, duration,
+ preemption_strategy);
+ AnimateToTransform(bottom_left_circle_layer_.get(),
+ transforms.bottom_left_circle, duration,
+ preemption_strategy);
+ AnimateToTransform(horizontal_rect_layer_.get(), transforms.horizontal_rect,
+ duration, preemption_strategy);
+ AnimateToTransform(vertical_rect_layer_.get(), transforms.vertical_rect,
+ duration, preemption_strategy);
}
-gfx::Rect InkDropAnimation::GetInkDropBounds() const {
- return ink_drop_bounds_;
+void InkDropAnimation::AnimateToTransform(
+ ui::Layer* layer,
+ const gfx::Transform& target_transform,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy) {
+ ui::LayerAnimator* animator = layer->GetAnimator();
+ ui::ScopedLayerAnimationSettings animation(animator);
+ animation.SetPreemptionStrategy(preemption_strategy);
+ ui::LayerAnimationElement* element =
+ ui::LayerAnimationElement::CreateTransformElement(target_transform,
+ duration);
+ ui::LayerAnimationSequence* sequence =
+ new ui::LayerAnimationSequence(element);
+ animator->StartAnimation(sequence);
}
-void InkDropAnimation::SetInkDropBounds(const gfx::Rect& bounds) {
- ink_drop_bounds_ = bounds;
- SetLayerBounds(ink_drop_layer_.get());
- SetLayerBounds(long_press_layer_.get());
+void InkDropAnimation::ResetTransformsToMinSize() {
+ // Using a size of 0x0 creates visual anomalies.
+ SetTransforms(CalculateCircleTransforms(gfx::Size(1, 1)));
jonross 2015/08/19 22:13:36 Does this do enough to warrant it being a standalo
bruthig 2015/08/20 20:35:35 The purpose of making this a standalone method is
jonross 2015/08/21 15:14:48 Acknowledged.
}
-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::SetTransforms(const InkDropTransforms& transforms) {
+ top_left_circle_layer_->SetTransform(transforms.top_left_circle);
+ top_right_circle_layer_->SetTransform(transforms.top_right_circle);
+ bottom_right_circle_layer_->SetTransform(transforms.bottom_right_circle);
+ bottom_left_circle_layer_->SetTransform(transforms.bottom_left_circle);
+ horizontal_rect_layer_->SetTransform(transforms.vertical_rect);
+ vertical_rect_layer_->SetTransform(transforms.horizontal_rect);
}
-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::SetOpacity(float opacity) {
+ root_layer_->SetOpacity(opacity);
}
-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));
+InkDropAnimation::InkDropTransforms InkDropAnimation::CalculateCircleTransforms(
+ const gfx::SizeF size) const {
+ return CalculateRectTransforms(size,
+ std::min(size.width(), size.height()) / 2.0f);
}
-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);
+InkDropAnimation::InkDropTransforms InkDropAnimation::CalculateRectTransforms(
+ const gfx::SizeF size,
+ float corner_radius) const {
+ InkDropTransforms transforms;
+
+ const float circle_radius = circle_layer_delegate_->radius();
tdanderson 2015/08/19 22:11:19 Probably already on your to-do list, but some inli
bruthig 2015/09/03 21:21:04 I've tried to address this with some refactoring a
+ const float corner_scale =
+ std::max(kMinimumCircleScale, corner_radius / circle_radius);
+ const float corner_circle_x_offset = size.width() / 2.0f - corner_radius;
+ const float corner_circle_y_offset = size.height() / 2.0f - corner_radius;
+
+ transforms.top_left_circle.Translate(circle_radius - corner_circle_x_offset,
+ circle_radius - corner_circle_y_offset);
+ transforms.top_left_circle.Scale(corner_scale, corner_scale);
+ transforms.top_left_circle.Translate(-circle_radius, -circle_radius);
+
+ transforms.top_right_circle.Translate(circle_radius + corner_circle_x_offset,
+ circle_radius - corner_circle_y_offset);
+ transforms.top_right_circle.Scale(corner_scale, corner_scale);
+ transforms.top_right_circle.Translate(-circle_radius, -circle_radius);
+
+ transforms.bottom_right_circle.Translate(
+ circle_radius + corner_circle_x_offset,
+ circle_radius + corner_circle_y_offset);
+ transforms.bottom_right_circle.Scale(corner_scale, corner_scale);
+ transforms.bottom_right_circle.Translate(-circle_radius, -circle_radius);
+
+ transforms.bottom_left_circle.Translate(
+ circle_radius - corner_circle_x_offset,
+ circle_radius + corner_circle_y_offset);
+ transforms.bottom_left_circle.Scale(corner_scale, corner_scale);
+ transforms.bottom_left_circle.Translate(-circle_radius, -circle_radius);
+
+ 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());
+
+ const float horizontal_rect_x_scale =
+ std::max(kMinimumRectScale, size.width() / rect_delegate_width);
+ const float horizontal_rect_y_scale =
+ std::max(kMinimumRectScale,
+ (size.height() - 2.0f * corner_radius) / rect_delegate_height);
+
+ transforms.horizontal_rect.Scale(horizontal_rect_x_scale,
+ horizontal_rect_y_scale);
+ transforms.horizontal_rect =
+ TransformAboutPivot(horizontal_rect_layer_->bounds().CenterPoint(),
+ transforms.horizontal_rect);
+
+ const float vertical_rect_x_scale =
+ std::max(kMinimumRectScale,
+ (size.width() - 2.0f * corner_radius) / rect_delegate_width);
+ const float vertical_rect_y_scale =
+ std::max(kMinimumRectScale, size.height() / rect_delegate_height);
+
+ transforms.vertical_rect.Scale(vertical_rect_x_scale, vertical_rect_y_scale);
+ transforms.vertical_rect = TransformAboutPivot(
+ vertical_rect_layer_->bounds().CenterPoint(), transforms.vertical_rect);
+
+ return transforms;
jonross 2015/08/19 22:13:36 Is this performing a move?
bruthig 2015/08/20 20:35:35 Doesn't exist anymore.
+}
- 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);
+InkDropAnimation::InkDropTransforms InkDropAnimation::GetCurrentTansforms()
+ const {
+ InkDropTransforms transforms;
+
+ transforms.top_left_circle = top_left_circle_layer_->GetTargetTransform();
+ transforms.top_right_circle = top_right_circle_layer_->GetTargetTransform();
+ transforms.bottom_right_circle =
+ bottom_right_circle_layer_->GetTargetTransform();
+ transforms.bottom_left_circle =
+ bottom_left_circle_layer_->GetTargetTransform();
+ transforms.horizontal_rect = horizontal_rect_layer_->GetTargetTransform();
+ transforms.vertical_rect = vertical_rect_layer_->GetTargetTransform();
+
+ return transforms;
}
-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::SetOrigin(const gfx::Point& origin) {
+ gfx::Rect bounds = root_layer_->bounds();
+ bounds.set_origin(origin);
+ root_layer_->SetBounds(bounds);
}
-void InkDropAnimation::SetupAnimationLayer(ui::Layer* layer,
- InkDropDelegate* delegate) {
+ui::Layer* InkDropAnimation::AddPaintLayer(ui::LayerDelegate* delegate) {
+ 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);
+
+ return layer;
}
} // namespace views

Powered by Google App Engine
This is Rietveld 408576698