bounds_animator.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
  5. #define UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
  6. #include <map>
  7. #include <memory>
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/observer_list.h"
  11. #include "ui/gfx/animation/animation_container.h"
  12. #include "ui/gfx/animation/animation_container_observer.h"
  13. #include "ui/gfx/animation/tween.h"
  14. #include "ui/gfx/geometry/rect.h"
  15. #include "ui/views/animation/animation_delegate_views.h"
  16. #include "ui/views/views_export.h"
  17. namespace gfx {
  18. class SlideAnimation;
  19. }
  20. namespace views {
  21. class BoundsAnimatorObserver;
  22. class View;
  23. // Bounds animator is responsible for animating the bounds of a view from the
  24. // the views current location and size to a target position and size. To use
  25. // BoundsAnimator invoke AnimateViewTo for the set of views you want to
  26. // animate.
  27. //
  28. // BoundsAnimator internally creates an animation for each view. If you need
  29. // a specific animation invoke SetAnimationForView after invoking AnimateViewTo.
  30. // You can attach an AnimationDelegate to the individual animation for a view
  31. // by way of SetAnimationDelegate. Additionally you can attach an observer to
  32. // the BoundsAnimator that is notified when all animations are complete.
  33. //
  34. // There is an option to apply transforms on the view instead of repainting and
  35. // relayouting each animation tick. This should be used if the size of the view
  36. // is not changing. It can be considered, but may have funny looking visuals for
  37. // other cases, depending on the content. If layers are not present, they are
  38. // created and destroyed as necessary.
  39. class VIEWS_EXPORT BoundsAnimator : public AnimationDelegateViews {
  40. public:
  41. explicit BoundsAnimator(View* view, bool use_transforms = false);
  42. BoundsAnimator(const BoundsAnimator&) = delete;
  43. BoundsAnimator& operator=(const BoundsAnimator&) = delete;
  44. ~BoundsAnimator() override;
  45. // Starts animating |view| from its current bounds to |target|. If there is
  46. // already an animation running for the view it's stopped and a new one
  47. // started. If an AnimationDelegate has been set for |view| it is removed
  48. // (after being notified that the animation was canceled).
  49. void AnimateViewTo(
  50. View* view,
  51. const gfx::Rect& target,
  52. std::unique_ptr<gfx::AnimationDelegate> delegate = nullptr);
  53. // Similar to |AnimateViewTo|, but does not reset the animation, only the
  54. // target bounds. If |view| is not being animated this is the same as
  55. // invoking |AnimateViewTo|.
  56. void SetTargetBounds(View* view, const gfx::Rect& target);
  57. // Returns the target bounds for the specified view. If |view| is not
  58. // animating its current bounds is returned.
  59. gfx::Rect GetTargetBounds(const View* view) const;
  60. // Returns the animation for the specified view. BoundsAnimator owns the
  61. // returned Animation.
  62. const gfx::SlideAnimation* GetAnimationForView(View* view);
  63. // Stops animating the specified view.
  64. void StopAnimatingView(View* view);
  65. // Sets the delegate for the animation for the specified view.
  66. void SetAnimationDelegate(View* view,
  67. std::unique_ptr<gfx::AnimationDelegate> delegate);
  68. // Returns true if BoundsAnimator is animating the bounds of |view|.
  69. bool IsAnimating(View* view) const;
  70. // Returns true if BoundsAnimator is animating any view.
  71. bool IsAnimating() const;
  72. // Finishes all animations, teleporting the views to their target bounds. Any
  73. // views marked for deletion are deleted.
  74. void Complete();
  75. // Cancels all animations, leaving the views at their current location and
  76. // size. Any views marked for deletion are deleted.
  77. void Cancel();
  78. // Overrides default animation duration.
  79. void SetAnimationDuration(base::TimeDelta duration);
  80. // Gets the currently used animation duration.
  81. base::TimeDelta GetAnimationDuration() const { return animation_duration_; }
  82. // Sets the tween type for new animations. Default is EASE_OUT.
  83. void set_tween_type(gfx::Tween::Type type) { tween_type_ = type; }
  84. void AddObserver(BoundsAnimatorObserver* observer);
  85. void RemoveObserver(BoundsAnimatorObserver* observer);
  86. gfx::AnimationContainer* container() { return container_.get(); }
  87. protected:
  88. // Creates the animation to use for animating views.
  89. virtual std::unique_ptr<gfx::SlideAnimation> CreateAnimation();
  90. private:
  91. // Tracks data about the view being animated.
  92. struct Data {
  93. Data();
  94. Data(Data&&);
  95. Data& operator=(Data&&);
  96. ~Data();
  97. // The initial bounds.
  98. gfx::Rect start_bounds;
  99. // Target bounds.
  100. gfx::Rect target_bounds;
  101. // The animation.
  102. std::unique_ptr<gfx::SlideAnimation> animation;
  103. // Delegate for the animation, may be nullptr.
  104. std::unique_ptr<gfx::AnimationDelegate> delegate;
  105. // Will only exist if |use_transforms_| is true.
  106. absl::optional<gfx::Transform> target_transform;
  107. };
  108. // Used by AnimationEndedOrCanceled.
  109. enum class AnimationEndType { kEnded, kCanceled };
  110. using ViewToDataMap = std::map<const View*, Data>;
  111. using AnimationToViewMap = std::map<const gfx::Animation*, View*>;
  112. // Removes references to |view| and its animation. Returns the data for the
  113. // caller to handle cleanup.
  114. Data RemoveFromMaps(View* view);
  115. // Does the necessary cleanup for |data|. If |send_cancel| is true and a
  116. // delegate has been installed on |data| AnimationCanceled is invoked on it.
  117. void CleanupData(bool send_cancel, Data* data);
  118. // Used when changing the animation for a view. This resets the maps for
  119. // the animation used by view and returns the current animation. Ownership
  120. // of the returned animation passes to the caller.
  121. std::unique_ptr<gfx::Animation> ResetAnimationForView(View* view);
  122. // Invoked from AnimationEnded and AnimationCanceled.
  123. void AnimationEndedOrCanceled(const gfx::Animation* animation,
  124. AnimationEndType type);
  125. // AnimationDelegateViews overrides.
  126. void AnimationProgressed(const gfx::Animation* animation) override;
  127. void AnimationEnded(const gfx::Animation* animation) override;
  128. void AnimationCanceled(const gfx::Animation* animation) override;
  129. void AnimationContainerProgressed(
  130. gfx::AnimationContainer* container) override;
  131. void AnimationContainerEmpty(gfx::AnimationContainer* container) override;
  132. void OnChildViewRemoved(views::View* observed_view,
  133. views::View* child) override;
  134. base::TimeDelta GetAnimationDurationForReporting() const override;
  135. // Parent of all views being animated.
  136. raw_ptr<View> parent_;
  137. // A more performant version of the bounds animations which updates the
  138. // transform of the views and therefore skips repainting and relayouting until
  139. // the end of the animation. Note that this may not look as good as the
  140. // regular version, depending on the content and the source and destination
  141. // bounds. In the case the provided source bounds is empty, we cannot derive a
  142. // transform so that particular view will still use a bounds animation, even
  143. // with this flag on.
  144. const bool use_transforms_;
  145. base::ObserverList<BoundsAnimatorObserver>::Unchecked observers_;
  146. // All animations we create up with the same container.
  147. scoped_refptr<gfx::AnimationContainer> container_;
  148. // Maps from view being animated to info about the view.
  149. ViewToDataMap data_;
  150. // Maps from animation to view.
  151. AnimationToViewMap animation_to_view_;
  152. // As the animations we create update (AnimationProgressed is invoked) this
  153. // is updated. When all the animations have completed for a given tick of
  154. // the timer (AnimationContainerProgressed is invoked) the parent_ is asked
  155. // to repaint these bounds.
  156. gfx::Rect repaint_bounds_;
  157. base::TimeDelta animation_duration_ = base::Milliseconds(200);
  158. gfx::Tween::Type tween_type_ = gfx::Tween::EASE_OUT;
  159. };
  160. } // namespace views
  161. #endif // UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_