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

Side by Side Diff: ui/message_center/views/notification_view_md.cc

Issue 2942143002: Add progress notification support to new-style notification. (Closed)
Patch Set: Resolve review comments. Created 3 years, 6 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 unified diff | Download patch
« no previous file with comments | « ui/message_center/views/notification_view_md.h ('k') | ui/views/controls/progress_bar.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/message_center/views/notification_view_md.h" 5 #include "ui/message_center/views/notification_view_md.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "ui/base/cursor/cursor.h" 10 #include "ui/base/cursor/cursor.h"
11 #include "ui/base/l10n/l10n_util.h" 11 #include "ui/base/l10n/l10n_util.h"
12 #include "ui/gfx/canvas.h"
12 #include "ui/gfx/geometry/size.h" 13 #include "ui/gfx/geometry/size.h"
13 #include "ui/gfx/image/image_skia_operations.h" 14 #include "ui/gfx/image/image_skia_operations.h"
14 #include "ui/gfx/paint_vector_icon.h" 15 #include "ui/gfx/paint_vector_icon.h"
15 #include "ui/gfx/skia_util.h" 16 #include "ui/gfx/skia_util.h"
16 #include "ui/gfx/text_elider.h" 17 #include "ui/gfx/text_elider.h"
17 #include "ui/message_center/message_center.h" 18 #include "ui/message_center/message_center.h"
18 #include "ui/message_center/message_center_style.h" 19 #include "ui/message_center/message_center_style.h"
19 #include "ui/message_center/notification.h" 20 #include "ui/message_center/notification.h"
20 #include "ui/message_center/notification_types.h" 21 #include "ui/message_center/notification_types.h"
21 #include "ui/message_center/vector_icons.h" 22 #include "ui/message_center/vector_icons.h"
22 #include "ui/message_center/views/bounded_label.h" 23 #include "ui/message_center/views/bounded_label.h"
23 #include "ui/message_center/views/constants.h" 24 #include "ui/message_center/views/constants.h"
24 #include "ui/message_center/views/message_center_controller.h" 25 #include "ui/message_center/views/message_center_controller.h"
25 #include "ui/message_center/views/notification_header_view.h" 26 #include "ui/message_center/views/notification_header_view.h"
26 #include "ui/message_center/views/padded_button.h" 27 #include "ui/message_center/views/padded_button.h"
27 #include "ui/message_center/views/proportional_image_view.h" 28 #include "ui/message_center/views/proportional_image_view.h"
28 #include "ui/strings/grit/ui_strings.h" 29 #include "ui/strings/grit/ui_strings.h"
29 #include "ui/views/background.h" 30 #include "ui/views/background.h"
30 #include "ui/views/border.h" 31 #include "ui/views/border.h"
31 #include "ui/views/controls/button/label_button.h" 32 #include "ui/views/controls/button/label_button.h"
32 #include "ui/views/controls/image_view.h" 33 #include "ui/views/controls/image_view.h"
33 #include "ui/views/controls/label.h" 34 #include "ui/views/controls/label.h"
35 #include "ui/views/controls/progress_bar.h"
34 #include "ui/views/focus/focus_manager.h" 36 #include "ui/views/focus/focus_manager.h"
35 #include "ui/views/layout/box_layout.h" 37 #include "ui/views/layout/box_layout.h"
36 #include "ui/views/layout/fill_layout.h" 38 #include "ui/views/layout/fill_layout.h"
37 #include "ui/views/native_cursor.h" 39 #include "ui/views/native_cursor.h"
38 #include "ui/views/view_targeter.h" 40 #include "ui/views/view_targeter.h"
39 #include "ui/views/widget/widget.h" 41 #include "ui/views/widget/widget.h"
40 42
41 namespace message_center { 43 namespace message_center {
42 44
43 namespace { 45 namespace {
44 46
45 // Dimensions. 47 // Dimensions.
46 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12); 48 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12);
47 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8); 49 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8);
48 constexpr int kActionsRowHorizontalSpacing = 8; 50 constexpr int kActionsRowHorizontalSpacing = 8;
49 constexpr gfx::Insets kImageContainerPadding(0, 12, 12, 12); 51 constexpr gfx::Insets kImageContainerPadding(0, 12, 12, 12);
50 52
51 // Foreground of small icon image. 53 // Foreground of small icon image.
52 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE; 54 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE;
53 // Background of small icon image. 55 // Background of small icon image.
54 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43); 56 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43);
55 // Background of inline actions area. 57 // Background of inline actions area.
56 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); 58 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee);
57 59
58 // Max number of lines for message_view_. 60 // Max number of lines for message_view_.
59 constexpr int kMaxLinesForMessageView = 1; 61 constexpr int kMaxLinesForMessageView = 1;
60 constexpr int kMaxLinesForExpandedMessageView = 4; 62 constexpr int kMaxLinesForExpandedMessageView = 4;
61 63
64 constexpr int kCompactTitleMessageViewSpacing = 12;
65
66 constexpr int kProgressBarHeight = 4;
67
62 const gfx::ImageSkia CreateSolidColorImage(int width, 68 const gfx::ImageSkia CreateSolidColorImage(int width,
63 int height, 69 int height,
64 SkColor color) { 70 SkColor color) {
65 SkBitmap bitmap; 71 SkBitmap bitmap;
66 bitmap.allocN32Pixels(width, height); 72 bitmap.allocN32Pixels(width, height);
67 bitmap.eraseColor(color); 73 bitmap.eraseColor(color);
68 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); 74 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
69 } 75 }
70 76
71 // Take the alpha channel of icon, mask it with the foreground, 77 // Take the alpha channel of icon, mask it with the foreground,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 views::Label* message = new views::Label(item.message); 124 views::Label* message = new views::Label(item.message);
119 message->set_collapse_when_hidden(true); 125 message->set_collapse_when_hidden(true);
120 message->SetHorizontalAlignment(gfx::ALIGN_LEFT); 126 message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
121 message->SetEnabledColor(message_center::kDimTextColor); 127 message->SetEnabledColor(message_center::kDimTextColor);
122 message->SetBackgroundColor(message_center::kDimTextBackgroundColor); 128 message->SetBackgroundColor(message_center::kDimTextBackgroundColor);
123 AddChildView(message); 129 AddChildView(message);
124 } 130 }
125 131
126 ItemView::~ItemView() {} 132 ItemView::~ItemView() {}
127 133
134 // CompactTitleMessageView /////////////////////////////////////////////////////
135
136 // CompactTitleMessageView shows notification title and message in a single
137 // line. This view is used for NOTIFICATION_TYPE_PROGRESS.
138 class CompactTitleMessageView : public views::View {
139 public:
140 explicit CompactTitleMessageView();
141 ~CompactTitleMessageView() override;
142
143 void OnPaint(gfx::Canvas* canvas) override;
144
145 void set_title(const base::string16& title) { title_ = title; }
146 void set_message(const base::string16& message) { message_ = message; }
147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(CompactTitleMessageView);
150
151 base::string16 title_;
152 base::string16 message_;
153
154 views::Label* title_view_ = nullptr;
155 views::Label* message_view_ = nullptr;
156 };
157
158 CompactTitleMessageView::~CompactTitleMessageView() {}
159
160 CompactTitleMessageView::CompactTitleMessageView() {
161 SetLayoutManager(new views::FillLayout());
162
163 const gfx::FontList& font_list = views::Label().font_list().Derive(
164 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
165
166 title_view_ = new views::Label();
167 title_view_->SetFontList(font_list);
168 title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
169 title_view_->SetEnabledColor(message_center::kRegularTextColor);
170 AddChildView(title_view_);
171
172 message_view_ = new views::Label();
173 message_view_->SetFontList(font_list);
174 message_view_->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
175 message_view_->SetEnabledColor(message_center::kDimTextColor);
176 AddChildView(message_view_);
177 }
178
179 void CompactTitleMessageView::OnPaint(gfx::Canvas* canvas) {
180 base::string16 title = title_;
181 base::string16 message = message_;
182
183 const gfx::FontList& font_list = views::Label().font_list().Derive(
184 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
185
186 // Elides title and message. The behavior is based on Android's one.
187 // * If the title is too long, only the title is shown.
188 // * If the message is too long, the full content of the title is shown,
189 // kCompactTitleMessageViewSpacing is added between them, and the elided
190 // message is shown.
191 // * If they are short enough, the title is left-aligned and the message is
192 // right-aligned.
193 const int original_title_width =
194 gfx::Canvas::GetStringWidthF(title, font_list);
195 if (original_title_width >= width())
196 message.clear();
197 title = gfx::ElideText(title, font_list, width(), gfx::ELIDE_TAIL);
198 const int title_width = gfx::Canvas::GetStringWidthF(title, font_list);
199 const int message_width =
200 std::max(0, width() - title_width - kCompactTitleMessageViewSpacing);
201 message = gfx::ElideText(message, font_list, message_width, gfx::ELIDE_TAIL);
202
203 title_view_->SetText(title);
204 message_view_->SetText(message);
205
206 views::View::OnPaint(canvas);
207 }
208
128 } // anonymous namespace 209 } // anonymous namespace
129 210
130 // //////////////////////////////////////////////////////////// 211 // ////////////////////////////////////////////////////////////
131 // NotificationViewMD 212 // NotificationViewMD
132 // //////////////////////////////////////////////////////////// 213 // ////////////////////////////////////////////////////////////
133 214
134 views::View* NotificationViewMD::TargetForRect(views::View* root, 215 views::View* NotificationViewMD::TargetForRect(views::View* root,
135 const gfx::Rect& rect) { 216 const gfx::Rect& rect) {
136 CHECK_EQ(root, this); 217 CHECK_EQ(root, this);
137 218
(...skipping 21 matching lines...) Expand all
159 return buttons[i]->GetEventHandlerForPoint(point_in_child); 240 return buttons[i]->GetEventHandlerForPoint(point_in_child);
160 } 241 }
161 242
162 return root; 243 return root;
163 } 244 }
164 245
165 void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) { 246 void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) {
166 CreateOrUpdateContextTitleView(notification); 247 CreateOrUpdateContextTitleView(notification);
167 CreateOrUpdateTitleView(notification); 248 CreateOrUpdateTitleView(notification);
168 CreateOrUpdateMessageView(notification); 249 CreateOrUpdateMessageView(notification);
250 CreateOrUpdateCompactTitleMessageView(notification);
169 CreateOrUpdateProgressBarView(notification); 251 CreateOrUpdateProgressBarView(notification);
170 CreateOrUpdateListItemViews(notification); 252 CreateOrUpdateListItemViews(notification);
171 CreateOrUpdateIconView(notification); 253 CreateOrUpdateIconView(notification);
172 CreateOrUpdateSmallIconView(notification); 254 CreateOrUpdateSmallIconView(notification);
173 CreateOrUpdateImageView(notification); 255 CreateOrUpdateImageView(notification);
174 CreateOrUpdateActionButtonViews(notification); 256 CreateOrUpdateActionButtonViews(notification);
175 CreateOrUpdateCloseButtonView(notification); 257 CreateOrUpdateCloseButtonView(notification);
176 CreateOrUpdateSettingsButtonView(notification); 258 CreateOrUpdateSettingsButtonView(notification);
177 UpdateViewForExpandedState(expanded_); 259 UpdateViewForExpandedState(expanded_);
178 } 260 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 header_row_->close_button()->RequestFocus(); 414 header_row_->close_button()->RequestFocus();
333 } 415 }
334 416
335 void NotificationViewMD::CreateOrUpdateContextTitleView( 417 void NotificationViewMD::CreateOrUpdateContextTitleView(
336 const Notification& notification) { 418 const Notification& notification) {
337 header_row_->SetAppName(notification.display_source()); 419 header_row_->SetAppName(notification.display_source());
338 } 420 }
339 421
340 void NotificationViewMD::CreateOrUpdateTitleView( 422 void NotificationViewMD::CreateOrUpdateTitleView(
341 const Notification& notification) { 423 const Notification& notification) {
424 if (notification.type() == NOTIFICATION_TYPE_PROGRESS) {
425 left_content_->RemoveChildView(title_view_);
426 title_view_ = nullptr;
427 return;
428 }
342 const gfx::FontList& font_list = views::Label().font_list().Derive( 429 const gfx::FontList& font_list = views::Label().font_list().Derive(
343 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL); 430 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
344 431
345 int title_character_limit = 432 int title_character_limit =
346 kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter; 433 kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter;
347 434
348 base::string16 title = gfx::TruncateString( 435 base::string16 title = gfx::TruncateString(
349 notification.title(), title_character_limit, gfx::WORD_BREAK); 436 notification.title(), title_character_limit, gfx::WORD_BREAK);
350 if (!title_view_) { 437 if (!title_view_) {
351 title_view_ = new views::Label(title); 438 title_view_ = new views::Label(title);
352 title_view_->SetFontList(font_list); 439 title_view_->SetFontList(font_list);
353 title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 440 title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
354 title_view_->SetEnabledColor(message_center::kRegularTextColor); 441 title_view_->SetEnabledColor(message_center::kRegularTextColor);
355 left_content_->AddChildView(title_view_); 442 left_content_->AddChildView(title_view_);
356 } else { 443 } else {
357 title_view_->SetText(title); 444 title_view_->SetText(title);
358 } 445 }
359 } 446 }
360 447
361 void NotificationViewMD::CreateOrUpdateMessageView( 448 void NotificationViewMD::CreateOrUpdateMessageView(
362 const Notification& notification) { 449 const Notification& notification) {
363 if (notification.message().empty()) { 450 if (notification.type() == NOTIFICATION_TYPE_PROGRESS ||
364 // Deletion will also remove |context_message_view_| from its parent. 451 notification.message().empty()) {
452 // Deletion will also remove |message_view_| from its parent.
365 delete message_view_; 453 delete message_view_;
366 message_view_ = nullptr; 454 message_view_ = nullptr;
367 return; 455 return;
368 } 456 }
369 457
370 base::string16 text = gfx::TruncateString( 458 base::string16 text = gfx::TruncateString(
371 notification.message(), kMessageCharacterLimit, gfx::WORD_BREAK); 459 notification.message(), kMessageCharacterLimit, gfx::WORD_BREAK);
372 460
373 const gfx::FontList& font_list = views::Label().font_list().Derive( 461 const gfx::FontList& font_list = views::Label().font_list().Derive(
374 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL); 462 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
375 463
376 if (!message_view_) { 464 if (!message_view_) {
377 message_view_ = new BoundedLabel(text, font_list); 465 message_view_ = new BoundedLabel(text, font_list);
378 message_view_->SetLineLimit(kMaxLinesForMessageView); 466 message_view_->SetLineLimit(kMaxLinesForMessageView);
379 message_view_->SetColors(message_center::kDimTextColor, 467 message_view_->SetColors(message_center::kDimTextColor,
380 kContextTextBackgroundColor); 468 kContextTextBackgroundColor);
381 left_content_->AddChildView(message_view_); 469 left_content_->AddChildView(message_view_);
382 } else { 470 } else {
383 message_view_->SetText(text); 471 message_view_->SetText(text);
384 } 472 }
385 473
386 message_view_->SetVisible(notification.items().empty()); 474 message_view_->SetVisible(notification.items().empty());
387 } 475 }
388 476
477 void NotificationViewMD::CreateOrUpdateCompactTitleMessageView(
478 const Notification& notification) {
479 if (notification.type() != NOTIFICATION_TYPE_PROGRESS) {
480 left_content_->RemoveChildView(compact_title_message_view_);
481 compact_title_message_view_ = nullptr;
482 return;
483 }
484 if (!compact_title_message_view_) {
485 compact_title_message_view_ = new CompactTitleMessageView();
486 left_content_->AddChildView(compact_title_message_view_);
487 }
488
489 compact_title_message_view_->set_title(notification.title());
490 compact_title_message_view_->set_message(notification.message());
491 left_content_->InvalidateLayout();
492 }
493
389 void NotificationViewMD::CreateOrUpdateProgressBarView( 494 void NotificationViewMD::CreateOrUpdateProgressBarView(
390 const Notification& notification) { 495 const Notification& notification) {
391 // TODO(yoshiki): Implement this. 496 if (notification.type() != NOTIFICATION_TYPE_PROGRESS) {
497 left_content_->RemoveChildView(progress_bar_view_);
498 progress_bar_view_ = nullptr;
499 return;
500 }
501
502 DCHECK(left_content_);
503
504 if (!progress_bar_view_) {
505 progress_bar_view_ = new views::ProgressBar(kProgressBarHeight,
506 /* allow_round_corner */ false);
507 progress_bar_view_->SetBorder(views::CreateEmptyBorder(
508 message_center::kProgressBarTopPadding, 0, 0, 0));
509 left_content_->AddChildView(progress_bar_view_);
510 }
511
512 progress_bar_view_->SetValue(notification.progress() / 100.0);
513 progress_bar_view_->SetVisible(notification.items().empty());
392 } 514 }
393 515
394 void NotificationViewMD::CreateOrUpdateListItemViews( 516 void NotificationViewMD::CreateOrUpdateListItemViews(
395 const Notification& notification) { 517 const Notification& notification) {
396 for (auto* item_view : item_views_) 518 for (auto* item_view : item_views_)
397 delete item_view; 519 delete item_view;
398 item_views_.clear(); 520 item_views_.clear();
399 521
400 const std::vector<NotificationItem>& items = notification.items(); 522 const std::vector<NotificationItem>& items = notification.items();
401 523
402 for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { 524 for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
403 ItemView* item_view = new ItemView(items[i]); 525 ItemView* item_view = new ItemView(items[i]);
404 item_views_.push_back(item_view); 526 item_views_.push_back(item_view);
405 left_content_->AddChildView(item_view); 527 left_content_->AddChildView(item_view);
406 } 528 }
407 529
408 // Needed when CreateOrUpdateViews is called for update. 530 // Needed when CreateOrUpdateViews is called for update.
409 if (!item_views_.empty()) 531 if (!item_views_.empty())
410 left_content_->InvalidateLayout(); 532 left_content_->InvalidateLayout();
411 } 533 }
412 534
413 void NotificationViewMD::CreateOrUpdateIconView( 535 void NotificationViewMD::CreateOrUpdateIconView(
414 const Notification& notification) { 536 const Notification& notification) {
537 if (notification.type() == NOTIFICATION_TYPE_PROGRESS ||
538 notification.type() == NOTIFICATION_TYPE_MULTIPLE) {
539 right_content_->RemoveChildView(icon_view_);
540 icon_view_ = nullptr;
541 return;
542 }
543
415 gfx::Size image_view_size(30, 30); 544 gfx::Size image_view_size(30, 30);
416 if (!icon_view_) { 545 if (!icon_view_) {
417 icon_view_ = new ProportionalImageView(image_view_size); 546 icon_view_ = new ProportionalImageView(image_view_size);
418 right_content_->AddChildView(icon_view_); 547 right_content_->AddChildView(icon_view_);
419 } 548 }
420 549
421 gfx::ImageSkia icon = notification.icon().AsImageSkia(); 550 gfx::ImageSkia icon = notification.icon().AsImageSkia();
422 icon_view_->SetImage(icon, icon.size()); 551 icon_view_->SetImage(icon, icon.size());
423 } 552 }
424 553
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 header_row_->expand_button()->HasFocus()) || 709 header_row_->expand_button()->HasFocus()) ||
581 (header_row_->IsCloseButtonEnabled() && 710 (header_row_->IsCloseButtonEnabled() &&
582 header_row_->close_button()->HasFocus()) || 711 header_row_->close_button()->HasFocus()) ||
583 (header_row_->IsSettingsButtonEnabled() && 712 (header_row_->IsSettingsButtonEnabled() &&
584 header_row_->settings_button()->HasFocus()); 713 header_row_->settings_button()->HasFocus());
585 714
586 header_row_->SetControlButtonsVisible(target_visibility); 715 header_row_->SetControlButtonsVisible(target_visibility);
587 } 716 }
588 717
589 } // namespace message_center 718 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/notification_view_md.h ('k') | ui/views/controls/progress_bar.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698