#ifndef UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_BASE_H_
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_BASE_H_
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/notification_input_container.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/animation/ink_drop_observer.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/delegating_layout_manager.h"
#include "ui/views/layout/fill_layout.h"
namespace views {
class BoxLayoutView;
class Label;
class LabelButton;
class LayoutManager;
class ProgressBar;
}
namespace message_center {
class NotificationHeaderView;
class ProportionalImageView;
class CompactTitleMessageView : public views::View,
public views::LayoutDelegate {
METADATA_HEADER(CompactTitleMessageView, views::View)
public:
CompactTitleMessageView();
CompactTitleMessageView(const CompactTitleMessageView&) = delete;
CompactTitleMessageView& operator=(const CompactTitleMessageView&) = delete;
~CompactTitleMessageView() override;
gfx::Size CalculatePreferredSize(
const views::SizeBounds& ) const override;
views::ProposedLayout CalculateProposedLayout(
const views::SizeBounds& size_bounds) const override;
void set_title(const std::u16string& title);
void set_message(const std::u16string& message);
private:
raw_ptr<views::Label> title_ = nullptr;
raw_ptr<views::Label> message_ = nullptr;
};
class MESSAGE_CENTER_EXPORT NotificationViewBase
: public MessageView,
public views::InkDropObserver,
public NotificationInputDelegate {
METADATA_HEADER(NotificationViewBase, MessageView)
public:
enum ViewId {
kHeaderRow = 1,
kAppNameView,
kHeaderDetailViews,
kSummaryTextView,
kContentRow,
kActionButtonsRow,
kInlineReply,
kMainRightView,
kHeaderLeftContent,
kCollapsedSummaryView,
kAppIconViewContainer,
kLargeImageView,
kMainView,
kIconView,
kInlineSettingsRow,
kExpandButton,
kLeftContent,
kImageContainerView,
};
NotificationViewBase(const NotificationViewBase&) = delete;
NotificationViewBase& operator=(const NotificationViewBase&) = delete;
~NotificationViewBase() override;
void OnFocus() override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void UpdateWithNotification(const Notification& notification) override;
NotificationControlButtonsView* GetControlButtonsView() const override;
bool IsExpanded() const override;
void SetExpanded(bool expanded) override;
bool IsManuallyExpandedOrCollapsed() const override;
void SetManuallyExpandedOrCollapsed(ExpandState state) override;
void ToggleInlineSettings(const ui::Event& event) override;
void ToggleSnoozeSettings(const ui::Event& event) override;
void InkDropAnimationStarted() override;
void InkDropRippleAnimationEnded(views::InkDropState ink_drop_state) override;
void OnNotificationInputSubmit(size_t index,
const std::u16string& text) override;
virtual bool IsIconViewShown() const;
views::Label* message_label_for_testing() { return message_label_; }
views::ProgressBar* progress_bar_view_for_testing() {
return progress_bar_view_;
}
views::Label* status_view_for_testing() { return status_view_; }
protected:
explicit NotificationViewBase(const Notification& notification);
views::Builder<NotificationControlButtonsView> CreateControlButtonsBuilder();
views::Builder<NotificationHeaderView> CreateHeaderRowBuilder();
views::Builder<views::BoxLayoutView> CreateLeftContentBuilder();
views::Builder<views::View> CreateRightContentBuilder();
views::Builder<views::View> CreateContentRowBuilder();
views::Builder<views::View> CreateImageContainerBuilder();
views::Builder<views::BoxLayoutView> CreateInlineSettingsBuilder();
views::Builder<views::BoxLayoutView> CreateSnoozeSettingsBuilder();
std::unique_ptr<views::View> CreateActionsRow(
std::unique_ptr<views::LayoutManager> layout_manager =
std::make_unique<views::FillLayout>());
static std::unique_ptr<views::Label> GenerateTitleView(
const std::u16string& title);
virtual std::unique_ptr<NotificationInputContainer>
GenerateNotificationInputContainer();
virtual std::unique_ptr<views::LabelButton> GenerateNotificationLabelButton(
views::Button::PressedCallback callback,
const std::u16string& label) = 0;
void CreateOrUpdateViews(const Notification& notification);
virtual void UpdateViewForExpandedState(bool expanded);
virtual void CreateOrUpdateHeaderView(const Notification& notification);
virtual void CreateOrUpdateCompactTitleMessageView(
const Notification& notification);
void CreateOrUpdateProgressBarView(const Notification& notification);
void CreateOrUpdateProgressStatusView(const Notification& notification);
virtual void CreateOrUpdateTitleView(const Notification& notification) = 0;
virtual void CreateOrUpdateSmallIconView(
const Notification& notification) = 0;
virtual void CreateOrUpdateInlineSettingsViews(
const Notification& notification) = 0;
virtual void CreateOrUpdateSnoozeSettingsViews(
const Notification& notification) = 0;
template <typename T>
T* AddViewToLeftContent(std::unique_ptr<T> view) {
return left_content_->AddChildViewAt(std::move(view),
left_content_count_++);
}
void ReorderViewInLeftContent(views::View* view);
virtual void ActionButtonPressed(size_t index, const ui::Event& event);
virtual void OnInlineReplyUpdated();
bool HasInlineReply(const Notification& notification) const;
NotificationControlButtonsView* control_buttons_view() {
return control_buttons_view_;
}
NotificationHeaderView* header_row() { return header_row_; }
views::View* content_row() { return content_row_; }
const views::View* content_row() const { return content_row_; }
views::BoxLayoutView* left_content() { return left_content_; }
views::View* right_content() { return right_content_; }
views::Label* message_label() { return message_label_; }
const views::Label* message_label() const { return message_label_; }
ProportionalImageView* icon_view() const { return icon_view_; }
views::BoxLayoutView* inline_settings_row() { return settings_row_; }
const views::BoxLayoutView* inline_settings_row() const {
return settings_row_;
}
views::BoxLayoutView* snooze_settings_row() { return snooze_row_; }
const views::BoxLayoutView* snooze_settings_row() const {
return snooze_row_;
}
views::View* image_container_view() { return image_container_view_; }
const views::View* image_container_view() const {
return image_container_view_;
}
views::View* actions_row() { return actions_row_; }
views::View* action_buttons_row() { return action_buttons_row_; }
const views::View* action_buttons_row() const { return action_buttons_row_; }
std::vector<raw_ptr<views::LabelButton, VectorExperimental>>
action_buttons() {
return action_buttons_;
}
views::ProgressBar* progress_bar_view() const { return progress_bar_view_; }
NotificationInputContainer* inline_reply() { return inline_reply_; }
views::Label* status_view() { return status_view_; }
const views::Label* status_view() const { return status_view_; }
const std::vector<raw_ptr<views::View, VectorExperimental>> item_views()
const {
return item_views_;
}
bool hide_icon_on_expanded() const { return hide_icon_on_expanded_; }
virtual bool IsExpandable() const = 0;
virtual void SetExpandButtonVisibility(bool visible);
virtual gfx::Size GetIconViewSize() const = 0;
virtual int GetLargeImageViewMaxWidth() const = 0;
private:
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, AppNameExtension);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, AppNameSystemNotification);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, AppNameWebNotification);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, AppNameWebAppNotification);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, CreateOrUpdateTest);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, InlineSettings);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest,
InlineSettingsInkDropAnimation);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, NotificationWithoutIcon);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, ShowProgress);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, ShowTimestamp);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, TestActionButtonClick);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, TestClick);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, TestClickExpanded);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest,
TestDeleteOnDisableNotification);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest,
TestDeleteOnToggleExpanded);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, TestInlineReply);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest,
TestInlineReplyActivateWithKeyPress);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest,
TestInlineReplyRemovedByUpdate);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, TestLongTitleAndMessage);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, UpdateAddingIcon);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, UpdateButtonCountTest);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, UpdateButtonsStateTest);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, UpdateInSettings);
FRIEND_TEST_ALL_PREFIXES(NotificationViewBaseTest, UseImageAsIcon);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, TestIconSizing);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, LeftContentResizeForIcon);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, ManuallyExpandedOrCollapsed);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, InlineSettingsNotBlock);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, InlineSettingsBlockAll);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, TestAccentColor);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest,
TestAccentColorTextFlagAffectsHeaderRow);
FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, ExpandLongMessage);
friend class NotificationViewBaseTest;
void CreateOrUpdateMessageLabel(const Notification& notification);
virtual void CreateOrUpdateProgressViews(const Notification& notification);
void CreateOrUpdateListItemViews(const Notification& notification);
void CreateOrUpdateIconView(const Notification& notification);
void CreateOrUpdateImageView(const Notification& notification);
void CreateOrUpdateActionButtonViews(const Notification& notification);
raw_ptr<NotificationControlButtonsView> control_buttons_view_ = nullptr;
bool expanded_ = false;
bool manually_expanded_or_collapsed_ = false;
bool hide_icon_on_expanded_ = false;
int list_items_count_ = 0;
bool clickable_;
const bool for_ash_notification_;
raw_ptr<NotificationHeaderView> header_row_ = nullptr;
raw_ptr<views::View> content_row_ = nullptr;
raw_ptr<views::View> actions_row_ = nullptr;
raw_ptr<views::BoxLayoutView> settings_row_ = nullptr;
raw_ptr<views::BoxLayoutView> snooze_row_ = nullptr;
raw_ptr<views::BoxLayoutView> left_content_ = nullptr;
raw_ptr<views::View> right_content_ = nullptr;
raw_ptr<views::Label, DanglingUntriaged> message_label_ = nullptr;
raw_ptr<views::Label, DanglingUntriaged> status_view_ = nullptr;
raw_ptr<ProportionalImageView, DanglingUntriaged> icon_view_ = nullptr;
raw_ptr<views::View> image_container_view_ = nullptr;
std::vector<raw_ptr<views::LabelButton, VectorExperimental>> action_buttons_;
std::vector<raw_ptr<views::View, VectorExperimental>> item_views_;
raw_ptr<views::ProgressBar, DanglingUntriaged> progress_bar_view_ = nullptr;
raw_ptr<CompactTitleMessageView, DanglingUntriaged>
compact_title_message_view_ = nullptr;
raw_ptr<views::View> action_buttons_row_ = nullptr;
raw_ptr<NotificationInputContainer> inline_reply_ = nullptr;
std::map<views::LabelButton*, std::optional<std::u16string>>
action_button_to_placeholder_map_;
size_t left_content_count_;
base::TimeTicks last_mouse_pressed_timestamp_;
base::WeakPtrFactory<NotificationViewBase> weak_ptr_factory_{this};
};
}
#endif