bubble_slide_animator.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2021 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_BUBBLE_SLIDE_ANIMATOR_H_
  5. #define UI_VIEWS_ANIMATION_BUBBLE_SLIDE_ANIMATOR_H_
  6. #include "base/callback_forward.h"
  7. #include "base/callback_list.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/time/time.h"
  10. #include "ui/gfx/animation/linear_animation.h"
  11. #include "ui/gfx/animation/tween.h"
  12. #include "ui/gfx/geometry/rect.h"
  13. #include "ui/views/animation/animation_delegate_views.h"
  14. #include "ui/views/views_export.h"
  15. #include "ui/views/widget/widget.h"
  16. #include "ui/views/widget/widget_observer.h"
  17. namespace views {
  18. class BubbleDialogDelegateView;
  19. class View;
  20. // Animates a bubble between anchor views on demand. Must be used with
  21. // BubbleDialogDelegateView because of its reliance on the anchoring system.
  22. class VIEWS_EXPORT BubbleSlideAnimator : public AnimationDelegateViews,
  23. public WidgetObserver {
  24. public:
  25. // Slide complete callback is called when a slide completes and the bubble is
  26. // safely anchored to the new view.
  27. using SlideCompleteCallbackSignature = void(BubbleSlideAnimator*);
  28. using SlideCompleteCallback =
  29. base::RepeatingCallback<SlideCompleteCallbackSignature>;
  30. // Slide progressed callback is called for each animation frame,
  31. // |animation_value| will be between 0 and 1 and will scale according to the
  32. // |tween_type| parameter.
  33. using SlideProgressedCallbackSignature = void(BubbleSlideAnimator*,
  34. double animation_value);
  35. using SlideProgressedCallback =
  36. base::RepeatingCallback<SlideProgressedCallbackSignature>;
  37. // Constructs a new BubbleSlideAnimator associated with the specified
  38. // |bubble_view|, which must already have a widget. If the bubble's widget is
  39. // destroyed, any animations will be canceled and this animator will no longer
  40. // be able to be used.
  41. explicit BubbleSlideAnimator(BubbleDialogDelegateView* bubble_view);
  42. BubbleSlideAnimator(const BubbleSlideAnimator&) = delete;
  43. BubbleSlideAnimator& operator=(const BubbleSlideAnimator&) = delete;
  44. ~BubbleSlideAnimator() override;
  45. bool is_animating() const { return slide_animation_.is_animating(); }
  46. // Sets the animation duration (a default is used if not set).
  47. void SetSlideDuration(base::TimeDelta duration);
  48. View* desired_anchor_view() { return desired_anchor_view_; }
  49. const View* desired_anchor_view() const { return desired_anchor_view_; }
  50. gfx::Tween::Type tween_type() const { return tween_type_; }
  51. void set_tween_type(gfx::Tween::Type tween_type) { tween_type_ = tween_type; }
  52. // Animates to a new anchor view.
  53. void AnimateToAnchorView(View* desired_anchor_view);
  54. // Ends any ongoing animation and immediately snaps the bubble to its target
  55. // bounds.
  56. void SnapToAnchorView(View* desired_anchor_view);
  57. // Retargets the current animation or snaps the bubble to its correct size
  58. // and position if there is no current animation.
  59. //
  60. // Call if the bubble contents change size in a way that would require the
  61. // bubble to be resized/repositioned. If you would like a new animation to
  62. // always play to the new bounds, call AnimateToAnchorView() instead.
  63. //
  64. // Note: This method expects the bubble to have a valid anchor view.
  65. void UpdateTargetBounds();
  66. // Stops the animation without snapping the widget to a particular anchor
  67. // view.
  68. void StopAnimation();
  69. // Adds a listener for slide progressed events.
  70. base::CallbackListSubscription AddSlideProgressedCallback(
  71. SlideProgressedCallback callback);
  72. // Adds a listener for slide complete events.
  73. base::CallbackListSubscription AddSlideCompleteCallback(
  74. SlideCompleteCallback callback);
  75. private:
  76. // AnimationDelegateViews:
  77. void AnimationProgressed(const gfx::Animation* animation) override;
  78. void AnimationEnded(const gfx::Animation* animation) override;
  79. void AnimationCanceled(const gfx::Animation* animation) override;
  80. // WidgetObserver:
  81. void OnWidgetDestroying(Widget* widget) override;
  82. // Determines where to animate the bubble to during an animation.
  83. gfx::Rect CalculateTargetBounds(const View* desired_anchor_view) const;
  84. const raw_ptr<BubbleDialogDelegateView> bubble_delegate_;
  85. base::ScopedObservation<Widget, WidgetObserver> widget_observation_{this};
  86. gfx::LinearAnimation slide_animation_{this};
  87. // The desired anchor view, which is valid during a slide animation. When not
  88. // animating, this value is null.
  89. raw_ptr<View> desired_anchor_view_ = nullptr;
  90. // The tween type to use when animating. The default should be aesthetically
  91. // pleasing for most applications.
  92. gfx::Tween::Type tween_type_ = gfx::Tween::FAST_OUT_SLOW_IN;
  93. gfx::Rect starting_bubble_bounds_;
  94. gfx::Rect target_bubble_bounds_;
  95. base::RepeatingCallbackList<SlideProgressedCallbackSignature>
  96. slide_progressed_callbacks_;
  97. base::RepeatingCallbackList<SlideCompleteCallbackSignature>
  98. slide_complete_callbacks_;
  99. };
  100. } // namespace views
  101. #endif // UI_VIEWS_ANIMATION_BUBBLE_SLIDE_ANIMATOR_H_