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