| OLD | NEW | 
|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "ui/views/animation/ink_drop_animation_controller_impl.h" | 5 #include "ui/views/animation/ink_drop_animation_controller_impl.h" | 
| 6 | 6 | 
| 7 #include "base/command_line.h" | 7 #include "ui/views/animation/ink_drop_animation.h" | 
| 8 #include "ui/base/ui_base_switches.h" |  | 
| 9 #include "ui/compositor/layer.h" |  | 
| 10 #include "ui/compositor/layer_animation_observer.h" |  | 
| 11 #include "ui/compositor/layer_animation_sequence.h" |  | 
| 12 #include "ui/compositor/paint_recorder.h" |  | 
| 13 #include "ui/compositor/scoped_layer_animation_settings.h" |  | 
| 14 #include "ui/events/event.h" |  | 
| 15 #include "ui/gfx/canvas.h" |  | 
| 16 #include "ui/gfx/geometry/size.h" |  | 
| 17 #include "ui/views/animation/ink_drop_delegate.h" |  | 
| 18 #include "ui/views/animation/ink_drop_host.h" | 8 #include "ui/views/animation/ink_drop_host.h" | 
| 19 #include "ui/views/view.h" |  | 
| 20 |  | 
| 21 namespace { |  | 
| 22 |  | 
| 23 // Animation constants |  | 
| 24 const float kMinimumScale = 0.1f; |  | 
| 25 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f; |  | 
| 26 |  | 
| 27 const int kHideAnimationDurationFastMs = 100; |  | 
| 28 const int kHideAnimationDurationSlowMs = 1000; |  | 
| 29 |  | 
| 30 const int kShowInkDropAnimationDurationFastMs = 250; |  | 
| 31 const int kShowInkDropAnimationDurationSlowMs = 750; |  | 
| 32 |  | 
| 33 const int kShowLongPressAnimationDurationFastMs = 250; |  | 
| 34 const int kShowLongPressAnimationDurationSlowMs = 2500; |  | 
| 35 |  | 
| 36 const int kRoundedRectCorners = 5; |  | 
| 37 const int kCircleRadius = 30; |  | 
| 38 |  | 
| 39 const SkColor kInkDropColor = SK_ColorLTGRAY; |  | 
| 40 const SkColor kLongPressColor = SkColorSetRGB(182, 182, 182); |  | 
| 41 |  | 
| 42 // Checks CommandLine switches to determine if the visual feedback should be |  | 
| 43 // circular. |  | 
| 44 bool UseCircularFeedback() { |  | 
| 45   static bool circular = |  | 
| 46       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |  | 
| 47           (::switches::kMaterialDesignInkDrop)) != |  | 
| 48       ::switches::kMaterialDesignInkDropSquare; |  | 
| 49   return circular; |  | 
| 50 } |  | 
| 51 |  | 
| 52 // Checks CommandLine switches to determine if the visual feedback should have |  | 
| 53 // a fast animations speed. |  | 
| 54 bool UseFastAnimations() { |  | 
| 55   static bool fast = |  | 
| 56       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |  | 
| 57           (::switches::kMaterialDesignInkDropAnimationSpeed)) != |  | 
| 58       ::switches::kMaterialDesignInkDropAnimationSpeedSlow; |  | 
| 59   return fast; |  | 
| 60 } |  | 
| 61 |  | 
| 62 }  // namespace |  | 
| 63 | 9 | 
| 64 namespace views { | 10 namespace views { | 
| 65 | 11 | 
| 66 // An animation observer that should be set on animations of the provided |  | 
| 67 // ui::Layer. Can be used to either start a hide animation, or to trigger one |  | 
| 68 // upon completion of the current animation. |  | 
| 69 // |  | 
| 70 // Sequential animations with PreemptionStrategy::ENQUEUE_NEW_ANIMATION cannot |  | 
| 71 // be used as the observed animation can complete before user input is received |  | 
| 72 // which determines if the hide animation should run. |  | 
| 73 class AppearAnimationObserver : public ui::LayerAnimationObserver { |  | 
| 74  public: |  | 
| 75   // Will automatically start a hide animation of |layer| if |hide| is true. |  | 
| 76   // Otherwise StartHideAnimation() or HideNowIfDoneOrOnceCompleted() must be |  | 
| 77   // called. |  | 
| 78   AppearAnimationObserver(ui::Layer* layer, bool hide); |  | 
| 79   ~AppearAnimationObserver() override; |  | 
| 80 |  | 
| 81   // Returns true during both the appearing animation, and the hiding animation. |  | 
| 82   bool IsAnimationActive(); |  | 
| 83 |  | 
| 84   // Starts a hide animation, preempting any current animations on |layer_|. |  | 
| 85   void StartHideAnimation(); |  | 
| 86 |  | 
| 87   // Starts a hide animation if |layer_| is no longer animating. Otherwise the |  | 
| 88   // hide animation will be started once the current animation is completed. |  | 
| 89   void HideNowIfDoneOrOnceCompleted(); |  | 
| 90 |  | 
| 91   // Hides |background_layer| (without animation) after the current animation |  | 
| 92   // completes. |  | 
| 93   void SetBackgroundToHide(ui::Layer* background_layer); |  | 
| 94 |  | 
| 95  private: |  | 
| 96   // ui::ImplicitAnimationObserver: |  | 
| 97   void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; |  | 
| 98   void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; |  | 
| 99   void OnLayerAnimationScheduled( |  | 
| 100       ui::LayerAnimationSequence* sequence) override {} |  | 
| 101 |  | 
| 102   bool RequiresNotificationWhenAnimatorDestroyed() const override; |  | 
| 103 |  | 
| 104   // The ui::Layer being observed, which hide animations will be set on. |  | 
| 105   ui::Layer* layer_; |  | 
| 106 |  | 
| 107   // Optional ui::Layer which will be hidden upon the completion of animating |  | 
| 108   // |layer_| |  | 
| 109   ui::Layer* background_layer_; |  | 
| 110 |  | 
| 111   // If true the hide animation will immediately be scheduled upon completion of |  | 
| 112   // the observed animation. |  | 
| 113   bool hide_; |  | 
| 114 |  | 
| 115   DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver); |  | 
| 116 }; |  | 
| 117 |  | 
| 118 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide) |  | 
| 119     : layer_(layer), background_layer_(nullptr), hide_(hide) {} |  | 
| 120 |  | 
| 121 AppearAnimationObserver::~AppearAnimationObserver() { |  | 
| 122   StopObserving(); |  | 
| 123 } |  | 
| 124 |  | 
| 125 bool AppearAnimationObserver::IsAnimationActive() { |  | 
| 126   // Initial animation ongoing |  | 
| 127   if (!attached_sequences().empty()) |  | 
| 128     return true; |  | 
| 129   // Maintain the animation until told to hide. |  | 
| 130   if (!hide_) |  | 
| 131     return true; |  | 
| 132 |  | 
| 133   // Check the state of the triggered hide animation |  | 
| 134   return layer_->GetAnimator()->IsAnimatingProperty( |  | 
| 135              ui::LayerAnimationElement::OPACITY) && |  | 
| 136          layer_->GetTargetOpacity() == 0.0f && |  | 
| 137          layer_->GetAnimator()->IsAnimatingProperty( |  | 
| 138              ui::LayerAnimationElement::VISIBILITY) && |  | 
| 139          !layer_->GetTargetVisibility(); |  | 
| 140 } |  | 
| 141 |  | 
| 142 void AppearAnimationObserver::StartHideAnimation() { |  | 
| 143   if (background_layer_) |  | 
| 144     background_layer_->SetVisible(false); |  | 
| 145   if (!layer_->GetTargetVisibility()) |  | 
| 146     return; |  | 
| 147 |  | 
| 148   ui::ScopedLayerAnimationSettings animation(layer_->GetAnimator()); |  | 
| 149   animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |  | 
| 150       UseFastAnimations() ? kHideAnimationDurationFastMs |  | 
| 151                           : kHideAnimationDurationSlowMs)); |  | 
| 152   animation.SetPreemptionStrategy( |  | 
| 153       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |  | 
| 154   layer_->SetOpacity(0.0f); |  | 
| 155   layer_->SetVisible(false); |  | 
| 156 } |  | 
| 157 |  | 
| 158 void AppearAnimationObserver::HideNowIfDoneOrOnceCompleted() { |  | 
| 159   hide_ = true; |  | 
| 160   if (attached_sequences().empty()) |  | 
| 161     StartHideAnimation(); |  | 
| 162 } |  | 
| 163 |  | 
| 164 void AppearAnimationObserver::SetBackgroundToHide(ui::Layer* background_layer) { |  | 
| 165   background_layer_ = background_layer; |  | 
| 166 } |  | 
| 167 |  | 
| 168 void AppearAnimationObserver::OnLayerAnimationEnded( |  | 
| 169     ui::LayerAnimationSequence* sequence) { |  | 
| 170   if (hide_) |  | 
| 171     StartHideAnimation(); |  | 
| 172 } |  | 
| 173 |  | 
| 174 void AppearAnimationObserver::OnLayerAnimationAborted( |  | 
| 175     ui::LayerAnimationSequence* sequence) { |  | 
| 176   if (hide_) |  | 
| 177     StartHideAnimation(); |  | 
| 178 } |  | 
| 179 |  | 
| 180 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() |  | 
| 181     const { |  | 
| 182   // Ensures that OnImplicitAnimationsCompleted is called even if the observed |  | 
| 183   // animation is deleted. Allows for setting the proper state on |layer_|. |  | 
| 184   return true; |  | 
| 185 } |  | 
| 186 |  | 
| 187 InkDropAnimationControllerImpl::InkDropAnimationControllerImpl( | 12 InkDropAnimationControllerImpl::InkDropAnimationControllerImpl( | 
| 188     InkDropHost* ink_drop_host) | 13     InkDropHost* ink_drop_host) | 
| 189     : ink_drop_host_(ink_drop_host), | 14     : ink_drop_host_(ink_drop_host), | 
| 190       root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)), | 15       ink_drop_animation_(new InkDropAnimation()) { | 
| 191       ink_drop_layer_(new ui::Layer()), |  | 
| 192       appear_animation_observer_(nullptr), |  | 
| 193       long_press_layer_(new ui::Layer()), |  | 
| 194       long_press_animation_observer_(nullptr), |  | 
| 195       ink_drop_bounds_(0, 0, 0, 0) { |  | 
| 196   ink_drop_delegate_.reset(new InkDropDelegate(ink_drop_layer_.get(), |  | 
| 197                                                kInkDropColor, kCircleRadius, |  | 
| 198                                                kRoundedRectCorners)); |  | 
| 199   long_press_delegate_.reset(new InkDropDelegate(long_press_layer_.get(), |  | 
| 200                                                  kLongPressColor, kCircleRadius, |  | 
| 201                                                  kRoundedRectCorners)); |  | 
| 202 |  | 
| 203   SetupAnimationLayer(long_press_layer_.get(), long_press_delegate_.get()); |  | 
| 204   SetupAnimationLayer(ink_drop_layer_.get(), ink_drop_delegate_.get()); |  | 
| 205 |  | 
| 206   root_layer_->Add(ink_drop_layer_.get()); |  | 
| 207   root_layer_->Add(long_press_layer_.get()); |  | 
| 208 |  | 
| 209   // TODO(bruthig): Change this to only be called before the ink drop becomes | 16   // TODO(bruthig): Change this to only be called before the ink drop becomes | 
| 210   // active. See www.crbug.com/522175. | 17   // active. See www.crbug.com/522175. | 
| 211   ink_drop_host_->AddInkDropLayer(root_layer_.get()); | 18   ink_drop_host_->AddInkDropLayer(ink_drop_animation_->GetRootLayer()); | 
| 212 } | 19 } | 
| 213 | 20 | 
| 214 InkDropAnimationControllerImpl::~InkDropAnimationControllerImpl() { | 21 InkDropAnimationControllerImpl::~InkDropAnimationControllerImpl() { | 
| 215   // TODO(bruthig): Change this to be called when the ink drop becomes hidden. | 22   // TODO(bruthig): Change this to be called when the ink drop becomes hidden. | 
| 216   // See www.crbug.com/522175. | 23   // See www.crbug.com/522175. | 
| 217   ink_drop_host_->RemoveInkDropLayer(root_layer_.get()); | 24   ink_drop_host_->RemoveInkDropLayer(ink_drop_animation_->GetRootLayer()); | 
| 218 } | 25 } | 
| 219 | 26 | 
| 220 void InkDropAnimationControllerImpl::AnimateToState(InkDropState state) { | 27 void InkDropAnimationControllerImpl::AnimateToState(InkDropState state) { | 
| 221   // TODO(bruthig): Do not transition if we are already in |state| and restrict | 28   ink_drop_animation_->AnimateToState(state); | 
| 222   // any state transition that don't make sense or wouldn't look visually |  | 
| 223   // appealing. |  | 
| 224   switch (state) { |  | 
| 225     case InkDropState::HIDDEN: |  | 
| 226       AnimateHide(); |  | 
| 227       break; |  | 
| 228     case InkDropState::ACTION_PENDING: |  | 
| 229       AnimateTapDown(); |  | 
| 230       break; |  | 
| 231     case InkDropState::QUICK_ACTION: |  | 
| 232       AnimateTapDown(); |  | 
| 233       AnimateHide(); |  | 
| 234       break; |  | 
| 235     case InkDropState::SLOW_ACTION: |  | 
| 236       AnimateLongPress(); |  | 
| 237       break; |  | 
| 238     case InkDropState::ACTIVATED: |  | 
| 239       AnimateLongPress(); |  | 
| 240       break; |  | 
| 241   } |  | 
| 242 } | 29 } | 
| 243 | 30 | 
| 244 void InkDropAnimationControllerImpl::SetInkDropSize(const gfx::Size& size) { | 31 void InkDropAnimationControllerImpl::SetInkDropSize(const gfx::Size& size) { | 
| 245   SetInkDropBounds(gfx::Rect(ink_drop_bounds_.origin(), size)); | 32   ink_drop_animation_->SetInkDropSize(size); | 
| 246 } | 33 } | 
| 247 | 34 | 
| 248 gfx::Rect InkDropAnimationControllerImpl::GetInkDropBounds() const { | 35 gfx::Rect InkDropAnimationControllerImpl::GetInkDropBounds() const { | 
| 249   return ink_drop_bounds_; | 36   return ink_drop_animation_->GetInkDropBounds(); | 
| 250 } | 37 } | 
| 251 | 38 | 
| 252 void InkDropAnimationControllerImpl::SetInkDropBounds(const gfx::Rect& bounds) { | 39 void InkDropAnimationControllerImpl::SetInkDropBounds(const gfx::Rect& bounds) { | 
| 253   ink_drop_bounds_ = bounds; | 40   ink_drop_animation_->SetInkDropBounds(bounds); | 
| 254   SetLayerBounds(ink_drop_layer_.get()); |  | 
| 255   SetLayerBounds(long_press_layer_.get()); |  | 
| 256 } |  | 
| 257 |  | 
| 258 void InkDropAnimationControllerImpl::AnimateTapDown() { |  | 
| 259   if ((appear_animation_observer_ && |  | 
| 260        appear_animation_observer_->IsAnimationActive()) || |  | 
| 261       (long_press_animation_observer_ && |  | 
| 262        long_press_animation_observer_->IsAnimationActive())) { |  | 
| 263     // Only one animation at a time. Subsequent tap downs are ignored until the |  | 
| 264     // current animation completes. |  | 
| 265     return; |  | 
| 266   } |  | 
| 267   appear_animation_observer_.reset( |  | 
| 268       new AppearAnimationObserver(ink_drop_layer_.get(), false)); |  | 
| 269   AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(), |  | 
| 270               base::TimeDelta::FromMilliseconds( |  | 
| 271                   (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs |  | 
| 272                                        : kShowInkDropAnimationDurationSlowMs))); |  | 
| 273 } |  | 
| 274 |  | 
| 275 void InkDropAnimationControllerImpl::AnimateHide() { |  | 
| 276   if (appear_animation_observer_ && |  | 
| 277       appear_animation_observer_->IsAnimationActive()) { |  | 
| 278     appear_animation_observer_->HideNowIfDoneOrOnceCompleted(); |  | 
| 279   } else if (long_press_animation_observer_) { |  | 
| 280     long_press_animation_observer_->HideNowIfDoneOrOnceCompleted(); |  | 
| 281   } |  | 
| 282 } |  | 
| 283 |  | 
| 284 void InkDropAnimationControllerImpl::AnimateLongPress() { |  | 
| 285   // Only one animation at a time. Subsequent long presses are ignored until the |  | 
| 286   // current animation completes. |  | 
| 287   if (long_press_animation_observer_ && |  | 
| 288       long_press_animation_observer_->IsAnimationActive()) { |  | 
| 289     return; |  | 
| 290   } |  | 
| 291   appear_animation_observer_.reset(); |  | 
| 292   long_press_animation_observer_.reset( |  | 
| 293       new AppearAnimationObserver(long_press_layer_.get(), false)); |  | 
| 294   long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get()); |  | 
| 295   AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(), |  | 
| 296               base::TimeDelta::FromMilliseconds( |  | 
| 297                   UseFastAnimations() ? kShowLongPressAnimationDurationFastMs |  | 
| 298                                       : kShowLongPressAnimationDurationSlowMs)); |  | 
| 299 } |  | 
| 300 |  | 
| 301 void InkDropAnimationControllerImpl::AnimateShow( |  | 
| 302     ui::Layer* layer, |  | 
| 303     AppearAnimationObserver* observer, |  | 
| 304     base::TimeDelta duration) { |  | 
| 305   layer->SetVisible(true); |  | 
| 306   layer->SetOpacity(1.0f); |  | 
| 307 |  | 
| 308   float start_x = ink_drop_bounds_.x() + |  | 
| 309                   layer->bounds().width() * kMinimumScaleCenteringOffset; |  | 
| 310   float start_y = ink_drop_bounds_.y() + |  | 
| 311                   layer->bounds().height() * kMinimumScaleCenteringOffset; |  | 
| 312 |  | 
| 313   gfx::Transform initial_transform; |  | 
| 314   initial_transform.Translate(start_x, start_y); |  | 
| 315   initial_transform.Scale(kMinimumScale, kMinimumScale); |  | 
| 316   layer->SetTransform(initial_transform); |  | 
| 317 |  | 
| 318   ui::LayerAnimator* animator = layer->GetAnimator(); |  | 
| 319   ui::ScopedLayerAnimationSettings animation(animator); |  | 
| 320   animation.SetPreemptionStrategy( |  | 
| 321       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |  | 
| 322 |  | 
| 323   gfx::Transform target_transform; |  | 
| 324   target_transform.Translate(ink_drop_bounds_.x(), ink_drop_bounds_.y()); |  | 
| 325   ui::LayerAnimationElement* element = |  | 
| 326       ui::LayerAnimationElement::CreateTransformElement(target_transform, |  | 
| 327                                                         duration); |  | 
| 328   ui::LayerAnimationSequence* sequence = |  | 
| 329       new ui::LayerAnimationSequence(element); |  | 
| 330   sequence->AddObserver(observer); |  | 
| 331   animator->StartAnimation(sequence); |  | 
| 332 } |  | 
| 333 |  | 
| 334 void InkDropAnimationControllerImpl::SetLayerBounds(ui::Layer* layer) { |  | 
| 335   bool circle = UseCircularFeedback(); |  | 
| 336   gfx::Size size = ink_drop_bounds_.size(); |  | 
| 337   float circle_width = circle ? 2.0f * kCircleRadius : size.width(); |  | 
| 338   float circle_height = circle ? 2.0f * kCircleRadius : size.height(); |  | 
| 339   float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0; |  | 
| 340   float circle_y = circle ? (size.height() - circle_height) * 0.5f : 0; |  | 
| 341   layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height)); |  | 
| 342 } |  | 
| 343 |  | 
| 344 void InkDropAnimationControllerImpl::SetupAnimationLayer( |  | 
| 345     ui::Layer* layer, |  | 
| 346     InkDropDelegate* delegate) { |  | 
| 347   layer->SetFillsBoundsOpaquely(false); |  | 
| 348   layer->set_delegate(delegate); |  | 
| 349   layer->SetVisible(false); |  | 
| 350   layer->SetBounds(gfx::Rect()); |  | 
| 351   delegate->set_should_render_circle(UseCircularFeedback()); |  | 
| 352 } | 41 } | 
| 353 | 42 | 
| 354 }  // namespace views | 43 }  // namespace views | 
| OLD | NEW | 
|---|