1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_MD_H_ 6 #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_MD_H_ 7 8 #include <vector> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/macros.h" 12 #include "base/optional.h" 13 #include "base/time/time.h" 14 #include "ui/message_center/message_center_export.h" 15 #include "ui/message_center/views/message_view.h" 16 #include "ui/views/animation/ink_drop_observer.h" 17 #include "ui/views/controls/button/button.h" 18 #include "ui/views/controls/button/label_button.h" 19 #include "ui/views/controls/textfield/textfield_controller.h" 20 21 namespace views { 22 class ImageButton; 23 class Label; 24 class LabelButton; 25 class ProgressBar; 26 class RadioButton; 27 class Textfield; 28 } 29 30 namespace message_center { 31 32 class NotificationHeaderView; 33 class ProportionalImageView; 34 35 // CompactTitleMessageView shows notification title and message in a single 36 // line. This view is used for NOTIFICATION_TYPE_PROGRESS. 37 class CompactTitleMessageView : public views::View { 38 public: 39 explicit CompactTitleMessageView(); 40 ~CompactTitleMessageView() override; 41 42 const char* GetClassName() const override; 43 44 gfx::Size CalculatePreferredSize() const override; 45 void Layout() override; 46 47 void set_title(const base::string16& title); 48 void set_message(const base::string16& message); 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(CompactTitleMessageView); 52 53 views::Label* title_ = nullptr; 54 views::Label* message_ = nullptr; 55 }; 56 57 class LargeImageView : public views::View { 58 public: 59 LargeImageView(); 60 ~LargeImageView() override; 61 62 void SetImage(const gfx::ImageSkia& image); 63 64 void OnPaint(gfx::Canvas* canvas) override; 65 const char* GetClassName() const override; 66 67 private: 68 gfx::Size GetResizedImageSize(); 69 70 gfx::ImageSkia image_; 71 72 DISALLOW_COPY_AND_ASSIGN(LargeImageView); 73 }; 74 75 // This class is needed in addition to LabelButton mainly becuase we want to set 76 // visible_opacity of InkDropHighlight. 77 // This button capitalizes the given label string. 78 class NotificationButtonMD : public views::LabelButton { 79 public: 80 // |is_inline_reply| is true when the notification action takes text as the 81 // return value i.e. the notification action is inline reply. 82 // The input field would be shown when the button is clicked. 83 // |placeholder| is placeholder text shown on the input field. Only used when 84 // |is_inline_reply| is true. 85 NotificationButtonMD(views::ButtonListener* listener, 86 const base::string16& label, 87 const base::Optional<base::string16>& placeholder); 88 ~NotificationButtonMD() override; 89 90 void SetText(const base::string16& text) override; 91 const char* GetClassName() const override; 92 93 std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() 94 const override; 95 enabled_color_for_testing()96 SkColor enabled_color_for_testing() { return label()->GetEnabledColor(); } 97 placeholder()98 const base::Optional<base::string16>& placeholder() const { 99 return placeholder_; 100 } set_placeholder(const base::Optional<base::string16> & placeholder)101 void set_placeholder(const base::Optional<base::string16>& placeholder) { 102 placeholder_ = placeholder; 103 } 104 105 private: 106 base::Optional<base::string16> placeholder_; 107 108 DISALLOW_COPY_AND_ASSIGN(NotificationButtonMD); 109 }; 110 111 class NotificationInputDelegate { 112 public: 113 virtual void OnNotificationInputSubmit(size_t index, 114 const base::string16& text) = 0; 115 virtual ~NotificationInputDelegate() = default; 116 }; 117 118 class NotificationInputContainerMD : public views::InkDropHostView, 119 public views::ButtonListener, 120 public views::TextfieldController { 121 public: 122 NotificationInputContainerMD(NotificationInputDelegate* delegate); 123 ~NotificationInputContainerMD() override; 124 125 void AnimateBackground(const ui::Event& event); 126 127 // views::InkDropHostView: 128 void AddLayerBeneathView(ui::Layer* layer) override; 129 void RemoveLayerBeneathView(ui::Layer* layer) override; 130 std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; 131 SkColor GetInkDropBaseColor() const override; 132 133 // Overridden from views::TextfieldController: 134 bool HandleKeyEvent(views::Textfield* sender, 135 const ui::KeyEvent& key_event) override; 136 void OnAfterUserAction(views::Textfield* sender) override; 137 138 // Overridden from views::ButtonListener: 139 void ButtonPressed(views::Button* sender, const ui::Event& event) override; 140 textfield()141 views::Textfield* textfield() const { return textfield_; } button()142 views::ImageButton* button() const { return button_; } 143 144 private: 145 NotificationInputDelegate* const delegate_; 146 147 views::InkDropContainerView* const ink_drop_container_; 148 149 views::Textfield* const textfield_; 150 views::ImageButton* const button_; 151 152 DISALLOW_COPY_AND_ASSIGN(NotificationInputContainerMD); 153 }; 154 155 // View that displays all current types of notification (web, basic, image, and 156 // list) except the custom notification. Future notification types may be 157 // handled by other classes, in which case instances of those classes would be 158 // returned by the Create() factory method below. 159 class MESSAGE_CENTER_EXPORT NotificationViewMD 160 : public MessageView, 161 public views::InkDropObserver, 162 public NotificationInputDelegate, 163 public views::ButtonListener { 164 public: 165 explicit NotificationViewMD(const Notification& notification); 166 ~NotificationViewMD() override; 167 168 void Activate(); 169 170 void AddBackgroundAnimation(const ui::Event& event); 171 void RemoveBackgroundAnimation(); 172 173 // MessageView: 174 void AddLayerBeneathView(ui::Layer* layer) override; 175 void RemoveLayerBeneathView(ui::Layer* layer) override; 176 void Layout() override; 177 void OnFocus() override; 178 bool OnMousePressed(const ui::MouseEvent& event) override; 179 bool OnMouseDragged(const ui::MouseEvent& event) override; 180 void OnMouseReleased(const ui::MouseEvent& event) override; 181 void OnMouseEvent(ui::MouseEvent* event) override; 182 void OnGestureEvent(ui::GestureEvent* event) override; 183 void PreferredSizeChanged() override; 184 std::unique_ptr<views::InkDrop> CreateInkDrop() override; 185 std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; 186 std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; 187 SkColor GetInkDropBaseColor() const override; 188 void UpdateWithNotification(const Notification& notification) override; 189 void ButtonPressed(views::Button* sender, const ui::Event& event) override; 190 void UpdateCornerRadius(int top_radius, int bottom_radius) override; 191 NotificationControlButtonsView* GetControlButtonsView() const override; 192 bool IsExpanded() const override; 193 void SetExpanded(bool expanded) override; 194 bool IsManuallyExpandedOrCollapsed() const override; 195 void SetManuallyExpandedOrCollapsed(bool value) override; 196 void OnSettingsButtonPressed(const ui::Event& event) override; 197 198 // views::InkDropObserver: 199 void InkDropAnimationStarted() override; 200 void InkDropRippleAnimationEnded(views::InkDropState ink_drop_state) override; 201 202 // Overridden from NotificationInputDelegate: 203 void OnNotificationInputSubmit(size_t index, 204 const base::string16& text) override; 205 206 private: 207 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, AppNameExtension); 208 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, AppNameSystemNotification); 209 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, AppNameWebNotification); 210 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, CreateOrUpdateTest); 211 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, ExpandLongMessage); 212 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, InlineSettings); 213 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, 214 InlineSettingsInkDropAnimation); 215 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, NotificationWithoutIcon); 216 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, ShowProgress); 217 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, ShowTimestamp); 218 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestAccentColor); 219 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestActionButtonClick); 220 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestClick); 221 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestClickExpanded); 222 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, 223 TestDeleteOnDisableNotification); 224 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestDeleteOnToggleExpanded); 225 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestIconSizing); 226 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestInlineReply); 227 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, 228 TestInlineReplyActivateWithKeyPress); 229 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, 230 TestInlineReplyRemovedByUpdate); 231 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestLongTitleAndMessage); 232 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateAddingIcon); 233 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonCountTest); 234 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonsStateTest); 235 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateInSettings); 236 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateType); 237 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateViewsOrderingTest); 238 FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UseImageAsIcon); 239 240 friend class NotificationViewMDTest; 241 242 class NotificationViewMDPathGenerator; 243 244 void UpdateControlButtonsVisibilityWithNotification( 245 const Notification& notification); 246 247 void CreateOrUpdateViews(const Notification& notification); 248 249 void CreateOrUpdateContextTitleView(const Notification& notification); 250 void CreateOrUpdateTitleView(const Notification& notification); 251 void CreateOrUpdateMessageView(const Notification& notification); 252 void CreateOrUpdateCompactTitleMessageView(const Notification& notification); 253 void CreateOrUpdateProgressBarView(const Notification& notification); 254 void CreateOrUpdateProgressStatusView(const Notification& notification); 255 void CreateOrUpdateListItemViews(const Notification& notification); 256 void CreateOrUpdateIconView(const Notification& notification); 257 void CreateOrUpdateSmallIconView(const Notification& notification); 258 void CreateOrUpdateImageView(const Notification& notification); 259 void CreateOrUpdateActionButtonViews(const Notification& notification); 260 void CreateOrUpdateInlineSettingsViews(const Notification& notification); 261 262 bool IsExpandable(); 263 void ToggleExpanded(); 264 void UpdateViewForExpandedState(bool expanded); 265 void ToggleInlineSettings(const ui::Event& event); 266 267 // Returns the list of children which need to have their layers created or 268 // destroyed when the ink drop is visible. 269 std::vector<views::View*> GetChildrenForLayerAdjustment() const; 270 271 views::InkDropContainerView* const ink_drop_container_; 272 273 // View containing close and settings buttons 274 std::unique_ptr<NotificationControlButtonsView> control_buttons_view_; 275 276 // Whether this notification is expanded or not. 277 bool expanded_ = false; 278 279 // True if the notification is expanded/collapsed by user interaction. 280 // If true, MessagePopupCollection will not auto-collapse the notification. 281 bool manually_expanded_or_collapsed_ = false; 282 283 // Whether hiding icon on the right side when expanded. 284 bool hide_icon_on_expanded_ = false; 285 286 // Number of total list items in the given Notification class. 287 int list_items_count_ = 0; 288 289 // Describes whether the view should display a hand pointer or not. 290 bool clickable_; 291 292 // Container views directly attached to this view. 293 NotificationHeaderView* header_row_ = nullptr; 294 views::View* content_row_ = nullptr; 295 views::View* actions_row_ = nullptr; 296 views::View* settings_row_ = nullptr; 297 298 // Containers for left and right side on |content_row_| 299 views::View* left_content_ = nullptr; 300 views::View* right_content_ = nullptr; 301 302 // Views which are dynamically created inside view hierarchy. 303 views::Label* title_view_ = nullptr; 304 views::Label* message_view_ = nullptr; 305 views::Label* status_view_ = nullptr; 306 ProportionalImageView* icon_view_ = nullptr; 307 views::View* image_container_view_ = nullptr; 308 std::vector<NotificationButtonMD*> action_buttons_; 309 std::vector<views::View*> item_views_; 310 views::ProgressBar* progress_bar_view_ = nullptr; 311 CompactTitleMessageView* compact_title_message_view_ = nullptr; 312 views::View* action_buttons_row_ = nullptr; 313 NotificationInputContainerMD* inline_reply_ = nullptr; 314 315 // Counter for view layouting, which is used during the CreateOrUpdate* 316 // phases to keep track of the view ordering. See crbug.com/901045 317 int left_content_count_; 318 319 // Views for inline settings. 320 views::RadioButton* block_all_button_ = nullptr; 321 views::RadioButton* dont_block_button_ = nullptr; 322 views::LabelButton* settings_done_button_ = nullptr; 323 324 // Owned by views properties. Guaranteed to be not null for the lifetime of 325 // |this| because views properties are the last thing cleaned up. 326 NotificationViewMDPathGenerator* highlight_path_generator_ = nullptr; 327 328 std::unique_ptr<ui::EventHandler> click_activator_; 329 330 base::TimeTicks last_mouse_pressed_timestamp_; 331 332 base::WeakPtrFactory<NotificationViewMD> weak_ptr_factory_{this}; 333 334 DISALLOW_COPY_AND_ASSIGN(NotificationViewMD); 335 }; 336 337 } // namespace message_center 338 339 #endif // UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_VIEW_MD_H_ 340