OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ | 5 #ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ |
6 #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ | 6 #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ |
7 | 7 |
8 #include <list> | 8 #include <list> |
9 #include <map> | 9 #include <map> |
10 | 10 |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/gtest_prod_util.h" | 12 #include "base/gtest_prod_util.h" |
13 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
14 #include "base/timer/timer.h" | 14 #include "base/timer/timer.h" |
15 #include "ui/gfx/display.h" | |
16 #include "ui/gfx/display_observer.h" | |
17 #include "ui/gfx/native_widget_types.h" | 15 #include "ui/gfx/native_widget_types.h" |
18 #include "ui/gfx/rect.h" | 16 #include "ui/gfx/rect.h" |
19 #include "ui/message_center/message_center_export.h" | 17 #include "ui/message_center/message_center_export.h" |
20 #include "ui/message_center/message_center_observer.h" | 18 #include "ui/message_center/message_center_observer.h" |
21 #include "ui/message_center/views/message_center_controller.h" | 19 #include "ui/message_center/views/message_center_controller.h" |
22 #include "ui/message_center/views/toast_contents_view.h" | 20 #include "ui/message_center/views/toast_contents_view.h" |
23 #include "ui/views/widget/widget_observer.h" | 21 #include "ui/views/widget/widget_observer.h" |
24 | 22 |
25 namespace base { | 23 namespace base { |
26 class RunLoop; | 24 class RunLoop; |
27 } | 25 } |
28 | 26 |
29 namespace views { | 27 namespace views { |
30 class Widget; | 28 class Widget; |
31 } | 29 } |
32 | 30 |
33 namespace ash { | |
34 class WebNotificationTrayTest; | |
35 FORWARD_DECLARE_TEST(WebNotificationTrayTest, ManyPopupNotifications); | |
36 } | |
37 | |
38 namespace gfx { | 31 namespace gfx { |
| 32 class Display; |
39 class Screen; | 33 class Screen; |
40 } | 34 } |
41 | 35 |
42 namespace message_center { | 36 namespace message_center { |
43 namespace test { | 37 namespace test { |
44 class MessagePopupCollectionTest; | 38 class MessagePopupCollectionTest; |
45 } | 39 } |
46 | 40 |
47 class MessageCenter; | 41 class MessageCenter; |
48 class MessageCenterTray; | 42 class MessageCenterTray; |
49 class MessageViewContextMenuController; | 43 class MessageViewContextMenuController; |
50 | 44 class PopupAlignmentDelegate; |
51 enum PopupAlignment { | |
52 POPUP_ALIGNMENT_TOP = 1 << 0, | |
53 POPUP_ALIGNMENT_LEFT = 1 << 1, | |
54 POPUP_ALIGNMENT_BOTTOM = 1 << 2, | |
55 POPUP_ALIGNMENT_RIGHT = 1 << 3, | |
56 }; | |
57 | 45 |
58 // Container for popup toasts. Because each toast is a frameless window rather | 46 // Container for popup toasts. Because each toast is a frameless window rather |
59 // than a view in a bubble, now the container just manages all of those toasts. | 47 // than a view in a bubble, now the container just manages all of those toasts. |
60 // This is similar to chrome/browser/notifications/balloon_collection, but the | 48 // This is similar to chrome/browser/notifications/balloon_collection, but the |
61 // contents of each toast are for the message center and layout strategy would | 49 // contents of each toast are for the message center and layout strategy would |
62 // be slightly different. | 50 // be slightly different. |
63 class MESSAGE_CENTER_EXPORT MessagePopupCollection | 51 class MESSAGE_CENTER_EXPORT MessagePopupCollection |
64 : public MessageCenterController, | 52 : public MessageCenterController, |
65 public MessageCenterObserver, | 53 public MessageCenterObserver { |
66 public gfx::DisplayObserver { | |
67 public: | 54 public: |
68 // |parent| specifies the parent widget of the toast windows. The default | 55 // |parent| specifies the parent widget of the toast windows. The default |
69 // parent will be used for NULL. Usually each icon is spacing against its | 56 // parent will be used for NULL. Usually each icon is spacing against its |
70 // predecessor. If |first_item_has_no_margin| is set however the first item | 57 // predecessor. |
71 // does not space against the tray. | |
72 MessagePopupCollection(gfx::NativeView parent, | 58 MessagePopupCollection(gfx::NativeView parent, |
73 MessageCenter* message_center, | 59 MessageCenter* message_center, |
74 MessageCenterTray* tray, | 60 MessageCenterTray* tray, |
75 bool first_item_has_no_margin); | 61 PopupAlignmentDelegate* alignment_delegate); |
76 virtual ~MessagePopupCollection(); | 62 virtual ~MessagePopupCollection(); |
77 | 63 |
78 // Overridden from MessageCenterController: | 64 // Overridden from MessageCenterController: |
79 virtual void ClickOnNotification(const std::string& notification_id) OVERRIDE; | 65 virtual void ClickOnNotification(const std::string& notification_id) OVERRIDE; |
80 virtual void RemoveNotification(const std::string& notification_id, | 66 virtual void RemoveNotification(const std::string& notification_id, |
81 bool by_user) OVERRIDE; | 67 bool by_user) OVERRIDE; |
82 virtual scoped_ptr<ui::MenuModel> CreateMenuModel( | 68 virtual scoped_ptr<ui::MenuModel> CreateMenuModel( |
83 const NotifierId& notifier_id, | 69 const NotifierId& notifier_id, |
84 const base::string16& display_source) OVERRIDE; | 70 const base::string16& display_source) OVERRIDE; |
85 virtual bool HasClickedListener(const std::string& notification_id) OVERRIDE; | 71 virtual bool HasClickedListener(const std::string& notification_id) OVERRIDE; |
(...skipping 16 matching lines...) Expand all Loading... |
102 void DecrementDeferCounter(); | 88 void DecrementDeferCounter(); |
103 | 89 |
104 // Runs the next step in update/animate sequence, if the defer counter is not | 90 // Runs the next step in update/animate sequence, if the defer counter is not |
105 // zero. Otherwise, simply waits when it becomes zero. | 91 // zero. Otherwise, simply waits when it becomes zero. |
106 void DoUpdateIfPossible(); | 92 void DoUpdateIfPossible(); |
107 | 93 |
108 // Removes the toast from our internal list of toasts; this is called when the | 94 // Removes the toast from our internal list of toasts; this is called when the |
109 // toast is irrevocably closed (such as within RemoveToast). | 95 // toast is irrevocably closed (such as within RemoveToast). |
110 void ForgetToast(ToastContentsView* toast); | 96 void ForgetToast(ToastContentsView* toast); |
111 | 97 |
112 // Updates |work_area_| and re-calculates the alignment of notification toasts | 98 // Called when the display bounds has been changed. Used in Windows only. |
113 // rearranging them if necessary. | 99 void OnDisplayMetricsChanged(const gfx::Display& display); |
114 // This is separated from methods from OnDisplayMetricsChanged(), since | |
115 // sometimes the display info has to be specified directly. One example is | |
116 // shelf's auto-hide change. When the shelf in ChromeOS is temporarily shown | |
117 // from auto hide status, it doesn't change the display's work area but the | |
118 // actual work area for toasts should be resized. | |
119 void SetDisplayInfo(const gfx::Rect& work_area, | |
120 const gfx::Rect& screen_bounds); | |
121 | |
122 // Overridden from gfx::DislayObserver: | |
123 virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE; | |
124 virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE; | |
125 virtual void OnDisplayMetricsChanged(const gfx::Display& display, | |
126 uint32_t metrics) OVERRIDE; | |
127 | 100 |
128 // Used by ToastContentsView to locate itself. | 101 // Used by ToastContentsView to locate itself. |
129 gfx::NativeView parent() const { return parent_; } | 102 gfx::NativeView parent() const { return parent_; } |
130 | 103 |
131 private: | 104 private: |
132 FRIEND_TEST_ALL_PREFIXES(ash::WebNotificationTrayTest, | |
133 ManyPopupNotifications); | |
134 friend class test::MessagePopupCollectionTest; | 105 friend class test::MessagePopupCollectionTest; |
135 friend class ash::WebNotificationTrayTest; | |
136 typedef std::list<ToastContentsView*> Toasts; | 106 typedef std::list<ToastContentsView*> Toasts; |
137 | 107 |
138 // Iterates toasts and starts closing them. | 108 // Iterates toasts and starts closing them. |
139 std::set<std::string> CloseAllWidgets(); | 109 std::set<std::string> CloseAllWidgets(); |
140 | 110 |
141 // Called by ToastContentsView when its window is closed. | 111 // Called by ToastContentsView when its window is closed. |
142 void RemoveToast(ToastContentsView* toast, bool mark_as_shown); | 112 void RemoveToast(ToastContentsView* toast, bool mark_as_shown); |
143 | 113 |
144 // Returns the x-origin for the given toast bounds in the current work area. | |
145 int GetToastOriginX(const gfx::Rect& toast_bounds) const; | |
146 | |
147 // Creates new widgets for new toast notifications, and updates |toasts_| and | 114 // Creates new widgets for new toast notifications, and updates |toasts_| and |
148 // |widgets_| correctly. | 115 // |widgets_| correctly. |
149 void UpdateWidgets(); | 116 void UpdateWidgets(); |
150 | 117 |
151 // Repositions all of the widgets based on the current work area. | 118 // Repositions all of the widgets based on the current work area. |
152 void RepositionWidgets(); | 119 void RepositionWidgets(); |
153 | 120 |
154 // Repositions widgets to the top edge of the notification toast that was | 121 // Repositions widgets to the top edge of the notification toast that was |
155 // just removed, so that the user can click close button without mouse moves. | 122 // just removed, so that the user can click close button without mouse moves. |
156 // See crbug.com/224089 | 123 // See crbug.com/224089 |
157 void RepositionWidgetsWithTarget(); | 124 void RepositionWidgetsWithTarget(); |
158 | 125 |
159 void ComputePopupAlignment(gfx::Rect work_area, gfx::Rect screen_bounds); | |
160 | |
161 // The base line is an (imaginary) line that would touch the bottom of the | 126 // The base line is an (imaginary) line that would touch the bottom of the |
162 // next created notification if bottom-aligned or its top if top-aligned. | 127 // next created notification if bottom-aligned or its top if top-aligned. |
163 int GetBaseLine(ToastContentsView* last_toast) const; | 128 int GetBaseLine(ToastContentsView* last_toast) const; |
164 | 129 |
165 // Overridden from MessageCenterObserver: | 130 // Overridden from MessageCenterObserver: |
166 virtual void OnNotificationAdded(const std::string& notification_id) OVERRIDE; | 131 virtual void OnNotificationAdded(const std::string& notification_id) OVERRIDE; |
167 virtual void OnNotificationRemoved(const std::string& notification_id, | 132 virtual void OnNotificationRemoved(const std::string& notification_id, |
168 bool by_user) OVERRIDE; | 133 bool by_user) OVERRIDE; |
169 virtual void OnNotificationUpdated( | 134 virtual void OnNotificationUpdated( |
170 const std::string& notification_id) OVERRIDE; | 135 const std::string& notification_id) OVERRIDE; |
171 | 136 |
172 ToastContentsView* FindToast(const std::string& notification_id) const; | 137 ToastContentsView* FindToast(const std::string& notification_id) const; |
173 | 138 |
174 // While the toasts are animated, avoid updating the collection, to reduce | 139 // While the toasts are animated, avoid updating the collection, to reduce |
175 // user confusion. Instead, update the collection when all animations are | 140 // user confusion. Instead, update the collection when all animations are |
176 // done. This method is run when defer counter is zero, may initiate next | 141 // done. This method is run when defer counter is zero, may initiate next |
177 // update/animation step. | 142 // update/animation step. |
178 void OnDeferTimerExpired(); | 143 void OnDeferTimerExpired(); |
179 | 144 |
180 // "ForTest" methods. | 145 // "ForTest" methods. |
181 views::Widget* GetWidgetForTest(const std::string& id) const; | 146 views::Widget* GetWidgetForTest(const std::string& id) const; |
182 void CreateRunLoopForTest(); | 147 void CreateRunLoopForTest(); |
183 void WaitForTest(); | 148 void WaitForTest(); |
184 gfx::Rect GetToastRectAt(size_t index) const; | 149 gfx::Rect GetToastRectAt(size_t index) const; |
185 | 150 |
186 gfx::NativeView parent_; | 151 gfx::NativeView parent_; |
187 MessageCenter* message_center_; | 152 MessageCenter* message_center_; |
188 MessageCenterTray* tray_; | 153 MessageCenterTray* tray_; |
189 Toasts toasts_; | 154 Toasts toasts_; |
190 gfx::Rect work_area_; | |
191 int64 display_id_; | |
192 gfx::Screen* screen_; | |
193 | 155 |
194 // Specifies which corner of the screen popups should show up. This should | 156 PopupAlignmentDelegate* alignment_delegate_; |
195 // ideally be the same corner the notification area (systray) is at. | |
196 PopupAlignment alignment_; | |
197 | 157 |
198 int defer_counter_; | 158 int defer_counter_; |
199 | 159 |
200 // This is only used to compare with incoming events, do not assume that | 160 // This is only used to compare with incoming events, do not assume that |
201 // the toast will be valid if this pointer is non-NULL. | 161 // the toast will be valid if this pointer is non-NULL. |
202 ToastContentsView* latest_toast_entered_; | 162 ToastContentsView* latest_toast_entered_; |
203 | 163 |
204 // Denotes a mode when user is clicking the Close button of toasts in a | 164 // Denotes a mode when user is clicking the Close button of toasts in a |
205 // sequence, w/o moving the mouse. We reposition the toasts so the next one | 165 // sequence, w/o moving the mouse. We reposition the toasts so the next one |
206 // happens to be right under the mouse, and the user can just dispose of | 166 // happens to be right under the mouse, and the user can just dispose of |
207 // multipel toasts by clicking. The mode ends when defer_timer_ expires. | 167 // multipel toasts by clicking. The mode ends when defer_timer_ expires. |
208 bool user_is_closing_toasts_by_clicking_; | 168 bool user_is_closing_toasts_by_clicking_; |
209 scoped_ptr<base::OneShotTimer<MessagePopupCollection> > defer_timer_; | 169 scoped_ptr<base::OneShotTimer<MessagePopupCollection> > defer_timer_; |
210 // The top edge to align the position of the next toast during 'close by | 170 // The top edge to align the position of the next toast during 'close by |
211 // clicking" mode. | 171 // clicking" mode. |
212 // Only to be used when user_is_closing_toasts_by_clicking_ is true. | 172 // Only to be used when user_is_closing_toasts_by_clicking_ is true. |
213 int target_top_edge_; | 173 int target_top_edge_; |
214 | 174 |
215 // Weak, only exists temporarily in tests. | 175 // Weak, only exists temporarily in tests. |
216 scoped_ptr<base::RunLoop> run_loop_for_test_; | 176 scoped_ptr<base::RunLoop> run_loop_for_test_; |
217 | 177 |
218 // True if the first item should not have spacing against the tray. | |
219 bool first_item_has_no_margin_; | |
220 | |
221 scoped_ptr<MessageViewContextMenuController> context_menu_controller_; | 178 scoped_ptr<MessageViewContextMenuController> context_menu_controller_; |
222 | 179 |
223 // Gives out weak pointers to toast contents views which have an unrelated | 180 // Gives out weak pointers to toast contents views which have an unrelated |
224 // lifetime. Must remain the last member variable. | 181 // lifetime. Must remain the last member variable. |
225 base::WeakPtrFactory<MessagePopupCollection> weak_factory_; | 182 base::WeakPtrFactory<MessagePopupCollection> weak_factory_; |
226 | 183 |
227 DISALLOW_COPY_AND_ASSIGN(MessagePopupCollection); | 184 DISALLOW_COPY_AND_ASSIGN(MessagePopupCollection); |
228 }; | 185 }; |
229 | 186 |
230 } // namespace message_center | 187 } // namespace message_center |
231 | 188 |
232 #endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ | 189 #endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_COLLECTION_H_ |
OLD | NEW |