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

Unified Diff: ui/message_center/views/notification_view.cc

Issue 12326091: Made notification center notifications collapsed and expandable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, rebase, and rebase again! Created 7 years, 9 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
« no previous file with comments | « ui/message_center/views/notification_view.h ('k') | ui/message_center/views/notifier_settings_view.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/message_center/views/notification_view.cc
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index e4b2cca234c25e8e7ae3dfb62d5a7d5a190c122e..268bd35a68d7e724ef0330f692280e7f4afa95f4 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
« no previous file with comments | « ui/message_center/views/notification_view.h ('k') | ui/message_center/views/notifier_settings_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698