ink_drop_impl.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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
  3. // found in the LICENSE file.
  4. #ifndef UI_VIEWS_ANIMATION_INK_DROP_IMPL_H_
  5. #define UI_VIEWS_ANIMATION_INK_DROP_IMPL_H_
  6. #include <memory>
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/time/time.h"
  9. #include "third_party/abseil-cpp/absl/types/optional.h"
  10. #include "ui/gfx/geometry/rect.h"
  11. #include "ui/gfx/geometry/size.h"
  12. #include "ui/views/animation/ink_drop.h"
  13. #include "ui/views/animation/ink_drop_highlight_observer.h"
  14. #include "ui/views/animation/ink_drop_ripple_observer.h"
  15. #include "ui/views/views_export.h"
  16. namespace views {
  17. namespace test {
  18. class InkDropImplTestApi;
  19. } // namespace test
  20. class InkDropRipple;
  21. class InkDropHost;
  22. class InkDropHighlight;
  23. // A functional implementation of an InkDrop.
  24. class VIEWS_EXPORT InkDropImpl : public InkDrop,
  25. public InkDropRippleObserver,
  26. public InkDropHighlightObserver {
  27. public:
  28. // The different auto highlight behaviors.
  29. enum class AutoHighlightMode {
  30. // No auto-highlighting is done. The highlight will only be shown/hidden as
  31. // per the hover/focus settings.
  32. NONE,
  33. // The highlight will be hidden when a ripple becomes visible. After the
  34. // ripple is hidden the highlight will be made visible again if the
  35. // hover/focus settings deem it should be.
  36. HIDE_ON_RIPPLE,
  37. // The highlight is made visible when the ripple becomes visible. After the
  38. // ripple is hidden the highlight will be hidden again if the hover/focus
  39. // settings deem it should be.
  40. SHOW_ON_RIPPLE,
  41. };
  42. // Constructs an ink drop that will attach the ink drop to the given
  43. // |ink_drop_host|. |host_size| is used to set the size of the ink drop layer.
  44. //
  45. // By default the highlight will be made visible while |this| is hovered but
  46. // not focused.
  47. InkDropImpl(InkDropHost* ink_drop_host,
  48. const gfx::Size& host_size,
  49. AutoHighlightMode auto_highlight_mode);
  50. InkDropImpl(const InkDropImpl&) = delete;
  51. InkDropImpl& operator=(const InkDropImpl&) = delete;
  52. ~InkDropImpl() override;
  53. const absl::optional<base::TimeDelta>& hover_highlight_fade_duration() const {
  54. return hover_highlight_fade_duration_;
  55. }
  56. // InkDrop:
  57. void HostSizeChanged(const gfx::Size& new_size) override;
  58. void HostTransformChanged(const gfx::Transform& new_transform) override;
  59. InkDropState GetTargetInkDropState() const override;
  60. void AnimateToState(InkDropState ink_drop_state) override;
  61. void SetHoverHighlightFadeDuration(base::TimeDelta duration) override;
  62. void UseDefaultHoverHighlightFadeDuration() override;
  63. void SnapToActivated() override;
  64. void SnapToHidden() override;
  65. void SetHovered(bool is_hovered) override;
  66. void SetFocused(bool is_focused) override;
  67. bool IsHighlightFadingInOrVisible() const override;
  68. void SetShowHighlightOnHover(bool show_highlight_on_hover) override;
  69. void SetShowHighlightOnFocus(bool show_highlight_on_focus) override;
  70. private:
  71. friend class InkDropImplTest;
  72. friend class test::InkDropImplTestApi;
  73. // Forward declaration for use by the HighlightState class definition.
  74. class HighlightStateFactory;
  75. // Base HighlightState defines functions to handle all state changes that may
  76. // affect the highlight state.
  77. //
  78. // Subclasses are expected to handle state changes and transition the
  79. // InkDropImpl::highlight_state_ to new states as desired via the
  80. // InkDropImpl::SetHighlightState() method.
  81. //
  82. // New states should be created via the HighlightStateFactory and not
  83. // directly. This makes it possible for highlighting strategies to extend the
  84. // behavior of existing states and re-use existing state behavior.
  85. //
  86. // Subclasses are also expected to trigger the appropriate highlight
  87. // animations (e.g. fade in/out) via GetInkDrop()->SetHighlight(). Typically
  88. // this is done in the Enter()/Exit() functions. Triggering animations
  89. // anywhere else may be a sign that a new state should exist.
  90. class HighlightState {
  91. public:
  92. HighlightState(const HighlightState&) = delete;
  93. HighlightState& operator=(const HighlightState&) = delete;
  94. virtual ~HighlightState() = default;
  95. // Called when |this| becomes the current state. Allows subclasses to
  96. // perform any work that should not be done in the constructor. It is ok for
  97. // subclass implementations to trigger state changes from within Enter().
  98. virtual void Enter() {}
  99. // Called just before |this| is removed as the current state. Allows
  100. // subclasses to perform any work that should not be done in the destructor
  101. // but is required before exiting |this| state (e.g. releasing resources).
  102. //
  103. // Subclass implementations should NOT do any work that may trigger another
  104. // state change since a state change is already in progress. They must also
  105. // avoid triggering any animations since Exit() will be called during
  106. // InkDropImpl destruction.
  107. virtual void Exit() {}
  108. // Input state change handlers.
  109. // Called when the value of InkDropImpl::show_highlight_on_hover_ changes.
  110. virtual void ShowOnHoverChanged() = 0;
  111. // Called when the value of InkDropImpl::is_hovered_ changes.
  112. virtual void OnHoverChanged() = 0;
  113. // Called when the value of InkDropImpl::show_highlight_on_focus_ changes.
  114. virtual void ShowOnFocusChanged() = 0;
  115. // Called when the value of InkDropImpl::is_focused_ changes.
  116. virtual void OnFocusChanged() = 0;
  117. // Called when an ink drop ripple animation is started.
  118. virtual void AnimationStarted(InkDropState ink_drop_state) = 0;
  119. // Called when an ink drop ripple animation has ended.
  120. virtual void AnimationEnded(InkDropState ink_drop_state,
  121. InkDropAnimationEndedReason reason) = 0;
  122. protected:
  123. explicit HighlightState(HighlightStateFactory* state_factory)
  124. : state_factory_(state_factory) {}
  125. HighlightStateFactory* state_factory() { return state_factory_; }
  126. // Returns the ink drop that has |this| as the current state.
  127. InkDropImpl* GetInkDrop();
  128. private:
  129. // Used by |this| to create the new states to transition to.
  130. const raw_ptr<HighlightStateFactory> state_factory_;
  131. };
  132. // Creates the different HighlightStates instances. A factory is used to make
  133. // it easier for states to extend and re-use existing state logic.
  134. class HighlightStateFactory {
  135. public:
  136. HighlightStateFactory(AutoHighlightMode highlight_mode,
  137. InkDropImpl* ink_drop);
  138. HighlightStateFactory(const HighlightStateFactory&) = delete;
  139. HighlightStateFactory& operator=(const HighlightStateFactory&) = delete;
  140. // Returns the initial state.
  141. std::unique_ptr<HighlightState> CreateStartState();
  142. std::unique_ptr<HighlightState> CreateHiddenState(
  143. base::TimeDelta animation_duration);
  144. std::unique_ptr<HighlightState> CreateVisibleState(
  145. base::TimeDelta animation_duration);
  146. InkDropImpl* ink_drop() { return ink_drop_; }
  147. private:
  148. // Defines which concrete state types to create.
  149. AutoHighlightMode highlight_mode_;
  150. // The ink drop to invoke highlight changes on.
  151. raw_ptr<InkDropImpl> ink_drop_;
  152. };
  153. class DestroyingHighlightState;
  154. // AutoHighlightMode::NONE
  155. class NoAutoHighlightHiddenState;
  156. class NoAutoHighlightVisibleState;
  157. // AutoHighlightMode::HIDE_ON_RIPPLE
  158. class HideHighlightOnRippleHiddenState;
  159. class HideHighlightOnRippleVisibleState;
  160. // AutoHighlightMode::SHOW_ON_RIPPLE states
  161. class ShowHighlightOnRippleHiddenState;
  162. class ShowHighlightOnRippleVisibleState;
  163. // Destroys |ink_drop_ripple_| if it's targeted to the HIDDEN state.
  164. void DestroyHiddenTargetedAnimations();
  165. // Creates a new InkDropRipple and sets it to |ink_drop_ripple_|. If
  166. // |ink_drop_ripple_| wasn't null then it will be destroyed using
  167. // DestroyInkDropRipple().
  168. void CreateInkDropRipple();
  169. // Destroys the current |ink_drop_ripple_|.
  170. void DestroyInkDropRipple();
  171. // Creates a new InkDropHighlight and assigns it to |highlight_|. If
  172. // |highlight_| wasn't null then it will be destroyed using
  173. // DestroyInkDropHighlight().
  174. void CreateInkDropHighlight();
  175. // Destroys the current |highlight_|.
  176. void DestroyInkDropHighlight();
  177. // Adds the |root_layer_| to the |ink_drop_host_| if it hasn't already been
  178. // added.
  179. void AddRootLayerToHostIfNeeded();
  180. // Removes the |root_layer_| from the |ink_drop_host_| if no ink drop ripple
  181. // or highlight is active.
  182. void RemoveRootLayerFromHostIfNeeded();
  183. // views::InkDropRippleObserver:
  184. void AnimationStarted(InkDropState ink_drop_state) override;
  185. void AnimationEnded(InkDropState ink_drop_state,
  186. InkDropAnimationEndedReason reason) override;
  187. // views::InkDropHighlightObserver:
  188. void AnimationStarted(
  189. InkDropHighlight::AnimationType animation_type) override;
  190. void AnimationEnded(InkDropHighlight::AnimationType animation_type,
  191. InkDropAnimationEndedReason reason) override;
  192. // Enables or disables the highlight state based on |should_highlight| and if
  193. // an animation is triggered it will be scheduled to have the given
  194. // |animation_duration|.
  195. void SetHighlight(bool should_highlight, base::TimeDelta animation_duration);
  196. // Returns true if |this| the highlight should be visible based on the
  197. // hover/focus status.
  198. bool ShouldHighlight() const;
  199. // Returns true if |this| the hilight should be visible based on the focus
  200. // status.
  201. bool ShouldHighlightBasedOnFocus() const;
  202. // Updates the current |highlight_state_|. Calls Exit()/Enter() on the
  203. // previous/new state to notify them of the transition.
  204. //
  205. // Uses ExitHighlightState() to exit the current state.
  206. void SetHighlightState(std::unique_ptr<HighlightState> highlight_state);
  207. // Exits the current |highlight_state_| and sets it to null. Ensures state
  208. // transitions are not triggered during HighlightStatae::Exit() calls on debug
  209. // builds.
  210. void ExitHighlightState();
  211. // The host of the ink drop. Used to create the ripples and highlights, and to
  212. // add/remove the root layer to/from it.
  213. const raw_ptr<InkDropHost> ink_drop_host_;
  214. // Used by |this| to initialize the starting |highlight_state_| and by the
  215. // current |highlight_state_| to create the next state.
  216. HighlightStateFactory highlight_state_factory_;
  217. // The root Layer that parents the InkDropRipple layers and the
  218. // InkDropHighlight layers. The |root_layer_| is the one that is added and
  219. // removed from the |ink_drop_host_|.
  220. std::unique_ptr<ui::Layer> root_layer_;
  221. // True when the |root_layer_| has been added to the |ink_drop_host_|.
  222. bool root_layer_added_to_host_ = false;
  223. // The current InkDropHighlight. Lazily created using
  224. // CreateInkDropHighlight();
  225. std::unique_ptr<InkDropHighlight> highlight_;
  226. // True denotes the highlight should be shown when |this| is hovered.
  227. bool show_highlight_on_hover_ = true;
  228. // True denotes the highlight should be shown when |this| is focused.
  229. bool show_highlight_on_focus_ = false;
  230. // Tracks the logical hovered state of |this| as manipulated by the public
  231. // SetHovered() function.
  232. bool is_hovered_ = false;
  233. // Tracks the logical focused state of |this| as manipulated by the public
  234. // SetFocused() function.
  235. bool is_focused_ = false;
  236. // The current InkDropRipple. Created on demand using CreateInkDropRipple().
  237. std::unique_ptr<InkDropRipple> ink_drop_ripple_;
  238. // The current state object that handles all inputs that affect the visibility
  239. // of the |highlight_|.
  240. std::unique_ptr<HighlightState> highlight_state_;
  241. // Overrides the default hover highlight fade durations when set.
  242. absl::optional<base::TimeDelta> hover_highlight_fade_duration_;
  243. // Used to ensure highlight state transitions are not triggered when exiting
  244. // the current state.
  245. bool exiting_highlight_state_ = false;
  246. // Used to fail DCHECKS to catch unexpected behavior during tear down.
  247. bool destroying_ = false;
  248. };
  249. } // namespace views
  250. #endif // UI_VIEWS_ANIMATION_INK_DROP_IMPL_H_