Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(629)

Side by Side Diff: ui/message_center/message_popup_bubble.cc

Issue 12082081: Sets per-item timers rather than global timer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/message_center/message_popup_bubble.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 #include "ui/message_center/message_popup_bubble.h" 5 #include "ui/message_center/message_popup_bubble.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/stl_util.h"
8 #include "ui/message_center/message_view.h" 9 #include "ui/message_center/message_view.h"
9 #include "ui/message_center/notification_view.h" 10 #include "ui/message_center/notification_view.h"
10 #include "ui/notifications/notification_types.h" 11 #include "ui/notifications/notification_types.h"
11 #include "ui/views/bubble/tray_bubble_view.h" 12 #include "ui/views/bubble/tray_bubble_view.h"
12 #include "ui/views/layout/box_layout.h" 13 #include "ui/views/layout/box_layout.h"
13 #include "ui/views/view.h" 14 #include "ui/views/view.h"
14 #include "ui/views/widget/widget.h" 15 #include "ui/views/widget/widget.h"
15 16
16 namespace message_center { 17 namespace message_center {
17 namespace { 18 namespace {
18 19
19 const int kAutocloseHighPriorityDelaySeconds = 25; 20 const int kAutocloseHighPriorityDelaySeconds = 25;
20 const int kAutocloseDefaultDelaySeconds = 8; 21 const int kAutocloseDefaultDelaySeconds = 8;
21 22
22 std::vector<const NotificationList::Notification*> GetNewNotifications(
23 const NotificationList::Notifications& old_list,
24 const NotificationList::Notifications& new_list) {
25 std::set<std::string> existing_ids;
26 std::vector<const NotificationList::Notification*> result;
27 for (NotificationList::Notifications::const_iterator iter = old_list.begin();
28 iter != old_list.end(); ++iter) {
29 existing_ids.insert(iter->id);
30 }
31 for (NotificationList::Notifications::const_iterator iter = new_list.begin();
32 iter != new_list.end(); ++iter) {
33 if (existing_ids.find(iter->id) == existing_ids.end())
34 result.push_back(&(*iter));
35 }
36 return result;
37 }
38
39 } // namespace 23 } // namespace
40 24
41 // Popup notifications contents. 25 // Popup notifications contents.
42 class PopupBubbleContentsView : public views::View { 26 class PopupBubbleContentsView : public views::View {
43 public: 27 public:
44 explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate) 28 explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate)
45 : list_delegate_(list_delegate) { 29 : list_delegate_(list_delegate) {
46 SetLayoutManager( 30 SetLayoutManager(
47 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); 31 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
48 32
(...skipping 30 matching lines...) Expand all
79 return content_->child_count(); 63 return content_->child_count();
80 } 64 }
81 65
82 private: 66 private:
83 NotificationList::Delegate* list_delegate_; 67 NotificationList::Delegate* list_delegate_;
84 views::View* content_; 68 views::View* content_;
85 69
86 DISALLOW_COPY_AND_ASSIGN(PopupBubbleContentsView); 70 DISALLOW_COPY_AND_ASSIGN(PopupBubbleContentsView);
87 }; 71 };
88 72
73 // The timer to call OnAutoClose for |notification|.
74 class MessagePopupBubble::AutocloseTimer {
75 public:
76 AutocloseTimer(const NotificationList::Notification& notification,
77 MessagePopupBubble* bubble)
78 : id_(notification.id),
79 bubble_(bubble) {
80 int seconds = kAutocloseDefaultDelaySeconds;
81 if (notification.priority > ui::notifications::DEFAULT_PRIORITY)
82 seconds = kAutocloseHighPriorityDelaySeconds;
83 delay_ = base::TimeDelta::FromSeconds(seconds);
84 }
dharcourt 2013/01/30 23:24:47 I may be misapplying that to this, but it seems th
Jun Mukai 2013/01/31 18:59:09 Thanks. Moved out-of-line (and fixed PopupBubbleC
85
86 void Start() {
87 start_time_ = base::Time::Now();
88 timer_.Start(FROM_HERE,
89 delay_,
90 base::Bind(&MessagePopupBubble::OnAutoClose,
91 base::Unretained(bubble_), id_));
92 }
93
94 void Suspend() {
95 base::TimeDelta passed = base::Time::Now() - start_time_;
96 delay_ = std::max(base::TimeDelta(), delay_ - passed);
97 timer_.Reset();
98 }
99
100 private:
101 const std::string id_;
102 base::TimeDelta delay_;
103 base::Time start_time_;
104 MessagePopupBubble* bubble_;
105 base::OneShotTimer<MessagePopupBubble> timer_;
106
107 DISALLOW_COPY_AND_ASSIGN(AutocloseTimer);
108 };
109
89 // MessagePopupBubble 110 // MessagePopupBubble
90 MessagePopupBubble::MessagePopupBubble(NotificationList::Delegate* delegate) 111 MessagePopupBubble::MessagePopupBubble(NotificationList::Delegate* delegate)
91 : MessageBubbleBase(delegate), 112 : MessageBubbleBase(delegate),
92 contents_view_(NULL), 113 contents_view_(NULL) {
93 should_run_default_timer_(false),
94 should_run_high_timer_(false) {
95 } 114 }
96 115
97 MessagePopupBubble::~MessagePopupBubble() { 116 MessagePopupBubble::~MessagePopupBubble() {
117 STLDeleteContainerPairSecondPointers(autoclose_timers_.begin(),
118 autoclose_timers_.end());
98 } 119 }
99 120
100 views::TrayBubbleView::InitParams MessagePopupBubble::GetInitParams( 121 views::TrayBubbleView::InitParams MessagePopupBubble::GetInitParams(
101 views::TrayBubbleView::AnchorAlignment anchor_alignment) { 122 views::TrayBubbleView::AnchorAlignment anchor_alignment) {
102 views::TrayBubbleView::InitParams init_params = 123 views::TrayBubbleView::InitParams init_params =
103 GetDefaultInitParams(anchor_alignment); 124 GetDefaultInitParams(anchor_alignment);
104 init_params.arrow_color = kBackgroundColor; 125 init_params.arrow_color = kBackgroundColor;
105 init_params.close_on_deactivate = false; 126 init_params.close_on_deactivate = false;
106 return init_params; 127 return init_params;
107 } 128 }
108 129
109 void MessagePopupBubble::InitializeContents( 130 void MessagePopupBubble::InitializeContents(
110 views::TrayBubbleView* new_bubble_view) { 131 views::TrayBubbleView* new_bubble_view) {
111 set_bubble_view(new_bubble_view); 132 set_bubble_view(new_bubble_view);
112 contents_view_ = new PopupBubbleContentsView(list_delegate()); 133 contents_view_ = new PopupBubbleContentsView(list_delegate());
113 bubble_view()->AddChildView(contents_view_); 134 bubble_view()->AddChildView(contents_view_);
114 UpdateBubbleView(); 135 UpdateBubbleView();
115 } 136 }
116 137
117 void MessagePopupBubble::OnBubbleViewDestroyed() { 138 void MessagePopupBubble::OnBubbleViewDestroyed() {
118 contents_view_ = NULL; 139 contents_view_ = NULL;
119 } 140 }
120 141
121 void MessagePopupBubble::UpdateBubbleView() { 142 void MessagePopupBubble::UpdateBubbleView() {
122 NotificationList::Notifications new_notifications; 143 NotificationList::Notifications popups;
123 list_delegate()->GetNotificationList()->GetPopupNotifications( 144 list_delegate()->GetNotificationList()->GetPopupNotifications(&popups);
124 &new_notifications); 145
125 if (new_notifications.size() == 0) { 146 if (popups.size() == 0) {
126 if (bubble_view()) 147 if (bubble_view())
127 bubble_view()->delegate()->HideBubble(bubble_view()); // deletes |this| 148 bubble_view()->delegate()->HideBubble(bubble_view()); // deletes |this|
128 return; 149 return;
129 } 150 }
130 // Only reset the timer when the number of visible notifications changes. 151
131 std::vector<const NotificationList::Notification*> added = 152 contents_view_->Update(popups);
132 GetNewNotifications(popup_notifications_, new_notifications);
133 bool run_default = false;
134 bool run_high = false;
135 for (std::vector<const NotificationList::Notification*>::const_iterator iter =
136 added.begin(); iter != added.end(); ++iter) {
137 if ((*iter)->priority == ui::notifications::DEFAULT_PRIORITY)
138 run_default = true;
139 else if ((*iter)->priority >= ui::notifications::HIGH_PRIORITY)
140 run_high = true;
141 }
142 // Currently MAX priority is same as HIGH priority.
143 if (run_high)
144 StartAutoCloseTimer(ui::notifications::MAX_PRIORITY);
145 if (run_default)
146 StartAutoCloseTimer(ui::notifications::DEFAULT_PRIORITY);
147 should_run_high_timer_ = run_high;
148 should_run_default_timer_ = run_default;
149 contents_view_->Update(new_notifications);
150 popup_notifications_.swap(new_notifications);
151 bubble_view()->Show(); 153 bubble_view()->Show();
152 bubble_view()->UpdateBubble(); 154 bubble_view()->UpdateBubble();
155
156 std::set<std::string> old_popup_ids;
157 old_popup_ids.swap(popup_ids_);
158
159 // Start autoclose timers.
160 for (NotificationList::Notifications::const_iterator iter = popups.begin();
161 iter != popups.end(); ++iter) {
162 std::map<std::string, AutocloseTimer*>::const_iterator timer_iter =
163 autoclose_timers_.find(iter->id);
164 if (timer_iter == autoclose_timers_.end()) {
165 AutocloseTimer *timer = new AutocloseTimer(*iter, this);
166 autoclose_timers_[iter->id] = timer;
167 timer->Start();
168 }
169 popup_ids_.insert(iter->id);
170 old_popup_ids.erase(iter->id);
171 }
172
173 // Stops timers whose notifications are gone.
174 for (std::set<std::string>::const_iterator iter = old_popup_ids.begin();
175 iter != old_popup_ids.end(); ++iter) {
176 DeleteTimer(*iter);
177 }
153 } 178 }
154 179
155 void MessagePopupBubble::OnMouseEnteredView() { 180 void MessagePopupBubble::OnMouseEnteredView() {
156 StopAutoCloseTimer(); 181 for (std::map<std::string, AutocloseTimer*>::iterator iter =
182 autoclose_timers_.begin(); iter != autoclose_timers_.end(); ++iter) {
183 iter->second->Suspend();
184 }
157 } 185 }
158 186
159 void MessagePopupBubble::OnMouseExitedView() { 187 void MessagePopupBubble::OnMouseExitedView() {
160 if (should_run_high_timer_) 188 for (std::map<std::string, AutocloseTimer*>::iterator iter =
161 StartAutoCloseTimer(ui::notifications::HIGH_PRIORITY); 189 autoclose_timers_.begin(); iter != autoclose_timers_.end(); ++iter) {
162 if (should_run_default_timer_) 190 iter->second->Start();
163 StartAutoCloseTimer(ui::notifications::DEFAULT_PRIORITY); 191 }
164 } 192 }
165 193
166 void MessagePopupBubble::StartAutoCloseTimer(int priority) { 194 void MessagePopupBubble::OnAutoClose(const std::string& id) {
167 base::TimeDelta seconds; 195 DeleteTimer(id);
168 base::OneShotTimer<MessagePopupBubble>* timer = NULL; 196 list_delegate()->GetNotificationList()->MarkSinglePopupAsShown(id, false);
169 if (priority == ui::notifications::MAX_PRIORITY) {
170 seconds = base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds);
171 timer = &autoclose_high_;
172 } else {
173 seconds = base::TimeDelta::FromSeconds(kAutocloseDefaultDelaySeconds);
174 timer = &autoclose_default_;
175 }
176
177 timer->Start(FROM_HERE,
178 seconds,
179 base::Bind(&MessagePopupBubble::OnAutoClose,
180 base::Unretained(this), priority));
181 }
182
183 void MessagePopupBubble::StopAutoCloseTimer() {
184 autoclose_high_.Stop();
185 autoclose_default_.Stop();
186 }
187
188 void MessagePopupBubble::OnAutoClose(int priority) {
189 list_delegate()->GetNotificationList()->MarkPopupsAsShown(priority);
190 if (priority == ui::notifications::MAX_PRIORITY)
191 list_delegate()->GetNotificationList()->MarkPopupsAsShown(
192 ui::notifications::HIGH_PRIORITY);
193
194 if (priority >= ui::notifications::MAX_PRIORITY)
195 should_run_high_timer_ = false;
196 else
197 should_run_default_timer_ = false;
198 UpdateBubbleView(); 197 UpdateBubbleView();
199 } 198 }
200 199
200 void MessagePopupBubble::DeleteTimer(const std::string& id) {
201 std::map<std::string, AutocloseTimer*>::iterator iter =
202 autoclose_timers_.find(id);
203 if (iter != autoclose_timers_.end()) {
204 delete iter->second;
205 autoclose_timers_.erase(iter);
dharcourt 2013/01/30 23:24:47 Will this make autoclose_timers_ briefly contain a
Jun Mukai 2013/01/31 18:59:09 using scoped_ptr to ensure releasing the object af
206 }
207 }
208
201 size_t MessagePopupBubble::NumMessageViewsForTest() const { 209 size_t MessagePopupBubble::NumMessageViewsForTest() const {
202 return contents_view_->NumMessageViews(); 210 return contents_view_->NumMessageViews();
203 } 211 }
204 212
205 } // namespace message_center 213 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/message_popup_bubble.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698