diff options
author | dimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-26 04:42:40 +0000 |
---|---|---|
committer | dimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-26 04:42:40 +0000 |
commit | 4c8f730b286880c832a30201efa7a7c4eecc6af5 (patch) | |
tree | 29b35f0ab660304b77a4199e6e3dd5397079d206 /ui/message_center | |
parent | 25c05b94f5022d1821b1706f5073d41e70be4d35 (diff) | |
download | chromium_src-4c8f730b286880c832a30201efa7a7c4eecc6af5.zip chromium_src-4c8f730b286880c832a30201efa7a7c4eecc6af5.tar.gz chromium_src-4c8f730b286880c832a30201efa7a7c4eecc6af5.tar.bz2 |
Notifications refactor step 2.
Moved notification_types.* from ui/notifications -> ui/message_center (ui/notifications is removed)
Made message_center::Notification a class rather then a struct. Its lifetime is managed by NotificationList.
Moved UnpackOptionalFields from NotificationList to Notification, it is a private member used in ctor.
Removed 2-level collections (set<list>), now all notifications are stored in a std::list (the ScopedVector didn't work since it can't be sorted)
Use stable sort() to figure out the order of notifications in popups and NotificationCenter.
Changed order of notifications in NotificationListUnittest::MarkSinglePopupAsShown - need mukai@ to verify correctness.
NotificationList::RemoveNotification is now void since its bool result was not used.
In NotificationListUnittest, instead of /gtest.gyp:gtest_main include base.gyp:run_all_unittests to initialize ICU etc.
BUG=174164
Review URL: https://chromiumcodereview.appspot.com/12277024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184581 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/message_center')
-rw-r--r-- | ui/message_center/message_center.cc | 13 | ||||
-rw-r--r-- | ui/message_center/message_center.gyp | 4 | ||||
-rw-r--r-- | ui/message_center/message_center.h | 4 | ||||
-rw-r--r-- | ui/message_center/message_center_bubble.cc | 7 | ||||
-rw-r--r-- | ui/message_center/message_center_tray_unittest.cc | 10 | ||||
-rw-r--r-- | ui/message_center/message_popup_bubble.cc | 38 | ||||
-rw-r--r-- | ui/message_center/message_simple_view.cc | 11 | ||||
-rw-r--r-- | ui/message_center/message_simple_view.h | 5 | ||||
-rw-r--r-- | ui/message_center/message_view.cc | 48 | ||||
-rw-r--r-- | ui/message_center/message_view.h | 15 | ||||
-rw-r--r-- | ui/message_center/notification.cc | 83 | ||||
-rw-r--r-- | ui/message_center/notification.h | 109 | ||||
-rw-r--r-- | ui/message_center/notification_list.cc | 414 | ||||
-rw-r--r-- | ui/message_center/notification_list.h | 64 | ||||
-rw-r--r-- | ui/message_center/notification_list_unittest.cc | 168 | ||||
-rw-r--r-- | ui/message_center/notification_types.cc | 23 | ||||
-rw-r--r-- | ui/message_center/notification_types.h | 46 | ||||
-rw-r--r-- | ui/message_center/notification_view.cc | 74 | ||||
-rw-r--r-- | ui/message_center/notification_view.h | 3 |
19 files changed, 625 insertions, 514 deletions
diff --git a/ui/message_center/message_center.cc b/ui/message_center/message_center.cc index 02ea67e..9ef0bc3 100644 --- a/ui/message_center/message_center.cc +++ b/ui/message_center/message_center.cc @@ -7,6 +7,8 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "base/observer_list.h" +#include "ui/message_center/notification.h" +#include "ui/message_center/notification_list.h" namespace message_center { @@ -52,7 +54,7 @@ bool MessageCenter::HasPopupNotifications() const { // Client code interface. void MessageCenter::AddNotification( - ui::notifications::NotificationType type, + NotificationType type, const std::string& id, const string16& title, const string16& message, @@ -76,8 +78,7 @@ void MessageCenter::UpdateNotification( } void MessageCenter::RemoveNotification(const std::string& id) { - if (!notification_list_->RemoveNotification(id)) - return; + notification_list_->RemoveNotification(id); NotifyMessageCenterChanged(false); } @@ -111,13 +112,13 @@ void MessageCenter::SendRemoveNotification(const std::string& id) { void MessageCenter::SendRemoveAllNotifications() { if (delegate_) { - NotificationList::Notifications notifications; - notification_list_->GetNotifications(¬ifications); + const NotificationList::Notifications& notifications = + notification_list_->GetNotifications(); for (NotificationList::Notifications::const_iterator loopiter = notifications.begin(); loopiter != notifications.end(); ) { NotificationList::Notifications::const_iterator curiter = loopiter++; - std::string notification_id = curiter->id; + std::string notification_id = (*curiter)->id(); // May call RemoveNotification and erase curiter. delegate_->NotificationRemoved(notification_id); } diff --git a/ui/message_center/message_center.gyp b/ui/message_center/message_center.gyp index 8cfad64..a1e583f 100644 --- a/ui/message_center/message_center.gyp +++ b/ui/message_center/message_center.gyp @@ -52,6 +52,8 @@ 'notification.h', 'notification_list.cc', 'notification_list.h', + 'notification_types.cc', + 'notification_types.h', 'notification_view.cc', 'notification_view.h', 'notifier_settings_view.cc', @@ -69,10 +71,10 @@ 'type': 'executable', 'dependencies': [ '../../base/base.gyp:base', + '../../base/base.gyp:run_all_unittests', '../../base/base.gyp:test_support_base', '../../skia/skia.gyp:skia', '../../testing/gtest.gyp:gtest', - '../../testing/gtest.gyp:gtest_main', '../ui.gyp:ui', 'message_center', ], diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h index 19b84d3..c4009cc 100644 --- a/ui/message_center/message_center.h +++ b/ui/message_center/message_center.h @@ -12,7 +12,7 @@ #include "ui/gfx/native_widget_types.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification_list.h" -#include "ui/notifications/notification_types.h" +#include "ui/message_center/notification_types.h" namespace base { class DictionaryValue; @@ -106,7 +106,7 @@ class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationList::Delegate { // from the extension. Otherwise if |display_source| is provided, a menu item // showing the source and allowing notifications from that source to be // disabled will be shown. All actual disabling is handled by the Delegate. - void AddNotification(ui::notifications::NotificationType type, + void AddNotification(NotificationType type, const std::string& id, const string16& title, const string16& message, diff --git a/ui/message_center/message_center_bubble.cc b/ui/message_center/message_center_bubble.cc index 8cf507a..141b5be 100644 --- a/ui/message_center/message_center_bubble.cc +++ b/ui/message_center/message_center_bubble.cc @@ -408,9 +408,8 @@ class MessageCenterContentsView : public views::View { for (NotificationList::Notifications::const_iterator iter = notifications.begin(); iter != notifications.end(); ++iter) { MessageView* view = - NotificationView::ViewForNotification(*iter, list_delegate_); + NotificationView::ViewForNotification(*(*iter), list_delegate_); view->set_scroller(scroller_); - view->SetUpView(); if (IsRichNotificationEnabled()) view->set_border(new MessageViewShadowBorder()); scroll_content_->AddChildView(view); @@ -508,8 +507,8 @@ void MessageCenterBubble::OnBubbleViewDestroyed() { void MessageCenterBubble::UpdateBubbleView() { if (!bubble_view()) return; // Could get called after view is closed - NotificationList::Notifications notifications; - list_delegate()->GetNotificationList()->GetNotifications(¬ifications); + const NotificationList::Notifications& notifications = + list_delegate()->GetNotificationList()->GetNotifications(); contents_view_->Update(notifications); bubble_view()->Show(); bubble_view()->UpdateBubble(); diff --git a/ui/message_center/message_center_tray_unittest.cc b/ui/message_center/message_center_tray_unittest.cc index e3fa107..406e360 100644 --- a/ui/message_center/message_center_tray_unittest.cc +++ b/ui/message_center/message_center_tray_unittest.cc @@ -7,7 +7,7 @@ #include "base/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/message_center/message_center.h" -#include "ui/notifications/notification_types.h" +#include "ui/message_center/notification_types.h" namespace message_center { namespace { @@ -102,7 +102,7 @@ TEST_F(MessageCenterTrayTest, BasicPopup) { ASSERT_FALSE(message_center_tray_->message_center_visible()); message_center_->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, + message_center::NOTIFICATION_TYPE_SIMPLE, "BasicPopup", ASCIIToUTF16("Test Web Notification"), ASCIIToUTF16("Notification message body."), @@ -124,7 +124,7 @@ TEST_F(MessageCenterTrayTest, MessageCenterClosesPopups) { ASSERT_FALSE(message_center_tray_->message_center_visible()); message_center_->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, + message_center::NOTIFICATION_TYPE_SIMPLE, "MessageCenterClosesPopups", ASCIIToUTF16("Test Web Notification"), ASCIIToUTF16("Notification message body."), @@ -142,7 +142,7 @@ TEST_F(MessageCenterTrayTest, MessageCenterClosesPopups) { ASSERT_TRUE(message_center_tray_->message_center_visible()); message_center_->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, + message_center::NOTIFICATION_TYPE_SIMPLE, "MessageCenterClosesPopups2", ASCIIToUTF16("Test Web Notification"), ASCIIToUTF16("Notification message body."), @@ -170,7 +170,7 @@ TEST_F(MessageCenterTrayTest, ShowBubbleFails) { ASSERT_FALSE(message_center_tray_->message_center_visible()); message_center_->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, + message_center::NOTIFICATION_TYPE_SIMPLE, "ShowBubbleFails", ASCIIToUTF16("Test Web Notification"), ASCIIToUTF16("Notification message body."), diff --git a/ui/message_center/message_popup_bubble.cc b/ui/message_center/message_popup_bubble.cc index 3b27a4a..88d1acb 100644 --- a/ui/message_center/message_popup_bubble.cc +++ b/ui/message_center/message_popup_bubble.cc @@ -8,8 +8,8 @@ #include "base/stl_util.h" #include "ui/message_center/message_view.h" #include "ui/message_center/notification.h" +#include "ui/message_center/notification_types.h" #include "ui/message_center/notification_view.h" -#include "ui/notifications/notification_types.h" #include "ui/views/bubble/tray_bubble_view.h" #include "ui/views/layout/box_layout.h" #include "ui/views/view.h" @@ -28,7 +28,7 @@ class PopupBubbleContentsView : public views::View { public: explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate); - void Update(const NotificationList::Notifications& popup_notifications); + void Update(const NotificationList::PopupNotifications& popup_notifications); size_t NumMessageViews() const { return content_->child_count(); @@ -59,15 +59,13 @@ PopupBubbleContentsView::PopupBubbleContentsView( } void PopupBubbleContentsView::Update( - const NotificationList::Notifications& popup_notifications) { + const NotificationList::PopupNotifications& popup_notifications) { content_->RemoveAllChildViews(true); - for (NotificationList::Notifications::const_iterator iter = + for (NotificationList::PopupNotifications::const_iterator iter = popup_notifications.begin(); iter != popup_notifications.end(); ++iter) { - MessageView* view = - NotificationView::ViewForNotification(*iter, list_delegate_); - view->SetUpView(); - content_->AddChildView(view); + content_->AddChildView( + NotificationView::ViewForNotification(*(*iter), list_delegate_)); } content_->SizeToPreferredSize(); content_->InvalidateLayout(); @@ -79,7 +77,7 @@ void PopupBubbleContentsView::Update( // The timer to call OnAutoClose for |notification|. class MessagePopupBubble::AutocloseTimer { public: - AutocloseTimer(const Notification& notification, MessagePopupBubble* bubble); + AutocloseTimer(Notification* notification, MessagePopupBubble* bubble); void Start(); @@ -96,12 +94,12 @@ class MessagePopupBubble::AutocloseTimer { }; MessagePopupBubble::AutocloseTimer::AutocloseTimer( - const Notification& notification, + Notification* notification, MessagePopupBubble* bubble) - : id_(notification.id), + : id_(notification->id()), bubble_(bubble) { int seconds = kAutocloseDefaultDelaySeconds; - if (notification.priority > ui::notifications::DEFAULT_PRIORITY) + if (notification->priority() > DEFAULT_PRIORITY) seconds = kAutocloseHighPriorityDelaySeconds; delay_ = base::TimeDelta::FromSeconds(seconds); } @@ -153,8 +151,8 @@ void MessagePopupBubble::OnBubbleViewDestroyed() { } void MessagePopupBubble::UpdateBubbleView() { - NotificationList::Notifications popups; - list_delegate()->GetNotificationList()->GetPopupNotifications(&popups); + NotificationList::PopupNotifications popups = + list_delegate()->GetNotificationList()->GetPopupNotifications(); if (popups.size() == 0) { if (bubble_view()) @@ -170,17 +168,19 @@ void MessagePopupBubble::UpdateBubbleView() { old_popup_ids.swap(popup_ids_); // Start autoclose timers. - for (NotificationList::Notifications::const_iterator iter = popups.begin(); + for (NotificationList::PopupNotifications::const_iterator iter = + popups.begin(); iter != popups.end(); ++iter) { + std::string id = (*iter)->id(); std::map<std::string, AutocloseTimer*>::const_iterator timer_iter = - autoclose_timers_.find(iter->id); + autoclose_timers_.find(id); if (timer_iter == autoclose_timers_.end()) { AutocloseTimer *timer = new AutocloseTimer(*iter, this); - autoclose_timers_[iter->id] = timer; + autoclose_timers_[id] = timer; timer->Start(); } - popup_ids_.insert(iter->id); - old_popup_ids.erase(iter->id); + popup_ids_.insert(id); + old_popup_ids.erase(id); } // Stops timers whose notifications are gone. diff --git a/ui/message_center/message_simple_view.cc b/ui/message_center/message_simple_view.cc index 94e1384..8f85b45 100644 --- a/ui/message_center/message_simple_view.cc +++ b/ui/message_center/message_simple_view.cc @@ -31,6 +31,7 @@ MessageSimpleView::MessageSimpleView( close->SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); old_style_close_button_.reset(close); + SetUpView(notification); } MessageSimpleView::~MessageSimpleView() { @@ -59,20 +60,20 @@ gfx::Size MessageSimpleView::GetPreferredSize() { return size; } -void MessageSimpleView::SetUpView() { +void MessageSimpleView::SetUpView(const Notification& notification) { views::ImageView* icon = new views::ImageView; icon->SetImageSize( gfx::Size(kWebNotificationIconSize, kWebNotificationIconSize)); - icon->SetImage(notification().primary_icon); + icon->SetImage(notification.primary_icon()); - views::Label* title = new views::Label(notification().title); + views::Label* title = new views::Label(notification.title()); title->SetHorizontalAlignment(gfx::ALIGN_LEFT); title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD)); - views::Label* message = new views::Label(notification().message); + views::Label* message = new views::Label(notification.message()); message->SetHorizontalAlignment(gfx::ALIGN_LEFT); message->SetMultiLine(true); - SkColor bg_color = notification().is_read ? + SkColor bg_color = notification.is_read() ? kNotificationReadColor : kNotificationColor; content_view_.reset(new views::View); content_view_->set_background( diff --git a/ui/message_center/message_simple_view.h b/ui/message_center/message_simple_view.h index b55ffb1..624f511 100644 --- a/ui/message_center/message_simple_view.h +++ b/ui/message_center/message_simple_view.h @@ -10,7 +10,7 @@ namespace message_center { -struct Notification; +class Notification; // A simple view for a notification entry (icon + message + buttons). class MessageSimpleView : public MessageView { @@ -20,7 +20,6 @@ class MessageSimpleView : public MessageView { virtual ~MessageSimpleView(); // Overridden from MessageView: - virtual void SetUpView() OVERRIDE; virtual void ButtonPressed(views::Button* sender, const ui::Event& event) OVERRIDE; @@ -32,6 +31,8 @@ class MessageSimpleView : public MessageView { MessageSimpleView(); private: + void SetUpView(const Notification& notification); + scoped_ptr<views::ImageButton> old_style_close_button_; scoped_ptr<views::View> content_view_; diff --git a/ui/message_center/message_view.cc b/ui/message_center/message_view.cc index 27535b7..4bb81d1 100644 --- a/ui/message_center/message_view.cc +++ b/ui/message_center/message_view.cc @@ -144,20 +144,23 @@ class WebNotificationMenuModel : public ui::SimpleMenuModel, public ui::SimpleMenuModel::Delegate { public: WebNotificationMenuModel(NotificationList::Delegate* list_delegate, - const Notification& notification) + const std::string& notification_id, + const string16& display_source, + const std::string& extension_id) : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), list_delegate_(list_delegate), - notification_(notification) { + notification_id_(notification_id), + display_source_(display_source) { // Add 'disable notifications' menu item. - if (!notification.extension_id.empty()) { + if (!extension_id.empty()) { AddItem(kToggleExtensionCommand, GetLabelForCommandId(kToggleExtensionCommand)); - } else if (!notification.display_source.empty()) { + } else if (!display_source.empty()) { AddItem(kTogglePermissionCommand, GetLabelForCommandId(kTogglePermissionCommand)); } // Add settings menu item. - if (!notification.display_source.empty()) { + if (!display_source.empty()) { AddItem(kShowSettingsCommand, GetLabelForCommandId(kShowSettingsCommand)); } @@ -173,7 +176,7 @@ class WebNotificationMenuModel : public ui::SimpleMenuModel, return l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_EXTENSIONS_DISABLE); case kTogglePermissionCommand: return l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_SITE_DISABLE, - notification_.display_source); + display_source_); case kShowSettingsCommand: return l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS); default: @@ -200,13 +203,13 @@ class WebNotificationMenuModel : public ui::SimpleMenuModel, virtual void ExecuteCommand(int command_id) OVERRIDE { switch (command_id) { case kToggleExtensionCommand: - list_delegate_->DisableNotificationByExtension(notification_.id); + list_delegate_->DisableNotificationByExtension(notification_id_); break; case kTogglePermissionCommand: - list_delegate_->DisableNotificationByUrl(notification_.id); + list_delegate_->DisableNotificationByUrl(notification_id_); break; case kShowSettingsCommand: - list_delegate_->ShowNotificationSettings(notification_.id); + list_delegate_->ShowNotificationSettings(notification_id_); break; default: NOTREACHED(); @@ -214,17 +217,19 @@ class WebNotificationMenuModel : public ui::SimpleMenuModel, } private: - NotificationList::Delegate* list_delegate_; - Notification notification_; + NotificationList::Delegate* list_delegate_; // Weak, global MessageCenter + std::string notification_id_; + string16 display_source_; DISALLOW_COPY_AND_ASSIGN(WebNotificationMenuModel); }; -MessageView::MessageView( - NotificationList::Delegate* list_delegate, - const Notification& notification) +MessageView::MessageView(NotificationList::Delegate* list_delegate, + const Notification& notification) : list_delegate_(list_delegate), - notification_(notification), + notification_id_(notification.id()), + display_source_(notification.display_source()), + extension_id_(notification.extension_id()), scroller_(NULL) { ControlButton *close = new ControlButton(this); close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding); @@ -245,13 +250,13 @@ bool MessageView::OnMousePressed(const ui::MouseEvent& event) { ShowMenu(event.location()); return true; } - list_delegate_->OnNotificationClicked(notification_.id); + list_delegate_->OnNotificationClicked(notification_id_); return true; } void MessageView::OnGestureEvent(ui::GestureEvent* event) { if (event->type() == ui::ET_GESTURE_TAP) { - list_delegate_->OnNotificationClicked(notification_.id); + list_delegate_->OnNotificationClicked(notification_id_); event->SetHandled(); return; } @@ -278,11 +283,14 @@ void MessageView::OnGestureEvent(ui::GestureEvent* event) { void MessageView::ButtonPressed(views::Button* sender, const ui::Event& event) { if (sender == close_button()) - list_delegate_->SendRemoveNotification(notification_.id); + list_delegate_->SendRemoveNotification(notification_id_); } void MessageView::ShowMenu(gfx::Point screen_location) { - WebNotificationMenuModel menu_model(list_delegate_, notification_); + WebNotificationMenuModel menu_model(list_delegate_, + notification_id_, + display_source_, + extension_id_); if (menu_model.GetItemCount() == 0) return; @@ -299,7 +307,7 @@ void MessageView::ShowMenu(gfx::Point screen_location) { } void MessageView::OnSlideOut() { - list_delegate_->SendRemoveNotification(notification_.id); + list_delegate_->SendRemoveNotification(notification_id_); } } // namespace message_center diff --git a/ui/message_center/message_view.h b/ui/message_center/message_view.h index be36eb4..cb6beee 100644 --- a/ui/message_center/message_view.h +++ b/ui/message_center/message_view.h @@ -34,10 +34,6 @@ class MessageView : public views::SlideOutView, virtual ~MessageView(); - // Creates the elements that make up the view layout. Must be called - // immediately after construction. - virtual void SetUpView() = 0; - void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; } // Overridden from views::View. @@ -60,13 +56,18 @@ class MessageView : public views::SlideOutView, virtual void OnSlideOut() OVERRIDE; NotificationList::Delegate* list_delegate() { return list_delegate_; } - Notification& notification() { return notification_; } + const std::string& notification_id() { return notification_id_; } + const string16& display_source() const { return display_source_; } + const std::string& extension_id() const { return extension_id_; } views::ImageButton* close_button() { return close_button_.get(); } views::ScrollView* scroller() { return scroller_; } private: - NotificationList::Delegate* list_delegate_; - Notification notification_; + NotificationList::Delegate* list_delegate_; // Weak, global (MessageCenter). + std::string notification_id_; + string16 display_source_; + std::string extension_id_; + scoped_ptr<views::ImageButton> close_button_; views::ScrollView* scroller_; diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc index c52cb95..5a92c09 100644 --- a/ui/message_center/notification.cc +++ b/ui/message_center/notification.cc @@ -4,19 +4,94 @@ #include "ui/message_center/notification.h" +#include "base/logging.h" +#include "ui/message_center/notification_types.h" + +namespace { +unsigned g_next_serial_number_ = 0; +} + namespace message_center { -NotificationItem::NotificationItem(string16 title, string16 message) +NotificationItem::NotificationItem(const string16& title, + const string16& message) : title(title), message(message) { } -Notification::Notification() - : is_read(false), - shown_as_popup(false) { +ButtonInfo::ButtonInfo(const string16& title) + : title(title) { +} + +Notification::Notification(NotificationType type, + const std::string& id, + const string16& title, + const string16& message, + const string16& display_source, + const std::string& extension_id, + const DictionaryValue* optional_fields) + : type_(type), + id_(id), + title_(title), + message_(message), + display_source_(display_source), + extension_id_(extension_id), + priority_(DEFAULT_PRIORITY), + timestamp_(base::Time::Now()), + serial_number_(g_next_serial_number_++), + is_read_(false), + shown_as_popup_(false) { + // This can override some data members initialized to deafule values above. + ApplyOptionalFields(optional_fields); } Notification::~Notification() { } +bool Notification::SetButtonIcon(size_t index, const gfx::ImageSkia& icon) { + if (index >= buttons_.size()) + return false; + buttons_[index].icon = icon; + return true; +} + +void Notification::ApplyOptionalFields(const DictionaryValue* fields) { + if (!fields) + return; + + fields->GetInteger(kPriorityKey, &priority_); + if (fields->HasKey(kTimestampKey)) { + std::string time_string; + fields->GetString(kTimestampKey, &time_string); + base::Time::FromString(time_string.c_str(), ×tamp_); + } + if (fields->HasKey(kButtonOneTitleKey) || + fields->HasKey(kButtonOneIconUrlKey)) { + string16 title; + string16 icon; + if (fields->GetString(kButtonOneTitleKey, &title) || + fields->GetString(kButtonOneIconUrlKey, &icon)) { + buttons_.push_back(ButtonInfo(title)); + if (fields->GetString(kButtonTwoTitleKey, &title) || + fields->GetString(kButtonTwoIconUrlKey, &icon)) { + buttons_.push_back(ButtonInfo(title)); + } + } + } + fields->GetString(kExpandedMessageKey, &expanded_message_); + if (fields->HasKey(kItemsKey)) { + const ListValue* items; + CHECK(fields->GetList(kItemsKey, &items)); + for (size_t i = 0; i < items->GetSize(); ++i) { + string16 title; + string16 message; + const base::DictionaryValue* item; + items->GetDictionary(i, &item); + item->GetString(kItemTitleKey, &title); + item->GetString(kItemMessageKey, &message); + items_.push_back(NotificationItem(title, message)); + } + } +} + } // namespace message_center diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h index 4e66035..3dfc813 100644 --- a/ui/message_center/notification.h +++ b/ui/message_center/notification.h @@ -5,13 +5,15 @@ #ifndef UI_MESSAGE_CENTER_NOTIFICATION_H_ #define UI_MESSAGE_CENTER_NOTIFICATION_H_ +#include <string> #include <vector> #include "base/string16.h" #include "base/time.h" +#include "base/values.h" #include "ui/gfx/image/image_skia.h" #include "ui/message_center/message_center_export.h" -#include "ui/notifications/notification_types.h" +#include "ui/message_center/notification_types.h" namespace message_center { @@ -19,37 +21,90 @@ struct MESSAGE_CENTER_EXPORT NotificationItem { string16 title; string16 message; - NotificationItem(string16 title, string16 message); + NotificationItem(const string16& title, const string16& message); }; -struct MESSAGE_CENTER_EXPORT Notification { - Notification(); +struct MESSAGE_CENTER_EXPORT ButtonInfo { + string16 title; + gfx::ImageSkia icon; + + ButtonInfo(const string16& title); +}; + +class MESSAGE_CENTER_EXPORT Notification { + public: + Notification(NotificationType type, + const std::string& id, + const string16& title, + const string16& message, + const string16& display_source, + const std::string& extension_id, + const DictionaryValue* optional_fields); // May be NULL. virtual ~Notification(); - ui::notifications::NotificationType type; - std::string id; - string16 title; - string16 message; - string16 display_source; - std::string extension_id; - - // Begin unpacked values from optional_fields - int priority; - base::Time timestamp; - std::vector<string16> button_titles; - string16 expanded_message; - std::vector<NotificationItem> items; - // End unpacked values - - // Images fetched asynchronously - gfx::ImageSkia primary_icon; - gfx::ImageSkia image; - std::vector<gfx::ImageSkia> button_icons; - - bool is_read; // True if this has been seen in the message center - bool shown_as_popup; // True if this has been shown as a popup notification + NotificationType type() const { return type_; } + const std::string& id() const { return id_; } + const string16& title() const { return title_; } + const string16& message() const { return message_; } + const string16& display_source() const { return display_source_; } + const std::string& extension_id() const { return extension_id_; } + + // Begin unpacked values from optional_fields. + int priority() { return priority_; } + base::Time timestamp() const { return timestamp_; } + const string16& expanded_message() const { return expanded_message_; } + const std::vector<NotificationItem>& items() const { return items_; } + // End unpacked values. + + // Images fetched asynchronously. + const gfx::ImageSkia& primary_icon() const { return primary_icon_; } + void set_primary_icon(const gfx::ImageSkia& icon) { primary_icon_ = icon; } + + const gfx::ImageSkia& image() const { return image_; } + void set_image(const gfx::ImageSkia& image) { image_ = image; } + + // Buttons, with icons fetched asynchronously. + const std::vector<ButtonInfo>& buttons() const { return buttons_; } + bool SetButtonIcon(size_t index, const gfx::ImageSkia& icon); + + // Status in MessageCenter. + bool is_read() const { return is_read_; } + void set_is_read(bool is_read) { is_read_ = is_read; } + + bool shown_as_popup() const { return shown_as_popup_; } + void set_shown_as_popup(bool shown_as_popup) { + shown_as_popup_ = shown_as_popup; + } + + // Used to keep the order of notifications with the same timestamp. + // The notification with lesser serial_number is considered 'older'. + unsigned serial_number() { return serial_number_; } + + private: + // Unpacks the provided |optional_fields| and applies the values to override + // the notification's data members. + void ApplyOptionalFields(const DictionaryValue* optional_fields); + + NotificationType type_; + std::string id_; + string16 title_; + string16 message_; + string16 display_source_; + std::string extension_id_; + int priority_; + base::Time timestamp_; + unsigned serial_number_; + string16 expanded_message_; + std::vector<NotificationItem> items_; + gfx::ImageSkia primary_icon_; + gfx::ImageSkia image_; + std::vector<ButtonInfo> buttons_; + bool is_read_; // True if this has been seen in the message center. + bool shown_as_popup_; // True if this has been shown as a popup notification. + + DISALLOW_COPY_AND_ASSIGN(Notification); }; } // namespace message_center -#endif // UI_MESSAGE_CENTER_NOTIFICATION_H_ +#endif // UI_MESSAGE_CENTER_NOTIFICATION_H_ diff --git a/ui/message_center/notification_list.cc b/ui/message_center/notification_list.cc index 677c24d..9fb8485 100644 --- a/ui/message_center/notification_list.cc +++ b/ui/message_center/notification_list.cc @@ -6,12 +6,35 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/stl_util.h" #include "base/time.h" #include "base/values.h" #include "ui/message_center/notification.h" +#include "ui/message_center/notification_types.h" namespace message_center { +bool ComparePriorityTimestampSerial::operator()(Notification* n1, + Notification* n2) { + if (n1->priority() > n2->priority()) // Higher pri go first. + return true; + if (n1->priority() < n2->priority()) + return false; + return CompareTimestampSerial()(n1, n2); +} + +bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) { + if (n1->timestamp() > n2->timestamp()) // Newer come first. + return true; + if (n1->timestamp() < n2->timestamp()) + return false; + if (n1->serial_number() > n2->serial_number()) // Newer come first. + return true; + if (n1->serial_number() < n2->serial_number()) + return false; + return false; +} + const size_t NotificationList::kMaxVisibleMessageCenterNotifications = 100; const size_t NotificationList::kMaxVisiblePopupNotifications = 2; @@ -23,6 +46,7 @@ NotificationList::NotificationList(Delegate* delegate) } NotificationList::~NotificationList() { + STLDeleteContainerPointers(notifications_.begin(), notifications_.end()); } void NotificationList::SetMessageCenterVisible(bool visible) { @@ -35,83 +59,27 @@ void NotificationList::SetMessageCenterVisible(bool visible) { if (!visible) unread_count_ = 0; - for (NotificationMap::iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - for (Notifications::iterator iter = mapiter->second.begin(); - iter != mapiter->second.end(); ++iter) { - if (visible) - iter->shown_as_popup = true; - else - iter->is_read = true; - } + for (Notifications::iterator iter = notifications_.begin(); + iter != notifications_.end(); ++iter) { + if (visible) + (*iter)->set_shown_as_popup(true); + else + (*iter)->set_is_read(true); } } void NotificationList::AddNotification( - ui::notifications::NotificationType type, + NotificationType type, const std::string& id, const string16& title, const string16& message, const string16& display_source, const std::string& extension_id, const DictionaryValue* optional_fields) { - Notification notification; - notification.type = type; - notification.id = id; - notification.title = title; - notification.message = message; - notification.display_source = display_source; - notification.extension_id = extension_id; - - // Initialize primitive fields before unpacking optional fields. - notification.priority = ui::notifications::DEFAULT_PRIORITY; - - UnpackOptionalFields(optional_fields, ¬ification); - - PushNotification(notification); -} - -void NotificationList::UnpackOptionalFields(const DictionaryValue* fields, - Notification* notification) { - if (!fields) - return; - - fields->GetInteger(ui::notifications::kPriorityKey, ¬ification->priority); - if (fields->HasKey(ui::notifications::kTimestampKey)) { - double time_double; - fields->GetDouble(ui::notifications::kTimestampKey, &time_double); - notification->timestamp = base::Time::FromJsTime(time_double); - } - if (fields->HasKey(ui::notifications::kButtonOneTitleKey) || - fields->HasKey(ui::notifications::kButtonOneIconUrlKey)) { - string16 title; - string16 icon; - if (fields->GetString(ui::notifications::kButtonOneTitleKey, &title) || - fields->GetString(ui::notifications::kButtonOneIconUrlKey, &icon)) { - notification->button_titles.push_back(title); - notification->button_icons.push_back(gfx::ImageSkia()); - if (fields->GetString(ui::notifications::kButtonTwoTitleKey, &title) || - fields->GetString(ui::notifications::kButtonTwoIconUrlKey, &icon)) { - notification->button_titles.push_back(title); - notification->button_icons.push_back(gfx::ImageSkia()); - } - } - } - fields->GetString(ui::notifications::kExpandedMessageKey, - ¬ification->expanded_message); - if (fields->HasKey(ui::notifications::kItemsKey)) { - const ListValue* items; - CHECK(fields->GetList(ui::notifications::kItemsKey, &items)); - for (size_t i = 0; i < items->GetSize(); ++i) { - string16 title; - string16 message; - const base::DictionaryValue* item; - items->GetDictionary(i, &item); - item->GetString(ui::notifications::kItemTitleKey, &title); - item->GetString(ui::notifications::kItemMessageKey, &message); - notification->items.push_back(NotificationItem(title, message)); - } - } + scoped_ptr<Notification> notification( + new Notification(type, id, title, message, display_source, extension_id, + optional_fields)); + PushNotification(notification.Pass()); } void NotificationList::UpdateNotificationMessage( @@ -120,176 +88,159 @@ void NotificationList::UpdateNotificationMessage( const string16& title, const string16& message, const base::DictionaryValue* optional_fields) { - Notifications::iterator iter; - if (!GetNotification(old_id, &iter)) + Notifications::iterator iter = GetNotification(old_id); + if (iter == notifications_.end()) return; - // Copy and update notification, then move it to the front of the list. - Notification notification(*iter); - notification.id = new_id; - notification.title = title; - notification.message = message; - UnpackOptionalFields(optional_fields, ¬ification); + + // Copy and update a notification. It has an effect of setting a new timestamp + // if not overridden by optional_fields + scoped_ptr<Notification> notification( + new Notification((*iter)->type(), + new_id, + title, + message, + (*iter)->display_source(), + (*iter)->extension_id(), + optional_fields)); EraseNotification(iter); - PushNotification(notification); + PushNotification(notification.Pass()); } -bool NotificationList::RemoveNotification(const std::string& id) { - Notifications::iterator iter; - if (!GetNotification(id, &iter)) - return false; - EraseNotification(iter); - return true; +void NotificationList::RemoveNotification(const std::string& id) { + EraseNotification(GetNotification(id)); } void NotificationList::RemoveAllNotifications() { - notifications_.clear(); + for (Notifications::iterator loopiter = notifications_.begin(); + loopiter != notifications_.end(); ) { + Notifications::iterator curiter = loopiter++; + EraseNotification(curiter); + } unread_count_ = 0; } void NotificationList::SendRemoveNotificationsBySource( const std::string& id) { - Notifications::iterator source_iter; - if (!GetNotification(id, &source_iter)) + Notifications::iterator source_iter = GetNotification(id); + if (source_iter == notifications_.end()) return; - string16 display_source = source_iter->display_source; - for (NotificationMap::iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - for (Notifications::iterator loopiter = mapiter->second.begin(); - loopiter != mapiter->second.end(); ) { - Notifications::iterator curiter = loopiter++; - if (curiter->display_source == display_source) - delegate_->SendRemoveNotification(curiter->id); - } + string16 display_source = (*source_iter)->display_source(); + + for (Notifications::iterator loopiter = notifications_.begin(); + loopiter != notifications_.end(); ) { + Notifications::iterator curiter = loopiter++; + if ((*curiter)->display_source() == display_source) + delegate_->SendRemoveNotification((*curiter)->id()); } } void NotificationList::SendRemoveNotificationsByExtension( const std::string& id) { - Notifications::iterator source_iter; - if (!GetNotification(id, &source_iter)) + Notifications::iterator source_iter = GetNotification(id); + if (source_iter == notifications_.end()) return; - std::string extension_id = source_iter->extension_id; - for (NotificationMap::iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - for (Notifications::iterator loopiter = mapiter->second.begin(); - loopiter != mapiter->second.end(); ) { - Notifications::iterator curiter = loopiter++; - if (curiter->extension_id == extension_id) - delegate_->SendRemoveNotification(curiter->id); - } + std::string extension_id = (*source_iter)->extension_id(); + for (Notifications::iterator loopiter = notifications_.begin(); + loopiter != notifications_.end(); ) { + Notifications::iterator curiter = loopiter++; + if ((*curiter)->extension_id() == extension_id) + delegate_->SendRemoveNotification((*curiter)->id()); } } bool NotificationList::SetNotificationIcon(const std::string& notification_id, const gfx::ImageSkia& image) { - Notifications::iterator iter; - if (!GetNotification(notification_id, &iter)) + Notifications::iterator iter = GetNotification(notification_id); + if (iter == notifications_.end()) return false; - iter->primary_icon = image; + (*iter)->set_primary_icon(image); return true; } bool NotificationList::SetNotificationImage(const std::string& notification_id, const gfx::ImageSkia& image) { - Notifications::iterator iter; - if (!GetNotification(notification_id, &iter)) + Notifications::iterator iter = GetNotification(notification_id); + if (iter == notifications_.end()) return false; - iter->image = image; + (*iter)->set_image(image); return true; } bool NotificationList::SetNotificationButtonIcon( const std::string& notification_id, int button_index, const gfx::ImageSkia& image) { - Notifications::iterator iter; - if (!GetNotification(notification_id, &iter) || - static_cast<size_t>(button_index) >= iter->button_icons.size()) + Notifications::iterator iter = GetNotification(notification_id); + if (iter == notifications_.end()) return false; - iter->button_icons[button_index] = image; - return true; + return (*iter)->SetButtonIcon(button_index, image); } bool NotificationList::HasNotification(const std::string& id) { - Notifications::iterator dummy; - return GetNotification(id, &dummy); + return GetNotification(id) != notifications_.end(); } bool NotificationList::HasPopupNotifications() { - for (int i = ui::notifications::DEFAULT_PRIORITY; - i <= ui::notifications::MAX_PRIORITY; ++i) { - Notifications notifications = notifications_[i]; - if (!notifications.empty() && !notifications.front().shown_as_popup) + for (Notifications::iterator iter = notifications_.begin(); + iter != notifications_.end(); ++iter) { + if ((*iter)->priority() < DEFAULT_PRIORITY) + break; + if (!(*iter)->shown_as_popup()) return true; } return false; } -void NotificationList::GetPopupNotifications( - NotificationList::Notifications* notifications) { - typedef std::pair<Notifications::iterator, Notifications::iterator> - NotificationRange; - // In the popup, latest should come earlier. - std::list<NotificationRange> iters; - for (int i = ui::notifications::DEFAULT_PRIORITY; - i <= ui::notifications::MAX_PRIORITY; ++i) { - Notifications::iterator first, last; - GetPopupIterators(i, &first, &last); - if (first != last) - iters.push_back(make_pair(first, last)); - } - notifications->clear(); - while (!iters.empty()) { - std::list<NotificationRange>::iterator max_iter = iters.begin(); - std::list<NotificationRange>::iterator iter = max_iter; - iter++; - for (; iter != iters.end(); ++iter) { - if (max_iter->first->timestamp < iter->first->timestamp) - max_iter = iter; +NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { + PopupNotifications result; + size_t default_priority_popup_count = 0; + + // Collect notifications that should be shown as popups. Start from oldest. + for (Notifications::const_reverse_iterator iter = notifications_.rbegin(); + iter != notifications_.rend(); iter++) { + + if ((*iter)->shown_as_popup()) + continue; + + // No popups for LOW/MIN priority. + if ((*iter)->priority() < DEFAULT_PRIORITY) + break; + + // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority + // will return at most kMaxVisiblePopupNotifications entries. If the + // popup entries are more, older entries are used. see crbug.com/165768 + if ((*iter)->priority() == DEFAULT_PRIORITY && + default_priority_popup_count++ >= kMaxVisiblePopupNotifications) { + continue; } - notifications->push_back(*(max_iter->first)); - ++(max_iter->first); - if (max_iter->first == max_iter->second) - iters.erase(max_iter); + + result.insert(*iter); } + return result; } void NotificationList::MarkPopupsAsShown(int priority) { - Notifications::iterator first, last; - GetPopupIterators(priority, &first, &last); - for (Notifications::iterator iter = first; iter != last; ++iter) - iter->shown_as_popup = true; + PopupNotifications popups = GetPopupNotifications(); + for (PopupNotifications::iterator iter = popups.begin(); + iter != popups.end(); ++iter) { + if ((*iter)->priority() == priority) + (*iter)->set_shown_as_popup(true); + } } void NotificationList::MarkSinglePopupAsShown( const std::string& id, bool mark_notification_as_read) { - Notifications::iterator iter; - if (!GetNotification(id, &iter)) - return; + Notifications::iterator iter = GetNotification(id); + DCHECK(iter != notifications_.end()); - if (iter->shown_as_popup) + if ((*iter)->shown_as_popup()) return; - // Moves the item to the beginning of the already-shown items. - Notification notification = *iter; - notification.shown_as_popup = true; + (*iter)->set_shown_as_popup(true); + if (mark_notification_as_read) { --unread_count_; - notification.is_read = true; - } - - notifications_[notification.priority].erase(iter); - for (Notifications::iterator iter2 = - notifications_[notification.priority].begin(); - iter2 != notifications_[notification.priority].end(); iter2++) { - if (iter2->shown_as_popup) { - notifications_[notification.priority].insert(iter2, notification); - return; - } + (*iter)->set_is_read(true); } - - // No notifications are already shown as popup, so just re-adding at the end - // of the list. - notifications_[notification.priority].push_back(notification); } void NotificationList::SetQuietMode(bool quiet_mode) { @@ -311,121 +262,64 @@ void NotificationList::EnterQuietModeWithExpire( } } -void NotificationList::GetNotifications( - NotificationList::Notifications* notifications) const { - DCHECK(notifications); - // Higher priority should come earlier. - for (NotificationMap::const_reverse_iterator mapiter = - notifications_.rbegin(); - mapiter != notifications_.rend(); ++mapiter) { - for (Notifications::const_iterator iter = mapiter->second.begin(); - iter != mapiter->second.end(); ++iter) { - notifications->push_back(*iter); - } - } +const NotificationList::Notifications& NotificationList::GetNotifications() { + return notifications_; } size_t NotificationList::NotificationCount() const { - size_t result = 0; - for (NotificationMap::const_iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - result += mapiter->second.size(); - } - return result; + return notifications_.size(); } void NotificationList::SetQuietModeInternal(bool quiet_mode) { quiet_mode_ = quiet_mode; if (quiet_mode_) { - for (NotificationMap::iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - for (Notifications::iterator iter = mapiter->second.begin(); - iter != mapiter->second.end(); ++iter) { - iter->is_read = true; - iter->shown_as_popup = true; - } + for (Notifications::iterator iter = notifications_.begin(); + iter != notifications_.end(); ++iter) { + (*iter)->set_is_read(true); + (*iter)->set_shown_as_popup(true); } unread_count_ = 0; } delegate_->OnQuietModeChanged(quiet_mode); } -bool NotificationList::GetNotification( - const std::string& id, Notifications::iterator* iter) { - for (NotificationMap::iterator mapiter = notifications_.begin(); - mapiter != notifications_.end(); ++mapiter) { - for (Notifications::iterator curiter = mapiter->second.begin(); - curiter != mapiter->second.end(); ++curiter) { - if (curiter->id == id) { - *iter = curiter; - return true; - } - } +NotificationList::Notifications::iterator + NotificationList::GetNotification(const std::string& id) { + for (Notifications::iterator iter = notifications_.begin(); + iter != notifications_.end(); ++iter) { + if ((*iter)->id() == id) + return iter; } - return false; + return notifications_.end(); } void NotificationList::EraseNotification(Notifications::iterator iter) { - if (!message_center_visible_ && !iter->is_read && - iter->priority > ui::notifications::MIN_PRIORITY) { + if (!message_center_visible_ && !(*iter)->is_read() && + (*iter)->priority() > MIN_PRIORITY) { --unread_count_; } - notifications_[iter->priority].erase(iter); + delete *iter; + notifications_.erase(iter); } -void NotificationList::PushNotification(Notification& notification) { +void NotificationList::PushNotification(scoped_ptr<Notification> notification) { // Ensure that notification.id is unique by erasing any existing // notification with the same id (shouldn't normally happen). - Notifications::iterator iter; - if (GetNotification(notification.id, &iter)) + Notifications::iterator iter = GetNotification(notification->id()); + if (iter != notifications_.end()) EraseNotification(iter); - // Add the notification to the front (top) of the list and mark it - // unread and unshown. + // Add the notification to the the list and mark it unread and unshown. if (!message_center_visible_) { - if (quiet_mode_) { - // TODO(mukai): needs to distinguish if a notification is dismissed by - // the quiet mode or user operation. - notification.is_read = true; - notification.shown_as_popup = true; - } else { - if (notification.priority > ui::notifications::MIN_PRIORITY) + // TODO(mukai): needs to distinguish if a notification is dismissed by + // the quiet mode or user operation. + notification->set_is_read(quiet_mode_); + notification->set_shown_as_popup(quiet_mode_); + if (!quiet_mode_ && notification->priority() > MIN_PRIORITY) ++unread_count_; - notification.is_read = false; - notification.shown_as_popup = false; - } - } - notifications_[notification.priority].push_front(notification); -} - -void NotificationList::GetPopupIterators(int priority, - Notifications::iterator* first, - Notifications::iterator* last) { - Notifications& notifications = notifications_[priority]; - // No popups for LOW/MIN priority. - if (priority < ui::notifications::DEFAULT_PRIORITY) { - *first = notifications.end(); - *last = notifications.end(); - return; - } - - size_t popup_count = 0; - *first = notifications.begin(); - *last = *first; - while (*last != notifications.end()) { - if ((*last)->shown_as_popup) - break; - ++(*last); - - // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority - // will return at most kMaxVisiblePopupNotifications entries. If the - // popup entries are more, older entries are used. see crbug.com/165768 - if (priority == ui::notifications::DEFAULT_PRIORITY && - popup_count >= kMaxVisiblePopupNotifications) { - ++(*first); - } else { - ++popup_count; - } } + // Take ownership. The notification can only be removed from the list + // in EraseNotification(), which will delete it. + notifications_.insert(notification.release()); } } // namespace message_center diff --git a/ui/message_center/notification_list.h b/ui/message_center/notification_list.h index ec8b4db..3d37713 100644 --- a/ui/message_center/notification_list.h +++ b/ui/message_center/notification_list.h @@ -5,8 +5,7 @@ #ifndef UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_ #define UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_ -#include <list> -#include <map> +#include <set> #include <string> #include "base/string16.h" @@ -16,7 +15,7 @@ #include "ui/gfx/native_widget_types.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification.h" -#include "ui/notifications/notification_types.h" +#include "ui/message_center/notification_types.h" namespace base { class DictionaryValue; @@ -24,10 +23,25 @@ class DictionaryValue; namespace message_center { +// Comparers used to auto-sort the lists of Notifications. +struct ComparePriorityTimestampSerial { + bool operator()(Notification* n1, Notification* n2); +}; + +struct CompareTimestampSerial { + bool operator()(Notification* n1, Notification* n2); +}; + // A helper class to manage the list of notifications. class MESSAGE_CENTER_EXPORT NotificationList { public: - typedef std::list<Notification> Notifications; + // Auto-sorted set. Matches the order in which Notifications are shown in + // Notification Center. + typedef std::set<Notification*, ComparePriorityTimestampSerial> Notifications; + + // Auto-sorted set used to return the Notifications to be shown as popup + // toasts. + typedef std::set<Notification*, CompareTimestampSerial> PopupNotifications; class MESSAGE_CENTER_EXPORT Delegate { public: @@ -69,7 +83,7 @@ class MESSAGE_CENTER_EXPORT NotificationList { // Affects whether or not a message has been "read". void SetMessageCenterVisible(bool visible); - void AddNotification(ui::notifications::NotificationType type, + void AddNotification(NotificationType type, const std::string& id, const string16& title, const string16& message, @@ -83,8 +97,7 @@ class MESSAGE_CENTER_EXPORT NotificationList { const string16& message, const base::DictionaryValue* optional_fields); - // Returns true if the notification was removed. - bool RemoveNotification(const std::string& id); + void RemoveNotification(const std::string& id); void RemoveAllNotifications(); @@ -111,9 +124,11 @@ class MESSAGE_CENTER_EXPORT NotificationList { // means that all notifications have been shown). bool HasPopupNotifications(); - // Modifies |notifications| to contain the |kMaxVisiblePopupNotifications| - // least recent notifications that have not been shown as a popup. - void GetPopupNotifications(Notifications* notifications); + // Returns the recent notifications of the priority higher then LOW, + // that have not been shown as a popup. kMaxVisiblePopupNotifications are + // used to limit the number of notifications for the DEFAULT priority. + // The returned list is sorted by timestamp, newer first. + PopupNotifications GetPopupNotifications(); // Marks the popups for the |priority| as shown. void MarkPopupsAsShown(int priority); @@ -133,7 +148,9 @@ class MESSAGE_CENTER_EXPORT NotificationList { // specified time-delta from now. void EnterQuietModeWithExpire(const base::TimeDelta& expires_in); - void GetNotifications(Notifications* notifications) const; + // Returns all notifications, in a (priority-timestamp) order. Suitable for + // rendering notifications in a NotificationCenter. + const Notifications& GetNotifications(); size_t NotificationCount() const; size_t unread_count() const { return unread_count_; } @@ -141,35 +158,18 @@ class MESSAGE_CENTER_EXPORT NotificationList { static const size_t kMaxVisibleMessageCenterNotifications; private: - typedef std::map<int, Notifications> NotificationMap; - - // Iterates through the list and stores the first notification matching |id| - // (should always be unique) to |iter|. Returns true if it's found. - bool GetNotification(const std::string& id, Notifications::iterator* iter); + // Iterates through the list and returns the first notification matching |id|. + Notifications::iterator GetNotification(const std::string& id); void EraseNotification(Notifications::iterator iter); - void PushNotification(Notification& notification); - - // Returns the recent notifications of the |priority| that have not been shown - // as a popup. kMaxVisiblePopupNotifications are used to limit the number of - // notifications for the default priority. - void GetPopupIterators(int priority, - Notifications::iterator* first, - Notifications::iterator* last); - - // Given a dictionary of optional notification fields (or NULL), unpacks all - // recognized values into the given Notification struct. We assume prior - // proper initialization of |notification| fields that correspond to - // |optional_fields|. - void UnpackOptionalFields(const base::DictionaryValue* optional_fields, - Notification* notification); + void PushNotification(scoped_ptr<Notification> notification); // Sets the current quiet mode status to |quiet_mode|. void SetQuietModeInternal(bool quiet_mode); Delegate* delegate_; - NotificationMap notifications_; + Notifications notifications_; bool message_center_visible_; size_t unread_count_; bool quiet_mode_; diff --git a/ui/message_center/notification_list_unittest.cc b/ui/message_center/notification_list_unittest.cc index 8d0664f..8685a21 100644 --- a/ui/message_center/notification_list_unittest.cc +++ b/ui/message_center/notification_list_unittest.cc @@ -10,7 +10,7 @@ #include "base/utf_string_conversions.h" #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/notifications/notification_types.h" +#include "ui/message_center/notification_types.h" namespace message_center { namespace { @@ -84,7 +84,7 @@ class NotificationListTest : public testing::Test { std::string AddNotification(const base::DictionaryValue* optional_fields) { std::string new_id = base::StringPrintf(kIdFormat, counter_); notification_list_->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, new_id, + message_center::NOTIFICATION_TYPE_SIMPLE, new_id, UTF8ToUTF16(StringPrintf(kTitleFormat, counter_)), UTF8ToUTF16(StringPrintf(kMessageFormat, counter_)), UTF8ToUTF16(kDisplaySource), kExtensionId, @@ -96,19 +96,17 @@ class NotificationListTest : public testing::Test { // Utility methods of AddNotification. std::string AddPriorityNotification(int priority) { base::DictionaryValue optional; - optional.SetInteger(ui::notifications::kPriorityKey, priority); + optional.SetInteger(message_center::kPriorityKey, priority); return AddNotification(&optional); } void SetupTimestampKey(const base::Time& time, base::DictionaryValue* optional) { string16 time_formatted = base::TimeFormatShortDateAndTime(time); - optional->SetString(ui::notifications::kTimestampKey, time_formatted); + optional->SetString(message_center::kTimestampKey, time_formatted); } size_t GetPopupCounts() { - NotificationList::Notifications popups; - notification_list()->GetPopupNotifications(&popups); - return popups.size(); + return notification_list()->GetPopupNotifications().size(); } MockNotificationListDelegate* delegate() { return delegate_.get(); } @@ -157,7 +155,7 @@ TEST_F(NotificationListTest, Basic) { EXPECT_EQ(2u, notification_list()->NotificationCount()); EXPECT_EQ(0u, GetPopupCounts()); - EXPECT_TRUE(notification_list()->RemoveNotification(id0)); + notification_list()->RemoveNotification(id0); EXPECT_EQ(1u, notification_list()->NotificationCount()); EXPECT_EQ(1u, notification_list()->unread_count()); @@ -189,25 +187,25 @@ TEST_F(NotificationListTest, UpdateNotification) { notification_list()->UpdateNotificationMessage( id0, replaced, UTF8ToUTF16("newtitle"), UTF8ToUTF16("newbody"), NULL); EXPECT_EQ(1u, notification_list()->NotificationCount()); - NotificationList::Notifications notifications; - notification_list()->GetNotifications(¬ifications); - EXPECT_EQ(replaced, notifications.begin()->id); - EXPECT_EQ(UTF8ToUTF16("newtitle"), notifications.begin()->title); - EXPECT_EQ(UTF8ToUTF16("newbody"), notifications.begin()->message); + const NotificationList::Notifications& notifications = + notification_list()->GetNotifications(); + EXPECT_EQ(replaced, (*notifications.begin())->id()); + EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title()); + EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); } TEST_F(NotificationListTest, SendRemoveNotifications) { notification_list()->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, "id0", UTF8ToUTF16("title0"), + message_center::NOTIFICATION_TYPE_SIMPLE, "id0", UTF8ToUTF16("title0"), UTF8ToUTF16("message0"), UTF8ToUTF16("source0"), "ext0", NULL); notification_list()->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title1"), + message_center::NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title1"), UTF8ToUTF16("message1"), UTF8ToUTF16("source0"), "ext0", NULL); notification_list()->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title1"), + message_center::NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title1"), UTF8ToUTF16("message1"), UTF8ToUTF16("source1"), "ext0", NULL); notification_list()->AddNotification( - ui::notifications::NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title1"), + message_center::NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title1"), UTF8ToUTF16("message1"), UTF8ToUTF16("source2"), "ext1", NULL); notification_list()->SendRemoveNotificationsBySource("id0"); @@ -223,24 +221,24 @@ TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) { ids.push_back(AddNotification(NULL)); } - NotificationList::Notifications popups; - notification_list()->GetPopupNotifications(&popups); + NotificationList::PopupNotifications popups = + notification_list()->GetPopupNotifications(); // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer // one should come earlier in the popup list. It means, the last element // of |popups| should be the firstly added one, and so on. EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications, popups.size()); - NotificationList::Notifications::const_reverse_iterator iter = + NotificationList::PopupNotifications::const_reverse_iterator iter = popups.rbegin(); for (size_t i = 0; i < NotificationList::kMaxVisiblePopupNotifications; ++i, ++iter) { - EXPECT_EQ(ids[i], iter->id) << i; + EXPECT_EQ(ids[i], (*iter)->id()) << i; } - notification_list()->MarkPopupsAsShown(ui::notifications::DEFAULT_PRIORITY); + notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY); popups.clear(); - notification_list()->GetPopupNotifications(&popups); + popups = notification_list()->GetPopupNotifications(); EXPECT_EQ(1u, popups.size()); - EXPECT_EQ(ids[ids.size() - 1], popups.begin()->id); + EXPECT_EQ(ids[ids.size() - 1], (*popups.begin())->id()); } TEST_F(NotificationListTest, Priority) { @@ -296,56 +294,60 @@ TEST_F(NotificationListTest, PriorityPromotion) { EXPECT_EQ(1u, notification_list()->NotificationCount()); EXPECT_EQ(0u, GetPopupCounts()); base::DictionaryValue optional; - optional.SetInteger(ui::notifications::kPriorityKey, 1); + optional.SetInteger(message_center::kPriorityKey, 1); notification_list()->UpdateNotificationMessage( id0, replaced, UTF8ToUTF16("newtitle"), UTF8ToUTF16("newbody"), &optional); EXPECT_EQ(1u, notification_list()->NotificationCount()); EXPECT_EQ(1u, GetPopupCounts()); - NotificationList::Notifications notifications; - notification_list()->GetNotifications(¬ifications); - EXPECT_EQ(replaced, notifications.begin()->id); - EXPECT_EQ(UTF8ToUTF16("newtitle"), notifications.begin()->title); - EXPECT_EQ(UTF8ToUTF16("newbody"), notifications.begin()->message); - EXPECT_EQ(1, notifications.begin()->priority); + const NotificationList::Notifications& notifications = + notification_list()->GetNotifications(); + EXPECT_EQ(replaced, (*notifications.begin())->id()); + EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title()); + EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); + EXPECT_EQ(1, (*notifications.begin())->priority()); } TEST_F(NotificationListTest, NotificationOrderAndPriority) { base::Time now = base::Time::Now(); base::DictionaryValue optional; SetupTimestampKey(now, &optional); - optional.SetInteger(ui::notifications::kPriorityKey, 2); + optional.SetInteger(message_center::kPriorityKey, 2); std::string max_id = AddNotification(&optional); now += base::TimeDelta::FromSeconds(1); SetupTimestampKey(now, &optional); - optional.SetInteger(ui::notifications::kPriorityKey, 1); + optional.SetInteger(message_center::kPriorityKey, 1); std::string high_id = AddNotification(&optional); now += base::TimeDelta::FromSeconds(1); SetupTimestampKey(now, &optional); - optional.SetInteger(ui::notifications::kPriorityKey, 0); + optional.SetInteger(message_center::kPriorityKey, 0); std::string default_id = AddNotification(&optional); - // Popups: latest comes first. - NotificationList::Notifications popups; - notification_list()->GetPopupNotifications(&popups); - EXPECT_EQ(3u, popups.size()); - NotificationList::Notifications::const_iterator iter = popups.begin(); - EXPECT_EQ(default_id, iter->id); - iter++; - EXPECT_EQ(high_id, iter->id); - iter++; - EXPECT_EQ(max_id, iter->id); - - // Notifications: high priority comes ealier. - NotificationList::Notifications notifications; - notification_list()->GetNotifications(¬ifications); - EXPECT_EQ(3u, notifications.size()); - iter = notifications.begin(); - EXPECT_EQ(max_id, iter->id); - iter++; - EXPECT_EQ(high_id, iter->id); - iter++; - EXPECT_EQ(default_id, iter->id); + { + // Popups: latest comes first. + NotificationList::PopupNotifications popups = + notification_list()->GetPopupNotifications(); + EXPECT_EQ(3u, popups.size()); + NotificationList::PopupNotifications::const_iterator iter = popups.begin(); + EXPECT_EQ(default_id, (*iter)->id()); + iter++; + EXPECT_EQ(high_id, (*iter)->id()); + iter++; + EXPECT_EQ(max_id, (*iter)->id()); + } + { + // Notifications: high priority comes ealier. + const NotificationList::Notifications& notifications = + notification_list()->GetNotifications(); + EXPECT_EQ(3u, notifications.size()); + NotificationList::Notifications::const_iterator iter = + notifications.begin(); + EXPECT_EQ(max_id, (*iter)->id()); + iter++; + EXPECT_EQ(high_id, (*iter)->id()); + iter++; + EXPECT_EQ(default_id, (*iter)->id()); + } } TEST_F(NotificationListTest, MarkSinglePopupAsShown) { @@ -362,50 +364,52 @@ TEST_F(NotificationListTest, MarkSinglePopupAsShown) { EXPECT_EQ(3u, notification_list()->NotificationCount()); EXPECT_EQ(2u, notification_list()->unread_count()); EXPECT_EQ(1u, GetPopupCounts()); - NotificationList::Notifications popups; - notification_list()->GetPopupNotifications(&popups); - EXPECT_EQ(id1, popups.begin()->id); - - // Reorder happens -- popup-notifications should be at the beginning of the - // list. - // TODO(mukai): confirm this behavior is expected. - NotificationList::Notifications notifications; - notification_list()->GetNotifications(¬ifications); + NotificationList::PopupNotifications popups = + notification_list()->GetPopupNotifications(); + EXPECT_EQ(id1, (*popups.begin())->id()); + + // The notifications in the NotificationCenter are unaffected by popups shown. + NotificationList::Notifications notifications = + notification_list()->GetNotifications(); NotificationList::Notifications::const_iterator iter = notifications.begin(); - EXPECT_EQ(id1, iter->id); + EXPECT_EQ(id3, (*iter)->id()); iter++; - EXPECT_EQ(id3, iter->id); + EXPECT_EQ(id2, (*iter)->id()); iter++; - EXPECT_EQ(id2, iter->id); + EXPECT_EQ(id1, (*iter)->id()); // Trickier scenario. - notification_list()->MarkPopupsAsShown(ui::notifications::DEFAULT_PRIORITY); + notification_list()->MarkPopupsAsShown(message_center::DEFAULT_PRIORITY); std::string id4 = AddNotification(NULL); std::string id5 = AddNotification(NULL); std::string id6 = AddNotification(NULL); notification_list()->MarkSinglePopupAsShown(id5, true); - popups.clear(); + + { + popups.clear(); + popups = notification_list()->GetPopupNotifications(); + EXPECT_EQ(2u, popups.size()); + NotificationList::PopupNotifications::const_iterator iter = popups.begin(); + EXPECT_EQ(id6, (*iter)->id()); + iter++; + EXPECT_EQ(id4, (*iter)->id()); + } + notifications.clear(); - notification_list()->GetPopupNotifications(&popups); - notification_list()->GetNotifications(¬ifications); - EXPECT_EQ(2u, popups.size()); - iter = popups.begin(); - EXPECT_EQ(id6, iter->id); - iter++; - EXPECT_EQ(id4, iter->id); + notifications = notification_list()->GetNotifications(); EXPECT_EQ(6u, notifications.size()); iter = notifications.begin(); - EXPECT_EQ(id6, iter->id); + EXPECT_EQ(id6, (*iter)->id()); iter++; - EXPECT_EQ(id4, iter->id); + EXPECT_EQ(id5, (*iter)->id()); iter++; - EXPECT_EQ(id5, iter->id); + EXPECT_EQ(id4, (*iter)->id()); iter++; - EXPECT_EQ(id1, iter->id); + EXPECT_EQ(id3, (*iter)->id()); iter++; - EXPECT_EQ(id3, iter->id); + EXPECT_EQ(id2, (*iter)->id()); iter++; - EXPECT_EQ(id2, iter->id); + EXPECT_EQ(id1, (*iter)->id()); } TEST_F(NotificationListTest, QuietMode) { diff --git a/ui/message_center/notification_types.cc b/ui/message_center/notification_types.cc new file mode 100644 index 0000000..0cd2140 --- /dev/null +++ b/ui/message_center/notification_types.cc @@ -0,0 +1,23 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/message_center/notification_types.h" + +namespace message_center { + +const char kMessageIntentKey[] = "message_intent"; +const char kPriorityKey[] = "priority"; +const char kTimestampKey[] = "timestamp"; +const char kUnreadCountKey[] = "unread_count"; +const char kButtonOneTitleKey[] = "button_one_title"; +const char kButtonOneIconUrlKey[] = "button_one_icon_url"; +const char kButtonTwoTitleKey[] = "button_two_title"; +const char kButtonTwoIconUrlKey[] = "button_two_icon_url"; +const char kExpandedMessageKey[] = "expanded_message"; +const char kImageUrlKey[] = "image_url"; +const char kItemsKey[] = "items"; +const char kItemTitleKey[] = "title"; +const char kItemMessageKey[] = "message"; + +} // namespace message_center diff --git a/ui/message_center/notification_types.h b/ui/message_center/notification_types.h new file mode 100644 index 0000000..95fc340 --- /dev/null +++ b/ui/message_center/notification_types.h @@ -0,0 +1,46 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_MESSAGE_CENTER_NOTIFICATION_TYPES_H_ +#define UI_MESSAGE_CENTER_NOTIFICATION_TYPES_H_ + + +#include <string> + +#include "ui/message_center/message_center_export.h" + +namespace message_center { + +// Keys for optional fields in Notification. +MESSAGE_CENTER_EXPORT extern const char kPriorityKey[]; +MESSAGE_CENTER_EXPORT extern const char kTimestampKey[]; +MESSAGE_CENTER_EXPORT extern const char kUnreadCountKey[]; +MESSAGE_CENTER_EXPORT extern const char kButtonOneTitleKey[]; +MESSAGE_CENTER_EXPORT extern const char kButtonOneIconUrlKey[]; +MESSAGE_CENTER_EXPORT extern const char kButtonTwoTitleKey[]; +MESSAGE_CENTER_EXPORT extern const char kButtonTwoIconUrlKey[]; +MESSAGE_CENTER_EXPORT extern const char kExpandedMessageKey[]; +MESSAGE_CENTER_EXPORT extern const char kImageUrlKey[]; +MESSAGE_CENTER_EXPORT extern const char kItemsKey[]; +MESSAGE_CENTER_EXPORT extern const char kItemTitleKey[]; +MESSAGE_CENTER_EXPORT extern const char kItemMessageKey[]; + +enum NotificationType { + NOTIFICATION_TYPE_SIMPLE, + NOTIFICATION_TYPE_BASE_FORMAT, + NOTIFICATION_TYPE_IMAGE, + NOTIFICATION_TYPE_MULTIPLE, +}; + +enum NotificationPriority { + MIN_PRIORITY = -2, + LOW_PRIORITY = -1, + DEFAULT_PRIORITY = 0, + HIGH_PRIORITY = 1, + MAX_PRIORITY = 2, +}; + +} // namespace message_center + +#endif // UI_MESSAGE_CENTER_NOTIFICATION_TYPES_H_ diff --git a/ui/message_center/notification_view.cc b/ui/message_center/notification_view.cc index f38713e..db4bdad 100644 --- a/ui/message_center/notification_view.cc +++ b/ui/message_center/notification_view.cc @@ -14,6 +14,8 @@ #include "ui/message_center/message_center_constants.h" #include "ui/message_center/message_center_switches.h" #include "ui/message_center/message_simple_view.h" +#include "ui/message_center/notification.h" +#include "ui/message_center/notification_types.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" @@ -199,7 +201,7 @@ MessageView* NotificationView::ViewForNotification( // For the time being, use MessageSimpleView for simple notifications unless // one of the use-the-new-style flags are set. This preserves the appearance // of notifications created by existing code that uses webkitNotifications. - if (notification.type == ui::notifications::NOTIFICATION_TYPE_SIMPLE && + if (notification.type() == NOTIFICATION_TYPE_SIMPLE && !CommandLine::ForCurrentProcess()->HasSwitch( message_center::switches::kEnableRichNotifications) && !CommandLine::ForCurrentProcess()->HasSwitch( @@ -207,11 +209,11 @@ MessageView* NotificationView::ViewForNotification( return new MessageSimpleView(list_delegate, notification); } - switch (notification.type) { - case ui::notifications::NOTIFICATION_TYPE_BASE_FORMAT: - case ui::notifications::NOTIFICATION_TYPE_IMAGE: - case ui::notifications::NOTIFICATION_TYPE_MULTIPLE: - case ui::notifications::NOTIFICATION_TYPE_SIMPLE: + switch (notification.type()) { + case NOTIFICATION_TYPE_BASE_FORMAT: + case NOTIFICATION_TYPE_IMAGE: + case NOTIFICATION_TYPE_MULTIPLE: + case NOTIFICATION_TYPE_SIMPLE: break; default: // If the caller asks for an unrecognized kind of view (entirely possible @@ -220,7 +222,7 @@ MessageView* NotificationView::ViewForNotification( // back to a notification instance that will provide at least basic // functionality. LOG(WARNING) << "Unable to fulfill request for unrecognized " - << "notification type " << notification.type << ". " + << "notification type " << notification.type() << ". " << "Falling back to simple notification type."; } @@ -228,10 +230,17 @@ MessageView* NotificationView::ViewForNotification( return new NotificationView(list_delegate, notification); } -NotificationView::NotificationView( - NotificationList::Delegate* list_delegate, - const Notification& notification) +NotificationView::NotificationView(NotificationList::Delegate* list_delegate, + const Notification& notification) : MessageView(list_delegate, notification) { + // This view is composed of two layers: The first layer has the notification + // content (text, images, action buttons, ...). This is overlaid by a second + // layer that has the notification close button and will later also have the + // expand button. This allows the close and expand buttons to overlap the + // content as needed to provide a large enough click area + // (<http://crbug.com/168822> and touch area <http://crbug.com/168856>). + AddChildView(MakeContentView(notification)); + AddChildView(close_button()); } NotificationView::~NotificationView() { @@ -260,29 +269,19 @@ gfx::Size NotificationView::GetPreferredSize() { return size; } -void NotificationView::SetUpView() { - // This view is composed of two layers: The first layer has the notification - // content (text, images, action buttons, ...). This is overlaid by a second - // layer that has the notification close button and will later also have the - // expand button. This allows the close and expand buttons to overlap the - // content as needed to provide a large enough click area - // (<http://crbug.com/168822> and touch area <http://crbug.com/168856>). - AddChildView(MakeContentView()); - AddChildView(close_button()); -} - void NotificationView::ButtonPressed(views::Button* sender, const ui::Event& event) { for (size_t i = 0; i < action_buttons_.size(); ++i) { if (action_buttons_[i] == sender) { - list_delegate()->OnButtonClicked(notification().id, i); + list_delegate()->OnButtonClicked(notification_id(), i); return; } } MessageView::ButtonPressed(sender, event); } -views::View* NotificationView::MakeContentView() { +views::View* NotificationView::MakeContentView( + const Notification& notification) { content_view_ = new views::View(); content_view_->set_background( views::Background::CreateSolidBackground(kBackgroundColor)); @@ -295,8 +294,8 @@ views::View* NotificationView::MakeContentView() { std::vector<views::View*> texts; // Title if it exists. - if (!notification().title.empty()) { - views::Label* title = new views::Label(notification().title); + if (!notification.title().empty()) { + views::Label* title = new views::Label(notification.title()); title->SetHorizontalAlignment(gfx::ALIGN_LEFT); title->SetElideBehavior(views::Label::ELIDE_AT_END); title->SetFont(title->font().DeriveFont(4)); @@ -307,8 +306,9 @@ views::View* NotificationView::MakeContentView() { } // Message if appropriate. - if (notification().items.size() == 0 && !notification().message.empty()) { - views::Label* message = new views::Label(notification().message); + if (notification.items().size() == 0 && + !notification.message().empty()) { + views::Label* message = new views::Label(notification.message()); message->SetHorizontalAlignment(gfx::ALIGN_LEFT); message->SetMultiLine(true); message->SetEnabledColor(kMessageColor); @@ -318,9 +318,10 @@ views::View* NotificationView::MakeContentView() { } // List notification items up to a maximum. - int items = std::min(notification().items.size(), kNotificationMaximumItems); + int items = std::min(notification.items().size(), + kNotificationMaximumItems); for (int i = 0; i < items; ++i) { - ItemView* item = new ItemView(notification().items[i]); + ItemView* item = new ItemView(notification.items()[i]); item->set_border(MakePadding(0, 0, 4, kTextRightPadding)); texts.push_back(item); } @@ -347,7 +348,7 @@ views::View* NotificationView::MakeContentView() { views::ImageView* icon = new views::ImageView(); icon->SetImageSize(gfx::Size(message_center::kNotificationIconSize, message_center::kNotificationIconSize)); - icon->SetImage(notification().primary_icon); + icon->SetImage(notification.primary_icon()); icon->SetHorizontalAlignment(views::ImageView::LEADING); icon->SetVerticalAlignment(views::ImageView::LEADING); icon->set_border(MakePadding(0, 0, 0, kIconToTextPadding)); @@ -376,26 +377,27 @@ views::View* NotificationView::MakeContentView() { } // Add an image row if appropriate. - if (!notification().image.isNull()) { + if (!notification.image().isNull()) { layout->StartRow(0, 0); views::ImageView* image = new ProportionalImageView(); - image->SetImageSize(notification().image.size()); - image->SetImage(notification().image); + image->SetImageSize(notification.image().size()); + image->SetImage(notification.image()); image->SetHorizontalAlignment(views::ImageView::CENTER); image->SetVerticalAlignment(views::ImageView::LEADING); layout->AddView(image, 2, 1); } // Add action button rows. - for (size_t i = 0; i < notification().button_titles.size(); ++i) { + for (size_t i = 0; i < notification.buttons().size(); ++i) { views::View* separator = new views::View(); separator->set_background(MakeBackground(kButtonSeparatorColor)); layout->StartRow(0, 0); layout->AddView(separator, 2, 1, views::GridLayout::FILL, views::GridLayout::FILL, 0, 1); NotificationButton* button = new NotificationButton(this); - button->SetTitle(notification().button_titles[i]); - button->SetIcon(notification().button_icons[i]); + ButtonInfo button_info = notification.buttons()[i]; + button->SetTitle(button_info.title); + button->SetIcon(button_info.icon); action_buttons_.push_back(button); layout->StartRow(0, 0); layout->AddView(button, 2, 1, diff --git a/ui/message_center/notification_view.h b/ui/message_center/notification_view.h index 1b9b630..833b93e 100644 --- a/ui/message_center/notification_view.h +++ b/ui/message_center/notification_view.h @@ -32,12 +32,11 @@ class NotificationView : public MessageView { virtual gfx::Size GetPreferredSize() OVERRIDE; // Overridden from MessageView. - virtual void SetUpView() OVERRIDE; virtual void ButtonPressed(views::Button* sender, const ui::Event& event) OVERRIDE; private: - views::View* MakeContentView(); + views::View* MakeContentView(const Notification& notification); views::View* content_view_; std::vector<views::Button*> action_buttons_; |