summaryrefslogtreecommitdiffstats
path: root/ui/message_center
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 05:47:05 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 05:47:05 +0000
commit151b5302d17d9d4b7d00afb47f347404e86f1fe7 (patch)
treecde2ff2f0d74dec11c1139ecaf71bc38c6e4746e /ui/message_center
parentb6b15bcc006c128a9f5f5bf857791c52d820193f (diff)
downloadchromium_src-151b5302d17d9d4b7d00afb47f347404e86f1fe7.zip
chromium_src-151b5302d17d9d4b7d00afb47f347404e86f1fe7.tar.gz
chromium_src-151b5302d17d9d4b7d00afb47f347404e86f1fe7.tar.bz2
Sets per-item timers rather than global timer.
BUG=163760,169151 Review URL: https://chromiumcodereview.appspot.com/12082081 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180087 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/message_center')
-rw-r--r--ui/message_center/message_popup_bubble.cc245
-rw-r--r--ui/message_center/message_popup_bubble.h18
2 files changed, 143 insertions, 120 deletions
diff --git a/ui/message_center/message_popup_bubble.cc b/ui/message_center/message_popup_bubble.cc
index 61abcef..0e998cf 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,61 +20,14 @@ 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.
class PopupBubbleContentsView : public views::View {
public:
- explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate)
- : list_delegate_(list_delegate) {
- SetLayoutManager(
- new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
-
- content_ = new views::View;
- content_->SetLayoutManager(
- new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
- AddChildView(content_);
-
- if (get_use_acceleration_when_possible()) {
- content_->SetPaintToLayer(true);
- content_->SetFillsBoundsOpaquely(false);
- content_->layer()->SetMasksToBounds(true);
- }
- }
+ explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate);
- void Update(const NotificationList::Notifications& popup_notifications) {
- content_->RemoveAllChildViews(true);
- for (NotificationList::Notifications::const_iterator iter =
- popup_notifications.begin();
- iter != popup_notifications.end(); ++iter) {
- MessageView* view =
- NotificationView::ViewForNotification(*iter, list_delegate_);
- view->SetUpView();
- content_->AddChildView(view);
- }
- content_->SizeToPreferredSize();
- content_->InvalidateLayout();
- Layout();
- if (GetWidget())
- GetWidget()->GetRootView()->SchedulePaint();
- }
+ void Update(const NotificationList::Notifications& popup_notifications);
size_t NumMessageViews() const {
return content_->child_count();
@@ -86,15 +40,95 @@ class PopupBubbleContentsView : public views::View {
DISALLOW_COPY_AND_ASSIGN(PopupBubbleContentsView);
};
+PopupBubbleContentsView::PopupBubbleContentsView(
+ NotificationList::Delegate* list_delegate)
+ : list_delegate_(list_delegate) {
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
+
+ content_ = new views::View;
+ content_->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
+ AddChildView(content_);
+
+ if (get_use_acceleration_when_possible()) {
+ content_->SetPaintToLayer(true);
+ content_->SetFillsBoundsOpaquely(false);
+ content_->layer()->SetMasksToBounds(true);
+ }
+}
+
+void PopupBubbleContentsView::Update(
+ const NotificationList::Notifications& popup_notifications) {
+ content_->RemoveAllChildViews(true);
+ for (NotificationList::Notifications::const_iterator iter =
+ popup_notifications.begin();
+ iter != popup_notifications.end(); ++iter) {
+ MessageView* view =
+ NotificationView::ViewForNotification(*iter, list_delegate_);
+ view->SetUpView();
+ content_->AddChildView(view);
+ }
+ content_->SizeToPreferredSize();
+ content_->InvalidateLayout();
+ Layout();
+ if (GetWidget())
+ GetWidget()->GetRootView()->SchedulePaint();
+}
+
+// The timer to call OnAutoClose for |notification|.
+class MessagePopupBubble::AutocloseTimer {
+ public:
+ AutocloseTimer(const NotificationList::Notification& notification,
+ MessagePopupBubble* bubble);
+
+ void Start();
+
+ void Suspend();
+
+ private:
+ const std::string id_;
+ base::TimeDelta delay_;
+ base::Time start_time_;
+ MessagePopupBubble* bubble_;
+ base::OneShotTimer<MessagePopupBubble> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutocloseTimer);
+};
+
+MessagePopupBubble::AutocloseTimer::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);
+}
+
+void MessagePopupBubble::AutocloseTimer::Start() {
+ start_time_ = base::Time::Now();
+ timer_.Start(FROM_HERE,
+ delay_,
+ base::Bind(&MessagePopupBubble::OnAutoClose,
+ base::Unretained(bubble_), id_));
+}
+
+void MessagePopupBubble::AutocloseTimer::Suspend() {
+ base::TimeDelta passed = base::Time::Now() - start_time_;
+ delay_ = std::max(base::TimeDelta(), delay_ - passed);
+ timer_.Reset();
+}
+
// 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 +153,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()) {
+ scoped_ptr<AutocloseTimer> release_timer(iter->second);
+ autoclose_timers_.erase(iter);
+ }
}
size_t MessagePopupBubble::NumMessageViewsForTest() const {
diff --git a/ui/message_center/message_popup_bubble.h b/ui/message_center/message_popup_bubble.h
index 7821386..07d3300 100644
--- a/ui/message_center/message_popup_bubble.h
+++ b/ui/message_center/message_popup_bubble.h
@@ -5,6 +5,10 @@
#ifndef UI_MESSAGE_CENTER_MESSAGE_POPUP_BUBBLE_H_
#define UI_MESSAGE_CENTER_MESSAGE_POPUP_BUBBLE_H_
+#include <map>
+#include <set>
+#include <string>
+
#include "base/timer.h"
#include "ui/message_center/message_bubble_base.h"
#include "ui/message_center/message_center_export.h"
@@ -33,17 +37,15 @@ class MESSAGE_CENTER_EXPORT MessagePopupBubble : public MessageBubbleBase {
size_t NumMessageViewsForTest() const;
private:
- void StartAutoCloseTimer(int priority);
- void StopAutoCloseTimer();
+ class AutocloseTimer;
+
+ void OnAutoClose(const std::string& id);
- void OnAutoClose(int priority);
+ void DeleteTimer(const std::string& id);
- base::OneShotTimer<MessagePopupBubble> autoclose_default_;
- base::OneShotTimer<MessagePopupBubble> autoclose_high_;
+ std::map<std::string, AutocloseTimer*> autoclose_timers_;
PopupBubbleContentsView* contents_view_;
- NotificationList::Notifications popup_notifications_;
- bool should_run_default_timer_;
- bool should_run_high_timer_;
+ std::set<std::string> popup_ids_;
DISALLOW_COPY_AND_ASSIGN(MessagePopupBubble);
};