summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordharcourt@chromium.org <dharcourt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-08 03:55:38 +0000
committerdharcourt@chromium.org <dharcourt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-08 03:55:38 +0000
commit73662cf81ff77c832db42eea71a3d6affed75f67 (patch)
tree0771461a941d4ff1993e94ba0b979103c3b262fd
parent2a98f90a3637e932db7db5da634b169f6553ac11 (diff)
downloadchromium_src-73662cf81ff77c832db42eea71a3d6affed75f67.zip
chromium_src-73662cf81ff77c832db42eea71a3d6affed75f67.tar.gz
chromium_src-73662cf81ff77c832db42eea71a3d6affed75f67.tar.bz2
Made notification center notifications collapsible and expandable.
Implemented collapse/expand for notifications in the notification center. Notifications are collapsed by default and can be expanded by pressing their expand button. Once expanded, they can't be collapsed again. Limitations of this version are: 1) Notifications in alerts/toasts are not affected (they're always expanded). 2) Notifications get expand buttons even if they have no content to expand. 3) Collapsed text is always collapsed to 1 lines (not 2 or 3 as required) and expanded text is always expanded to its full height (not limited to 7 lines as required). 4) Notification expansion is lost when notifications are added to the notification center or when the notification center is closed and opened again. These issues will be addressed in separate change lists. BUG=161098 TBR=stevenjb@chromium.org Review URL: https://chromiumcodereview.appspot.com/12326091 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186873 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/system/web_notification/web_notification_tray_unittest.cc8
-rw-r--r--chrome/browser/extensions/api/notifications/notifications_apitest.cc12
-rw-r--r--chrome/browser/extensions/extension_crash_recovery_browsertest.cc6
-rw-r--r--chrome/browser/notifications/message_center_notification_manager.cc2
-rw-r--r--chrome/browser/ui/views/message_center/web_notification_tray_win_browsertest.cc5
-rw-r--r--ui/message_center/message_center.cc44
-rw-r--r--ui/message_center/message_center.gyp1
-rw-r--r--ui/message_center/message_center.h37
-rw-r--r--ui/message_center/message_center_tray.h2
-rw-r--r--ui/message_center/notification.cc3
-rw-r--r--ui/message_center/notification.h21
-rw-r--r--ui/message_center/notification_change_observer.h35
-rw-r--r--ui/message_center/notification_list.cc11
-rw-r--r--ui/message_center/notification_list.h28
-rw-r--r--ui/message_center/notification_list_unittest.cc29
-rw-r--r--ui/message_center/views/message_bubble_base.cc4
-rw-r--r--ui/message_center/views/message_bubble_base.h8
-rw-r--r--ui/message_center/views/message_center_bubble.cc276
-rw-r--r--ui/message_center/views/message_center_bubble.h29
-rw-r--r--ui/message_center/views/message_popup_bubble.cc25
-rw-r--r--ui/message_center/views/message_popup_bubble.h5
-rw-r--r--ui/message_center/views/message_popup_collection.cc26
-rw-r--r--ui/message_center/views/message_popup_collection.h12
-rw-r--r--ui/message_center/views/message_simple_view.cc10
-rw-r--r--ui/message_center/views/message_simple_view.h6
-rw-r--r--ui/message_center/views/message_view.cc67
-rw-r--r--ui/message_center/views/message_view.h34
-rw-r--r--ui/message_center/views/notification_view.cc227
-rw-r--r--ui/message_center/views/notification_view.h31
-rw-r--r--ui/message_center/views/notifier_settings_view.cc2
-rw-r--r--ui/message_center/views/notifier_settings_view.h4
31 files changed, 606 insertions, 404 deletions
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc
index b58845c..7895d18 100644
--- a/ash/system/web_notification/web_notification_tray_unittest.cc
+++ b/ash/system/web_notification/web_notification_tray_unittest.cc
@@ -74,6 +74,10 @@ class TestDelegate : public message_center::MessageCenter::Delegate {
virtual void OnClicked(const std::string& notifcation_id) OVERRIDE {
}
+ virtual void OnButtonClicked(const std::string& id,
+ int button_index) OVERRIDE {
+ }
+
void AddNotification(WebNotificationTray* tray, const std::string& id) {
notification_ids_.insert(id);
get_message_center()->AddNotification(
@@ -222,10 +226,8 @@ TEST_F(WebNotificationTrayTest, ManyPopupNotifications) {
EXPECT_EQ(notifications_to_add,
get_message_center()->NotificationCount());
if (message_center::IsRichNotificationEnabled()) {
- NotificationList::Delegate* list_delegate =
- tray->popup_collection_.get()->list_delegate_;
NotificationList::PopupNotifications popups =
- list_delegate->GetNotificationList()->GetPopupNotifications();
+ get_message_center()->notification_list()->GetPopupNotifications();
EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications, popups.size());
} else {
EXPECT_EQ(NotificationList::kMaxVisiblePopupNotifications,
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 523643d..27bb6f3 100644
--- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -283,18 +283,6 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
true);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-
- {
- ResultCatcher catcher;
- g_browser_process->message_center()->SendRemoveAllNotifications(false);
- EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
- }
-
- {
- ResultCatcher catcher;
- g_browser_process->message_center()->SendRemoveAllNotifications(true);
- EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
- }
}
#endif
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index 220885c..af461a7 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -125,11 +125,11 @@ class MessageCenterExtensionCrashRecoveryTest
message_center::MessageCenter::Get();
ASSERT_GT(message_center->NotificationCount(), index);
message_center::NotificationList::Notifications::reverse_iterator it =
- message_center->GetNotificationList()->GetNotifications().rbegin();
+ message_center->notification_list()->GetNotifications().rbegin();
for (size_t i=0; i < index; ++i)
it++;
std::string id = (*it)->id();
- message_center->OnNotificationClicked(id);
+ message_center->OnClicked(id);
WaitForExtensionLoad();
}
@@ -138,7 +138,7 @@ class MessageCenterExtensionCrashRecoveryTest
message_center::MessageCenter::Get();
ASSERT_GT(message_center->NotificationCount(), index);
message_center::NotificationList::Notifications::reverse_iterator it =
- message_center->GetNotificationList()->GetNotifications().rbegin();
+ message_center->notification_list()->GetNotifications().rbegin();
for (size_t i=0; i < index; i++) { it++; }
ASSERT_TRUE(
g_browser_process->notification_ui_manager()->CancelById((*it)->id()));
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc
index 347f26b..38d1995 100644
--- a/chrome/browser/notifications/message_center_notification_manager.cc
+++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -141,7 +141,7 @@ bool MessageCenterNotificationManager::UpdateNotification(
old_notification->profile()->IsSameProfile(profile)) {
std::string old_id =
old_notification->notification().notification_id();
- DCHECK(message_center_->GetNotificationList()->HasNotification(old_id));
+ DCHECK(message_center_->notification_list()->HasNotification(old_id));
// Add/remove notification in the local list but just update the same
// one in MessageCenter.
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray_win_browsertest.cc b/chrome/browser/ui/views/message_center/web_notification_tray_win_browsertest.cc
index b7c9c39..efe5429 100644
--- a/chrome/browser/ui/views/message_center/web_notification_tray_win_browsertest.cc
+++ b/chrome/browser/ui/views/message_center/web_notification_tray_win_browsertest.cc
@@ -52,9 +52,10 @@ class TestDelegate : public message_center::MessageCenter::Delegate {
virtual void DisableExtension(const std::string& notification_id) OVERRIDE { }
virtual void ShowSettings(const std::string& notification_id) OVERRIDE { }
- virtual void OnClicked(const std::string& notification_id) OVERRIDE { }
virtual void ShowSettingsDialog(gfx::NativeView context) OVERRIDE { }
-
+ virtual void OnClicked(const std::string& notification_id) OVERRIDE { }
+ virtual void OnButtonClicked(const std::string& id,
+ int button_index) OVERRIDE {}
void AddNotification(const std::string& id) {
notification_ids_.insert(id);
diff --git a/ui/message_center/message_center.cc b/ui/message_center/message_center.cc
index 29492a8..9f67ecd 100644
--- a/ui/message_center/message_center.cc
+++ b/ui/message_center/message_center.cc
@@ -36,6 +36,12 @@ void MessageCenter::Shutdown() {
}
//------------------------------------------------------------------------------
+
+MessageCenter::Delegate::~Delegate() {
+}
+
+//------------------------------------------------------------------------------
+
MessageCenter::MessageCenter()
: delegate_(NULL) {
notification_list_.reset(new NotificationList(this));
@@ -126,15 +132,14 @@ void MessageCenter::SetNotificationButtonIcon(
}
//------------------------------------------------------------------------------
-// Overridden from NotificationList::Delegate.
+// Overridden from NotificationChangeObserver:
-void MessageCenter::SendRemoveNotification(const std::string& id,
- bool by_user) {
+void MessageCenter::OnRemoveNotification(const std::string& id, bool by_user) {
if (delegate_)
delegate_->NotificationRemoved(id, by_user);
}
-void MessageCenter::SendRemoveAllNotifications(bool by_user) {
+void MessageCenter::OnRemoveAllNotifications(bool by_user) {
if (delegate_) {
const NotificationList::Notifications& notifications =
notification_list_->GetNotifications();
@@ -149,7 +154,7 @@ void MessageCenter::SendRemoveAllNotifications(bool by_user) {
}
}
-void MessageCenter::DisableNotificationByExtension(
+void MessageCenter::OnDisableNotificationsByExtension(
const std::string& id) {
if (delegate_)
delegate_->DisableExtension(id);
@@ -158,23 +163,27 @@ void MessageCenter::DisableNotificationByExtension(
notification_list_->SendRemoveNotificationsByExtension(id);
}
-void MessageCenter::DisableNotificationByUrl(const std::string& id) {
+void MessageCenter::OnDisableNotificationsByUrl(const std::string& id) {
if (delegate_)
delegate_->DisableNotificationsFromSource(id);
notification_list_->SendRemoveNotificationsBySource(id);
}
-void MessageCenter::ShowNotificationSettings(const std::string& id) {
+void MessageCenter::OnShowNotificationSettings(const std::string& id) {
if (delegate_)
delegate_->ShowSettings(id);
}
-void MessageCenter::ShowNotificationSettingsDialog(gfx::NativeView context) {
+void MessageCenter::OnShowNotificationSettingsDialog(gfx::NativeView context) {
if (delegate_)
delegate_->ShowSettingsDialog(context);
}
-void MessageCenter::OnNotificationClicked(const std::string& id) {
+void MessageCenter::OnExpanded(const std::string& id) {
+ notification_list_->MarkNotificationAsExpanded(id);
+}
+
+void MessageCenter::OnClicked(const std::string& id) {
if (delegate_)
delegate_->OnClicked(id);
if (HasPopupNotifications()) {
@@ -183,10 +192,6 @@ void MessageCenter::OnNotificationClicked(const std::string& id) {
}
}
-void MessageCenter::OnQuietModeChanged(bool quiet_mode) {
- NotifyMessageCenterChanged(true);
-}
-
void MessageCenter::OnButtonClicked(const std::string& id, int button_index) {
if (delegate_)
delegate_->OnButtonClicked(id, button_index);
@@ -196,12 +201,17 @@ void MessageCenter::OnButtonClicked(const std::string& id, int button_index) {
}
}
-NotificationList* MessageCenter::GetNotificationList() {
- return notification_list_.get();
+//------------------------------------------------------------------------------
+// Overridden from NotificationList::Delegate:
+
+void MessageCenter::SendRemoveNotification(const std::string& id,
+ bool by_user) {
+ if (delegate_)
+ delegate_->NotificationRemoved(id, by_user);
}
-void MessageCenter::Delegate::OnButtonClicked(const std::string& id,
- int button_index) {
+void MessageCenter::OnQuietModeChanged(bool quiet_mode) {
+ NotifyMessageCenterChanged(true);
}
//------------------------------------------------------------------------------
diff --git a/ui/message_center/message_center.gyp b/ui/message_center/message_center.gyp
index 04847d1..46c8f8c 100644
--- a/ui/message_center/message_center.gyp
+++ b/ui/message_center/message_center.gyp
@@ -40,6 +40,7 @@
'message_center_util.h',
'notification.cc',
'notification.h',
+ 'notification_change_observer.h',
'notification_list.cc',
'notification_list.h',
'notification_types.cc',
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h
index a0c6e94..58575bd 100644
--- a/ui/message_center/message_center.h
+++ b/ui/message_center/message_center.h
@@ -11,6 +11,7 @@
#include "base/observer_list.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/message_center/message_center_export.h"
+#include "ui/message_center/notification_change_observer.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/notification_types.h"
@@ -28,7 +29,8 @@ class DictionaryValue;
namespace message_center {
-class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationList::Delegate {
+class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationChangeObserver,
+ public NotificationList::Delegate {
public:
// Creates the global message center object.
static void Initialize();
@@ -51,6 +53,8 @@ class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationList::Delegate {
class MESSAGE_CENTER_EXPORT Delegate {
public:
+ virtual ~Delegate();
+
// Called when the notification associated with |notification_id| is
// removed (i.e. closed by the user).
virtual void NotificationRemoved(const std::string& notification_id,
@@ -81,10 +85,7 @@ class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationList::Delegate {
// TODO(miket): consider providing default implementations for the pure
// virtuals above, to avoid changing so many files in disparate parts of
// the codebase each time we enhance this interface.
- virtual void OnButtonClicked(const std::string& id, int button_index);
-
- protected:
- virtual ~Delegate() {}
+ virtual void OnButtonClicked(const std::string& id, int button_index) = 0;
};
// Called to set the delegate. Generally called only once, except in tests.
@@ -145,19 +146,25 @@ class MESSAGE_CENTER_EXPORT MessageCenter : public NotificationList::Delegate {
NotificationList* notification_list() { return notification_list_.get(); }
bool quiet_mode() const { return notification_list_->quiet_mode(); }
- // Overridden from NotificationList::Delegate.
+ // Overridden from NotificationChangeObserver:
+ virtual void OnRemoveNotification(const std::string& id, bool by_user)
+ OVERRIDE;
+ virtual void OnRemoveAllNotifications(bool by_user) OVERRIDE;
+ virtual void OnDisableNotificationsByExtension(const std::string& id)
+ OVERRIDE;
+ virtual void OnDisableNotificationsByUrl(const std::string& id) OVERRIDE;
+ virtual void OnShowNotificationSettings(const std::string& id) OVERRIDE;
+ virtual void OnShowNotificationSettingsDialog(gfx::NativeView context)
+ OVERRIDE;
+ virtual void OnExpanded(const std::string& id) OVERRIDE;
+ virtual void OnClicked(const std::string& id) OVERRIDE;
+ virtual void OnButtonClicked(const std::string& id, int button_index)
+ OVERRIDE;
+
+ // Overridden from NotificationList::Delegate:
virtual void SendRemoveNotification(const std::string& id,
bool by_user) OVERRIDE;
- virtual void SendRemoveAllNotifications(bool by_user) OVERRIDE;
- virtual void DisableNotificationByExtension(const std::string& id) OVERRIDE;
- virtual void DisableNotificationByUrl(const std::string& id) OVERRIDE;
- virtual void ShowNotificationSettings(const std::string& id) OVERRIDE;
- virtual void ShowNotificationSettingsDialog(gfx::NativeView context) OVERRIDE;
- virtual void OnNotificationClicked(const std::string& id) OVERRIDE;
virtual void OnQuietModeChanged(bool quiet_mode) OVERRIDE;
- virtual void OnButtonClicked(const std::string& id, int button_index)
- OVERRIDE;
- virtual NotificationList* GetNotificationList() OVERRIDE;
protected:
MessageCenter();
diff --git a/ui/message_center/message_center_tray.h b/ui/message_center/message_center_tray.h
index f40026f..9a3b33c0 100644
--- a/ui/message_center/message_center_tray.h
+++ b/ui/message_center/message_center_tray.h
@@ -60,7 +60,7 @@ class MESSAGE_CENTER_EXPORT MessageCenterTray
}
message_center::MessageCenter* message_center() { return message_center_; }
- // Overridden from message_center::MessageCenter::Observer.
+ // Overridden from message_center::MessageCenter::Observer:
virtual void OnMessageCenterChanged(bool new_notification) OVERRIDE;
// Overridden from SimpleMenuModel::Delegate.
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc
index 4bd1911..284d278 100644
--- a/ui/message_center/notification.cc
+++ b/ui/message_center/notification.cc
@@ -39,8 +39,9 @@ Notification::Notification(NotificationType type,
priority_(DEFAULT_PRIORITY),
timestamp_(base::Time::Now()),
serial_number_(g_next_serial_number_++),
+ shown_as_popup_(false),
is_read_(false),
- shown_as_popup_(false) {
+ is_expanded_(false) {
// This can override some data members initialized to deafule values above.
ApplyOptionalFields(optional_fields);
}
diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h
index 2aed7d5..ffb301b 100644
--- a/ui/message_center/notification.h
+++ b/ui/message_center/notification.h
@@ -57,8 +57,8 @@ class MESSAGE_CENTER_EXPORT Notification {
// End unpacked values.
// Images fetched asynchronously.
- const gfx::Image& primary_icon() const { return primary_icon_; }
- void set_primary_icon(const gfx::Image& icon) { primary_icon_ = icon; }
+ const gfx::Image& icon() const { return icon_; }
+ void set_icon(const gfx::Image& icon) { icon_ = icon; }
const gfx::Image& image() const { return image_; }
void set_image(const gfx::Image& image) { image_ = image; }
@@ -67,15 +67,19 @@ class MESSAGE_CENTER_EXPORT Notification {
const std::vector<ButtonInfo>& buttons() const { return buttons_; }
bool SetButtonIcon(size_t index, const gfx::Image& 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;
}
+ // Read status in the message center.
+ bool is_read() const { return is_read_; }
+ void set_is_read(bool read) { is_read_ = read; }
+
+ // Expanded status in the message center (not the popups).
+ bool is_expanded() const { return is_expanded_; }
+ void set_is_expanded(bool expanded) { is_expanded_ = expanded; }
+
// 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_; }
@@ -96,11 +100,12 @@ class MESSAGE_CENTER_EXPORT Notification {
unsigned serial_number_;
string16 expanded_message_;
std::vector<NotificationItem> items_;
- gfx::Image primary_icon_;
+ gfx::Image icon_;
gfx::Image image_;
std::vector<ButtonInfo> buttons_;
+ bool shown_as_popup_; // True if this has been shown as a popup.
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.
+ bool is_expanded_; // True if this has been expanded in the message center.
DISALLOW_COPY_AND_ASSIGN(Notification);
};
diff --git a/ui/message_center/notification_change_observer.h b/ui/message_center/notification_change_observer.h
new file mode 100644
index 0000000..ff45685
--- /dev/null
+++ b/ui/message_center/notification_change_observer.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 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_CHANGE_OBSERVER_H_
+#define UI_MESSAGE_CENTER_NOTIFICATION_CHANGE_OBSERVER_H_
+
+#include <string>
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace message_center {
+
+// For classes that need to handle or propagate notification changes.
+class MESSAGE_CENTER_EXPORT NotificationChangeObserver {
+ public:
+ virtual ~NotificationChangeObserver() {};
+
+ virtual void OnRemoveNotification(const std::string& id, bool by_user) {};
+ virtual void OnRemoveAllNotifications(bool by_user) {};
+
+ virtual void OnDisableNotificationsByExtension(const std::string& id) {};
+ virtual void OnDisableNotificationsByUrl(const std::string& id) {};
+
+ virtual void OnShowNotificationSettings(const std::string& id) {};
+ virtual void OnShowNotificationSettingsDialog(gfx::NativeView context) {};
+
+ virtual void OnExpanded(const std::string& id) {};
+ virtual void OnClicked(const std::string& id) {};
+ virtual void OnButtonClicked(const std::string& id, int button_index) {};
+};
+
+} // namespace message_center
+
+#endif // UI_MESSAGE_CENTER_NOTIFICATION_CHANGE_OBSERVER_H_
diff --git a/ui/message_center/notification_list.cc b/ui/message_center/notification_list.cc
index 4f0c69a..2e108f9 100644
--- a/ui/message_center/notification_list.cc
+++ b/ui/message_center/notification_list.cc
@@ -38,6 +38,9 @@ bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) {
const size_t NotificationList::kMaxVisibleMessageCenterNotifications = 100;
const size_t NotificationList::kMaxVisiblePopupNotifications = 2;
+NotificationList::Delegate::~Delegate() {
+}
+
NotificationList::NotificationList(Delegate* delegate)
: delegate_(delegate),
message_center_visible_(false),
@@ -157,7 +160,7 @@ bool NotificationList::SetNotificationIcon(const std::string& notification_id,
Notifications::iterator iter = GetNotification(notification_id);
if (iter == notifications_.end())
return false;
- (*iter)->set_primary_icon(image);
+ (*iter)->set_icon(image);
return true;
}
@@ -247,6 +250,12 @@ void NotificationList::MarkSinglePopupAsShown(
}
}
+void NotificationList::MarkNotificationAsExpanded(const std::string& id) {
+ Notifications::iterator iter = GetNotification(id);
+ if (iter != notifications_.end())
+ (*iter)->set_is_expanded(true);
+}
+
void NotificationList::SetQuietMode(bool quiet_mode) {
SetQuietModeInternal(quiet_mode);
quiet_mode_timer_.reset();
diff --git a/ui/message_center/notification_list.h b/ui/message_center/notification_list.h
index be8718c..9a4c957 100644
--- a/ui/message_center/notification_list.h
+++ b/ui/message_center/notification_list.h
@@ -45,37 +45,14 @@ class MESSAGE_CENTER_EXPORT NotificationList {
class MESSAGE_CENTER_EXPORT Delegate {
public:
- Delegate() {}
- virtual ~Delegate() {}
+ virtual ~Delegate();
// Removes notifications
virtual void SendRemoveNotification(const std::string& id,
bool by_user) = 0;
- virtual void SendRemoveAllNotifications(bool by_user) = 0;
-
- // Disables notifications
- virtual void DisableNotificationByExtension(const std::string& id) = 0;
- virtual void DisableNotificationByUrl(const std::string& id) = 0;
-
- // Requests the Delegate to show the settings page.
- virtual void ShowNotificationSettings(const std::string& id) = 0;
-
- // Requests the Delegate to show the settings dialog.
- virtual void ShowNotificationSettingsDialog(gfx::NativeView context) = 0;
-
- // Called when a notification is clicked on.
- virtual void OnNotificationClicked(const std::string& id) = 0;
// Called when the quiet mode status has been changed.
virtual void OnQuietModeChanged(bool quiet_mode) = 0;
-
- // Called when a button in a notification is clicked. |button_index|
- // indicates which button was clicked, zero-indexed (button one is 0,
- // button two is 1).
- virtual void OnButtonClicked(const std::string& id, int button_index) = 0;
-
- // Returns the list of notifications to display.
- virtual NotificationList* GetNotificationList() = 0;
};
explicit NotificationList(Delegate* delegate);
@@ -139,6 +116,9 @@ class MESSAGE_CENTER_EXPORT NotificationList {
void MarkSinglePopupAsShown(const std::string& id,
bool mark_notification_as_read);
+ // Marks the specified notification as expanded in the notification center.
+ void MarkNotificationAsExpanded(const std::string& id);
+
bool quiet_mode() const { return quiet_mode_; }
// Sets the current quiet mode status to |quiet_mode|. The new status is not
diff --git a/ui/message_center/notification_list_unittest.cc b/ui/message_center/notification_list_unittest.cc
index 4cf791e..aa4ab66 100644
--- a/ui/message_center/notification_list_unittest.cc
+++ b/ui/message_center/notification_list_unittest.cc
@@ -27,42 +27,15 @@ class MockNotificationListDelegate : public NotificationList::Delegate {
}
private:
- // NotificationList::Delegate overrides:
+ // Overridden from NotificationList::Delegate:
virtual void SendRemoveNotification(const std::string& id,
bool by_user) OVERRIDE {
send_remove_count_++;
}
- virtual void SendRemoveAllNotifications(bool by_user) OVERRIDE {
- }
-
- virtual void DisableNotificationByExtension(const std::string& id) OVERRIDE {
- }
-
- virtual void DisableNotificationByUrl(const std::string& id) OVERRIDE {
- }
-
- virtual void ShowNotificationSettings(const std::string& id) OVERRIDE {
- }
-
- virtual void ShowNotificationSettingsDialog(
- gfx::NativeView context) OVERRIDE {
- }
-
- virtual void OnNotificationClicked(const std::string& id) OVERRIDE {
- }
-
virtual void OnQuietModeChanged(bool quiet_mode) OVERRIDE {
}
- virtual void OnButtonClicked(const std::string& id,
- int button_index) OVERRIDE {
- }
-
- virtual NotificationList* GetNotificationList() OVERRIDE {
- return NULL;
- }
-
size_t send_remove_count_;
DISALLOW_COPY_AND_ASSIGN(MockNotificationListDelegate);
};
diff --git a/ui/message_center/views/message_bubble_base.cc b/ui/message_center/views/message_bubble_base.cc
index d7fc5e7..7438496 100644
--- a/ui/message_center/views/message_bubble_base.cc
+++ b/ui/message_center/views/message_bubble_base.cc
@@ -26,8 +26,8 @@ const SkColor MessageBubbleBase::kHeaderBackgroundColorLight =
const SkColor MessageBubbleBase::kHeaderBackgroundColorDark =
SkColorSetRGB(0xe7, 0xe7, 0xe7);
-MessageBubbleBase::MessageBubbleBase(NotificationList::Delegate* list_delegate)
- : list_delegate_(list_delegate),
+MessageBubbleBase::MessageBubbleBase(MessageCenter* message_center)
+ : message_center_(message_center),
bubble_view_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
max_height_(kMessageBubbleBaseDefaultMaxHeight) {
diff --git a/ui/message_center/views/message_bubble_base.h b/ui/message_center/views/message_bubble_base.h
index f43c9b7..c7255f8 100644
--- a/ui/message_center/views/message_bubble_base.h
+++ b/ui/message_center/views/message_bubble_base.h
@@ -6,15 +6,15 @@
#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_BUBBLE_BASE_H_
#include "base/memory/scoped_ptr.h"
+#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_export.h"
-#include "ui/message_center/notification_list.h"
#include "ui/views/bubble/tray_bubble_view.h"
namespace message_center {
class MESSAGE_CENTER_EXPORT MessageBubbleBase {
public:
- explicit MessageBubbleBase(NotificationList::Delegate* list_delegate);
+ explicit MessageBubbleBase(MessageCenter* message_center);
virtual ~MessageBubbleBase();
@@ -61,13 +61,13 @@ class MESSAGE_CENTER_EXPORT MessageBubbleBase {
protected:
views::TrayBubbleView::InitParams GetDefaultInitParams(
views::TrayBubbleView::AnchorAlignment anchor_alignment);
- NotificationList::Delegate* list_delegate() { return list_delegate_; }
+ MessageCenter* message_center() { return message_center_; }
void set_bubble_view(views::TrayBubbleView* bubble_view) {
bubble_view_ = bubble_view;
}
private:
- NotificationList::Delegate* list_delegate_;
+ MessageCenter* message_center_;
views::TrayBubbleView* bubble_view_;
base::WeakPtrFactory<MessageBubbleBase> weak_ptr_factory_;
int max_height_;
diff --git a/ui/message_center/views/message_center_bubble.cc b/ui/message_center/views/message_center_bubble.cc
index a64c854..b91854e 100644
--- a/ui/message_center/views/message_center_bubble.cc
+++ b/ui/message_center/views/message_center_bubble.cc
@@ -4,6 +4,8 @@
#include "ui/message_center/views/message_center_bubble.h"
+#include <map>
+
#include "grit/ui_strings.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "ui/base/l10n/l10n_util.h"
@@ -49,8 +51,8 @@ const SkColor kFocusBorderColor = SkColorSetRGB(0x40, 0x80, 0xfa);
class WebNotificationButtonViewBase : public views::View {
public:
- WebNotificationButtonViewBase(NotificationList::Delegate* list_delegate)
- : list_delegate_(list_delegate),
+ WebNotificationButtonViewBase(NotificationChangeObserver* observer)
+ : observer_(observer),
close_all_button_(NULL) {}
void SetCloseAllVisible(bool visible) {
@@ -63,11 +65,11 @@ class WebNotificationButtonViewBase : public views::View {
}
protected:
- NotificationList::Delegate* list_delegate() { return list_delegate_; }
+ NotificationChangeObserver* observer() { return observer_; }
views::Button* close_all_button() { return close_all_button_; }
private:
- NotificationList::Delegate* list_delegate_;
+ NotificationChangeObserver* observer_; // Weak reference.
views::Button* close_all_button_;
DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonViewBase);
@@ -77,8 +79,8 @@ class WebNotificationButtonViewBase : public views::View {
class WebNotificationButtonView : public WebNotificationButtonViewBase,
public views::ButtonListener {
public:
- explicit WebNotificationButtonView(NotificationList::Delegate* list_delegate)
- : WebNotificationButtonViewBase(list_delegate) {
+ explicit WebNotificationButtonView(NotificationChangeObserver* observer)
+ : WebNotificationButtonViewBase(observer) {
set_background(views::Background::CreateBackgroundPainter(
true,
views::Painter::CreateVerticalGradient(
@@ -111,11 +113,11 @@ class WebNotificationButtonView : public WebNotificationButtonViewBase,
virtual ~WebNotificationButtonView() {}
- // Overridden from ButtonListener.
+ // Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE {
if (sender == close_all_button())
- list_delegate()->SendRemoveAllNotifications(true); // Action by user.
+ observer()->OnRemoveAllNotifications(true); // Action by user.
}
private:
@@ -134,7 +136,7 @@ class WebNotificationButton : public views::TextButton {
}
protected:
- // views::View overrides:
+ // Overridden from views::View:
virtual gfx::Size GetPreferredSize() OVERRIDE {
// Returns an empty size when invisible, to trim its space in the parent's
// GridLayout.
@@ -164,8 +166,8 @@ class WebNotificationButton : public views::TextButton {
class WebNotificationButtonView2 : public WebNotificationButtonViewBase,
public views::ButtonListener {
public:
- explicit WebNotificationButtonView2(NotificationList::Delegate* list_delegate)
- : WebNotificationButtonViewBase(list_delegate) {
+ explicit WebNotificationButtonView2(NotificationChangeObserver* observer)
+ : WebNotificationButtonViewBase(observer) {
set_background(views::Background::CreateSolidBackground(
kMessageCenterBackgroundColor));
set_border(views::Border::CreateSolidSidedBorder(
@@ -206,13 +208,13 @@ class WebNotificationButtonView2 : public WebNotificationButtonViewBase,
}
private:
- // views::ButtonListener overrides:
+ // Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE {
if (sender == close_all_button())
- list_delegate()->SendRemoveAllNotifications(true); // Action by user.
+ observer()->OnRemoveAllNotifications(true); // Action by user.
else if (sender == settings_button_)
- list_delegate()->ShowNotificationSettingsDialog(
+ observer()->OnShowNotificationSettingsDialog(
GetWidget()->GetNativeView());
else
NOTREACHED();
@@ -224,10 +226,13 @@ class WebNotificationButtonView2 : public WebNotificationButtonViewBase,
DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView2);
};
-// A custom scroll-view that has a specified size.
-class FixedSizedScrollView : public views::ScrollView {
+// A custom scroll view whose height has a minimum and maximum value and whose
+// scroll bar disappears when not needed.
+class BoundedScrollView : public views::ScrollView {
public:
- FixedSizedScrollView() {
+ BoundedScrollView(int min_height, int max_height)
+ : min_height_(min_height),
+ max_height_(max_height) {
set_notify_enter_exit_on_child(true);
if (IsRichNotificationEnabled()) {
set_background(views::Background::CreateSolidBackground(
@@ -235,53 +240,51 @@ class FixedSizedScrollView : public views::ScrollView {
}
}
- virtual ~FixedSizedScrollView() {}
-
- void SetFixedSize(const gfx::Size& size) {
- if (fixed_size_ == size)
- return;
- fixed_size_ = size;
- PreferredSizeChanged();
- }
+ virtual ~BoundedScrollView() {}
- // views::View overrides.
+ // Overridden from views::View:
virtual gfx::Size GetPreferredSize() OVERRIDE {
- gfx::Size size = fixed_size_.IsEmpty() ?
- contents()->GetPreferredSize() : fixed_size_;
+ gfx::Size size = contents()->GetPreferredSize();
+ size.ClampToMin(gfx::Size(size.width(), min_height_));
+ size.ClampToMax(gfx::Size(size.width(), max_height_));
gfx::Insets insets = GetInsets();
size.Enlarge(insets.width(), insets.height());
return size;
}
virtual void Layout() OVERRIDE {
- gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize());
- bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
- contents()->SetBoundsRect(bounds);
-
+ // Lay out the view as if it will have a scroll bar.
+ gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
+ content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
+ contents()->SetBoundsRect(content_bounds);
views::ScrollView::Layout();
+
+ // But use the scroll bar space if no scroll bar is needed.
if (!vertical_scroll_bar()->visible()) {
- gfx::Rect bounds = contents()->bounds();
- bounds.set_width(bounds.width() + GetScrollBarWidth());
- contents()->SetBoundsRect(bounds);
+ content_bounds = contents()->bounds();
+ content_bounds.set_width(content_bounds.width() + GetScrollBarWidth());
+ contents()->SetBoundsRect(content_bounds);
}
}
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
- gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize());
- bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
- contents()->SetBoundsRect(bounds);
+ // Make sure any content resizing takes into account the scroll bar.
+ gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
+ content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
+ contents()->SetBoundsRect(content_bounds);
}
private:
- gfx::Size fixed_size_;
+ int min_height_;
+ int max_height_;
- DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView);
+ DISALLOW_COPY_AND_ASSIGN(BoundedScrollView);
};
-// Container for the messages.
-class ScrollContentView : public views::View {
+// Displays a list of messages.
+class MessageListView : public views::View {
public:
- ScrollContentView() {
+ MessageListView() {
if (IsRichNotificationEnabled()) {
// Set the margin to 0 for the layout. BoxLayout assumes the same margin
// for top and bottom, but the bottom margin here should be smaller
@@ -308,39 +311,33 @@ class ScrollContentView : public views::View {
}
}
- virtual ~ScrollContentView() {
- }
-
- virtual gfx::Size GetPreferredSize() OVERRIDE {
- if (!preferred_size_.IsEmpty())
- return preferred_size_;
- return views::View::GetPreferredSize();
+ virtual ~MessageListView() {
}
- void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
-
private:
- gfx::Size preferred_size_;
- DISALLOW_COPY_AND_ASSIGN(ScrollContentView);
+ DISALLOW_COPY_AND_ASSIGN(MessageListView);
};
} // namespace
-// Message Center contents.
-class MessageCenterContentsView : public views::View {
+// View that displays the whole message center.
+class MessageCenterView : public views::View {
public:
- explicit MessageCenterContentsView(MessageCenterBubble* bubble,
- NotificationList::Delegate* list_delegate)
- : list_delegate_(list_delegate),
- bubble_(bubble) {
+ MessageCenterView(MessageCenterBubble* bubble) : bubble_(bubble) {
int between_child = IsRichNotificationEnabled() ? 0 : 1;
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child));
- scroll_content_ = new ScrollContentView;
- scroller_ = new FixedSizedScrollView;
- scroller_->SetContents(scroll_content_);
- AddChildView(scroller_);
+
+ if (IsRichNotificationEnabled())
+ button_view_ = new WebNotificationButtonView2(bubble_);
+ else
+ button_view_ = new WebNotificationButtonView(bubble_);
+
+ const int button_height = button_view_->GetPreferredSize().height();
+ const int min_height = kMessageBubbleBaseMinHeight - button_height;
+ const int max_height = bubble_->max_height() - button_height;
+ scroller_ = new BoundedScrollView(min_height, max_height);
if (get_use_acceleration_when_possible()) {
scroller_->SetPaintToLayer(true);
@@ -348,31 +345,28 @@ class MessageCenterContentsView : public views::View {
scroller_->layer()->SetMasksToBounds(true);
}
- if (IsRichNotificationEnabled())
- button_view_ = new WebNotificationButtonView2(list_delegate);
- else
- button_view_ = new WebNotificationButtonView(list_delegate);
+ message_list_view_ = new MessageListView();
+ scroller_->SetContents(message_list_view_);
+
+ AddChildView(scroller_);
AddChildView(button_view_);
}
void FocusContents() {
}
- void Update(const NotificationList::Notifications& notifications) {
- scroll_content_->RemoveAllChildViews(true);
- scroll_content_->set_preferred_size(gfx::Size());
- size_t num_children = 0;
+ void UpdateAllNotifications(
+ const NotificationList::Notifications& notifications) {
+ RemoveAllNotifications();
for (NotificationList::Notifications::const_iterator iter =
notifications.begin(); iter != notifications.end(); ++iter) {
- MessageView* view = NotificationView::Create(*(*iter), list_delegate_);
- view->set_scroller(scroller_);
- scroll_content_->AddChildView(view);
- if (++num_children >=
+ AddNotification(*(*iter));
+ if (message_views_.size() >=
NotificationList::kMaxVisibleMessageCenterNotifications) {
break;
}
}
- if (num_children == 0) {
+ if (message_views_.empty()) {
views::Label* label = new views::Label(l10n_util::GetStringUTF16(
IDS_MESSAGE_CENTER_NO_MESSAGES));
label->SetFont(label->font().DeriveFont(1));
@@ -380,53 +374,70 @@ class MessageCenterContentsView : public views::View {
// Set transparent background to ensure that subpixel rendering
// is disabled. See crbug.com/169056
label->SetBackgroundColor(kTransparentColor);
- scroll_content_->AddChildView(label);
+ message_list_view_->AddChildView(label);
button_view_->SetCloseAllVisible(false);
scroller_->set_focusable(false);
} else {
button_view_->SetCloseAllVisible(true);
scroller_->set_focusable(true);
}
- SizeScrollContent();
Layout();
- if (GetWidget())
- GetWidget()->GetRootView()->SchedulePaint();
+ }
+
+ void UpdateOneNotification(const Notification& notification) {
+ // Update the corresponding message view if there is one and explicitly
+ // update this view's layout as this is not automatic in spite of the
+ // updated view's likely size change because ScrollView's Viewport breaks
+ // the ChildPreferredSizeChange() chain.
+ MessageView* view = message_views_[notification.id()];
+ if (view) {
+ view->Update(notification);
+ Layout();
+ }
}
size_t NumMessageViews() const {
- return scroll_content_->child_count();
+ return message_list_view_->child_count();
+ }
+
+ protected:
+ // Overridden from views::View:
+ virtual void Layout() OVERRIDE {
+ scroller_->SizeToPreferredSize();
+ views::View::Layout();
+ if (GetWidget())
+ GetWidget()->GetRootView()->SchedulePaint();
+ bubble_->bubble_view()->UpdateBubble();
}
private:
- void SizeScrollContent() {
- gfx::Size scroll_size = scroll_content_->GetPreferredSize();
- const int button_height = button_view_->GetPreferredSize().height();
- const int min_height = kMessageBubbleBaseMinHeight - button_height;
- const int max_height = bubble_->max_height() - button_height;
- int scroll_height = std::min(std::max(
- scroll_size.height(), min_height), max_height);
- scroll_size.set_height(scroll_height);
- if (scroll_height == min_height)
- scroll_content_->set_preferred_size(scroll_size);
- else
- scroll_content_->set_preferred_size(gfx::Size());
- scroller_->SetFixedSize(scroll_size);
- scroller_->SizeToPreferredSize();
- scroll_content_->InvalidateLayout();
+
+ void RemoveAllNotifications() {
+ message_views_.clear();
+ message_list_view_->RemoveAllChildViews(true);
+ }
+
+ void AddNotification(const Notification& notification) {
+ // Always expand the first (topmost) notification.
+ bool expand = (notification.is_expanded() || message_views_.empty());
+ MessageView* view = NotificationView::Create(notification, bubble_, expand);
+ view->set_scroller(scroller_);
+ message_views_[notification.id()] = view;
+ message_list_view_->AddChildView(view);
}
- NotificationList::Delegate* list_delegate_;
- FixedSizedScrollView* scroller_;
- ScrollContentView* scroll_content_;
+ MessageCenterBubble* bubble_; // Weak reference.
+ std::map<std::string,MessageView*> message_views_;
+ BoundedScrollView* scroller_;
+ MessageListView* message_list_view_;
WebNotificationButtonViewBase* button_view_;
- MessageCenterBubble* bubble_;
- DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView);
+ DISALLOW_COPY_AND_ASSIGN(MessageCenterView);
};
// Message Center Bubble.
-MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate)
- : MessageBubbleBase(delegate),
+MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center)
+ : MessageBubbleBase(message_center),
contents_view_(NULL) {
}
@@ -448,7 +459,7 @@ views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams(
void MessageCenterBubble::InitializeContents(
views::TrayBubbleView* new_bubble_view) {
set_bubble_view(new_bubble_view);
- contents_view_ = new MessageCenterContentsView(this, list_delegate());
+ contents_view_ = new MessageCenterView(this);
bubble_view()->AddChildView(contents_view_);
// Resize the content of the bubble view to the given bubble size. This is
// necessary in case of the bubble border forcing a bigger size then the
@@ -466,8 +477,8 @@ void MessageCenterBubble::UpdateBubbleView() {
if (!bubble_view())
return; // Could get called after view is closed
const NotificationList::Notifications& notifications =
- list_delegate()->GetNotificationList()->GetNotifications();
- contents_view_->Update(notifications);
+ message_center()->notification_list()->GetNotifications();
+ contents_view_->UpdateAllNotifications(notifications);
bubble_view()->Show();
bubble_view()->UpdateBubble();
}
@@ -478,6 +489,57 @@ void MessageCenterBubble::OnMouseEnteredView() {
void MessageCenterBubble::OnMouseExitedView() {
}
+void MessageCenterBubble::OnRemoveNotification(const std::string& id,
+ bool by_user) {
+ message_center()->OnRemoveNotification(id, by_user);
+}
+
+void MessageCenterBubble::OnRemoveAllNotifications(bool by_user) {
+ message_center()->OnRemoveAllNotifications(by_user);
+}
+
+void MessageCenterBubble::OnDisableNotificationsByExtension(
+ const std::string& id) {
+ message_center()->OnDisableNotificationsByExtension(id);
+}
+
+void MessageCenterBubble::OnDisableNotificationsByUrl(const std::string& id) {
+ message_center()->OnDisableNotificationsByUrl(id);
+}
+
+void MessageCenterBubble::OnShowNotificationSettings(const std::string& id) {
+ message_center()->OnShowNotificationSettings(id);
+}
+
+void MessageCenterBubble::OnShowNotificationSettingsDialog(
+ gfx::NativeView context) {
+ message_center()->OnShowNotificationSettingsDialog(context);
+}
+
+void MessageCenterBubble::OnClicked(const std::string& id) {
+ message_center()->OnClicked(id);
+}
+
+void MessageCenterBubble::OnButtonClicked(const std::string& id,
+ int button_index) {
+ message_center()->OnButtonClicked(id, button_index);
+}
+
+void MessageCenterBubble::OnExpanded(const std::string& id) {
+ message_center()->OnExpanded(id);
+
+ // Update the view corresponding to this notification.
+ const NotificationList::Notifications& notifications =
+ message_center()->notification_list()->GetNotifications();
+ for (NotificationList::Notifications::const_iterator iter =
+ notifications.begin(); iter != notifications.end(); ++iter) {
+ if ((*iter)->id() == id) {
+ contents_view_->UpdateOneNotification(*(*iter));
+ break;
+ }
+ }
+}
+
size_t MessageCenterBubble::NumMessageViewsForTest() const {
return contents_view_->NumMessageViews();
}
diff --git a/ui/message_center/views/message_center_bubble.h b/ui/message_center/views/message_center_bubble.h
index 3b77571..bed2262 100644
--- a/ui/message_center/views/message_center_bubble.h
+++ b/ui/message_center/views/message_center_bubble.h
@@ -6,21 +6,23 @@
#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUBBLE_H_
#include "ui/message_center/message_center_export.h"
-#include "ui/message_center/notification_list.h"
+#include "ui/message_center/notification_change_observer.h"
#include "ui/message_center/views/message_bubble_base.h"
namespace message_center {
-class MessageCenterContentsView;
+class MessageCenterView;
// Bubble for message center.
-class MESSAGE_CENTER_EXPORT MessageCenterBubble : public MessageBubbleBase {
+class MESSAGE_CENTER_EXPORT MessageCenterBubble
+ : public MessageBubbleBase,
+ public NotificationChangeObserver {
public:
- explicit MessageCenterBubble(NotificationList::Delegate* delegate);
+ explicit MessageCenterBubble(MessageCenter* message_center);
virtual ~MessageCenterBubble();
- // Overridden from MessageBubbleBase.
+ // Overridden from MessageBubbleBase:
virtual views::TrayBubbleView::InitParams GetInitParams(
views::TrayBubbleView::AnchorAlignment anchor_alignment) OVERRIDE;
virtual void InitializeContents(views::TrayBubbleView* bubble_view) OVERRIDE;
@@ -29,10 +31,25 @@ class MESSAGE_CENTER_EXPORT MessageCenterBubble : public MessageBubbleBase {
virtual void OnMouseEnteredView() OVERRIDE;
virtual void OnMouseExitedView() OVERRIDE;
+ // Overridden from NotificationChangeObserver:
+ virtual void OnRemoveNotification(const std::string& id, bool by_user)
+ OVERRIDE;
+ virtual void OnRemoveAllNotifications(bool by_user) OVERRIDE;
+ virtual void OnDisableNotificationsByExtension(const std::string& id)
+ OVERRIDE;
+ virtual void OnDisableNotificationsByUrl(const std::string& id) OVERRIDE;
+ virtual void OnShowNotificationSettings(const std::string& id) OVERRIDE;
+ virtual void OnShowNotificationSettingsDialog(gfx::NativeView context)
+ OVERRIDE;
+ virtual void OnExpanded(const std::string& id) OVERRIDE;
+ virtual void OnClicked(const std::string& id) OVERRIDE;
+ virtual void OnButtonClicked(const std::string& id,
+ int button_index) OVERRIDE;
+
size_t NumMessageViewsForTest() const;
private:
- MessageCenterContentsView* contents_view_;
+ MessageCenterView* contents_view_;
// The maximum height
int max_height_;
diff --git a/ui/message_center/views/message_popup_bubble.cc b/ui/message_center/views/message_popup_bubble.cc
index 696b016..46238dd 100644
--- a/ui/message_center/views/message_popup_bubble.cc
+++ b/ui/message_center/views/message_popup_bubble.cc
@@ -8,6 +8,7 @@
#include "base/stl_util.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_change_observer.h"
#include "ui/message_center/notification_types.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/notification_view.h"
@@ -21,7 +22,7 @@ namespace message_center {
// Popup notifications contents.
class PopupBubbleContentsView : public views::View {
public:
- explicit PopupBubbleContentsView(NotificationList::Delegate* list_delegate);
+ explicit PopupBubbleContentsView(NotificationChangeObserver* observer);
void Update(const NotificationList::PopupNotifications& popup_notifications);
@@ -30,15 +31,15 @@ class PopupBubbleContentsView : public views::View {
}
private:
- NotificationList::Delegate* list_delegate_;
+ NotificationChangeObserver* observer_; // Weak reference.
views::View* content_;
DISALLOW_COPY_AND_ASSIGN(PopupBubbleContentsView);
};
PopupBubbleContentsView::PopupBubbleContentsView(
- NotificationList::Delegate* list_delegate)
- : list_delegate_(list_delegate) {
+ NotificationChangeObserver* observer)
+ : observer_(observer) {
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
content_ = new views::View;
@@ -59,7 +60,11 @@ void PopupBubbleContentsView::Update(
for (NotificationList::PopupNotifications::const_iterator iter =
popup_notifications.begin();
iter != popup_notifications.end(); ++iter) {
- content_->AddChildView(NotificationView::Create(*(*iter), list_delegate_));
+ // NotificationViews are expanded by default here because MessagePopupBubble
+ // hasn't been tested yet with changing subview sizes, and such changes
+ // could come if those subviews were initially collapsed and allowed to be
+ // expanded by users. TODO(dharcourt): Fix.
+ content_->AddChildView(NotificationView::Create(*(*iter), observer_, true));
}
content_->SizeToPreferredSize();
content_->InvalidateLayout();
@@ -113,8 +118,8 @@ void MessagePopupBubble::AutocloseTimer::Suspend() {
}
// MessagePopupBubble
-MessagePopupBubble::MessagePopupBubble(NotificationList::Delegate* delegate)
- : MessageBubbleBase(delegate),
+MessagePopupBubble::MessagePopupBubble(MessageCenter* message_center)
+ : MessageBubbleBase(message_center),
contents_view_(NULL) {
}
@@ -135,7 +140,7 @@ views::TrayBubbleView::InitParams MessagePopupBubble::GetInitParams(
void MessagePopupBubble::InitializeContents(
views::TrayBubbleView* new_bubble_view) {
set_bubble_view(new_bubble_view);
- contents_view_ = new PopupBubbleContentsView(list_delegate());
+ contents_view_ = new PopupBubbleContentsView(message_center());
bubble_view()->AddChildView(contents_view_);
UpdateBubbleView();
}
@@ -146,7 +151,7 @@ void MessagePopupBubble::OnBubbleViewDestroyed() {
void MessagePopupBubble::UpdateBubbleView() {
NotificationList::PopupNotifications popups =
- list_delegate()->GetNotificationList()->GetPopupNotifications();
+ message_center()->notification_list()->GetPopupNotifications();
if (popups.size() == 0) {
if (bubble_view())
@@ -200,7 +205,7 @@ void MessagePopupBubble::OnMouseExitedView() {
void MessagePopupBubble::OnAutoClose(const std::string& id) {
DeleteTimer(id);
- list_delegate()->GetNotificationList()->MarkSinglePopupAsShown(id, false);
+ message_center()->notification_list()->MarkSinglePopupAsShown(id, false);
UpdateBubbleView();
}
diff --git a/ui/message_center/views/message_popup_bubble.h b/ui/message_center/views/message_popup_bubble.h
index 060d22f..671c0b6 100644
--- a/ui/message_center/views/message_popup_bubble.h
+++ b/ui/message_center/views/message_popup_bubble.h
@@ -11,7 +11,6 @@
#include "base/timer.h"
#include "ui/message_center/message_center_export.h"
-#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_bubble_base.h"
namespace message_center {
@@ -21,11 +20,11 @@ class PopupBubbleContentsView;
// Bubble for popup notifications.
class MESSAGE_CENTER_EXPORT MessagePopupBubble : public MessageBubbleBase {
public:
- explicit MessagePopupBubble(NotificationList::Delegate* delegate);
+ explicit MessagePopupBubble(MessageCenter* message_center);
virtual ~MessagePopupBubble();
- // Overridden from MessageBubbleBase.
+ // Overridden from MessageBubbleBase:
virtual views::TrayBubbleView::InitParams GetInitParams(
views::TrayBubbleView::AnchorAlignment anchor_alignment) OVERRIDE;
virtual void InitializeContents(views::TrayBubbleView* bubble_view) OVERRIDE;
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
index f00308d..fb81d69 100644
--- a/ui/message_center/views/message_popup_collection.cc
+++ b/ui/message_center/views/message_popup_collection.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/timer.h"
#include "ui/gfx/screen.h"
+#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_list.h"
@@ -18,6 +19,7 @@
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
namespace message_center {
@@ -85,7 +87,7 @@ class ToastContentsView : public views::WidgetDelegateView {
base::Unretained(GetWidget())));
}
- // views::WidgetDelegate overrides:
+ // Overridden from views::WidgetDelegate:
virtual views::View* GetContentsView() OVERRIDE {
return this;
}
@@ -99,7 +101,7 @@ class ToastContentsView : public views::WidgetDelegateView {
return false;
}
- // views::View overrides:
+ // Overridden from views::View:
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
collection_->OnMouseEntered();
}
@@ -117,12 +119,11 @@ class ToastContentsView : public views::WidgetDelegateView {
DISALLOW_COPY_AND_ASSIGN(ToastContentsView);
};
-MessagePopupCollection::MessagePopupCollection(
- gfx::NativeView context,
- NotificationList::Delegate* list_delegate)
+MessagePopupCollection::MessagePopupCollection(gfx::NativeView context,
+ MessageCenter* message_center)
: context_(context),
- list_delegate_(list_delegate) {
- DCHECK(list_delegate_);
+ message_center_(message_center) {
+ DCHECK(message_center_);
}
MessagePopupCollection::~MessagePopupCollection() {
@@ -131,7 +132,7 @@ MessagePopupCollection::~MessagePopupCollection() {
void MessagePopupCollection::UpdatePopups() {
NotificationList::PopupNotifications popups =
- list_delegate_->GetNotificationList()->GetPopupNotifications();
+ message_center_->notification_list()->GetPopupNotifications();
if (popups.empty()) {
CloseAllWidgets();
@@ -153,7 +154,12 @@ void MessagePopupCollection::UpdatePopups() {
popups.begin(); iter != popups.end(); ++iter) {
ToastContainer::iterator toast_iter = toasts_.find((*iter)->id());
views::Widget* widget = NULL;
- MessageView* view = NotificationView::Create(*(*iter), list_delegate_);
+ // NotificationViews are expanded by default here because
+ // MessagePopupCollection hasn't been tested yet with changing subview
+ // sizes, and such changes could come if those subviews were initially
+ // collapsed and allowed to be expanded by users. TODO(dharcourt): Fix.
+ MessageView* view = NotificationView::Create(*(*iter), message_center_,
+ true);
if (toast_iter != toasts_.end()) {
widget = toast_iter->second->GetWidget();
old_toast_ids.erase((*iter)->id());
@@ -240,7 +246,7 @@ void MessagePopupCollection::OnWidgetDestroying(views::Widget* widget) {
for (ToastContainer::iterator iter = toasts_.begin();
iter != toasts_.end(); ++iter) {
if (iter->second->GetWidget() == widget) {
- list_delegate_->GetNotificationList()->MarkSinglePopupAsShown(
+ message_center_->notification_list()->MarkSinglePopupAsShown(
iter->first, false);
toasts_.erase(iter);
break;
diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h
index 0f71a2f..b85bcf0 100644
--- a/ui/message_center/views/message_popup_collection.h
+++ b/ui/message_center/views/message_popup_collection.h
@@ -8,11 +8,10 @@
#include <list>
#include <map>
+#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
-#include "base/timer.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/message_center/message_center_export.h"
-#include "ui/message_center/notification_list.h"
-#include "ui/message_center/views/message_bubble_base.h"
#include "ui/views/widget/widget_observer.h"
namespace views {
@@ -25,6 +24,7 @@ FORWARD_DECLARE_TEST(WebNotificationTrayTest, ManyPopupNotifications);
namespace message_center {
+class MessageCenter;
class ToastContentsView;
// Container for popup toasts. Because each toast is a frameless window rather
@@ -38,7 +38,7 @@ class MESSAGE_CENTER_EXPORT MessagePopupCollection
// |context| specifies the context to create toast windows. It can be NULL
// for non-aura environment. See comments in ui/views/widget/widget.h.
MessagePopupCollection(gfx::NativeView context,
- NotificationList::Delegate* list_delegate);
+ MessageCenter* message_center);
virtual ~MessagePopupCollection();
void UpdatePopups();
@@ -53,11 +53,11 @@ class MESSAGE_CENTER_EXPORT MessagePopupCollection
void CloseAllWidgets();
- // views::WidgetObserver overrides:
+ // Overridden from views::WidgetObserver:
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
gfx::NativeView context_;
- NotificationList::Delegate* list_delegate_;
+ MessageCenter* message_center_;
ToastContainer toasts_;
DISALLOW_COPY_AND_ASSIGN(MessagePopupCollection);
diff --git a/ui/message_center/views/message_simple_view.cc b/ui/message_center/views/message_simple_view.cc
index 3fe905a..9402eee 100644
--- a/ui/message_center/views/message_simple_view.cc
+++ b/ui/message_center/views/message_simple_view.cc
@@ -7,7 +7,6 @@
#include "grit/ui_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/message_center/notification.h"
-#include "ui/message_center/notification_list.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
@@ -20,10 +19,9 @@ namespace message_center {
const SkColor kNotificationColor = SkColorSetRGB(0xfe, 0xfe, 0xfe);
const SkColor kNotificationReadColor = SkColorSetRGB(0xfa, 0xfa, 0xfa);
-MessageSimpleView::MessageSimpleView(
- NotificationList::Delegate* list_delegate,
- const Notification& notification)
- : MessageView(list_delegate, notification) {
+MessageSimpleView::MessageSimpleView(const Notification& notification,
+ NotificationChangeObserver* observer)
+ : MessageView(notification, observer, false) {
views::ImageButton* close = new views::ImageButton(this);
close->SetImage(
views::CustomButton::STATE_NORMAL,
@@ -64,7 +62,7 @@ void MessageSimpleView::SetUpView(const Notification& notification) {
views::ImageView* icon = new views::ImageView;
icon->SetImageSize(
gfx::Size(kWebNotificationIconSize, kWebNotificationIconSize));
- icon->SetImage(notification.primary_icon().AsImageSkia());
+ icon->SetImage(notification.icon().AsImageSkia());
views::Label* title = new views::Label(notification.title());
title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
diff --git a/ui/message_center/views/message_simple_view.h b/ui/message_center/views/message_simple_view.h
index 2a9e9b1..50cd5d3 100644
--- a/ui/message_center/views/message_simple_view.h
+++ b/ui/message_center/views/message_simple_view.h
@@ -5,18 +5,18 @@
#ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_SIMPLE_VIEW_H_
#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_SIMPLE_VIEW_H_
-#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_view.h"
namespace message_center {
class Notification;
+class NotificationChangeObserver;
// A simple view for a notification entry (icon + message + buttons).
class MessageSimpleView : public MessageView {
public:
- MessageSimpleView(NotificationList::Delegate* list_delegate,
- const Notification& notification);
+ MessageSimpleView(const Notification& notification,
+ NotificationChangeObserver* observer);
virtual ~MessageSimpleView();
// Overridden from MessageView:
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index 0ea4f91..a8c1a63 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -14,6 +14,7 @@
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/skia_util.h"
#include "ui/message_center/message_center_util.h"
+#include "ui/message_center/notification_change_observer.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
@@ -22,9 +23,12 @@
namespace {
-const int kCloseButtonSize = 29;
+const int kControlButtonSize = 29;
const int kCloseIconTopPadding = 5;
const int kCloseIconRightPadding = 5;
+const int kExpandIconBottomPadding = 8;
+const int kExpandIconRightPadding = 11;
+
const int kShadowOffset = 1;
const int kShadowBlur = 4;
@@ -104,7 +108,7 @@ void ControlButton::SetPressedImage(int resource_id) {
}
gfx::Size ControlButton::GetPreferredSize() {
- return gfx::Size(kCloseButtonSize, kCloseButtonSize);
+ return gfx::Size(kControlButtonSize, kControlButtonSize);
}
void ControlButton::OnPaint(gfx::Canvas* canvas) {
@@ -151,7 +155,7 @@ class ShadowBorder : public views::Border {
virtual ~ShadowBorder() {}
protected:
- // views::Border overrides:
+ // Overridden from views::Border:
virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE;
virtual gfx::Insets GetInsets() const OVERRIDE;
@@ -180,7 +184,7 @@ gfx::Insets ShadowBorder::GetInsets() const {
class MenuModel : public ui::SimpleMenuModel,
public ui::SimpleMenuModel::Delegate {
public:
- MenuModel(message_center::NotificationList::Delegate* list_delegate,
+ MenuModel(message_center::NotificationChangeObserver* observer,
const std::string& notification_id,
const string16& display_source,
const std::string& extension_id);
@@ -196,19 +200,18 @@ class MenuModel : public ui::SimpleMenuModel,
virtual void ExecuteCommand(int command_id) OVERRIDE;
private:
- message_center::NotificationList::Delegate* list_delegate_;
- // Weak, global MessageCenter
+ message_center::NotificationChangeObserver* observer_; // Weak reference.
std::string notification_id_;
DISALLOW_COPY_AND_ASSIGN(MenuModel);
};
-MenuModel::MenuModel(message_center::NotificationList::Delegate* list_delegate,
+MenuModel::MenuModel(message_center::NotificationChangeObserver* observer,
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),
+ observer_(observer),
notification_id_(notification_id) {
// Add 'disable notifications' menu item.
if (!extension_id.empty()) {
@@ -249,13 +252,13 @@ bool MenuModel::GetAcceleratorForCommandId(int command_id,
void MenuModel::ExecuteCommand(int command_id) {
switch (command_id) {
case kToggleExtensionCommand:
- list_delegate_->DisableNotificationByExtension(notification_id_);
+ observer_->OnDisableNotificationsByExtension(notification_id_);
break;
case kTogglePermissionCommand:
- list_delegate_->DisableNotificationByUrl(notification_id_);
+ observer_->OnDisableNotificationsByUrl(notification_id_);
break;
case kShowSettingsCommand:
- list_delegate_->ShowNotificationSettings(notification_id_);
+ observer_->OnShowNotificationSettings(notification_id_);
break;
default:
NOTREACHED();
@@ -266,19 +269,31 @@ void MenuModel::ExecuteCommand(int command_id) {
namespace message_center {
-MessageView::MessageView(NotificationList::Delegate* list_delegate,
- const Notification& notification)
- : list_delegate_(list_delegate),
+MessageView::MessageView(const Notification& notification,
+ NotificationChangeObserver* observer,
+ bool expanded)
+ : observer_(observer),
notification_id_(notification.id()),
display_source_(notification.display_source()),
extension_id_(notification.extension_id()),
- scroller_(NULL) {
+ scroller_(NULL),
+ is_expanded_(expanded) {
ControlButton *close = new ControlButton(this);
close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
+ close->set_owned_by_client();
close_button_.reset(close);
+
+ ControlButton *expand = new ControlButton(this);
+ expand->SetPadding(-kExpandIconRightPadding, -kExpandIconBottomPadding);
+ expand->SetNormalImage(IDR_NOTIFICATIONS_EXPAND);
+ expand->SetHoveredImage(IDR_NOTIFICATIONS_EXPAND_HOVER);
+ expand->SetPressedImage(IDR_NOTIFICATIONS_EXPAND_PRESSED);
+ expand->set_owned_by_client();
+ expand_button_.reset(expand);
+
if (IsRichNotificationEnabled())
set_border(new ShadowBorder());
}
@@ -297,18 +312,24 @@ gfx::Insets MessageView::GetShadowInsets() {
kShadowBlur / 2);
}
+void MessageView::Update(const Notification& notification) {
+ notification_id_ = notification.id();
+ display_source_ = notification.display_source();
+ extension_id_ = notification.extension_id();
+}
+
bool MessageView::OnMousePressed(const ui::MouseEvent& event) {
if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON) {
ShowMenu(event.location());
return true;
}
- list_delegate_->OnNotificationClicked(notification_id_);
+ observer_->OnClicked(notification_id_);
return true;
}
void MessageView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP) {
- list_delegate_->OnNotificationClicked(notification_id_);
+ observer_->OnClicked(notification_id_);
event->SetHandled();
return;
}
@@ -334,12 +355,16 @@ 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_, true); // By user.
+ if (sender == close_button()) {
+ observer_->OnRemoveNotification(notification_id_, true); // By user.
+ } else if (sender == expand_button()) {
+ is_expanded_ = true;
+ observer_->OnExpanded(notification_id_);
+ }
}
void MessageView::ShowMenu(gfx::Point screen_location) {
- MenuModel menu_model(list_delegate_, notification_id_,
+ MenuModel menu_model(observer_, notification_id_,
display_source_, extension_id_);
if (menu_model.GetItemCount() == 0)
return;
@@ -357,7 +382,7 @@ void MessageView::ShowMenu(gfx::Point screen_location) {
}
void MessageView::OnSlideOut() {
- list_delegate_->SendRemoveNotification(notification_id_, true); // By user.
+ observer_->OnRemoveNotification(notification_id_, true); // By user.
}
} // namespace message_center
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index 86920b9..37725db 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -7,18 +7,19 @@
#include "ui/gfx/insets.h"
#include "ui/message_center/notification.h"
-#include "ui/message_center/notification_list.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/slide_out_view.h"
-#include "ui/views/view.h"
namespace views {
class ImageButton;
+class ImageView;
class ScrollView;
}
namespace message_center {
+class NotificationChangeObserver;
+
// Individual notifications constants.
const int kPaddingBetweenItems = 10;
const int kPaddingHorizontal = 18;
@@ -30,52 +31,59 @@ const int kWebNotificationWidth = 300;
class MessageView : public views::SlideOutView,
public views::ButtonListener {
public:
- MessageView(NotificationList::Delegate* list_delegate,
- const Notification& notification);
-
+ MessageView(const Notification& notification,
+ NotificationChangeObserver* observer,
+ bool expanded);
virtual ~MessageView();
// Returns the insets for the shadow it will have for rich notification.
static gfx::Insets GetShadowInsets();
- void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
+ // Adjust to any change in notification data or expanded status.
+ virtual void Update(const Notification& notification);
- // Overridden from views::View.
+ // Overridden from views::View:
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
- // Overridden from ui::EventHandler.
+ // Overridden from ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- // Overridden from ButtonListener.
+ // Overridden from ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;
+ void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
+
protected:
MessageView();
// Shows the menu for the notification.
void ShowMenu(gfx::Point screen_location);
- // Overridden from views::SlideOutView.
+ // Overridden from views::SlideOutView:
virtual void OnSlideOut() OVERRIDE;
- NotificationList::Delegate* list_delegate() { return list_delegate_; }
+ NotificationChangeObserver* observer() { return observer_; }
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::ImageButton* expand_button() { return expand_button_.get(); }
views::ScrollView* scroller() { return scroller_; }
+ const bool is_expanded() { return is_expanded_; }
private:
- NotificationList::Delegate* list_delegate_; // Weak, global (MessageCenter).
+ NotificationChangeObserver* observer_; // Weak reference.
std::string notification_id_;
string16 display_source_;
std::string extension_id_;
scoped_ptr<views::ImageButton> close_button_;
-
+ scoped_ptr<views::ImageButton> expand_button_;
views::ScrollView* scroller_;
+ bool is_expanded_;
+
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index e4b2cca..268bd35 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -10,11 +10,13 @@
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/text/text_elider.h"
+#include "ui/gfx/canvas.h"
#include "ui/gfx/size.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/message_center_switches.h"
#include "ui/message_center/message_center_util.h"
#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_change_observer.h"
#include "ui/message_center/notification_types.h"
#include "ui/message_center/views/message_simple_view.h"
#include "ui/native_theme/native_theme.h"
@@ -96,17 +98,22 @@ ItemView::ItemView(const message_center::NotificationItem& item) {
ItemView::~ItemView() {
}
-// ProportionalImageViews match their heights to their widths to preserve the
-// proportions of their images.
+// ProportionalImageViews center their images to preserve their proportion.
+// Note that for this subclass of views::ImageView GetImageBounds() will return
+// potentially incorrect values (this can't be fixed because GetImageBounds()
+// is not virtual) and horizontal and vertical alignments will be ignored.
class ProportionalImageView : public views::ImageView {
public:
ProportionalImageView();
virtual ~ProportionalImageView();
- // Overridden from views::View.
+ // Overridden from views::View:
virtual int GetHeightForWidth(int width) OVERRIDE;
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
private:
+ gfx::Size GetImageSizeForWidth(int width);
+
DISALLOW_COPY_AND_ASSIGN(ProportionalImageView);
};
@@ -117,18 +124,42 @@ ProportionalImageView::~ProportionalImageView() {
}
int ProportionalImageView::GetHeightForWidth(int width) {
- int height = 0;
- gfx::ImageSkia image = GetImage();
- if (image.width() > 0 && image.height() > 0) {
- double proportion = image.height() / (double) image.width();
- height = 0.5 + width * proportion;
- if (height > message_center::kNotificationMaximumImageHeight) {
- height = message_center::kNotificationMaximumImageHeight;
- width = 0.5 + height / proportion;
+ return GetImageSizeForWidth(width).height();
+}
+
+void ProportionalImageView::OnPaint(gfx::Canvas* canvas) {
+ View::OnPaint(canvas);
+
+ gfx::Size draw_size(GetImageSizeForWidth(width()));
+ if (!draw_size.IsEmpty()) {
+ int x = (width() - draw_size.width()) / 2;
+ int y = (height() - draw_size.height()) / 2;
+
+ gfx::Size image_size(GetImage().size());
+ if (image_size == draw_size) {
+ canvas->DrawImageInt(GetImage(), x, y);
+ } else {
+ // Resize case
+ SkPaint paint;
+ paint.setFilterBitmap(true);
+ canvas->DrawImageInt(GetImage(), 0, 0,
+ image_size.width(), image_size.height(), x, y,
+ draw_size.width(), draw_size.height(), true, paint);
+ }
+ }
+}
+
+gfx::Size ProportionalImageView::GetImageSizeForWidth(int width) {
+ gfx::Size size(GetImage().size());
+ if (width > 0 && !size.IsEmpty()) {
+ double proportion = size.height() / (double) size.width();
+ size.SetSize(width, std::max(0.5 + width * proportion, 1.0));
+ if (size.height() > message_center::kNotificationMaximumImageHeight) {
+ int height = message_center::kNotificationMaximumImageHeight;
+ size.SetSize(std::max(0.5 + height / proportion, 1.0), height);
}
- SetImageSize(gfx::Size(width, height));
}
- return height;
+ return size;
}
// NotificationsButtons render the action buttons of notifications.
@@ -196,9 +227,9 @@ void NotificationButton::SetTitle(const string16& title) {
namespace message_center {
// static
-MessageView* NotificationView::Create(
- const Notification& notification,
- NotificationList::Delegate* list_delegate) {
+MessageView* NotificationView::Create(const Notification& notification,
+ NotificationChangeObserver* observer,
+ bool expanded) {
// 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.
@@ -206,7 +237,7 @@ MessageView* NotificationView::Create(
!IsRichNotificationEnabled() &&
!CommandLine::ForCurrentProcess()->HasSwitch(
message_center::switches::kEnableNewSimpleNotifications)) {
- return new MessageSimpleView(list_delegate, notification);
+ return new MessageSimpleView(notification, observer);
}
switch (notification.type()) {
@@ -227,61 +258,89 @@ MessageView* NotificationView::Create(
}
// Currently all roads lead to the generic NotificationView.
- return new NotificationView(list_delegate, notification);
+ return new NotificationView(notification, observer, expanded);
}
-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(const Notification& notification,
+ NotificationChangeObserver* observer,
+ bool expanded)
+ : MessageView(notification, observer, expanded),
+ content_view_(NULL),
+ icon_view_(NULL) {
+ AddChildViews(notification);
}
NotificationView::~NotificationView() {
}
void NotificationView::Layout() {
- if (content_view_) {
- gfx::Rect contents_bounds = GetContentsBounds();
- content_view_->SetBoundsRect(contents_bounds);
- if (close_button()) {
- gfx::Size size(close_button()->GetPreferredSize());
- close_button()->SetBounds(contents_bounds.right() - size.width(), 0,
- size.width(), size.height());
- }
- }
+ gfx::Rect content_bounds(GetLocalBounds());
+ content_bounds.Inset(GetInsets());
+ content_view_->SetBoundsRect(content_bounds);
+
+ gfx::Size close_size(close_button()->GetPreferredSize());
+ close_button()->SetBounds(content_bounds.right() - close_size.width(),
+ content_bounds.y(),
+ close_size.width(),
+ close_size.height());
+
+ gfx::Rect icon_bounds(content_bounds.origin(), icon_view_->size());
+ gfx::Size expand_size(expand_button()->GetPreferredSize());
+ expand_button()->SetBounds(content_bounds.right() - expand_size.width(),
+ icon_bounds.bottom() - expand_size.height(),
+ expand_size.width(),
+ expand_size.height());
}
gfx::Size NotificationView::GetPreferredSize() {
- if (!content_view_)
- return gfx::Size();
- gfx::Size size = content_view_->GetPreferredSize();
- if (border()) {
- gfx::Insets border_insets = border()->GetInsets();
- size.Enlarge(border_insets.width(), border_insets.height());
+ gfx::Size size;
+ if (content_view_) {
+ size = content_view_->GetPreferredSize();
+ if (border()) {
+ gfx::Insets insets = border()->GetInsets();
+ size.Enlarge(insets.width(), insets.height());
+ }
}
return size;
}
+void NotificationView::Update(const Notification& notification) {
+ MessageView::Update(notification);
+ content_view_ = NULL;
+ icon_view_ = NULL;
+ action_buttons_.clear();
+ RemoveAllChildViews(true);
+ AddChildViews(notification);
+ PreferredSizeChanged();
+ SchedulePaint();
+}
+
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);
+ if (sender == action_buttons_[i]) {
+ observer()->OnButtonClicked(notification_id(), i);
return;
}
}
MessageView::ButtonPressed(sender, event);
}
-views::View* NotificationView::MakeContentView(
- const Notification& notification) {
+void NotificationView::AddChildViews(const Notification& notification) {
+ // Child views are in 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 and expand buttons. This allows the close
+ // and expand buttons to overlap the content as needed to provide large enough
+ // click and touch areas (<http://crbug.com/168822> and
+ // <http://crbug.com/168856>).
+ AddContentView(notification);
+ AddChildView(close_button());
+ if (!is_expanded()) {
+ AddChildView(expand_button());
+ }
+}
+
+void NotificationView::AddContentView(const Notification& notification) {
content_view_ = new views::View();
content_view_->set_background(
views::Background::CreateSolidBackground(kBackgroundColor));
@@ -291,39 +350,44 @@ views::View* NotificationView::MakeContentView(
// items), followed by a padding view. Laying out the icon view will require
// information about the text views, so these are created first and collected
// in this vector.
- std::vector<views::View*> texts;
+ std::vector<views::View*> text_views;
// Title if it exists.
if (!notification.title().empty()) {
views::Label* title = new views::Label(notification.title());
title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title->SetElideBehavior(views::Label::ELIDE_AT_END);
+ if (is_expanded())
+ title->SetMultiLine(true);
+ else
+ title->SetElideBehavior(views::Label::ELIDE_AT_END);
title->SetFont(title->font().DeriveFont(4));
title->SetEnabledColor(kTitleColor);
title->SetBackgroundColor(kTitleBackgroundColor);
title->set_border(MakePadding(kTextTopPadding, 0, 3, kTextRightPadding));
- texts.push_back(title);
+ text_views.push_back(title);
+ }
+
+ // List notification items up to a maximum if appropriate.
+ size_t maximum = is_expanded() ? kNotificationMaximumItems : 0ul;
+ size_t items = std::min(notification.items().size(), maximum);
+ for (size_t i = 0; i < items; ++i) {
+ ItemView* item = new ItemView(notification.items()[i]);
+ item->set_border(MakePadding(0, 0, 4, kTextRightPadding));
+ text_views.push_back(item);
}
// Message if appropriate.
- if (notification.items().size() == 0 &&
- !notification.message().empty()) {
+ if (items == 0ul && !notification.message().empty()) {
views::Label* message = new views::Label(notification.message());
message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- message->SetMultiLine(true);
+ if (is_expanded())
+ message->SetMultiLine(true);
+ else
+ message->SetElideBehavior(views::Label::ELIDE_AT_END);
message->SetEnabledColor(kMessageColor);
message->SetBackgroundColor(kMessageBackgroundColor);
message->set_border(MakePadding(0, 0, 3, kTextRightPadding));
- texts.push_back(message);
- }
-
- // List notification items up to a maximum.
- int items = std::min(notification.items().size(),
- kNotificationMaximumItems);
- for (int i = 0; i < items; ++i) {
- ItemView* item = new ItemView(notification.items()[i]);
- item->set_border(MakePadding(0, 0, 4, kTextRightPadding));
- texts.push_back(item);
+ text_views.push_back(message);
}
// Set up the content view with a fixed-width icon column on the left and a
@@ -345,28 +409,28 @@ views::View* NotificationView::MakeContentView(
// Create the first row and its icon view, which spans all the text views
// to its right as well as the padding view below them.
layout->StartRow(0, 0);
- views::ImageView* icon = new views::ImageView();
- icon->SetImageSize(gfx::Size(message_center::kNotificationIconSize,
- message_center::kNotificationIconSize));
- icon->SetImage(notification.primary_icon().AsImageSkia());
- icon->SetHorizontalAlignment(views::ImageView::LEADING);
- icon->SetVerticalAlignment(views::ImageView::LEADING);
- icon->set_border(MakePadding(0, 0, 0, kIconToTextPadding));
- layout->AddView(icon, 1, texts.size() + 1);
+ icon_view_ = new views::ImageView();
+ icon_view_->SetImageSize(gfx::Size(message_center::kNotificationIconSize,
+ message_center::kNotificationIconSize));
+ icon_view_->SetImage(notification.icon().AsImageSkia());
+ icon_view_->SetHorizontalAlignment(views::ImageView::LEADING);
+ icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
+ icon_view_->set_border(MakePadding(0, 0, 0, kIconToTextPadding));
+ layout->AddView(icon_view_, 1, text_views.size() + 1);
// Add the text views, creating rows for them if necessary.
- for (size_t i = 0; i < texts.size(); ++i) {
+ for (size_t i = 0; i < text_views.size(); ++i) {
if (i > 0) {
layout->StartRow(0, 0);
layout->SkipColumns(1);
}
- layout->AddView(texts[i]);
+ layout->AddView(text_views[i]);
}
// Add a text padding row if necessary. This adds some space between the last
// line of text and anything below it but it also ensures views above it are
// top-justified by expanding vertically to take up any extra space.
- if (texts.size() == 0) {
+ if (text_views.size() == 0) {
layout->SkipColumns(1);
} else {
layout->StartRow(100, 0);
@@ -377,14 +441,11 @@ views::View* NotificationView::MakeContentView(
}
// Add an image row if appropriate.
- if (!notification.image().IsEmpty()) {
+ if (is_expanded() && !notification.image().IsEmpty()) {
layout->StartRow(0, 0);
- views::ImageView* image = new ProportionalImageView();
- image->SetImageSize(notification.image().ToImageSkia()->size());
- image->SetImage(notification.image().ToImageSkia());
- image->SetHorizontalAlignment(views::ImageView::CENTER);
- image->SetVerticalAlignment(views::ImageView::LEADING);
- layout->AddView(image, 2, 1);
+ ProportionalImageView* image_view = new ProportionalImageView();
+ image_view->SetImage(notification.image().ToImageSkia());
+ layout->AddView(image_view, 2, 1);
}
// Add action button rows.
@@ -404,7 +465,7 @@ views::View* NotificationView::MakeContentView(
views::GridLayout::FILL, views::GridLayout::FILL, 0, 40);
}
- return content_view_;
+ AddChildView(content_view_);
}
} // namespace message_center
diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h
index dee7e98..a0b23e9 100644
--- a/ui/message_center/views/notification_view.h
+++ b/ui/message_center/views/notification_view.h
@@ -5,40 +5,49 @@
#ifndef UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_H_
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_H_
-#include "ui/message_center/notification_list.h"
+#include <vector>
+
#include "ui/message_center/views/message_view.h"
namespace message_center {
+class NotificationChangeObserver;
+
// View that displays all current types of notification (web, basic, image, and
// list). Future notification types may be handled by other classes, in which
-// case instances of those classes would be returned by the
-// ViewForNotification() factory method below.
+// case instances of those classes would be returned by the Create() factory
+// method below.
class NotificationView : public MessageView {
public:
// Creates appropriate MessageViews for notifications. Those currently are
- // always NotificationView instances but in the future may be instances of
- // other classes, with the class depending on the notification type.
+ // always NotificationView or MessageSimpleView instances but in the future
+ // may be instances of other classes, with the class depending on the
+ // notification type.
static MessageView* Create(const Notification& notification,
- NotificationList::Delegate* list_delegate);
+ NotificationChangeObserver* observer,
+ bool expanded);
virtual ~NotificationView();
- // Overridden from View.
+ // Overridden from views::View:
virtual void Layout() OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
- // Overridden from MessageView.
+ // Overridden from MessageView:
+ virtual void Update(const Notification& notification) OVERRIDE;
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;
private:
- NotificationView(NotificationList::Delegate* list_delegate,
- const Notification& notification);
+ NotificationView(const Notification& notification,
+ NotificationChangeObserver* observer,
+ bool expanded);
- views::View* MakeContentView(const Notification& notification);
+ void AddChildViews(const Notification& notification);
+ void AddContentView(const Notification& notification);
views::View* content_view_;
+ views::ImageView* icon_view_;
std::vector<views::Button*> action_buttons_;
DISALLOW_COPY_AND_ASSIGN(NotificationView);
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc
index 3de1f0b..c65d4e0 100644
--- a/ui/message_center/views/notifier_settings_view.cc
+++ b/ui/message_center/views/notifier_settings_view.cc
@@ -83,7 +83,7 @@ class NotifierSettingsView::NotifierButton : public views::CustomButton,
}
private:
- // views::ButtonListener overrides:
+ // Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* button,
const ui::Event& event) OVERRIDE {
DCHECK(button == checkbox_);
diff --git a/ui/message_center/views/notifier_settings_view.h b/ui/message_center/views/notifier_settings_view.h
index a296dd5..4aa7701 100644
--- a/ui/message_center/views/notifier_settings_view.h
+++ b/ui/message_center/views/notifier_settings_view.h
@@ -45,13 +45,13 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
NotifierSettingsView(NotifierSettingsViewDelegate* delegate);
virtual ~NotifierSettingsView();
- // views::WidgetDelegate overrides:
+ // Overridden from views::WidgetDelegate:
virtual bool CanResize() const OVERRIDE;
virtual string16 GetWindowTitle() const OVERRIDE;
virtual void WindowClosing() OVERRIDE;
virtual views::View* GetContentsView() OVERRIDE;
- // views::ButtonListener overrides:
+ // Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;