Chromium Code Reviews| 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 |