Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: ui/message_center/views/notification_view_md.cc

Issue 2925263003: Notification: Implement two-leveled notification. (Closed)
Patch Set: Remove an unused function. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/message_center/views/notification_view_md.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "ui/base/l10n/l10n_util.h" 11 #include "ui/base/l10n/l10n_util.h"
12 #include "ui/gfx/geometry/size.h" 12 #include "ui/gfx/geometry/size.h"
13 #include "ui/gfx/image/image_skia_operations.h" 13 #include "ui/gfx/image/image_skia_operations.h"
14 #include "ui/gfx/paint_vector_icon.h" 14 #include "ui/gfx/paint_vector_icon.h"
15 #include "ui/gfx/skia_util.h" 15 #include "ui/gfx/skia_util.h"
16 #include "ui/gfx/text_elider.h" 16 #include "ui/gfx/text_elider.h"
17 #include "ui/message_center/message_center.h" 17 #include "ui/message_center/message_center.h"
18 #include "ui/message_center/message_center_style.h" 18 #include "ui/message_center/message_center_style.h"
19 #include "ui/message_center/notification.h" 19 #include "ui/message_center/notification.h"
20 #include "ui/message_center/notification_types.h" 20 #include "ui/message_center/notification_types.h"
21 #include "ui/message_center/vector_icons.h" 21 #include "ui/message_center/vector_icons.h"
22 #include "ui/message_center/views/bounded_label.h" 22 #include "ui/message_center/views/bounded_label.h"
23 #include "ui/message_center/views/constants.h" 23 #include "ui/message_center/views/constants.h"
24 #include "ui/message_center/views/message_center_controller.h" 24 #include "ui/message_center/views/message_center_controller.h"
25 #include "ui/message_center/views/notification_button.h" 25 #include "ui/message_center/views/notification_header_view.h"
26 #include "ui/message_center/views/padded_button.h" 26 #include "ui/message_center/views/padded_button.h"
27 #include "ui/message_center/views/proportional_image_view.h"
27 #include "ui/strings/grit/ui_strings.h" 28 #include "ui/strings/grit/ui_strings.h"
28 #include "ui/views/background.h" 29 #include "ui/views/background.h"
29 #include "ui/views/border.h" 30 #include "ui/views/border.h"
31 #include "ui/views/controls/button/label_button.h"
30 #include "ui/views/controls/image_view.h" 32 #include "ui/views/controls/image_view.h"
31 #include "ui/views/controls/label.h" 33 #include "ui/views/controls/label.h"
32 #include "ui/views/focus/focus_manager.h" 34 #include "ui/views/focus/focus_manager.h"
33 #include "ui/views/layout/box_layout.h" 35 #include "ui/views/layout/box_layout.h"
36 #include "ui/views/layout/fill_layout.h"
34 #include "ui/views/native_cursor.h" 37 #include "ui/views/native_cursor.h"
35 #include "ui/views/view_targeter.h" 38 #include "ui/views/view_targeter.h"
39 #include "ui/views/widget/widget.h"
36 40
37 namespace message_center { 41 namespace message_center {
38 42
39 namespace { 43 namespace {
40 44
41 // Dimensions. 45 // Dimensions.
42 constexpr int kNotificationRightPadding = 13; 46 constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12);
43 constexpr int kNotificationLeftPadding = 13; 47 constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8);
44 constexpr int kNotificationTopPadding = 6; 48 constexpr int kActionsRowHorizontalSpacing = 8;
45 constexpr int kNotificationBottomPadding = 10; 49 constexpr gfx::Insets kImageContainerPadding(0, 12, 12, 12);
46 constexpr gfx::Insets kNotificationPadding(kNotificationTopPadding,
47 kNotificationLeftPadding,
48 kNotificationBottomPadding,
49 kNotificationRightPadding);
50
51 constexpr int kMaxContextTitleLines = 1;
52 50
53 // Foreground of small icon image. 51 // Foreground of small icon image.
54 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE; 52 constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE;
55 // Background of small icon image. 53 // Background of small icon image.
56 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43); 54 const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43);
55 // Background of inline actions area.
56 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee);
57
58 // Max number of lines for message_view_.
59 constexpr int kMaxLinesForMessageView = 1;
60 constexpr int kMaxLinesForExpandedMessageView = 4;
57 61
58 const gfx::ImageSkia CreateSolidColorImage(int width, 62 const gfx::ImageSkia CreateSolidColorImage(int width,
59 int height, 63 int height,
60 SkColor color) { 64 SkColor color) {
61 SkBitmap bitmap; 65 SkBitmap bitmap;
62 bitmap.allocN32Pixels(width, height); 66 bitmap.allocN32Pixels(width, height);
63 bitmap.eraseColor(color); 67 bitmap.eraseColor(color);
64 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); 68 return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
65 } 69 }
66 70
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 102
99 // TODO(tdanderson): Modify this function to support rect-based event 103 // TODO(tdanderson): Modify this function to support rect-based event
100 // targeting. Using the center point of |rect| preserves this function's 104 // targeting. Using the center point of |rect| preserves this function's
101 // expected behavior for the time being. 105 // expected behavior for the time being.
102 gfx::Point point = rect.CenterPoint(); 106 gfx::Point point = rect.CenterPoint();
103 107
104 // Want to return this for underlying views, otherwise GetCursor is not 108 // Want to return this for underlying views, otherwise GetCursor is not
105 // called. But buttons are exceptions, they'll have their own event handlings. 109 // called. But buttons are exceptions, they'll have their own event handlings.
106 std::vector<views::View*> buttons(action_buttons_.begin(), 110 std::vector<views::View*> buttons(action_buttons_.begin(),
107 action_buttons_.end()); 111 action_buttons_.end());
108 if (settings_button_) 112 if (header_row_->settings_button())
109 buttons.push_back(settings_button_.get()); 113 buttons.push_back(header_row_->settings_button());
110 if (close_button_) 114 if (header_row_->close_button())
111 buttons.push_back(close_button_.get()); 115 buttons.push_back(header_row_->close_button());
116 if (header_row_->expand_button())
117 buttons.push_back(header_row_->expand_button());
118 buttons.push_back(header_row_);
112 119
113 for (size_t i = 0; i < buttons.size(); ++i) { 120 for (size_t i = 0; i < buttons.size(); ++i) {
114 gfx::Point point_in_child = point; 121 gfx::Point point_in_child = point;
115 ConvertPointToTarget(this, buttons[i], &point_in_child); 122 ConvertPointToTarget(this, buttons[i], &point_in_child);
116 if (buttons[i]->HitTestPoint(point_in_child)) 123 if (buttons[i]->HitTestPoint(point_in_child))
117 return buttons[i]->GetEventHandlerForPoint(point_in_child); 124 return buttons[i]->GetEventHandlerForPoint(point_in_child);
118 } 125 }
119 126
120 return root; 127 return root;
121 } 128 }
122 129
123 void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) { 130 void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) {
124 CreateOrUpdateContextTitleView(notification); 131 CreateOrUpdateContextTitleView(notification);
125 CreateOrUpdateTitleView(notification); 132 CreateOrUpdateTitleView(notification);
126 CreateOrUpdateMessageView(notification); 133 CreateOrUpdateMessageView(notification);
127 CreateOrUpdateProgressBarView(notification); 134 CreateOrUpdateProgressBarView(notification);
128 CreateOrUpdateListItemViews(notification); 135 CreateOrUpdateListItemViews(notification);
129 CreateOrUpdateIconView(notification); 136 CreateOrUpdateIconView(notification);
130 CreateOrUpdateSmallIconView(notification); 137 CreateOrUpdateSmallIconView(notification);
131 CreateOrUpdateImageView(notification); 138 CreateOrUpdateImageView(notification);
132 CreateOrUpdateActionButtonViews(notification); 139 CreateOrUpdateActionButtonViews(notification);
133 CreateOrUpdateCloseButtonView(notification); 140 CreateOrUpdateCloseButtonView(notification);
134 CreateOrUpdateSettingsButtonView(notification); 141 CreateOrUpdateSettingsButtonView(notification);
142 UpdateViewForExpandedState(expanded_);
135 } 143 }
136 144
137 NotificationViewMD::NotificationViewMD(MessageCenterController* controller, 145 NotificationViewMD::NotificationViewMD(MessageCenterController* controller,
138 const Notification& notification) 146 const Notification& notification)
139 : MessageView(controller, notification), 147 : MessageView(controller, notification),
140 clickable_(notification.clickable()) { 148 clickable_(notification.clickable()) {
141 layout_ = new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 2); 149 SetLayoutManager(
142 layout_->set_inside_border_insets(kNotificationPadding); 150 new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0));
143 SetLayoutManager(layout_);
144 151
145 // Create the top_view_, which collects into a vertical box all content 152 // |header_row_| contains app_icon, app_name, control buttons, etc...
146 // at the top of the notification (to the right of the icon) except for the 153 header_row_ = new NotificationHeaderView(this);
147 // close button. 154 AddChildView(header_row_);
148 top_view_ = new views::View();
149 views::BoxLayout* top_box_layout =
150 new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(1, 0), 5);
151 top_box_layout->set_cross_axis_alignment(
152 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
153 top_view_->SetLayoutManager(top_box_layout);
154 AddChildView(top_view_);
155 155
156 main_view_ = new views::View(); 156 // |content_row_| contains title, message, image, progressbar, etc...
157 main_view_->SetLayoutManager( 157 content_row_ = new views::View();
158 new views::BoxLayout(views::BoxLayout::kVertical)); 158 views::BoxLayout* content_row_layout = new views::BoxLayout(
159 AddChildView(main_view_); 159 views::BoxLayout::kHorizontal, kContentRowPadding, 0);
160 content_row_layout->set_cross_axis_alignment(
161 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
162 content_row_->SetLayoutManager(content_row_layout);
163 AddChildView(content_row_);
160 164
161 // Create the bottom_view_, which collects notification icon. 165 // |left_content_| contains most contents like title, message, etc...
162 bottom_view_ = new views::View(); 166 left_content_ = new views::View();
163 bottom_view_->SetLayoutManager( 167 left_content_->SetLayoutManager(
164 new views::BoxLayout(views::BoxLayout::kVertical)); 168 new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0));
165 AddChildView(bottom_view_); 169 content_row_layout->SetFlexForView(left_content_, 1);
170 content_row_->AddChildView(left_content_);
166 171
167 views::ImageView* small_image_view = new views::ImageView(); 172 // |right_content_| contains notification icon and small image.
168 small_image_view->SetImageSize(gfx::Size(kSmallImageSize, kSmallImageSize)); 173 right_content_ = new views::View();
169 small_image_view->set_owned_by_client(); 174 right_content_->SetLayoutManager(new views::FillLayout());
170 small_image_view_.reset(small_image_view); 175 content_row_->AddChildView(right_content_);
171 top_view_->AddChildView(small_image_view_.get()); 176
177 // |action_row_| contains inline action button.
178 actions_row_ = new views::View();
179 actions_row_->SetLayoutManager(
180 new views::BoxLayout(views::BoxLayout::kHorizontal, kActionsRowPadding,
181 kActionsRowHorizontalSpacing));
182 actions_row_->SetBackground(
183 views::CreateSolidBackground(kActionsRowBackgroundColor));
184 actions_row_->SetVisible(false);
185 AddChildView(actions_row_);
172 186
173 CreateOrUpdateViews(notification); 187 CreateOrUpdateViews(notification);
174 188
175 SetEventTargeter( 189 SetEventTargeter(
176 std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); 190 std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
177 } 191 }
178 192
179 NotificationViewMD::~NotificationViewMD() {} 193 NotificationViewMD::~NotificationViewMD() {}
180 194
181 void NotificationViewMD::Layout() { 195 void NotificationViewMD::Layout() {
182 MessageView::Layout(); 196 MessageView::Layout();
183 197
184 // Before any resizing, set or adjust the number of message lines. 198 // We need to call IsExpandable() at the end of Layout() call, since whether
185 int title_lines = 0; 199 // we should show expand button or not depends on the current view layout.
186 if (title_view_) { 200 // (e.g. Show expand button when |message_view_| exceeds one line.)
187 title_lines = title_view_->GetLinesForWidthAndLimit(title_view_->width(), 201 header_row_->SetExpandButtonEnabled(IsExpandable());
188 kMaxTitleLines);
189 }
190 if (message_view_) {
191 message_view_->SetLineLimit(
192 std::max(0, message_center::kMessageExpandedLineLimit - title_lines));
193 }
194
195 // Settings & Bottom views.
196 if (settings_button_) {
197 gfx::Rect content_bounds = GetContentsBounds();
198 const gfx::Size settings_size(settings_button_->GetPreferredSize());
199 int marginFromRight = settings_size.width() + kControlButtonPadding;
200 if (close_button_)
201 marginFromRight += close_button_->GetPreferredSize().width();
202 gfx::Rect settings_rect(content_bounds.right() - marginFromRight,
203 GetContentsBounds().y() + kControlButtonPadding,
204 settings_size.width(), settings_size.height());
205 settings_button_->SetBoundsRect(settings_rect);
206 }
207
208 // Close button.
209 if (close_button_) {
210 gfx::Rect content_bounds = GetContentsBounds();
211 gfx::Size close_size(close_button_->GetPreferredSize());
212 gfx::Rect close_rect(
213 content_bounds.right() - close_size.width() - kControlButtonPadding,
214 content_bounds.y() + kControlButtonPadding, close_size.width(),
215 close_size.height());
216 close_button_->SetBoundsRect(close_rect);
217 }
218 } 202 }
219 203
220 void NotificationViewMD::OnFocus() { 204 void NotificationViewMD::OnFocus() {
221 MessageView::OnFocus(); 205 MessageView::OnFocus();
222 ScrollRectToVisible(GetLocalBounds()); 206 ScrollRectToVisible(GetLocalBounds());
223 } 207 }
224 208
225 void NotificationViewMD::ScrollRectToVisible(const gfx::Rect& rect) { 209 void NotificationViewMD::ScrollRectToVisible(const gfx::Rect& rect) {
226 // Notification want to show the whole notification when a part of it (like 210 // Notification want to show the whole notification when a part of it (like
227 // a button) gets focused. 211 // a button) gets focused.
228 views::View::ScrollRectToVisible(GetLocalBounds()); 212 views::View::ScrollRectToVisible(GetLocalBounds());
229 } 213 }
230 214
231 gfx::NativeCursor NotificationViewMD::GetCursor(const ui::MouseEvent& event) { 215 gfx::NativeCursor NotificationViewMD::GetCursor(const ui::MouseEvent& event) {
232 if (!clickable_ || !controller()->HasClickedListener(notification_id())) 216 if (!clickable_ || !controller()->HasClickedListener(notification_id()))
233 return views::View::GetCursor(event); 217 return views::View::GetCursor(event);
234 218
235 return views::GetNativeHandCursor(); 219 return views::GetNativeHandCursor();
236 } 220 }
237 221
222 void NotificationViewMD::OnMouseMoved(const ui::MouseEvent& event) {
223 MessageView::OnMouseMoved(event);
224 UpdateControlButtonsVisibility();
225 }
226
238 void NotificationViewMD::OnMouseEntered(const ui::MouseEvent& event) { 227 void NotificationViewMD::OnMouseEntered(const ui::MouseEvent& event) {
239 MessageView::OnMouseEntered(event); 228 MessageView::OnMouseEntered(event);
240 UpdateControlButtonsVisibility(); 229 UpdateControlButtonsVisibility();
241 } 230 }
242 231
243 void NotificationViewMD::OnMouseExited(const ui::MouseEvent& event) { 232 void NotificationViewMD::OnMouseExited(const ui::MouseEvent& event) {
244 MessageView::OnMouseExited(event); 233 MessageView::OnMouseExited(event);
245 UpdateControlButtonsVisibility(); 234 UpdateControlButtonsVisibility();
246 } 235 }
247 236
248 void NotificationViewMD::UpdateWithNotification( 237 void NotificationViewMD::UpdateWithNotification(
249 const Notification& notification) { 238 const Notification& notification) {
250 MessageView::UpdateWithNotification(notification); 239 MessageView::UpdateWithNotification(notification);
251 240
252 CreateOrUpdateViews(notification); 241 CreateOrUpdateViews(notification);
253 Layout(); 242 Layout();
254 SchedulePaint(); 243 SchedulePaint();
255 } 244 }
256 245
257 void NotificationViewMD::ButtonPressed(views::Button* sender, 246 void NotificationViewMD::ButtonPressed(views::Button* sender,
258 const ui::Event& event) { 247 const ui::Event& event) {
259 // Certain operations can cause |this| to be destructed, so copy the members 248 // Certain operations can cause |this| to be destructed, so copy the members
260 // we send to other parts of the code. 249 // we send to other parts of the code.
261 // TODO(dewittj): Remove this hack. 250 // TODO(dewittj): Remove this hack.
262 std::string id(notification_id()); 251 std::string id(notification_id());
263 252
264 if (close_button_ && sender == close_button_.get()) { 253 if (header_row_->IsCloseButtonEnabled() &&
254 sender == header_row_->close_button()) {
265 // Warning: This causes the NotificationViewMD itself to be deleted, so 255 // Warning: This causes the NotificationViewMD itself to be deleted, so
266 // don't do anything afterwards. 256 // don't do anything afterwards.
267 OnCloseButtonPressed(); 257 OnCloseButtonPressed();
268 return; 258 return;
269 } 259 }
270 260
271 if (sender == settings_button_.get()) { 261 if (header_row_->IsSettingsButtonEnabled() &&
262 sender == header_row_->settings_button()) {
272 controller()->ClickOnSettingsButton(id); 263 controller()->ClickOnSettingsButton(id);
273 return; 264 return;
274 } 265 }
275 266
267 // Tapping anywhere on |header_row_| can expand the notification, though only
268 // |expand_button| can be focused by TAB.
269 if (IsExpandable() &&
270 (sender == header_row_ || sender == header_row_->expand_button())) {
271 ToggleExpanded();
272 Layout();
273 SchedulePaint();
274 return;
275 }
276
276 // See if the button pressed was an action button. 277 // See if the button pressed was an action button.
277 for (size_t i = 0; i < action_buttons_.size(); ++i) { 278 for (size_t i = 0; i < action_buttons_.size(); ++i) {
278 if (sender == action_buttons_[i]) { 279 if (sender == action_buttons_[i]) {
279 controller()->ClickOnNotificationButton(id, i); 280 controller()->ClickOnNotificationButton(id, i);
280 return; 281 return;
281 } 282 }
282 } 283 }
283 } 284 }
284 285
285 bool NotificationViewMD::IsCloseButtonFocused() const { 286 bool NotificationViewMD::IsCloseButtonFocused() const {
286 if (!close_button_) 287 if (!header_row_->IsCloseButtonEnabled())
287 return false; 288 return false;
288 289
289 const views::FocusManager* focus_manager = GetFocusManager(); 290 const views::FocusManager* focus_manager = GetFocusManager();
290 return focus_manager && 291 return focus_manager &&
291 focus_manager->GetFocusedView() == close_button_.get(); 292 focus_manager->GetFocusedView() == header_row_->close_button();
292 } 293 }
293 294
294 void NotificationViewMD::RequestFocusOnCloseButton() { 295 void NotificationViewMD::RequestFocusOnCloseButton() {
295 if (close_button_) 296 if (header_row_->IsCloseButtonEnabled())
296 close_button_->RequestFocus(); 297 header_row_->close_button()->RequestFocus();
297 } 298 }
298 299
299 void NotificationViewMD::CreateOrUpdateContextTitleView( 300 void NotificationViewMD::CreateOrUpdateContextTitleView(
300 const Notification& notification) { 301 const Notification& notification) {
301 DCHECK(top_view_); 302 header_row_->SetAppName(notification.display_source());
302
303 const gfx::FontList& font_list = views::Label().font_list().Derive(
304 -2, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
305
306 base::string16 sub_title = notification.display_source();
307 if (!context_title_view_) {
308 context_title_view_ = new BoundedLabel(sub_title, font_list);
309 context_title_view_->SetLineHeight(kTitleLineHeight);
310 context_title_view_->SetLineLimit(kMaxContextTitleLines);
311 top_view_->AddChildView(context_title_view_);
312 } else {
313 context_title_view_->SetText(sub_title);
314 }
315 } 303 }
316 304
317 void NotificationViewMD::CreateOrUpdateTitleView( 305 void NotificationViewMD::CreateOrUpdateTitleView(
318 const Notification& notification) { 306 const Notification& notification) {
319 DCHECK(top_view_ != NULL);
320
321 const gfx::FontList& font_list = views::Label().font_list().Derive( 307 const gfx::FontList& font_list = views::Label().font_list().Derive(
322 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL); 308 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
323 309
324 int title_character_limit = 310 int title_character_limit =
325 kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter; 311 kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter;
326 312
327 base::string16 title = gfx::TruncateString( 313 base::string16 title = gfx::TruncateString(
328 notification.title(), title_character_limit, gfx::WORD_BREAK); 314 notification.title(), title_character_limit, gfx::WORD_BREAK);
329 if (!title_view_) { 315 if (!title_view_) {
330 title_view_ = new BoundedLabel(title, font_list); 316 title_view_ = new views::Label(title);
331 title_view_->SetLineHeight(kMessageLineHeight); 317 title_view_->SetFontList(font_list);
332 title_view_->SetColors(message_center::kRegularTextColor, 318 title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
333 kDimTextBackgroundColor); 319 title_view_->SetEnabledColor(message_center::kRegularTextColor);
334 main_view_->AddChildView(title_view_); 320 left_content_->AddChildView(title_view_);
335 } else { 321 } else {
336 title_view_->SetText(title); 322 title_view_->SetText(title);
337 } 323 }
338 } 324 }
339 325
340 void NotificationViewMD::CreateOrUpdateMessageView( 326 void NotificationViewMD::CreateOrUpdateMessageView(
341 const Notification& notification) { 327 const Notification& notification) {
342 if (notification.message().empty()) { 328 if (notification.message().empty()) {
343 // Deletion will also remove |context_message_view_| from its parent. 329 // Deletion will also remove |context_message_view_| from its parent.
344 delete message_view_; 330 delete message_view_;
345 message_view_ = nullptr; 331 message_view_ = nullptr;
346 return; 332 return;
347 } 333 }
348 334
349 DCHECK(top_view_ != NULL);
350
351 base::string16 text = gfx::TruncateString( 335 base::string16 text = gfx::TruncateString(
352 notification.message(), kMessageCharacterLimit, gfx::WORD_BREAK); 336 notification.message(), kMessageCharacterLimit, gfx::WORD_BREAK);
353 337
354 const gfx::FontList& font_list = views::Label().font_list().Derive( 338 const gfx::FontList& font_list = views::Label().font_list().Derive(
355 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL); 339 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
356 340
357 if (!message_view_) { 341 if (!message_view_) {
358 message_view_ = new BoundedLabel(text, font_list); 342 message_view_ = new BoundedLabel(text, font_list);
359 message_view_->SetLineLimit(message_center::kMessageExpandedLineLimit); 343 message_view_->SetLineLimit(kMaxLinesForMessageView);
360 message_view_->SetColors(message_center::kDimTextColor, 344 message_view_->SetColors(message_center::kDimTextColor,
361 kContextTextBackgroundColor); 345 kContextTextBackgroundColor);
362 main_view_->AddChildView(message_view_); 346 left_content_->AddChildView(message_view_);
363 } else { 347 } else {
364 message_view_->SetText(text); 348 message_view_->SetText(text);
365 } 349 }
366 } 350 }
367 351
368 void NotificationViewMD::CreateOrUpdateProgressBarView( 352 void NotificationViewMD::CreateOrUpdateProgressBarView(
369 const Notification& notification) { 353 const Notification& notification) {
370 // TODO(yoshiki): Implement this. 354 // TODO(yoshiki): Implement this.
371 } 355 }
372 356
373 void NotificationViewMD::CreateOrUpdateListItemViews( 357 void NotificationViewMD::CreateOrUpdateListItemViews(
374 const Notification& notification) { 358 const Notification& notification) {
375 // TODO(yoshiki): Implement this. 359 // TODO(yoshiki): Implement this.
376 } 360 }
377 361
378 void NotificationViewMD::CreateOrUpdateIconView( 362 void NotificationViewMD::CreateOrUpdateIconView(
379 const Notification& notification) { 363 const Notification& notification) {
380 // TODO(yoshiki): Implement this. 364 gfx::Size image_view_size(30, 30);
365 if (!icon_view_) {
366 icon_view_ = new ProportionalImageView(image_view_size);
367 right_content_->AddChildView(icon_view_);
368 }
369
370 gfx::ImageSkia icon = notification.icon().AsImageSkia();
371 icon_view_->SetImage(icon, icon.size());
381 } 372 }
382 373
383 void NotificationViewMD::CreateOrUpdateSmallIconView( 374 void NotificationViewMD::CreateOrUpdateSmallIconView(
384 const Notification& notification) { 375 const Notification& notification) {
385 gfx::ImageSkia icon = 376 gfx::ImageSkia icon =
386 notification.small_image().IsEmpty() 377 notification.small_image().IsEmpty()
387 ? GetProductIcon() 378 ? GetProductIcon()
388 : GetMaskedIcon(notification.small_image().AsImageSkia()); 379 : GetMaskedIcon(notification.small_image().AsImageSkia());
389 380 header_row_->SetAppIcon(icon);
390 small_image_view_->SetImage(icon);
391 } 381 }
392 382
393 void NotificationViewMD::CreateOrUpdateImageView( 383 void NotificationViewMD::CreateOrUpdateImageView(
394 const Notification& notification) { 384 const Notification& notification) {
395 // TODO(yoshiki): Implement this. 385 // |image_view_| is the view representing the area covered by the
386 // notification's image, including background and border. Its size can be
387 // specified in advance and images will be scaled to fit including a border if
388 // necessary.
389 if (notification.image().IsEmpty()) {
390 left_content_->RemoveChildView(image_container_);
391 image_container_ = NULL;
392 image_view_ = NULL;
393 return;
394 }
395
396 gfx::Size ideal_size(kNotificationPreferredImageWidth,
397 kNotificationPreferredImageHeight);
398
399 if (!image_container_) {
400 image_container_ = new views::View();
401 image_container_->SetLayoutManager(new views::FillLayout());
402 image_container_->SetBorder(
403 views::CreateEmptyBorder(kImageContainerPadding));
404 image_container_->SetBackground(
405 views::CreateSolidBackground(message_center::kImageBackgroundColor));
406
407 image_view_ = new message_center::ProportionalImageView(ideal_size);
408 image_container_->AddChildView(image_view_);
409 // Insert the created image container just after the |content_row_|.
410 AddChildViewAt(image_container_, GetIndexOf(content_row_) + 1);
411 }
412
413 DCHECK(image_view_);
414 image_view_->SetImage(notification.image().AsImageSkia(), ideal_size);
396 } 415 }
397 416
398 void NotificationViewMD::CreateOrUpdateActionButtonViews( 417 void NotificationViewMD::CreateOrUpdateActionButtonViews(
399 const Notification& notification) { 418 const Notification& notification) {
400 // TODO(yoshiki): Implement this. 419 std::vector<ButtonInfo> buttons = notification.buttons();
420 bool new_buttons = action_buttons_.size() != buttons.size();
421
422 if (new_buttons || buttons.size() == 0) {
423 for (auto* item : action_buttons_)
424 delete item;
425 action_buttons_.clear();
426 }
427
428 DCHECK_EQ(this, actions_row_->parent());
429
430 for (size_t i = 0; i < buttons.size(); ++i) {
431 ButtonInfo button_info = buttons[i];
432 if (new_buttons) {
433 views::LabelButton* button = new views::LabelButton(
434 this, button_info.title, views::style::CONTEXT_BUTTON_MD);
435 button->SetFocusForPlatform();
436 action_buttons_.push_back(button);
437 actions_row_->AddChildView(button);
438 } else {
439 action_buttons_[i]->SetText(button_info.title);
440 action_buttons_[i]->SchedulePaint();
441 action_buttons_[i]->Layout();
442 }
443 }
444
445 if (new_buttons) {
446 // TODO(fukino): Investigate if this Layout() is necessary.
447 Layout();
448 views::Widget* widget = GetWidget();
449 if (widget != NULL) {
450 widget->SetSize(widget->GetContentsView()->GetPreferredSize());
451 GetWidget()->SynthesizeMouseMoveEvent();
452 }
453 }
401 } 454 }
402 455
403 void NotificationViewMD::CreateOrUpdateCloseButtonView( 456 void NotificationViewMD::CreateOrUpdateCloseButtonView(
404 const Notification& notification) { 457 const Notification& notification) {
405 if (!notification.pinned() && !close_button_) { 458 if (!notification.pinned()) {
406 close_button_ = base::MakeUnique<PaddedButton>(this); 459 header_row_->SetCloseButtonEnabled(true);
407 close_button_->SetImage(views::Button::STATE_NORMAL, GetCloseIcon()); 460 } else {
408 close_button_->SetAccessibleName(l10n_util::GetStringUTF16( 461 header_row_->SetCloseButtonEnabled(false);
409 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
410 close_button_->SetTooltipText(l10n_util::GetStringUTF16(
411 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_TOOLTIP));
412 close_button_->set_owned_by_client();
413 AddChildView(close_button_.get());
414 UpdateControlButtonsVisibility();
415 } else if (notification.pinned() && close_button_) {
416 close_button_.reset();
417 } 462 }
418 } 463 }
419 464
420 void NotificationViewMD::CreateOrUpdateSettingsButtonView( 465 void NotificationViewMD::CreateOrUpdateSettingsButtonView(
421 const Notification& notification) { 466 const Notification& notification) {
422 if (!settings_button_ && notification.delegate() && 467 if (notification.delegate() &&
423 notification.delegate()->ShouldDisplaySettingsButton()) { 468 notification.delegate()->ShouldDisplaySettingsButton())
424 settings_button_ = base::MakeUnique<PaddedButton>(this); 469 header_row_->SetSettingsButtonEnabled(true);
425 settings_button_->SetImage(views::Button::STATE_NORMAL, GetSettingsIcon()); 470 else
426 settings_button_->SetAccessibleName(l10n_util::GetStringUTF16( 471 header_row_->SetSettingsButtonEnabled(false);
427 IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME)); 472 }
428 settings_button_->SetTooltipText(l10n_util::GetStringUTF16( 473
429 IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME)); 474 bool NotificationViewMD::IsExpandable() {
430 settings_button_->set_owned_by_client(); 475 // Expandable if the message exceeds one line.
431 AddChildView(settings_button_.get()); 476 if (message_view_ && message_view_->visible() &&
432 } else { 477 message_view_->GetLinesForWidthAndLimit(message_view_->width(), -1) > 1) {
433 settings_button_.reset(); 478 return true;
434 } 479 }
435 UpdateControlButtonsVisibility(); 480 // Expandable if there is at least one inline action.
481 if (actions_row_->has_children())
482 return true;
483
484 // Expandable if the notification has image.
485 if (image_view_)
486 return true;
487
488 // TODO(fukino): Expandable if both progress bar and message exist.
489
490 return false;
491 }
492
493 void NotificationViewMD::ToggleExpanded() {
494 expanded_ = !expanded_;
495 UpdateViewForExpandedState(expanded_);
496 content_row_->InvalidateLayout();
497 if (controller())
498 controller()->UpdateNotificationSize(notification_id());
499 }
500
501 void NotificationViewMD::UpdateViewForExpandedState(bool expanded) {
502 header_row_->SetExpanded(expanded);
503 if (message_view_) {
504 message_view_->SetLineLimit(expanded ? kMaxLinesForExpandedMessageView
505 : kMaxLinesForMessageView);
506 }
507 if (image_container_)
508 image_container_->SetVisible(expanded);
509 actions_row_->SetVisible(expanded && actions_row_->has_children());
436 } 510 }
437 511
438 void NotificationViewMD::UpdateControlButtonsVisibility() { 512 void NotificationViewMD::UpdateControlButtonsVisibility() {
439 const bool target_visibility = 513 const bool target_visibility = IsMouseHovered() || HasFocus() ||
440 IsMouseHovered() || HasFocus() || 514 (header_row_->IsExpandButtonEnabled() &&
441 (close_button_ && close_button_->HasFocus()) || 515 header_row_->expand_button()->HasFocus()) ||
442 (settings_button_ && settings_button_->HasFocus()); 516 (header_row_->IsCloseButtonEnabled() &&
517 header_row_->close_button()->HasFocus()) ||
518 (header_row_->IsSettingsButtonEnabled() &&
519 header_row_->settings_button()->HasFocus());
443 520
444 if (close_button_) { 521 header_row_->SetControlButtonsVisible(target_visibility);
445 if (target_visibility != close_button_->visible())
446 close_button_->SetVisible(target_visibility);
447 }
448
449 if (settings_button_) {
450 if (target_visibility != settings_button_->visible())
451 settings_button_->SetVisible(target_visibility);
452 }
453 } 522 }
454 523
455 } // namespace message_center 524 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/notification_view_md.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698