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

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

Issue 271773002: Retain popup bubble mouse status even through updates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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/views/notification_view.cc
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index 671b42045bb9d8202761c8b9ca07a2bdf43bc32d..75b8011d3418bec6bf5e1560423c32081fe489db 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -291,6 +291,29 @@ NotificationView* NotificationView::Create(MessageCenterController* controller,
return notification_view;
}
+void NotificationView::CreateViews(const Notification& notification) {
+ CreateTitleView(notification);
+ CreateMessageView(notification);
+ CreateProgressBarView(notification);
+ CreateListItemViews(notification);
+ CreateIconView(notification);
+ CreateImageView(notification);
+ CreateActionButtonViews(notification);
+}
+
+void NotificationView::SetAccessibleName(const Notification& notification) {
+ std::vector<base::string16> accessible_lines;
+ accessible_lines.push_back(notification.title());
+ accessible_lines.push_back(notification.message());
+ accessible_lines.push_back(notification.context_message());
+ std::vector<NotificationItem> items = notification.items();
+ for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
+ accessible_lines.push_back(
+ items[i].title + base::ASCIIToUTF16(" ") + items[i].message);
+ }
+ set_accessible_name(JoinString(accessible_lines, '\n'));
+}
+
NotificationView::NotificationView(MessageCenterController* controller,
const Notification& notification)
: MessageView(this,
@@ -299,8 +322,15 @@ NotificationView::NotificationView(MessageCenterController* controller,
notification.small_image().AsImageSkia(),
notification.display_source()),
controller_(controller),
- clickable_(notification.clickable()) {
- std::vector<base::string16> accessible_lines;
+ clickable_(notification.clickable()),
+ top_view_(NULL),
+ title_view_(NULL),
+ message_view_(NULL),
+ context_message_view_(NULL),
+ icon_view_(NULL),
+ bottom_view_(NULL),
+ image_view_(NULL),
+ progress_bar_view_(NULL) {
// Create the top_view_, which collects into a vertical box all content
// at the top of the notification (to the right of the icon) except for the
// close button.
@@ -309,152 +339,32 @@ NotificationView::NotificationView(MessageCenterController* controller,
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
top_view_->SetBorder(
MakeEmptyBorder(kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0));
-
- const gfx::FontList default_label_font_list = views::Label().font_list();
-
- // Create the title view if appropriate.
- title_view_ = NULL;
- if (!notification.title().empty()) {
- const gfx::FontList& font_list =
- default_label_font_list.DeriveWithSizeDelta(2);
- int padding = kTitleLineHeight - font_list.GetHeight();
- int title_lines = notification.message().empty() ? kTitleNoMessageLineLimit
- : kTitleLineLimit;
- int title_character_limit =
- kNotificationWidth * title_lines / kMinPixelsPerTitleCharacter;
- title_view_ = new BoundedLabel(
- gfx::TruncateString(notification.title(), title_character_limit),
- font_list);
- title_view_->SetLineHeight(kTitleLineHeight);
- title_view_->SetLineLimit(title_lines);
- title_view_->SetColors(message_center::kRegularTextColor,
- kRegularTextBackgroundColor);
- title_view_->SetBorder(MakeTextBorder(padding, 3, 0));
- top_view_->AddChildView(title_view_);
- accessible_lines.push_back(notification.title());
- }
-
- // Create the message view if appropriate.
- message_view_ = NULL;
- if (!notification.message().empty()) {
- int padding = kMessageLineHeight - default_label_font_list.GetHeight();
- message_view_ = new BoundedLabel(
- gfx::TruncateString(notification.message(), kMessageCharacterLimit));
- message_view_->SetLineHeight(kMessageLineHeight);
- message_view_->SetVisible(!notification.items().size());
- message_view_->SetColors(message_center::kRegularTextColor,
- kDimTextBackgroundColor);
- message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
- top_view_->AddChildView(message_view_);
- accessible_lines.push_back(notification.message());
- }
-
- // Create the context message view if appropriate.
- context_message_view_ = NULL;
- if (!notification.context_message().empty()) {
- int padding = kMessageLineHeight - default_label_font_list.GetHeight();
- context_message_view_ =
- new BoundedLabel(gfx::TruncateString(notification.context_message(),
- kContextMessageCharacterLimit),
- default_label_font_list);
- context_message_view_->SetLineLimit(
- message_center::kContextMessageLineLimit);
- context_message_view_->SetLineHeight(kMessageLineHeight);
- context_message_view_->SetColors(message_center::kDimTextColor,
- kContextTextBackgroundColor);
- context_message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
- top_view_->AddChildView(context_message_view_);
- accessible_lines.push_back(notification.context_message());
- }
-
- // Create the progress bar view.
- progress_bar_view_ = NULL;
- if (notification.type() == NOTIFICATION_TYPE_PROGRESS) {
- progress_bar_view_ = new NotificationProgressBar();
- progress_bar_view_->SetBorder(MakeProgressBarBorder(
- message_center::kProgressBarTopPadding, kProgressBarBottomPadding));
- progress_bar_view_->SetValue(notification.progress() / 100.0);
- top_view_->AddChildView(progress_bar_view_);
- }
-
- // Create the list item views (up to a maximum).
- int padding = kMessageLineHeight - default_label_font_list.GetHeight();
- std::vector<NotificationItem> items = notification.items();
- for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
- ItemView* item_view = new ItemView(items[i]);
- item_view->SetBorder(MakeTextBorder(padding, i ? 0 : 4, 0));
- item_views_.push_back(item_view);
- top_view_->AddChildView(item_view);
- accessible_lines.push_back(
- items[i].title + base::ASCIIToUTF16(" ") + items[i].message);
- }
-
- // Create the notification icon view.
- gfx::ImageSkia icon = notification.icon().AsImageSkia();
- if (notification.type() == NOTIFICATION_TYPE_SIMPLE &&
- (icon.width() != kIconSize ||
- icon.height() != kIconSize ||
- HasAlpha(icon, GetWidget()))) {
- views::ImageView* icon_view = new views::ImageView();
- icon_view->SetImage(icon);
- icon_view->SetImageSize(gfx::Size(kLegacyIconSize, kLegacyIconSize));
- icon_view->SetHorizontalAlignment(views::ImageView::CENTER);
- icon_view->SetVerticalAlignment(views::ImageView::CENTER);
- icon_view_ = icon_view;
- } else {
- icon_view_ =
- new ProportionalImageView(icon, gfx::Size(kIconSize, kIconSize));
- }
-
- icon_view_->set_background(
- views::Background::CreateSolidBackground(kIconBackgroundColor));
+ AddChildView(top_view_);
// Create the bottom_view_, which collects into a vertical box all content
// below the notification icon.
bottom_view_ = new views::View();
bottom_view_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
+ AddChildView(bottom_view_);
- // Create the image view if appropriate.
- image_view_ = NULL;
- if (!notification.image().IsEmpty()) {
- gfx::Size image_size(
- kNotificationPreferredImageWidth, kNotificationPreferredImageHeight);
- image_view_ = MakeNotificationImage(notification.image(), image_size);
- bottom_view_->AddChildView(image_view_);
- }
-
- // Create action buttons if appropriate.
- std::vector<ButtonInfo> buttons = notification.buttons();
- for (size_t i = 0; i < buttons.size(); ++i) {
- views::View* separator = new views::ImageView();
- separator->SetBorder(MakeSeparatorBorder(1, 0, kButtonSeparatorColor));
- bottom_view_->AddChildView(separator);
- NotificationButton* button = new NotificationButton(this);
- ButtonInfo button_info = buttons[i];
- button->SetTitle(button_info.title);
- button->SetIcon(button_info.icon.AsImageSkia());
- action_buttons_.push_back(button);
- bottom_view_->AddChildView(button);
- }
+ CreateViews(notification);
// Put together the different content and control views. Layering those allows
// for proper layout logic and it also allows the close button and small
// image to overlap the content as needed to provide large enough click and
// touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>).
- AddChildView(top_view_);
- AddChildView(icon_view_);
- AddChildView(bottom_view_);
AddChildView(small_image());
AddChildView(close_button());
- set_accessible_name(JoinString(accessible_lines, '\n'));
+ SetAccessibleName(notification);
}
NotificationView::~NotificationView() {
}
gfx::Size NotificationView::GetPreferredSize() {
- int top_width = top_view_->GetPreferredSize().width();
+ int top_width = top_view_->GetPreferredSize().width() +
+ icon_view_->GetPreferredSize().width();
int bottom_width = bottom_view_->GetPreferredSize().width();
int preferred_width = std::max(top_width, bottom_width) + GetInsets().width();
return gfx::Size(preferred_width, GetHeightForWidth(preferred_width));
@@ -551,6 +461,16 @@ gfx::NativeCursor NotificationView::GetCursor(const ui::MouseEvent& event) {
return ui::kCursorHand;
}
+void NotificationView::UpdateWithNotification(
+ const Notification& notification) {
+ MessageView::UpdateWithNotification(notification);
+
+ CreateViews(notification);
+ SetAccessibleName(notification);
+ Layout();
+ SchedulePaint();
+}
+
void NotificationView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
// Certain operations can cause |this| to be destructed, so copy the members
@@ -580,6 +500,215 @@ void NotificationView::RemoveNotification(const std::string& notification_id,
controller_->RemoveNotification(notification_id, by_user);
}
+void NotificationView::CreateTitleView(const Notification& notification) {
+ if (notification.title().empty()) {
+ if (title_view_) {
+ // Deletion will also remove |title_view_| from its parent.
+ delete title_view_;
+ title_view_ = NULL;
+ }
+ return;
+ }
+
+ DCHECK(top_view_ != NULL);
+
+ const gfx::FontList& font_list =
+ views::Label().font_list().DeriveWithSizeDelta(2);
+ int title_lines = notification.message().empty() ? kTitleNoMessageLineLimit
+ : kTitleLineLimit;
+ int title_character_limit =
+ kNotificationWidth * title_lines / kMinPixelsPerTitleCharacter;
+
+ if (!title_view_) {
+ int padding = kTitleLineHeight - font_list.GetHeight();
+
+ title_view_ = new BoundedLabel(
+ gfx::TruncateString(notification.title(), title_character_limit),
+ font_list);
+ title_view_->SetLineHeight(kTitleLineHeight);
+ title_view_->SetLineLimit(title_lines);
+ title_view_->SetColors(message_center::kRegularTextColor,
+ kRegularTextBackgroundColor);
+ title_view_->SetBorder(MakeTextBorder(padding, 3, 0));
+ top_view_->AddChildView(title_view_);
+ } else {
+ title_view_->SetText(
+ gfx::TruncateString(notification.title(), title_character_limit));
+ }
+}
+
+void NotificationView::CreateMessageView(const Notification& notification) {
+ if (notification.message().empty()) {
+ if (message_view_) {
+ // Deletion will also remove |message_view_| from its parent.
+ delete message_view_;
+ message_view_ = NULL;
+ }
+ return;
+ }
+
+ DCHECK(top_view_ != NULL);
+
+ if (!message_view_) {
+ int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
+ message_view_ = new BoundedLabel(
+ gfx::TruncateString(notification.message(), kMessageCharacterLimit));
+ message_view_->SetLineHeight(kMessageLineHeight);
+ message_view_->SetColors(message_center::kRegularTextColor,
+ kDimTextBackgroundColor);
+ message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
+ top_view_->AddChildView(message_view_);
+ } else {
+ message_view_->SetText(
+ gfx::TruncateString(notification.message(), kMessageCharacterLimit));
+ }
+
+ message_view_->SetVisible(!notification.items().size());
+}
+
+void NotificationView::CreateContextMessageView(
+ const Notification& notification) {
+ if (notification.context_message().empty()) {
+ if (context_message_view_) {
+ // Deletion will also remove |context_message_view_| from its parent.
+ delete context_message_view_;
+ context_message_view_ = NULL;
+ }
+ return;
+ }
+
+ DCHECK(top_view_ != NULL);
+
+ if (!context_message_view_) {
+ int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
+ context_message_view_ = new BoundedLabel(gfx::TruncateString(
+ notification.context_message(), kContextMessageCharacterLimit));
+ context_message_view_->SetLineLimit(
+ message_center::kContextMessageLineLimit);
+ context_message_view_->SetLineHeight(kMessageLineHeight);
+ context_message_view_->SetColors(message_center::kDimTextColor,
+ kContextTextBackgroundColor);
+ context_message_view_->SetBorder(MakeTextBorder(padding, 4, 0));
+ top_view_->AddChildView(context_message_view_);
+ } else {
+ context_message_view_->SetText(gfx::TruncateString(
+ notification.context_message(), kContextMessageCharacterLimit));
+ }
+}
+
+void NotificationView::CreateProgressBarView(const Notification& notification) {
+ if (notification.type() != NOTIFICATION_TYPE_PROGRESS) {
+ if (progress_bar_view_) {
+ // Deletion will also remove |progress_bar_view_| from its parent.
+ delete progress_bar_view_;
+ progress_bar_view_ = NULL;
+ }
+ return;
+ }
+
+ DCHECK(top_view_ != NULL);
+
+ if (!progress_bar_view_) {
+ progress_bar_view_ = new NotificationProgressBar();
+ progress_bar_view_->SetBorder(MakeProgressBarBorder(
+ message_center::kProgressBarTopPadding, kProgressBarBottomPadding));
+ top_view_->AddChildView(progress_bar_view_);
+ }
+
+ progress_bar_view_->SetValue(notification.progress() / 100.0);
+ progress_bar_view_->SetVisible(!notification.items().size());
+}
+
+void NotificationView::CreateListItemViews(const Notification& notification) {
+ for (size_t i = 0; i < item_views_.size(); ++i)
+ delete item_views_[i];
+ item_views_.clear();
+
+ int padding = kMessageLineHeight - views::Label().font_list().GetHeight();
+ std::vector<NotificationItem> items = notification.items();
+
+ if (items.size() == 0)
+ return;
+
+ DCHECK(top_view_);
+ for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
+ ItemView* item_view = new ItemView(items[i]);
+ item_view->SetBorder(MakeTextBorder(padding, i ? 0 : 4, 0));
+ item_views_.push_back(item_view);
+ top_view_->AddChildView(item_view);
+ }
+}
+
+void NotificationView::CreateIconView(const Notification& notification) {
+ if (icon_view_)
+ delete icon_view_;
+
+ // TODO(dewittj): Detect a compatible update and use the existing icon view.
+ gfx::ImageSkia icon = notification.icon().AsImageSkia();
+ if (notification.type() == NOTIFICATION_TYPE_SIMPLE &&
+ (icon.width() != kIconSize || icon.height() != kIconSize ||
+ HasAlpha(icon, GetWidget()))) {
+ views::ImageView* icon_view = new views::ImageView();
+ icon_view->SetImage(icon);
+ icon_view->SetImageSize(gfx::Size(kLegacyIconSize, kLegacyIconSize));
+ icon_view->SetHorizontalAlignment(views::ImageView::CENTER);
+ icon_view->SetVerticalAlignment(views::ImageView::CENTER);
+ icon_view_ = icon_view;
+ } else {
+ icon_view_ =
+ new ProportionalImageView(icon, gfx::Size(kIconSize, kIconSize));
+ }
+
+ icon_view_->set_background(
+ views::Background::CreateSolidBackground(kIconBackgroundColor));
+
+ AddChildView(icon_view_);
+}
+
+void NotificationView::CreateImageView(const Notification& notification) {
+ if (image_view_)
+ delete image_view_;
+
+ DCHECK(bottom_view_);
+ DCHECK_EQ(this, bottom_view_->parent());
+
+ // TODO(dewittj): Detect a compatible update and use the existing image view.
+ if (!notification.image().IsEmpty()) {
+ gfx::Size image_size(kNotificationPreferredImageWidth,
+ kNotificationPreferredImageHeight);
+ image_view_ = MakeNotificationImage(notification.image(), image_size);
+ bottom_view_->AddChildView(image_view_);
+ }
+}
+
+void NotificationView::CreateActionButtonViews(
+ const Notification& notification) {
+ for (size_t i = 0; i < separators_.size(); ++i)
+ delete separators_[i];
+ separators_.clear();
+
+ for (size_t i = 0; i < action_buttons_.size(); ++i)
+ delete action_buttons_[i];
+ action_buttons_.clear();
+
+ DCHECK(bottom_view_);
+ DCHECK_EQ(this, bottom_view_->parent());
+
+ std::vector<ButtonInfo> buttons = notification.buttons();
+ for (size_t i = 0; i < buttons.size(); ++i) {
+ views::View* separator = new views::ImageView();
+ separator->SetBorder(MakeSeparatorBorder(1, 0, kButtonSeparatorColor));
+ separators_.push_back(separator);
+ bottom_view_->AddChildView(separator);
+ NotificationButton* button = new NotificationButton(this);
+ ButtonInfo button_info = buttons[i];
+ button->SetTitle(button_info.title);
+ button->SetIcon(button_info.icon.AsImageSkia());
+ action_buttons_.push_back(button);
+ bottom_view_->AddChildView(button);
+ }
+}
+
int NotificationView::GetMessageLineLimit(int width) {
// Image notifications require that the image must be kept flush against
// their icons, but we can allow more text if no image.

Powered by Google App Engine
This is Rietveld 408576698