Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(502)

Unified Diff: ui/message_center/message_center_bubble.cc

Issue 12326091: Made notification center notifications collapsed and expandable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased, which led to many changes. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/message_center/message_center_bubble.cc
diff --git a/ui/message_center/message_center_bubble.cc b/ui/message_center/message_center_bubble.cc
index 007edb0fea996e4b3cfd4680819ebd9d3600539f..d869bd22c564aa618ef49c6170e8105948a22823 100644
--- a/ui/message_center/message_center_bubble.cc
+++ b/ui/message_center/message_center_bubble.cc
@@ -4,6 +4,8 @@
#include "ui/message_center/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"
@@ -67,7 +69,7 @@ class WebNotificationButtonViewBase : public views::View {
views::Button* close_all_button() { return close_all_button_; }
private:
- NotificationList::Delegate* list_delegate_;
+ NotificationList::Delegate* list_delegate_; // Weak reference.
views::Button* close_all_button_;
DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonViewBase);
@@ -111,7 +113,7 @@ 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())
@@ -134,7 +136,7 @@ class WebNotificationButton : public views::TextButton {
}
protected:
- // views::View overrides:
+ // Overridden from views::View:
dharcourt 2013/03/01 10:17:31 I took this opportunity to make the override comme
virtual gfx::Size GetPreferredSize() OVERRIDE {
// Returns an empty size when invisible, to trim its space in the parent's
// GridLayout.
@@ -206,7 +208,7 @@ 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())
@@ -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_focusable(true);
set_notify_enter_exit_on_child(true);
if (IsRichNotificationEnabled()) {
@@ -236,53 +241,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
@@ -309,39 +312,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);
@@ -349,10 +346,10 @@ 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_);
}
@@ -360,21 +357,18 @@ class MessageCenterContentsView : public views::View {
scroller_->RequestFocus();
}
- 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));
@@ -382,53 +376,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) {
}
@@ -450,7 +461,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
@@ -468,8 +479,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();
}
@@ -480,6 +491,61 @@ void MessageCenterBubble::OnMouseEnteredView() {
void MessageCenterBubble::OnMouseExitedView() {
}
+void MessageCenterBubble::SendRemoveNotification(const std::string& id,
+ bool by_user) {
+ message_center()->SendRemoveNotification(id, by_user);
+}
+
+void MessageCenterBubble::SendRemoveAllNotifications(bool by_user) {
+ message_center()->SendRemoveAllNotifications(by_user);
+}
+
+void MessageCenterBubble::DisableNotificationByExtension(
+ const std::string& id) {
+ message_center()->DisableNotificationByExtension(id);
+}
+
+void MessageCenterBubble::DisableNotificationByUrl(const std::string& id) {
+ message_center()->DisableNotificationByUrl(id);
+}
+
+void MessageCenterBubble::ShowNotificationSettings(const std::string& id) {
+ message_center()->ShowNotificationSettings(id);
+}
+
+void MessageCenterBubble::ShowNotificationSettingsDialog(
+ gfx::NativeView context) {
+ message_center()->ShowNotificationSettingsDialog(context);
+}
+
+void MessageCenterBubble::OnNotificationClicked(const std::string& id) {
+ message_center()->OnNotificationClicked(id);
+}
+
+void MessageCenterBubble::OnButtonClicked(const std::string& id,
+ int button_index) {
+ message_center()->OnButtonClicked(id, button_index);
+}
+
+void MessageCenterBubble::OnExpand(const std::string& id) {
+ message_center()->OnExpand(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;
+ }
+ }
+}
+
+void MessageCenterBubble::OnQuietModeChanged(bool quiet_mode) {
+ message_center()->OnQuietModeChanged(quiet_mode);
+}
+
dharcourt 2013/03/02 02:08:02 This isn't now only in NotificationList::Delegate
size_t MessageCenterBubble::NumMessageViewsForTest() const {
return contents_view_->NumMessageViews();
}

Powered by Google App Engine
This is Rietveld 408576698