123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/app_menu/notification_overflow_view.h"
- #include "ash/public/cpp/app_menu_constants.h"
- #include "ui/base/models/menu_separator_types.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size.h"
- #include "ui/gfx/image/image.h"
- #include "ui/gfx/paint_vector_icon.h"
- #include "ui/message_center/views/proportional_image_view.h"
- #include "ui/views/background.h"
- #include "ui/views/border.h"
- #include "ui/views/controls/menu/menu_config.h"
- #include "ui/views/controls/menu/menu_separator.h"
- #include "ui/views/vector_icons.h"
- namespace {
- // Padding in dips between the overflow separator and overflow icons.
- constexpr int kOverflowSeparatorToIconPadding = 8;
- // Padding in dips below the overflow icons.
- constexpr int kOverflowAreaBottomPadding = 12;
- // Size of overflow icons in dips.
- constexpr int kIconSize = 16;
- // Size used for laying out overflow icons in dips to prevent clipping.
- constexpr int kIconLayoutSize = kIconSize + 1;
- // Padding between overflow icons in dips.
- constexpr int kInterIconPadding = 8;
- } // namespace
- namespace ash {
- // The icon which represents a notification.
- class NotificationOverflowImageView
- : public message_center::ProportionalImageView {
- public:
- NotificationOverflowImageView(const ui::ImageModel& image,
- const std::string& notification_id)
- : message_center::ProportionalImageView(gfx::Size(kIconSize, kIconSize)),
- notification_id_(notification_id) {
- SetID(kNotificationOverflowIconId);
- SetImage(image, gfx::Size(kIconSize, kIconSize));
- }
- NotificationOverflowImageView(const NotificationOverflowImageView&) = delete;
- NotificationOverflowImageView& operator=(
- const NotificationOverflowImageView&) = delete;
- ~NotificationOverflowImageView() override = default;
- const std::string& notification_id() const { return notification_id_; }
- private:
- std::string const notification_id_;
- };
- NotificationOverflowView::NotificationOverflowView()
- : separator_(AddChildView(std::make_unique<views::MenuSeparator>(
- ui::MenuSeparatorType::NORMAL_SEPARATOR))) {
- SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR(
- 0, kNotificationHorizontalPadding, kOverflowAreaBottomPadding,
- kNotificationHorizontalPadding)));
- SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
- }
- NotificationOverflowView::~NotificationOverflowView() = default;
- void NotificationOverflowView::AddIcon(
- const message_center::ProportionalImageView& image_view,
- const std::string& notification_id) {
- // Insert the image at the front of the list, so that it appears on the right
- // side.
- image_views_.insert(
- image_views_.begin(),
- AddChildView(std::make_unique<NotificationOverflowImageView>(
- image_view.image(), notification_id)));
- if (image_views_.size() > kMaxOverflowIcons) {
- if (!overflow_icon_) {
- auto icon = ui::ImageModel::FromVectorIcon(views::kOptionsIcon,
- ui::kColorIcon, kIconSize);
- auto overflow_icon =
- std::make_unique<message_center::ProportionalImageView>(
- gfx::Size(kIconSize, kIconSize));
- overflow_icon->SetID(kOverflowIconId);
- overflow_icon->SetImage(icon, gfx::Size(kIconSize, kIconSize));
- overflow_icon_ = AddChildView(std::move(overflow_icon));
- }
- overflow_icon_->SetVisible(true);
- image_views_.at(kMaxOverflowIcons)->SetVisible(false);
- }
- Layout();
- }
- void NotificationOverflowView::RemoveIcon(const std::string& notification_id) {
- auto it = std::find_if(image_views_.begin(), image_views_.end(),
- [notification_id](const auto& item) {
- return item->notification_id() == notification_id;
- });
- if (it != image_views_.end()) {
- RemoveChildViewT(*it);
- image_views_.erase(it);
- MaybeRemoveOverflowIcon();
- Layout();
- }
- }
- void NotificationOverflowView::Layout() {
- separator_->SetBoundsRect(
- gfx::Rect(width(), separator_->GetPreferredSize().height()));
- int x = width() - GetInsets().right();
- const int y =
- separator_->GetPreferredSize().height() + kOverflowSeparatorToIconPadding;
- for (size_t i = 0; i < image_views_.size() && i <= kMaxOverflowIcons; ++i) {
- views::View* icon = image_views_.at(i);
- if (i == kMaxOverflowIcons)
- icon = overflow_icon_;
- x -= kIconLayoutSize;
- icon->SetBounds(x, y, kIconLayoutSize, kIconLayoutSize);
- x -= kInterIconPadding;
- }
- }
- gfx::Size NotificationOverflowView::CalculatePreferredSize() const {
- // This view is the last element in a MenuItemView, which means it has extra
- // padding on the bottom due to the corner radius of the root MenuItemView. If
- // the corner radius changes, |kOverflowSeparatorToIconPadding| must be
- // modified to vertically center the overflow icons.
- return gfx::Size(views::MenuConfig::instance().touchable_menu_min_width,
- separator_->GetPreferredSize().height() +
- kOverflowSeparatorToIconPadding + kIconLayoutSize);
- }
- void NotificationOverflowView::MaybeRemoveOverflowIcon() {
- if (!overflow_icon_ || image_views_.size() > kMaxOverflowIcons)
- return;
- overflow_icon_->SetVisible(false);
- }
- } // namespace ash
|