Index: ui/message_center/message_popup_bubble.cc |
diff --git a/ui/message_center/message_popup_bubble.cc b/ui/message_center/message_popup_bubble.cc |
index 61abcefab7e4db8eafa51ec92728be25b6c22d42..17a43bceff11de270686efd2fa126bc15d6f14b9 100644 |
--- a/ui/message_center/message_popup_bubble.cc |
+++ b/ui/message_center/message_popup_bubble.cc |
@@ -5,6 +5,7 @@ |
#include "ui/message_center/message_popup_bubble.h" |
#include "base/bind.h" |
+#include "base/stl_util.h" |
#include "ui/message_center/message_view.h" |
#include "ui/message_center/notification_view.h" |
#include "ui/notifications/notification_types.h" |
@@ -19,23 +20,6 @@ namespace { |
const int kAutocloseHighPriorityDelaySeconds = 25; |
const int kAutocloseDefaultDelaySeconds = 8; |
-std::vector<const NotificationList::Notification*> GetNewNotifications( |
- const NotificationList::Notifications& old_list, |
- const NotificationList::Notifications& new_list) { |
- std::set<std::string> existing_ids; |
- std::vector<const NotificationList::Notification*> result; |
- for (NotificationList::Notifications::const_iterator iter = old_list.begin(); |
- iter != old_list.end(); ++iter) { |
- existing_ids.insert(iter->id); |
- } |
- for (NotificationList::Notifications::const_iterator iter = new_list.begin(); |
- iter != new_list.end(); ++iter) { |
- if (existing_ids.find(iter->id) == existing_ids.end()) |
- result.push_back(&(*iter)); |
- } |
- return result; |
-} |
- |
} // namespace |
// Popup notifications contents. |
@@ -86,15 +70,52 @@ class PopupBubbleContentsView : public views::View { |
DISALLOW_COPY_AND_ASSIGN(PopupBubbleContentsView); |
}; |
+// The timer to call OnAutoClose for |notification|. |
+class MessagePopupBubble::AutocloseTimer { |
+ public: |
+ AutocloseTimer(const NotificationList::Notification& notification, |
+ MessagePopupBubble* bubble) |
+ : id_(notification.id), |
+ bubble_(bubble) { |
+ int seconds = kAutocloseDefaultDelaySeconds; |
+ if (notification.priority > ui::notifications::DEFAULT_PRIORITY) |
+ seconds = kAutocloseHighPriorityDelaySeconds; |
+ delay_ = base::TimeDelta::FromSeconds(seconds); |
+ } |
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
|
+ |
+ void Start() { |
+ start_time_ = base::Time::Now(); |
+ timer_.Start(FROM_HERE, |
+ delay_, |
+ base::Bind(&MessagePopupBubble::OnAutoClose, |
+ base::Unretained(bubble_), id_)); |
+ } |
+ |
+ void Suspend() { |
+ base::TimeDelta passed = base::Time::Now() - start_time_; |
+ delay_ = std::max(base::TimeDelta(), delay_ - passed); |
+ timer_.Reset(); |
+ } |
+ |
+ private: |
+ const std::string id_; |
+ base::TimeDelta delay_; |
+ base::Time start_time_; |
+ MessagePopupBubble* bubble_; |
+ base::OneShotTimer<MessagePopupBubble> timer_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AutocloseTimer); |
+}; |
+ |
// MessagePopupBubble |
MessagePopupBubble::MessagePopupBubble(NotificationList::Delegate* delegate) |
: MessageBubbleBase(delegate), |
- contents_view_(NULL), |
- should_run_default_timer_(false), |
- should_run_high_timer_(false) { |
+ contents_view_(NULL) { |
} |
MessagePopupBubble::~MessagePopupBubble() { |
+ STLDeleteContainerPairSecondPointers(autoclose_timers_.begin(), |
+ autoclose_timers_.end()); |
} |
views::TrayBubbleView::InitParams MessagePopupBubble::GetInitParams( |
@@ -119,83 +140,70 @@ void MessagePopupBubble::OnBubbleViewDestroyed() { |
} |
void MessagePopupBubble::UpdateBubbleView() { |
- NotificationList::Notifications new_notifications; |
- list_delegate()->GetNotificationList()->GetPopupNotifications( |
- &new_notifications); |
- if (new_notifications.size() == 0) { |
+ NotificationList::Notifications popups; |
+ list_delegate()->GetNotificationList()->GetPopupNotifications(&popups); |
+ |
+ if (popups.size() == 0) { |
if (bubble_view()) |
bubble_view()->delegate()->HideBubble(bubble_view()); // deletes |this| |
return; |
} |
- // Only reset the timer when the number of visible notifications changes. |
- std::vector<const NotificationList::Notification*> added = |
- GetNewNotifications(popup_notifications_, new_notifications); |
- bool run_default = false; |
- bool run_high = false; |
- for (std::vector<const NotificationList::Notification*>::const_iterator iter = |
- added.begin(); iter != added.end(); ++iter) { |
- if ((*iter)->priority == ui::notifications::DEFAULT_PRIORITY) |
- run_default = true; |
- else if ((*iter)->priority >= ui::notifications::HIGH_PRIORITY) |
- run_high = true; |
- } |
- // Currently MAX priority is same as HIGH priority. |
- if (run_high) |
- StartAutoCloseTimer(ui::notifications::MAX_PRIORITY); |
- if (run_default) |
- StartAutoCloseTimer(ui::notifications::DEFAULT_PRIORITY); |
- should_run_high_timer_ = run_high; |
- should_run_default_timer_ = run_default; |
- contents_view_->Update(new_notifications); |
- popup_notifications_.swap(new_notifications); |
+ |
+ contents_view_->Update(popups); |
bubble_view()->Show(); |
bubble_view()->UpdateBubble(); |
+ |
+ std::set<std::string> old_popup_ids; |
+ old_popup_ids.swap(popup_ids_); |
+ |
+ // Start autoclose timers. |
+ for (NotificationList::Notifications::const_iterator iter = popups.begin(); |
+ iter != popups.end(); ++iter) { |
+ std::map<std::string, AutocloseTimer*>::const_iterator timer_iter = |
+ autoclose_timers_.find(iter->id); |
+ if (timer_iter == autoclose_timers_.end()) { |
+ AutocloseTimer *timer = new AutocloseTimer(*iter, this); |
+ autoclose_timers_[iter->id] = timer; |
+ timer->Start(); |
+ } |
+ popup_ids_.insert(iter->id); |
+ old_popup_ids.erase(iter->id); |
+ } |
+ |
+ // Stops timers whose notifications are gone. |
+ for (std::set<std::string>::const_iterator iter = old_popup_ids.begin(); |
+ iter != old_popup_ids.end(); ++iter) { |
+ DeleteTimer(*iter); |
+ } |
} |
void MessagePopupBubble::OnMouseEnteredView() { |
- StopAutoCloseTimer(); |
+ for (std::map<std::string, AutocloseTimer*>::iterator iter = |
+ autoclose_timers_.begin(); iter != autoclose_timers_.end(); ++iter) { |
+ iter->second->Suspend(); |
+ } |
} |
void MessagePopupBubble::OnMouseExitedView() { |
- if (should_run_high_timer_) |
- StartAutoCloseTimer(ui::notifications::HIGH_PRIORITY); |
- if (should_run_default_timer_) |
- StartAutoCloseTimer(ui::notifications::DEFAULT_PRIORITY); |
-} |
- |
-void MessagePopupBubble::StartAutoCloseTimer(int priority) { |
- base::TimeDelta seconds; |
- base::OneShotTimer<MessagePopupBubble>* timer = NULL; |
- if (priority == ui::notifications::MAX_PRIORITY) { |
- seconds = base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds); |
- timer = &autoclose_high_; |
- } else { |
- seconds = base::TimeDelta::FromSeconds(kAutocloseDefaultDelaySeconds); |
- timer = &autoclose_default_; |
+ for (std::map<std::string, AutocloseTimer*>::iterator iter = |
+ autoclose_timers_.begin(); iter != autoclose_timers_.end(); ++iter) { |
+ iter->second->Start(); |
} |
- |
- timer->Start(FROM_HERE, |
- seconds, |
- base::Bind(&MessagePopupBubble::OnAutoClose, |
- base::Unretained(this), priority)); |
} |
-void MessagePopupBubble::StopAutoCloseTimer() { |
- autoclose_high_.Stop(); |
- autoclose_default_.Stop(); |
+void MessagePopupBubble::OnAutoClose(const std::string& id) { |
+ DeleteTimer(id); |
+ list_delegate()->GetNotificationList()->MarkSinglePopupAsShown(id, false); |
+ UpdateBubbleView(); |
} |
-void MessagePopupBubble::OnAutoClose(int priority) { |
- list_delegate()->GetNotificationList()->MarkPopupsAsShown(priority); |
- if (priority == ui::notifications::MAX_PRIORITY) |
- list_delegate()->GetNotificationList()->MarkPopupsAsShown( |
- ui::notifications::HIGH_PRIORITY); |
- |
- if (priority >= ui::notifications::MAX_PRIORITY) |
- should_run_high_timer_ = false; |
- else |
- should_run_default_timer_ = false; |
- UpdateBubbleView(); |
+void MessagePopupBubble::DeleteTimer(const std::string& id) { |
+ std::map<std::string, AutocloseTimer*>::iterator iter = |
+ autoclose_timers_.find(id); |
+ if (iter != autoclose_timers_.end()) { |
+ delete iter->second; |
+ 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
|
+ } |
} |
size_t MessagePopupBubble::NumMessageViewsForTest() const { |