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

Unified Diff: ui/message_center/notification_view.cc

Issue 12326091: Made notification center notifications collapsed and expandable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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/notification_view.cc
diff --git a/ui/message_center/notification_view.cc b/ui/message_center/notification_view.cc
index f38713e472f8e7372b0e5b83fa4abc8c79b956c4..018c3c68f68d7d66b7a2a04321d0f566e8165f4f 100644
--- a/ui/message_center/notification_view.cc
+++ b/ui/message_center/notification_view.cc
@@ -10,6 +10,7 @@
#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"
@@ -57,6 +58,29 @@ views::Background* MakeBackground(SkColor color) {
return views::Background::CreateSolidBackground(color);
}
+// ContentViews just propagate their children's preferred size changes.
+class ContentView : public views::View {
+ public:
+ ContentView();
+ virtual ~ContentView();
+
+ // Overridden from views::View.
+ virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ContentView);
+};
+
+ContentView::ContentView() {
+}
+
+ContentView::~ContentView() {
+}
+
+void ContentView::ChildPreferredSizeChanged(views::View* child) {
+ PreferredSizeChanged();
+}
+
// ItemViews are responsible for drawing each list notification item's title and
// message next to each other within a single column.
class ItemView : public views::View {
@@ -93,8 +117,10 @@ 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();
@@ -102,8 +128,11 @@ class ProportionalImageView : public views::ImageView {
// 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);
};
@@ -114,18 +143,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();
+}
dharcourt 2013/02/23 04:32:00 SetImageSize() needed to be removed from GetImageS
+
+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);
}
- SetImageSize(gfx::Size(width, height));
}
- return height;
+}
+
+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);
+ }
+ }
+ return size;
}
// NotificationsButtons render the action buttons of notifications.
@@ -228,53 +281,81 @@ MessageView* NotificationView::ViewForNotification(
return new NotificationView(list_delegate, notification);
}
-NotificationView::NotificationView(
- NotificationList::Delegate* list_delegate,
- const Notification& notification)
- : MessageView(list_delegate, notification) {
+NotificationView::NotificationView(NotificationList::Delegate* list_delegate,
+ const Notification& notification)
+ : MessageView(list_delegate, notification),
+ content_view_(NULL),
+ icon_view_(NULL) {
}
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());
+ // Create the child views if necessary. Those 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 a large enough click area
+ // (<http://crbug.com/168822> and touch area <http://crbug.com/168856>).
+ if (!content_view_) {
+ AddChildView(MakeContentView());
+ AddChildView(close_button());
+ if (!IsExpanded()) {
+ AddChildView(expand_button());
}
}
+
+ 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;
dharcourt 2013/02/23 04:32:00 Having a return gfx::Size() in the middle of this
}
-void NotificationView::SetUpView() {
- // This view is composed of two layers: The first layer has the notification
- // content (text, images, action buttons, ...). This is overlaid by a second
- // layer that has the notification close button and will later also have the
- // expand button. This allows the close and expand buttons to overlap the
- // content as needed to provide a large enough click area
- // (<http://crbug.com/168822> and touch area <http://crbug.com/168856>).
- AddChildView(MakeContentView());
- AddChildView(close_button());
+void NotificationView::ChildPreferredSizeChanged(views::View* child) {
+ PreferredSizeChanged();
+}
+
+void NotificationView::SetExpanded(bool expanded) {
+ if (expanded != IsExpanded()) {
+ MessageView::SetExpanded(expanded);
+ content_view_ = NULL;
+ icon_view_ = NULL;
+ action_buttons_.clear();
+ RemoveAllChildViews(true);
+ 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) {
+ if (sender == action_buttons_[i]) {
list_delegate()->OnButtonClicked(notification().id, i);
return;
}
@@ -283,7 +364,7 @@ void NotificationView::ButtonPressed(views::Button* sender,
}
views::View* NotificationView::MakeContentView() {
- content_view_ = new views::View();
+ content_view_ = new ContentView();
content_view_->set_background(
views::Background::CreateSolidBackground(kBackgroundColor));
@@ -292,37 +373,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 (IsExpanded())
+ 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.
+ int items = static_cast<int>(notification().items.size());
+ items = std::min(items, IsExpanded() ? kNotificationMaximumItems : 0);
Jun Mukai 2013/02/26 02:23:30 as I wrote in _constants.h, I prefer to keep size_
dharcourt 2013/02/26 03:23:30 Done.
+ for (int 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);
}
dharcourt 2013/02/23 04:32:00 Item display had to be moved up here so the displa
// Message if appropriate.
- if (notification().items.size() == 0 && !notification().message.empty()) {
+ if (items == 0 && !notification().message.empty()) {
views::Label* message = new views::Label(notification().message);
message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- message->SetMultiLine(true);
+ if (IsExpanded())
+ 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
@@ -344,28 +432,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);
- 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().primary_icon);
+ 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);
@@ -376,14 +464,11 @@ views::View* NotificationView::MakeContentView() {
}
// Add an image row if appropriate.
- if (!notification().image.isNull()) {
+ if (IsExpanded() && !notification().image.isNull()) {
layout->StartRow(0, 0);
- views::ImageView* image = new ProportionalImageView();
- image->SetImageSize(notification().image.size());
- image->SetImage(notification().image);
- 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);
+ layout->AddView(image_view, 2, 1);
}
// Add action button rows.
« ui/message_center/notification_view.h ('K') | « ui/message_center/notification_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698