unified_message_list_view.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright 2018 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 ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_
  5. #define ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_
  6. #include "ash/ash_export.h"
  7. #include "ash/system/unified/unified_system_tray_model.h"
  8. #include "base/memory/scoped_refptr.h"
  9. #include "base/scoped_multi_source_observation.h"
  10. #include "base/scoped_observation.h"
  11. #include "ui/compositor/throughput_tracker.h"
  12. #include "ui/message_center/message_center.h"
  13. #include "ui/message_center/message_center_observer.h"
  14. #include "ui/message_center/notification_view_controller.h"
  15. #include "ui/message_center/views/message_view.h"
  16. #include "ui/views/animation/animation_delegate_views.h"
  17. #include "ui/views/view.h"
  18. namespace gfx {
  19. class LinearAnimation;
  20. } // namespace gfx
  21. namespace message_center {
  22. class MessageView;
  23. class Notification;
  24. } // namespace message_center
  25. namespace ash {
  26. class UnifiedMessageCenterView;
  27. class UnifiedSystemTrayModel;
  28. // Manages list of notifications. The class doesn't know about the ScrollView
  29. // it's enclosed. This class is used only from UnifiedMessageCenterView.
  30. class ASH_EXPORT UnifiedMessageListView
  31. : public views::View,
  32. public message_center::MessageCenterObserver,
  33. public message_center::NotificationViewController,
  34. public message_center::MessageView::Observer,
  35. public views::AnimationDelegateViews {
  36. public:
  37. // |message_center_view| can be null in unit tests.
  38. UnifiedMessageListView(UnifiedMessageCenterView* message_center_view,
  39. scoped_refptr<UnifiedSystemTrayModel> model);
  40. UnifiedMessageListView(const UnifiedMessageListView& other) = delete;
  41. UnifiedMessageListView& operator=(const UnifiedMessageListView& other) =
  42. delete;
  43. ~UnifiedMessageListView() override;
  44. // Initializes the view with existing notifications. Should be called right
  45. // after ctor.
  46. void Init();
  47. // Starts Clear All animation and removes all notifications. Notifications are
  48. // removed from MessageCenter at the beginning of the animation.
  49. void ClearAllWithAnimation();
  50. // Return the bounds of the specified notification view. If the given id is
  51. // invalid, return an empty rect.
  52. gfx::Rect GetNotificationBounds(const std::string& id) const;
  53. // Return the bounds of the last notification view. If there is no view,
  54. // return an empty rect.
  55. gfx::Rect GetLastNotificationBounds() const;
  56. // Return the bounds of the first notification whose bottom is below
  57. // |y_offset|.
  58. gfx::Rect GetNotificationBoundsBelowY(int y_offset) const;
  59. // Returns all notifications in the view hierarchy that are also in the
  60. // MessageCenter.
  61. std::vector<message_center::Notification*> GetAllNotifications() const;
  62. // Returns all notification ids in the view hierarchy regardless of whether
  63. // they are in also in the MessageCenter.
  64. std::vector<std::string> GetAllNotificationIds() const;
  65. // Returns the notifications in the view hierarchy that are also in the
  66. // MessageCenter, whose bottom position is above |y_offset|. O(n) where n is
  67. // number of notifications.
  68. std::vector<message_center::Notification*> GetNotificationsAboveY(
  69. int y_offset) const;
  70. // Returns the notifications in the view hierarchy that are also in the
  71. // MessageCenter, whose bottom position is below |y_offset|. O(n) where n is
  72. // number of notifications.
  73. std::vector<message_center::Notification*> GetNotificationsBelowY(
  74. int y_offset) const;
  75. // Same as GetNotificationsAboveY, but returns notifications that are not in
  76. // the MessageCenter. This is useful for the clear all animation which first
  77. // removes all notifications before asking for stacked notifications.
  78. std::vector<std::string> GetNotificationIdsAboveY(int y_offset) const;
  79. // Returns notifications that are in the view hierarchy below `y_offset`
  80. // without checking whether they are in the MessageCenter. This is useful for
  81. // the clear all animation which first removes all notifications before asking
  82. // for stacked notifications.
  83. std::vector<std::string> GetNotificationIdsBelowY(int y_offset) const;
  84. // Returns the total number of notifications in the list.
  85. int GetTotalNotificationCount() const;
  86. // Returns the total number of pinned notifications in the list.
  87. int GetTotalPinnedNotificationCount() const;
  88. // Returns true if `animation_` is currently in progress.
  89. bool IsAnimating() const;
  90. // Returns whether `message_view_container` is being animated for expand or
  91. // collapse.
  92. bool IsAnimatingExpandOrCollapseContainer(const views::View* view) const;
  93. // Called when a notification is slid out so we can run the MOVE_DOWN
  94. // animation.
  95. void OnNotificationSlidOut();
  96. // views::View:
  97. void ChildPreferredSizeChanged(views::View* child) override;
  98. void PreferredSizeChanged() override;
  99. void Layout() override;
  100. gfx::Size CalculatePreferredSize() const override;
  101. const char* GetClassName() const override;
  102. // message_center::NotificationViewController:
  103. void AnimateResize() override;
  104. message_center::MessageView* GetMessageViewForNotificationId(
  105. const std::string& id) override;
  106. void ConvertNotificationViewToGroupedNotificationView(
  107. const std::string& ungrouped_notification_id,
  108. const std::string& new_grouped_notification_id) override;
  109. void ConvertGroupedNotificationViewToNotificationView(
  110. const std::string& grouped_notification_id,
  111. const std::string& new_single_notification_id) override;
  112. // message_center::MessageCenterObserver:
  113. void OnNotificationAdded(const std::string& id) override;
  114. void OnNotificationRemoved(const std::string& id, bool by_user) override;
  115. void OnNotificationUpdated(const std::string& id) override;
  116. // message_center::MessageView::Observer:
  117. void OnSlideStarted(const std::string& notification_id) override;
  118. void OnCloseButtonPressed(const std::string& notification_id) override;
  119. void OnSettingsButtonPressed(const std::string& notification_id) override;
  120. void OnSnoozeButtonPressed(const std::string& notification_id) override;
  121. // views::AnimationDelegateViews:
  122. void AnimationEnded(const gfx::Animation* animation) override;
  123. void AnimationProgressed(const gfx::Animation* animation) override;
  124. void AnimationCanceled(const gfx::Animation* animation) override;
  125. bool is_deleting_removed_notifications() const {
  126. return is_deleting_removed_notifications_;
  127. }
  128. protected:
  129. // Virtual for testing.
  130. virtual message_center::MessageView* CreateMessageView(
  131. const message_center::Notification& notification);
  132. void ConfigureMessageView(message_center::MessageView* message_view);
  133. // Virtual for testing.
  134. virtual std::vector<message_center::Notification*> GetStackedNotifications()
  135. const;
  136. // Virtual for testing.
  137. virtual std::vector<std::string> GetNonVisibleNotificationIdsInViewHierarchy()
  138. const;
  139. private:
  140. friend class UnifiedMessageCenterViewTest;
  141. friend class UnifiedMessageListViewTest;
  142. friend class UnifiedMessageCenterBubbleTest;
  143. class Background;
  144. class MessageViewContainer;
  145. // UnifiedMessageListView always runs a single animation at one time. When
  146. // `state_` is IDLE, `animation_->is_animating()` is always false and vice
  147. // versa.
  148. enum class State {
  149. // No animation is running.
  150. IDLE,
  151. // Moving down notifications.
  152. MOVE_DOWN,
  153. // Part 1 of Clear All animation. Removing all hidden notifications above
  154. // the visible area.
  155. CLEAR_ALL_STACKED,
  156. // Part 2 of Clear All animation. Removing all visible notifications.
  157. CLEAR_ALL_VISIBLE,
  158. // Animating an increase or decrease in height of a notification. Only one
  159. // may animate at a time.
  160. EXPAND_OR_COLLAPSE
  161. };
  162. // Syntactic sugar to downcast.
  163. static const MessageViewContainer* AsMVC(const views::View* v);
  164. static MessageViewContainer* AsMVC(views::View* v);
  165. // Returns the notification with the provided |id|.
  166. const MessageViewContainer* GetNotificationById(const std::string& id) const;
  167. MessageViewContainer* GetNotificationById(const std::string& id) {
  168. return const_cast<MessageViewContainer*>(
  169. static_cast<const UnifiedMessageListView*>(this)->GetNotificationById(
  170. id));
  171. }
  172. // Returns the first removable notification from the top.
  173. MessageViewContainer* GetNextRemovableNotification();
  174. // Current progress of the animation between 0.0 and 1.0. Returns 1.0 when
  175. // it's not animating.
  176. double GetCurrentValue() const;
  177. // Collapses all the existing notifications. It does not trigger
  178. // PreferredSizeChanged() (See |ignore_size_change_|).
  179. void CollapseAllNotifications();
  180. // Updates the borders of notifications. It adds separators between
  181. // notifications, and rounds notification corners at the top and the bottom.
  182. // `force_update` indicates if we should update borders on all notifications
  183. // regardless of their previous state.
  184. void UpdateBorders(bool force_update);
  185. // Updates |final_bounds| of all notifications and moves old |final_bounds| to
  186. // |start_bounds|.
  187. void UpdateBounds();
  188. // Resets the animation, and makes all notifications immediately positioned at
  189. // |final_bounds|.
  190. void ResetBounds();
  191. // Interrupts clear all animation and deletes all the remaining notifications.
  192. // ResetBounds() should be called after that.
  193. void InterruptClearAll();
  194. // Deletes all the MessageViewContainer marked as |is_removed|.
  195. void DeleteRemovedNotifications();
  196. // Starts the animation for current |state_|.
  197. void StartAnimation();
  198. // Updates the state between each Clear All animation phase.
  199. void UpdateClearAllAnimation();
  200. UnifiedMessageCenterView* const message_center_view_;
  201. scoped_refptr<UnifiedSystemTrayModel> model_;
  202. // Non-null during State::EXPAND_OR_COLLAPSE. Keeps track of the
  203. // MessageViewContainer that is animating.
  204. MessageViewContainer* expand_or_collapsing_container_ = nullptr;
  205. // If true, ChildPreferredSizeChanged() will be ignored. This is used in
  206. // CollapseAllNotifications() to prevent PreferredSizeChanged() triggered
  207. // multiple times because of sequential SetExpanded() calls.
  208. bool ignore_size_change_ = false;
  209. // If true, OnNotificationRemoved() will be ignored. Used in
  210. // ClearAllWithAnimation().
  211. bool ignore_notification_remove_ = false;
  212. // Manages notification closing animation. UnifiedMessageListView does not use
  213. // implicit animation.
  214. const std::unique_ptr<gfx::LinearAnimation> animation_;
  215. // Measure animation smoothness metrics for `animation_`.
  216. absl::optional<ui::ThroughputTracker> throughput_tracker_;
  217. State state_ = State::IDLE;
  218. // The height the UnifiedMessageListView starts animating from. If not
  219. // animating, it's ignored.
  220. int start_height_ = 0;
  221. // The final height of the UnifiedMessageListView. If not animating, it's same
  222. // as height().
  223. int target_height_ = 0;
  224. // True if the UnifiedMessageListView is currently deleting notifications
  225. // marked for removal. This check is needed to prevent re-entrancing issues
  226. // (e.g. crbug.com/933327) caused by the View destructor.
  227. bool is_deleting_removed_notifications_ = false;
  228. const bool is_notifications_refresh_enabled_;
  229. const int message_view_width_;
  230. base::ScopedObservation<message_center::MessageCenter,
  231. message_center::MessageCenterObserver>
  232. message_center_observation_{this};
  233. base::ScopedMultiSourceObservation<message_center::MessageView,
  234. message_center::MessageView::Observer>
  235. message_view_multi_source_observation_{this};
  236. };
  237. } // namespace ash
  238. #endif // ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_