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

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

Issue 2969603003: Implement new-style image notification resizing. (Closed)
Patch Set: Fix memory leak. Created 3 years, 4 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') | no next file » | 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/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include "ui/views/widget/widget.h" 43 #include "ui/views/widget/widget.h"
44 44
45 namespace message_center { 45 namespace message_center {
46 46
47 namespace { 47 namespace {
48 48
49 // Dimensions. 49 // Dimensions.
50 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12); 50 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12);
51 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8); 51 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8);
52 constexpr int kActionsRowHorizontalSpacing = 8; 52 constexpr int kActionsRowHorizontalSpacing = 8;
53 constexpr gfx::Insets kImageContainerPadding(0, 12, 12, 12);
54 constexpr gfx::Insets kActionButtonPadding(0, 12, 0, 12); 53 constexpr gfx::Insets kActionButtonPadding(0, 12, 0, 12);
55 constexpr gfx::Size kActionButtonMinSize(88, 32); 54 constexpr gfx::Size kActionButtonMinSize(88, 32);
56 constexpr gfx::Size kIconViewSize(30, 30); 55 constexpr gfx::Size kIconViewSize(30, 30);
56 constexpr gfx::Insets kLargeImageContainerPadding(0, 12, 12, 12);
57 constexpr gfx::Size kLargeImageMinSize(328, 0);
58 constexpr gfx::Size kLargeImageMaxSize(328, 218);
57 59
58 // Foreground of small icon image. 60 // Foreground of small icon image.
59 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE; 61 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE;
60 // Background of small icon image. 62 // Background of small icon image.
61 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43); 63 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43);
62 // Background of inline actions area. 64 // Background of inline actions area.
63 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); 65 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee);
64 // Base ink drop color of action buttons. 66 // Base ink drop color of action buttons.
65 const SkColor kActionButtonInkDropBaseColor = SkColorSetRGB(0x0, 0x0, 0x0); 67 const SkColor kActionButtonInkDropBaseColor = SkColorSetRGB(0x0, 0x0, 0x0);
66 // Ripple ink drop opacity of action buttons. 68 // Ripple ink drop opacity of action buttons.
67 const float kActionButtonInkDropRippleVisibleOpacity = 0.08f; 69 const float kActionButtonInkDropRippleVisibleOpacity = 0.08f;
68 // Highlight (hover) ink drop opacity of action buttons. 70 // Highlight (hover) ink drop opacity of action buttons.
69 const float kActionButtonInkDropHighlightVisibleOpacity = 0.08f; 71 const float kActionButtonInkDropHighlightVisibleOpacity = 0.08f;
70 // Text color of action button. 72 // Text color of action button.
71 const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6); 73 const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6);
74 // Background color of the large image.
75 const SkColor kLargeImageBackgroundColor = SkColorSetRGB(0xf5, 0xf5, 0xf5);
72 76
73 // Max number of lines for message_view_. 77 // Max number of lines for message_view_.
74 constexpr int kMaxLinesForMessageView = 1; 78 constexpr int kMaxLinesForMessageView = 1;
75 constexpr int kMaxLinesForExpandedMessageView = 4; 79 constexpr int kMaxLinesForExpandedMessageView = 4;
76 80
77 constexpr int kCompactTitleMessageViewSpacing = 12; 81 constexpr int kCompactTitleMessageViewSpacing = 12;
78 82
79 constexpr int kProgressBarHeight = 4; 83 constexpr int kProgressBarHeight = 4;
80 84
81 constexpr int kMessageViewWidth = 85 constexpr int kMessageViewWidth =
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 } 287 }
284 288
285 std::unique_ptr<views::InkDropHighlight> 289 std::unique_ptr<views::InkDropHighlight>
286 NotificationButtonMD::CreateInkDropHighlight() const { 290 NotificationButtonMD::CreateInkDropHighlight() const {
287 std::unique_ptr<views::InkDropHighlight> highlight = 291 std::unique_ptr<views::InkDropHighlight> highlight =
288 views::LabelButton::CreateInkDropHighlight(); 292 views::LabelButton::CreateInkDropHighlight();
289 highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity); 293 highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity);
290 return highlight; 294 return highlight;
291 } 295 }
292 296
297 // LargeImageView //////////////////////////////////////////////////////////////
298
299 class LargeImageView : public views::View {
300 public:
301 explicit LargeImageView();
302 ~LargeImageView() override;
303
304 void SetImage(const gfx::ImageSkia& image);
305
306 void OnPaint(gfx::Canvas* canvas) override;
307 const char* GetClassName() const override;
308
309 views::View* container() { return container_; }
310
311 private:
312 gfx::Size GetResizedImageSize();
313
314 views::View* container_ = nullptr;
yoshiki 2017/07/28 06:13:03 Could you add const?
tetsui 2017/07/28 06:38:45 Done.
315 gfx::ImageSkia image_;
316 };
yoshiki 2017/07/28 06:13:03 Please add DISALLOW_COPY_AND_ASSIGN
tetsui 2017/07/28 06:38:45 Done.
317
318 LargeImageView::LargeImageView() {
319 SetBackground(views::CreateSolidBackground(kLargeImageBackgroundColor));
320 container_ = new views::View;
321 container_->SetLayoutManager(new views::FillLayout());
322 container_->SetBorder(views::CreateEmptyBorder(kLargeImageContainerPadding));
323 container_->SetBackground(
324 views::CreateSolidBackground(message_center::kImageBackgroundColor));
325 container_->AddChildView(this);
326 }
327
328 LargeImageView::~LargeImageView() {
329 delete container_;
330 }
331
332 void LargeImageView::SetImage(const gfx::ImageSkia& image) {
333 image_ = image;
334 gfx::Size preferred_size = GetResizedImageSize();
335 preferred_size.SetToMax(kLargeImageMinSize);
336 preferred_size.SetToMin(kLargeImageMaxSize);
337 SetPreferredSize(preferred_size);
338 SchedulePaint();
339 Layout();
340 }
341
342 void LargeImageView::OnPaint(gfx::Canvas* canvas) {
343 views::View::OnPaint(canvas);
344
345 gfx::Size resized_size = GetResizedImageSize();
346 gfx::Size drawn_size = resized_size;
347 drawn_size.SetToMin(kLargeImageMaxSize);
348 gfx::Rect drawn_bounds = GetContentsBounds();
349 drawn_bounds.ClampToCenteredSize(drawn_size);
350
351 gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage(
352 image_, skia::ImageOperations::RESIZE_BEST, resized_size);
353
354 // Cut off the overflown part.
355 gfx::ImageSkia drawn_image = gfx::ImageSkiaOperations::ExtractSubset(
356 resized_image, gfx::Rect(drawn_size));
357
358 canvas->DrawImageInt(drawn_image, drawn_bounds.x(), drawn_bounds.y());
359 }
360
361 const char* LargeImageView::GetClassName() const {
362 return "LargeImageView";
363 }
364
365 // Returns expected size of the image right after resizing.
366 // The GetResizedImageSize().width() <= kLargeImageMaxSize.width() holds, but
367 // GetResizedImageSize().height() may be larger than kLargeImageMaxSize.height()
368 // In this case, the overflown part will be just cutted off from the view.
369 gfx::Size LargeImageView::GetResizedImageSize() {
370 gfx::Size original_size = image_.size();
371 if (original_size.width() <= kLargeImageMaxSize.width()) {
372 return image_.size();
373 } else {
374 const double proportion =
375 original_size.height() / static_cast<double>(original_size.width());
376 gfx::Size resized_size;
377 resized_size.SetSize(kLargeImageMaxSize.width(),
378 kLargeImageMaxSize.width() * proportion);
379 return resized_size;
380 }
381 }
382
293 } // anonymous namespace 383 } // anonymous namespace
294 384
295 // //////////////////////////////////////////////////////////// 385 // ////////////////////////////////////////////////////////////
296 // NotificationViewMD 386 // NotificationViewMD
297 // //////////////////////////////////////////////////////////// 387 // ////////////////////////////////////////////////////////////
298 388
299 views::View* NotificationViewMD::TargetForRect(views::View* root, 389 views::View* NotificationViewMD::TargetForRect(views::View* root,
300 const gfx::Rect& rect) { 390 const gfx::Rect& rect) {
301 CHECK_EQ(root, this); 391 CHECK_EQ(root, this);
302 392
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 list_items_count_ = items.size(); 724 list_items_count_ = items.size();
635 725
636 // Needed when CreateOrUpdateViews is called for update. 726 // Needed when CreateOrUpdateViews is called for update.
637 if (!item_views_.empty()) 727 if (!item_views_.empty())
638 left_content_->InvalidateLayout(); 728 left_content_->InvalidateLayout();
639 } 729 }
640 730
641 void NotificationViewMD::CreateOrUpdateIconView( 731 void NotificationViewMD::CreateOrUpdateIconView(
642 const Notification& notification) { 732 const Notification& notification) {
643 if (notification.type() == NOTIFICATION_TYPE_PROGRESS || 733 if (notification.type() == NOTIFICATION_TYPE_PROGRESS ||
644 notification.type() == NOTIFICATION_TYPE_MULTIPLE) { 734 notification.type() == NOTIFICATION_TYPE_MULTIPLE ||
735 notification.type() == NOTIFICATION_TYPE_IMAGE) {
645 DCHECK(!icon_view_ || right_content_->Contains(icon_view_)); 736 DCHECK(!icon_view_ || right_content_->Contains(icon_view_));
646 delete icon_view_; 737 delete icon_view_;
647 icon_view_ = nullptr; 738 icon_view_ = nullptr;
648 return; 739 return;
649 } 740 }
650 741
651 if (!icon_view_) { 742 if (!icon_view_) {
652 icon_view_ = new ProportionalImageView(kIconViewSize); 743 icon_view_ = new ProportionalImageView(kIconViewSize);
653 right_content_->AddChildView(icon_view_); 744 right_content_->AddChildView(icon_view_);
654 } 745 }
655 746
656 gfx::ImageSkia icon = notification.icon().AsImageSkia(); 747 gfx::ImageSkia icon = notification.icon().AsImageSkia();
657 icon_view_->SetImage(icon, icon.size()); 748 icon_view_->SetImage(icon, icon.size());
658 } 749 }
659 750
660 void NotificationViewMD::CreateOrUpdateSmallIconView( 751 void NotificationViewMD::CreateOrUpdateSmallIconView(
661 const Notification& notification) { 752 const Notification& notification) {
662 gfx::ImageSkia icon = 753 gfx::ImageSkia icon =
663 notification.small_image().IsEmpty() 754 notification.small_image().IsEmpty()
664 ? GetProductIcon() 755 ? GetProductIcon()
665 : GetMaskedIcon(notification.small_image().AsImageSkia()); 756 : GetMaskedIcon(notification.small_image().AsImageSkia());
666 header_row_->SetAppIcon(icon); 757 header_row_->SetAppIcon(icon);
667 } 758 }
668 759
669 void NotificationViewMD::CreateOrUpdateImageView( 760 void NotificationViewMD::CreateOrUpdateImageView(
670 const Notification& notification) { 761 const Notification& notification) {
671 // |image_view_| is the view representing the area covered by the
672 // notification's image, including background and border. Its size can be
673 // specified in advance and images will be scaled to fit including a border if
674 // necessary.
675 if (notification.image().IsEmpty()) { 762 if (notification.image().IsEmpty()) {
676 if (image_container_) { 763 if (image_view_) {
677 DCHECK(image_view_); 764 DCHECK(Contains(image_view_->container()));
678 DCHECK(Contains(image_container_)); 765 delete image_view_;
679 delete image_container_; 766 image_view_ = nullptr;
680 image_container_ = NULL;
681 image_view_ = NULL;
682 } else {
683 DCHECK(!image_view_);
684 } 767 }
685 return; 768 return;
686 } 769 }
687 770
688 gfx::Size ideal_size(kNotificationPreferredImageWidth, 771 if (!image_view_) {
689 kNotificationPreferredImageHeight); 772 image_view_ = new LargeImageView();
690
691 if (!image_container_) {
692 image_container_ = new views::View();
693 image_container_->SetLayoutManager(new views::FillLayout());
694 image_container_->SetBorder(
695 views::CreateEmptyBorder(kImageContainerPadding));
696 image_container_->SetBackground(
697 views::CreateSolidBackground(message_center::kImageBackgroundColor));
698
699 DCHECK(!image_view_);
700 image_view_ = new message_center::ProportionalImageView(ideal_size);
701 image_container_->AddChildView(image_view_);
702 // Insert the created image container just after the |content_row_|. 773 // Insert the created image container just after the |content_row_|.
703 AddChildViewAt(image_container_, GetIndexOf(content_row_) + 1); 774 AddChildViewAt(image_view_->container(), GetIndexOf(content_row_) + 1);
704 } 775 }
705 776
706 DCHECK(image_view_); 777 image_view_->SetImage(notification.image().AsImageSkia());
707 image_view_->SetImage(notification.image().AsImageSkia(), ideal_size);
708 } 778 }
709 779
710 void NotificationViewMD::CreateOrUpdateActionButtonViews( 780 void NotificationViewMD::CreateOrUpdateActionButtonViews(
711 const Notification& notification) { 781 const Notification& notification) {
712 std::vector<ButtonInfo> buttons = notification.buttons(); 782 std::vector<ButtonInfo> buttons = notification.buttons();
713 bool new_buttons = action_buttons_.size() != buttons.size(); 783 bool new_buttons = action_buttons_.size() != buttons.size();
714 784
715 if (new_buttons || buttons.size() == 0) { 785 if (new_buttons || buttons.size() == 0) {
716 for (auto* item : action_buttons_) 786 for (auto* item : action_buttons_)
717 delete item; 787 delete item;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 if (controller()) 866 if (controller())
797 controller()->UpdateNotificationSize(notification_id()); 867 controller()->UpdateNotificationSize(notification_id());
798 } 868 }
799 869
800 void NotificationViewMD::UpdateViewForExpandedState(bool expanded) { 870 void NotificationViewMD::UpdateViewForExpandedState(bool expanded) {
801 header_row_->SetExpanded(expanded); 871 header_row_->SetExpanded(expanded);
802 if (message_view_) { 872 if (message_view_) {
803 message_view_->SetLineLimit(expanded ? kMaxLinesForExpandedMessageView 873 message_view_->SetLineLimit(expanded ? kMaxLinesForExpandedMessageView
804 : kMaxLinesForMessageView); 874 : kMaxLinesForMessageView);
805 } 875 }
806 if (image_container_) 876 if (image_view_)
807 image_container_->SetVisible(expanded); 877 image_view_->container()->SetVisible(expanded);
808 actions_row_->SetVisible(expanded && actions_row_->has_children()); 878 actions_row_->SetVisible(expanded && actions_row_->has_children());
809 for (size_t i = kMaxLinesForMessageView; i < item_views_.size(); ++i) { 879 for (size_t i = kMaxLinesForMessageView; i < item_views_.size(); ++i) {
810 item_views_[i]->SetVisible(expanded); 880 item_views_[i]->SetVisible(expanded);
811 } 881 }
812 header_row_->SetOverflowIndicator( 882 header_row_->SetOverflowIndicator(
813 list_items_count_ - 883 list_items_count_ -
814 (expanded ? item_views_.size() : kMaxLinesForMessageView)); 884 (expanded ? item_views_.size() : kMaxLinesForMessageView));
815 } 885 }
816 886
817 void NotificationViewMD::UpdateControlButtonsVisibility() { 887 void NotificationViewMD::UpdateControlButtonsVisibility() {
818 const bool target_visibility = IsMouseHovered() || HasFocus() || 888 const bool target_visibility = IsMouseHovered() || HasFocus() ||
819 (header_row_->IsExpandButtonEnabled() && 889 (header_row_->IsExpandButtonEnabled() &&
820 header_row_->expand_button()->HasFocus()) || 890 header_row_->expand_button()->HasFocus()) ||
821 (header_row_->IsCloseButtonEnabled() && 891 (header_row_->IsCloseButtonEnabled() &&
822 header_row_->close_button()->HasFocus()) || 892 header_row_->close_button()->HasFocus()) ||
823 (header_row_->IsSettingsButtonEnabled() && 893 (header_row_->IsSettingsButtonEnabled() &&
824 header_row_->settings_button()->HasFocus()); 894 header_row_->settings_button()->HasFocus());
825 895
826 header_row_->SetControlButtonsVisible(target_visibility); 896 header_row_->SetControlButtonsVisible(target_visibility);
827 } 897 }
828 898
829 } // namespace message_center 899 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/notification_view_md.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698