Chromium Code Reviews| 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/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" |
| 11 #include "ui/base/cursor/cursor.h" | 11 #include "ui/base/cursor/cursor.h" |
| 12 #include "ui/base/l10n/l10n_util.h" | 12 #include "ui/base/l10n/l10n_util.h" |
| 13 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
| 14 #include "ui/gfx/geometry/size.h" | 14 #include "ui/gfx/geometry/size.h" |
| 15 #include "ui/gfx/image/image_skia_operations.h" | |
| 15 #include "ui/gfx/paint_vector_icon.h" | 16 #include "ui/gfx/paint_vector_icon.h" |
| 16 #include "ui/gfx/skia_util.h" | 17 #include "ui/gfx/skia_util.h" |
| 17 #include "ui/gfx/text_elider.h" | 18 #include "ui/gfx/text_elider.h" |
| 18 #include "ui/message_center/message_center.h" | 19 #include "ui/message_center/message_center.h" |
| 19 #include "ui/message_center/message_center_style.h" | 20 #include "ui/message_center/message_center_style.h" |
| 20 #include "ui/message_center/notification.h" | 21 #include "ui/message_center/notification.h" |
| 21 #include "ui/message_center/notification_types.h" | 22 #include "ui/message_center/notification_types.h" |
| 22 #include "ui/message_center/vector_icons.h" | 23 #include "ui/message_center/vector_icons.h" |
| 23 #include "ui/message_center/views/bounded_label.h" | 24 #include "ui/message_center/views/bounded_label.h" |
| 24 #include "ui/message_center/views/constants.h" | 25 #include "ui/message_center/views/constants.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 42 #include "ui/views/widget/widget.h" | 43 #include "ui/views/widget/widget.h" |
| 43 | 44 |
| 44 namespace message_center { | 45 namespace message_center { |
| 45 | 46 |
| 46 namespace { | 47 namespace { |
| 47 | 48 |
| 48 // Dimensions. | 49 // Dimensions. |
| 49 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12); | 50 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12); |
| 50 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8); | 51 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8); |
| 51 constexpr int kActionsRowHorizontalSpacing = 8; | 52 constexpr int kActionsRowHorizontalSpacing = 8; |
| 52 constexpr gfx::Insets kImageContainerPadding(0, 12, 12, 12); | |
| 53 constexpr gfx::Insets kActionButtonPadding(0, 12, 0, 12); | 53 constexpr gfx::Insets kActionButtonPadding(0, 12, 0, 12); |
| 54 constexpr gfx::Insets kStatusTextPadding(4, 0, 0, 0); | 54 constexpr gfx::Insets kStatusTextPadding(4, 0, 0, 0); |
| 55 constexpr gfx::Size kActionButtonMinSize(88, 32); | 55 constexpr gfx::Size kActionButtonMinSize(88, 32); |
| 56 constexpr gfx::Size kIconViewSize(30, 30); | 56 constexpr gfx::Size kIconViewSize(30, 30); |
| 57 constexpr gfx::Insets kLargeImageContainerPadding(0, 12, 12, 12); | |
| 58 constexpr gfx::Size kLargeImageMinSize(328, 0); | |
| 59 constexpr gfx::Size kLargeImageMaxSize(328, 218); | |
| 57 | 60 |
| 58 // Background of inline actions area. | 61 // Background of inline actions area. |
| 59 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); | 62 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); |
| 60 // Base ink drop color of action buttons. | 63 // Base ink drop color of action buttons. |
| 61 const SkColor kActionButtonInkDropBaseColor = SkColorSetRGB(0x0, 0x0, 0x0); | 64 const SkColor kActionButtonInkDropBaseColor = SkColorSetRGB(0x0, 0x0, 0x0); |
| 62 // Ripple ink drop opacity of action buttons. | 65 // Ripple ink drop opacity of action buttons. |
| 63 const float kActionButtonInkDropRippleVisibleOpacity = 0.08f; | 66 const float kActionButtonInkDropRippleVisibleOpacity = 0.08f; |
| 64 // Highlight (hover) ink drop opacity of action buttons. | 67 // Highlight (hover) ink drop opacity of action buttons. |
| 65 const float kActionButtonInkDropHighlightVisibleOpacity = 0.08f; | 68 const float kActionButtonInkDropHighlightVisibleOpacity = 0.08f; |
| 66 // Text color of action button. | 69 // Text color of action button. |
| 67 const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6); | 70 const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6); |
| 71 // Background color of the large image. | |
| 72 const SkColor kLargeImageBackgroundColor = SkColorSetRGB(0xf5, 0xf5, 0xf5); | |
| 68 | 73 |
| 69 // Max number of lines for message_view_. | 74 // Max number of lines for message_view_. |
| 70 constexpr int kMaxLinesForMessageView = 1; | 75 constexpr int kMaxLinesForMessageView = 1; |
| 71 constexpr int kMaxLinesForExpandedMessageView = 4; | 76 constexpr int kMaxLinesForExpandedMessageView = 4; |
| 72 | 77 |
| 73 constexpr int kCompactTitleMessageViewSpacing = 12; | 78 constexpr int kCompactTitleMessageViewSpacing = 12; |
| 74 | 79 |
| 75 constexpr int kProgressBarHeight = 4; | 80 constexpr int kProgressBarHeight = 4; |
| 76 | 81 |
| 77 constexpr int kMessageViewWidth = | 82 constexpr int kMessageViewWidth = |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 } | 253 } |
| 249 | 254 |
| 250 std::unique_ptr<views::InkDropHighlight> | 255 std::unique_ptr<views::InkDropHighlight> |
| 251 NotificationButtonMD::CreateInkDropHighlight() const { | 256 NotificationButtonMD::CreateInkDropHighlight() const { |
| 252 std::unique_ptr<views::InkDropHighlight> highlight = | 257 std::unique_ptr<views::InkDropHighlight> highlight = |
| 253 views::LabelButton::CreateInkDropHighlight(); | 258 views::LabelButton::CreateInkDropHighlight(); |
| 254 highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity); | 259 highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity); |
| 255 return highlight; | 260 return highlight; |
| 256 } | 261 } |
| 257 | 262 |
| 263 // LargeImageView ////////////////////////////////////////////////////////////// | |
| 264 | |
| 265 class LargeImageView : public views::View { | |
| 266 public: | |
| 267 explicit LargeImageView(); | |
| 268 ~LargeImageView() override; | |
| 269 | |
| 270 void SetImage(const gfx::ImageSkia& image); | |
| 271 | |
| 272 void OnPaint(gfx::Canvas* canvas) override; | |
| 273 const char* GetClassName() const override; | |
| 274 | |
| 275 // We have a container view outside LargeImageView, because we want to fill | |
| 276 // area that is not coverted by the image by background color. | |
| 277 // When adding this view to the parent, add this container instead of the | |
| 278 // LargeImageView instance itself. | |
| 279 // When removing, just delete the LargeImageView instance. | |
| 280 views::View* container() { return container_; } | |
| 281 | |
| 282 private: | |
| 283 gfx::Size GetResizedImageSize(); | |
| 284 | |
| 285 views::View* const container_; | |
|
Yoshiki IGUCHI
2017/08/04 07:00:33
It's not good that a child has a parent. In this i
tetsui
2017/08/04 07:39:31
Done.
| |
| 286 gfx::ImageSkia image_; | |
| 287 | |
| 288 DISALLOW_COPY_AND_ASSIGN(LargeImageView); | |
| 289 }; | |
| 290 | |
| 291 LargeImageView::LargeImageView() : container_(new views::View) { | |
| 292 set_owned_by_client(); | |
| 293 SetBackground(views::CreateSolidBackground(kLargeImageBackgroundColor)); | |
| 294 container_->SetLayoutManager(new views::FillLayout()); | |
| 295 container_->SetBorder(views::CreateEmptyBorder(kLargeImageContainerPadding)); | |
| 296 container_->SetBackground( | |
| 297 views::CreateSolidBackground(message_center::kImageBackgroundColor)); | |
| 298 container_->AddChildView(this); | |
| 299 } | |
| 300 | |
| 301 LargeImageView::~LargeImageView() { | |
| 302 delete container_; | |
| 303 } | |
| 304 | |
| 305 void LargeImageView::SetImage(const gfx::ImageSkia& image) { | |
| 306 image_ = image; | |
| 307 gfx::Size preferred_size = GetResizedImageSize(); | |
| 308 preferred_size.SetToMax(kLargeImageMinSize); | |
| 309 preferred_size.SetToMin(kLargeImageMaxSize); | |
| 310 SetPreferredSize(preferred_size); | |
| 311 SchedulePaint(); | |
| 312 Layout(); | |
| 313 } | |
| 314 | |
| 315 void LargeImageView::OnPaint(gfx::Canvas* canvas) { | |
| 316 views::View::OnPaint(canvas); | |
| 317 | |
| 318 gfx::Size resized_size = GetResizedImageSize(); | |
| 319 gfx::Size drawn_size = resized_size; | |
| 320 drawn_size.SetToMin(kLargeImageMaxSize); | |
| 321 gfx::Rect drawn_bounds = GetContentsBounds(); | |
| 322 drawn_bounds.ClampToCenteredSize(drawn_size); | |
| 323 | |
| 324 gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage( | |
| 325 image_, skia::ImageOperations::RESIZE_BEST, resized_size); | |
| 326 | |
| 327 // Cut off the overflown part. | |
| 328 gfx::ImageSkia drawn_image = gfx::ImageSkiaOperations::ExtractSubset( | |
| 329 resized_image, gfx::Rect(drawn_size)); | |
| 330 | |
| 331 canvas->DrawImageInt(drawn_image, drawn_bounds.x(), drawn_bounds.y()); | |
| 332 } | |
| 333 | |
| 334 const char* LargeImageView::GetClassName() const { | |
| 335 return "LargeImageView"; | |
| 336 } | |
| 337 | |
| 338 // Returns expected size of the image right after resizing. | |
| 339 // The GetResizedImageSize().width() <= kLargeImageMaxSize.width() holds, but | |
| 340 // GetResizedImageSize().height() may be larger than kLargeImageMaxSize.height() | |
| 341 // In this case, the overflown part will be just cutted off from the view. | |
| 342 gfx::Size LargeImageView::GetResizedImageSize() { | |
| 343 gfx::Size original_size = image_.size(); | |
| 344 if (original_size.width() <= kLargeImageMaxSize.width()) | |
| 345 return image_.size(); | |
| 346 | |
| 347 const double proportion = | |
| 348 original_size.height() / static_cast<double>(original_size.width()); | |
| 349 gfx::Size resized_size; | |
| 350 resized_size.SetSize(kLargeImageMaxSize.width(), | |
| 351 kLargeImageMaxSize.width() * proportion); | |
| 352 return resized_size; | |
| 353 } | |
| 354 | |
| 258 } // anonymous namespace | 355 } // anonymous namespace |
| 259 | 356 |
| 260 // //////////////////////////////////////////////////////////// | 357 // //////////////////////////////////////////////////////////// |
| 261 // NotificationViewMD | 358 // NotificationViewMD |
| 262 // //////////////////////////////////////////////////////////// | 359 // //////////////////////////////////////////////////////////// |
| 263 | 360 |
| 264 views::View* NotificationViewMD::TargetForRect(views::View* root, | 361 views::View* NotificationViewMD::TargetForRect(views::View* root, |
| 265 const gfx::Rect& rect) { | 362 const gfx::Rect& rect) { |
| 266 CHECK_EQ(root, this); | 363 CHECK_EQ(root, this); |
| 267 | 364 |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 list_items_count_ = items.size(); | 727 list_items_count_ = items.size(); |
| 631 | 728 |
| 632 // Needed when CreateOrUpdateViews is called for update. | 729 // Needed when CreateOrUpdateViews is called for update. |
| 633 if (!item_views_.empty()) | 730 if (!item_views_.empty()) |
| 634 left_content_->InvalidateLayout(); | 731 left_content_->InvalidateLayout(); |
| 635 } | 732 } |
| 636 | 733 |
| 637 void NotificationViewMD::CreateOrUpdateIconView( | 734 void NotificationViewMD::CreateOrUpdateIconView( |
| 638 const Notification& notification) { | 735 const Notification& notification) { |
| 639 if (notification.type() == NOTIFICATION_TYPE_PROGRESS || | 736 if (notification.type() == NOTIFICATION_TYPE_PROGRESS || |
| 640 notification.type() == NOTIFICATION_TYPE_MULTIPLE) { | 737 notification.type() == NOTIFICATION_TYPE_MULTIPLE || |
| 738 notification.type() == NOTIFICATION_TYPE_IMAGE) { | |
| 641 DCHECK(!icon_view_ || right_content_->Contains(icon_view_)); | 739 DCHECK(!icon_view_ || right_content_->Contains(icon_view_)); |
| 642 delete icon_view_; | 740 delete icon_view_; |
| 643 icon_view_ = nullptr; | 741 icon_view_ = nullptr; |
| 644 return; | 742 return; |
| 645 } | 743 } |
| 646 | 744 |
| 647 if (!icon_view_) { | 745 if (!icon_view_) { |
| 648 icon_view_ = new ProportionalImageView(kIconViewSize); | 746 icon_view_ = new ProportionalImageView(kIconViewSize); |
| 649 right_content_->AddChildView(icon_view_); | 747 right_content_->AddChildView(icon_view_); |
| 650 } | 748 } |
| 651 | 749 |
| 652 gfx::ImageSkia icon = notification.icon().AsImageSkia(); | 750 gfx::ImageSkia icon = notification.icon().AsImageSkia(); |
| 653 icon_view_->SetImage(icon, icon.size()); | 751 icon_view_->SetImage(icon, icon.size()); |
| 654 } | 752 } |
| 655 | 753 |
| 656 void NotificationViewMD::CreateOrUpdateSmallIconView( | 754 void NotificationViewMD::CreateOrUpdateSmallIconView( |
| 657 const Notification& notification) { | 755 const Notification& notification) { |
| 658 if (notification.small_image().IsEmpty()) | 756 if (notification.small_image().IsEmpty()) |
| 659 header_row_->ClearAppIcon(); | 757 header_row_->ClearAppIcon(); |
| 660 else | 758 else |
| 661 header_row_->SetAppIcon(notification.small_image().AsImageSkia()); | 759 header_row_->SetAppIcon(notification.small_image().AsImageSkia()); |
| 662 } | 760 } |
| 663 | 761 |
| 664 void NotificationViewMD::CreateOrUpdateImageView( | 762 void NotificationViewMD::CreateOrUpdateImageView( |
| 665 const Notification& notification) { | 763 const Notification& notification) { |
| 666 // |image_view_| is the view representing the area covered by the | |
| 667 // notification's image, including background and border. Its size can be | |
| 668 // specified in advance and images will be scaled to fit including a border if | |
| 669 // necessary. | |
| 670 if (notification.image().IsEmpty()) { | 764 if (notification.image().IsEmpty()) { |
| 671 if (image_container_) { | 765 if (image_view_) { |
| 672 DCHECK(image_view_); | 766 DCHECK(Contains(image_view_->container())); |
| 673 DCHECK(Contains(image_container_)); | 767 delete image_view_; |
| 674 delete image_container_; | 768 image_view_ = nullptr; |
| 675 image_container_ = NULL; | |
| 676 image_view_ = NULL; | |
| 677 } else { | |
| 678 DCHECK(!image_view_); | |
| 679 } | 769 } |
| 680 return; | 770 return; |
| 681 } | 771 } |
| 682 | 772 |
| 683 gfx::Size ideal_size(kNotificationPreferredImageWidth, | 773 if (!image_view_) { |
| 684 kNotificationPreferredImageHeight); | 774 image_view_ = new LargeImageView(); |
| 685 | |
| 686 if (!image_container_) { | |
| 687 image_container_ = new views::View(); | |
| 688 image_container_->SetLayoutManager(new views::FillLayout()); | |
| 689 image_container_->SetBorder( | |
| 690 views::CreateEmptyBorder(kImageContainerPadding)); | |
| 691 image_container_->SetBackground( | |
| 692 views::CreateSolidBackground(message_center::kImageBackgroundColor)); | |
| 693 | |
| 694 DCHECK(!image_view_); | |
| 695 image_view_ = new message_center::ProportionalImageView(ideal_size); | |
| 696 image_container_->AddChildView(image_view_); | |
| 697 // Insert the created image container just after the |content_row_|. | 775 // Insert the created image container just after the |content_row_|. |
| 698 AddChildViewAt(image_container_, GetIndexOf(content_row_) + 1); | 776 AddChildViewAt(image_view_->container(), GetIndexOf(content_row_) + 1); |
| 699 } | 777 } |
| 700 | 778 |
| 701 DCHECK(image_view_); | 779 image_view_->SetImage(notification.image().AsImageSkia()); |
| 702 image_view_->SetImage(notification.image().AsImageSkia(), ideal_size); | |
| 703 } | 780 } |
| 704 | 781 |
| 705 void NotificationViewMD::CreateOrUpdateActionButtonViews( | 782 void NotificationViewMD::CreateOrUpdateActionButtonViews( |
| 706 const Notification& notification) { | 783 const Notification& notification) { |
| 707 std::vector<ButtonInfo> buttons = notification.buttons(); | 784 std::vector<ButtonInfo> buttons = notification.buttons(); |
| 708 bool new_buttons = action_buttons_.size() != buttons.size(); | 785 bool new_buttons = action_buttons_.size() != buttons.size(); |
| 709 | 786 |
| 710 if (new_buttons || buttons.size() == 0) { | 787 if (new_buttons || buttons.size() == 0) { |
| 711 for (auto* item : action_buttons_) | 788 for (auto* item : action_buttons_) |
| 712 delete item; | 789 delete item; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 797 if (controller()) | 874 if (controller()) |
| 798 controller()->UpdateNotificationSize(notification_id()); | 875 controller()->UpdateNotificationSize(notification_id()); |
| 799 } | 876 } |
| 800 | 877 |
| 801 void NotificationViewMD::UpdateViewForExpandedState(bool expanded) { | 878 void NotificationViewMD::UpdateViewForExpandedState(bool expanded) { |
| 802 header_row_->SetExpanded(expanded); | 879 header_row_->SetExpanded(expanded); |
| 803 if (message_view_) { | 880 if (message_view_) { |
| 804 message_view_->SetLineLimit(expanded ? kMaxLinesForExpandedMessageView | 881 message_view_->SetLineLimit(expanded ? kMaxLinesForExpandedMessageView |
| 805 : kMaxLinesForMessageView); | 882 : kMaxLinesForMessageView); |
| 806 } | 883 } |
| 807 if (image_container_) | 884 if (image_view_) |
| 808 image_container_->SetVisible(expanded); | 885 image_view_->container()->SetVisible(expanded); |
| 809 actions_row_->SetVisible(expanded && actions_row_->has_children()); | 886 actions_row_->SetVisible(expanded && actions_row_->has_children()); |
| 810 for (size_t i = kMaxLinesForMessageView; i < item_views_.size(); ++i) { | 887 for (size_t i = kMaxLinesForMessageView; i < item_views_.size(); ++i) { |
| 811 item_views_[i]->SetVisible(expanded); | 888 item_views_[i]->SetVisible(expanded); |
| 812 } | 889 } |
| 813 if (status_view_) | 890 if (status_view_) |
| 814 status_view_->SetVisible(expanded); | 891 status_view_->SetVisible(expanded); |
| 815 header_row_->SetOverflowIndicator( | 892 header_row_->SetOverflowIndicator( |
| 816 list_items_count_ - | 893 list_items_count_ - |
| 817 (expanded ? item_views_.size() : kMaxLinesForMessageView)); | 894 (expanded ? item_views_.size() : kMaxLinesForMessageView)); |
| 818 } | 895 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 829 header_row_->SetControlButtonsVisible(target_visibility); | 906 header_row_->SetControlButtonsVisible(target_visibility); |
| 830 } | 907 } |
| 831 | 908 |
| 832 NotificationControlButtonsView* NotificationViewMD::GetControlButtonsView() | 909 NotificationControlButtonsView* NotificationViewMD::GetControlButtonsView() |
| 833 const { | 910 const { |
| 834 // TODO(yoshiki): have this view use NotificationControlButtonsView. | 911 // TODO(yoshiki): have this view use NotificationControlButtonsView. |
| 835 return nullptr; | 912 return nullptr; |
| 836 } | 913 } |
| 837 | 914 |
| 838 } // namespace message_center | 915 } // namespace message_center |
| OLD | NEW |