| 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..0e998cf8a3856136b68cd0c1efc09a800a44275d 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 {
|
|
|