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

Side by Side Diff: ash/system/web_notification/web_notification_tray.cc

Issue 10546125: Add WebNotificationTray to the status area (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 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 | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "ash/system/web_notification/web_notification_tray.h"
6
7 #include "ash/shell.h"
8 #include "ash/system/status_area_widget.h"
9 #include "ash/system/status_area_widget.h"
10 #include "ash/system/tray/tray_bubble_view.h"
11 #include "ash/system/tray/tray_constants.h"
12 #include "ash/system/tray/tray_views.h"
13 #include "grit/ash_strings.h"
14 #include "grit/ui_resources.h"
15 #include "grit/ui_resources_standard.h"
16 #include "ui/aura/event.h"
17 #include "ui/aura/window.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/base/models/simple_menu_model.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/views/controls/button/button.h"
22 #include "ui/views/controls/button/menu_button.h"
23 #include "ui/views/controls/button/menu_button_listener.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/controls/menu/menu_model_adapter.h"
26 #include "ui/views/controls/menu/menu_runner.h"
27 #include "ui/views/layout/box_layout.h"
28 #include "ui/views/layout/fill_layout.h"
29 #include "ui/views/layout/grid_layout.h"
30 #include "ui/views/painter.h"
31
32 namespace {
33
34 const int kTrayBorder = 4;
35 const int kNotificationIconWidth = 40;
36 const int kNotificationIconHeight = 25;
37 const int kWebNotificationBubbleMinHeight = 80;
38 const int kWebNotificationBubbleMaxHeight = 400;
39 const int kWebNotificationWidth = 400;
40 const int kWebNotificationButtonWidth = 32;
41
42 const int kTogglePermissionCommand = 0;
43 const int kToggleExtensionCommand = 1;
44 const int kShowSettingsCommand = 2;
45
46 // The image has three icons: 1 notifiaction, 2 notifications, and 3+.
47 SkBitmap GetNotificationImage(int notification_count) {
48 SkBitmap image;
49 gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
50 IDR_AURA_UBER_TRAY_WEB_NOTIFICATON);
51 int image_index = notification_count - 1;
52 image_index = std::max(0, std::min(image_index, 2));
53 SkIRect region = SkIRect::MakeXYWH(
54 0, image_index * kNotificationIconHeight,
55 kNotificationIconWidth, kNotificationIconHeight);
56 all.ToSkBitmap()->extractSubset(&image, region);
57 return image;
58 }
59
60 } // namespace
61
62 namespace ash {
63
64 namespace internal {
65
66 struct WebNotification {
67 WebNotification(const std::string& i,
68 const string16& t,
69 const string16& m,
70 const string16& s,
71 const std::string& e)
72 : id(i),
73 title(t),
74 message(m),
75 display_source(s),
76 extension_id(e) {
77 }
78
79 std::string id;
80 string16 title;
81 string16 message;
82 string16 display_source;
83 std::string extension_id;
84 gfx::ImageSkia image;
85 };
86
87 // A helper class to manage the list of notifications.
88 class WebNotificationList {
89 public:
90 typedef std::list<WebNotification> Notifications;
91
92 WebNotificationList() {
93 }
94
95 void AddNotification(const std::string& id,
96 const string16& title,
97 const string16& message,
98 const string16& source,
99 const std::string& extension) {
100 Notifications::iterator iter = GetNotification(id);
101 if (iter != notifications_.end()) {
102 // Update existing notification.
103 iter->title = title;
104 iter->message = message;
105 iter->display_source = source;
106 iter->extension_id = extension;
107 } else {
108 notifications_.push_back(
109 WebNotification(id, title, message, source, extension));
110 }
111 }
112
113 void UpdateNotificationMessage(const std::string& id,
114 const string16& title,
115 const string16& message) {
116 Notifications::iterator iter = GetNotification(id);
117 if (iter == notifications_.end())
118 return;
119 iter->title = title;
120 iter->message = message;
121 }
122
123 bool RemoveNotification(const std::string& id) {
124 Notifications::iterator iter = GetNotification(id);
125 if (iter == notifications_.end())
126 return false;
127 notifications_.erase(iter);
128 return true;
129 }
130
131 void RemoveAllNotifications() {
132 notifications_.clear();
133 }
134
135 void RemoveNotificationsBySource(const std::string& id) {
136 Notifications::iterator source_iter = GetNotification(id);
137 if (source_iter == notifications_.end())
138 return;
139 string16 display_source = source_iter->display_source;
140 for (Notifications::iterator loopiter = notifications_.begin();
141 loopiter != notifications_.end(); ) {
142 Notifications::iterator curiter = loopiter++;
143 if (curiter->display_source == display_source)
144 notifications_.erase(curiter);
145 }
146 }
147
148 void RemoveNotificationsByExtension(const std::string& id) {
149 Notifications::iterator source_iter = GetNotification(id);
150 if (source_iter == notifications_.end())
151 return;
152 std::string extension_id = source_iter->extension_id;
153 for (Notifications::iterator loopiter = notifications_.begin();
154 loopiter != notifications_.end(); ) {
155 Notifications::iterator curiter = loopiter++;
156 if (curiter->extension_id == extension_id)
157 notifications_.erase(curiter);
158 }
159 }
160
161 bool SetNotificationImage(const std::string& id,
162 const gfx::ImageSkia& image) {
163 Notifications::iterator iter = GetNotification(id);
164 if (iter == notifications_.end())
165 return false;
166 iter->image = image;
167 return true;
168 }
169
170 const Notifications& notifications() const { return notifications_; }
171
172 private:
173 Notifications::iterator GetNotification(const std::string& id) {
174 for (Notifications::iterator iter = notifications_.begin();
175 iter != notifications_.end(); ++iter) {
176 if (iter->id == id)
177 return iter;
178 }
179 return notifications_.end();
180 }
181
182 Notifications notifications_;
183
184 DISALLOW_COPY_AND_ASSIGN(WebNotificationList);
185 };
186
187 // A simple view for the text (title and message) of a notification.
188 class WebNotificationMessageView : public views::View {
189 public:
190 explicit WebNotificationMessageView(const WebNotification& notification) {
191 views::Label* title = new views::Label(notification.title);
192 title->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
193 title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD));
194 views::Label* message = new views::Label(notification.message);
195 message->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
196 message->SetMultiLine(true);
197
198 SetLayoutManager(
199 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
200 AddChildView(title);
201 AddChildView(message);
202 }
203
204 virtual ~WebNotificationMessageView() {
205 }
206
207 private:
208 DISALLOW_COPY_AND_ASSIGN(WebNotificationMessageView);
209 };
210
211 // A dropdown menu for notifications.
212 class WebNotificationMenuModel : public ui::SimpleMenuModel,
213 public ui::SimpleMenuModel::Delegate {
214 public:
215 explicit WebNotificationMenuModel(WebNotificationTray* tray,
216 const WebNotification& notification)
217 : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)),
218 tray_(tray),
219 notification_(notification) {
220 // Add 'disable notifications' menu item.
221 if (!notification.extension_id.empty()) {
222 AddItem(kToggleExtensionCommand,
223 GetLabelForCommandId(kToggleExtensionCommand));
224 } else if (!notification.display_source.empty()) {
225 AddItem(kTogglePermissionCommand,
226 GetLabelForCommandId(kTogglePermissionCommand));
227 }
228 // Add settings menu item.
229 if (!notification.display_source.empty()) {
230 AddItem(kShowSettingsCommand,
231 GetLabelForCommandId(kShowSettingsCommand));
232 }
233 }
234
235 virtual ~WebNotificationMenuModel() {
236 }
237
238 // Overridden from ui::SimpleMenuModel:
239 virtual string16 GetLabelForCommandId(int command_id) const OVERRIDE {
240 switch (command_id) {
241 case kToggleExtensionCommand:
242 return l10n_util::GetStringUTF16(
243 IDS_ASH_WEB_NOTFICATION_TRAY_EXTENSIONS_DISABLE);
244 case kTogglePermissionCommand:
245 return l10n_util::GetStringFUTF16(
246 IDS_ASH_WEB_NOTFICATION_TRAY_SITE_DISABLE,
247 notification_.display_source);
248 case kShowSettingsCommand:
249 return l10n_util::GetStringUTF16(
250 IDS_ASH_WEB_NOTFICATION_TRAY_SETTINGS);
251 default:
252 NOTREACHED();
253 }
254 return string16();
255 }
256
257 // Overridden from ui::SimpleMenuModel::Delegate:
258 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE {
259 return false;
260 }
261
262 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
263 return true;
264 }
265
266 virtual bool GetAcceleratorForCommandId(
267 int command_id,
268 ui::Accelerator* accelerator) OVERRIDE {
269 return false;
270 }
271
272 virtual void ExecuteCommand(int command_id) OVERRIDE {
273 switch (command_id) {
274 case kToggleExtensionCommand:
275 tray_->DisableByExtension(notification_.id);
276 break;
277 case kTogglePermissionCommand:
278 tray_->DisableByUrl(notification_.id);
279 break;
280 case kShowSettingsCommand:
281 tray_->ShowSettings(notification_.id);
282 break;
283 default:
284 NOTREACHED();
285 }
286 }
287
288 private:
289 WebNotificationTray* tray_;
290 WebNotification notification_;
291
292 DISALLOW_COPY_AND_ASSIGN(WebNotificationMenuModel);
293 };
294
295 // The view for a notification entry (icon + message + buttons).
296 class WebNotificationView : public views::View,
297 public views::ButtonListener,
298 public views::MenuButtonListener {
299 public:
300 WebNotificationView(WebNotificationTray* tray,
301 const WebNotification& notification)
302 : tray_(tray),
303 notification_(notification),
304 icon_(NULL),
305 menu_button_(NULL),
306 close_button_(NULL) {
307 InitView(tray, notification);
308 }
309
310 virtual ~WebNotificationView() {
311 }
312
313 void InitView(WebNotificationTray* tray,
314 const WebNotification& notification) {
315 set_border(views::Border::CreateSolidSidedBorder(
316 1, 0, 0, 0, kBorderLightColor));
317 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
318
319 icon_ = new views::ImageView;
320 icon_->SetImage(notification.image);
321
322 WebNotificationMessageView* message_view
323 = new WebNotificationMessageView(notification);
324
325 close_button_ = new views::ImageButton(this);
326 close_button_->SetImage(
327 views::CustomButton::BS_NORMAL,
328 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
329 IDR_AURA_WINDOW_CLOSE));
330
331 if (!notification.extension_id.empty() ||
332 !notification.display_source.empty()) {
333 menu_button_ = new views::MenuButton(NULL, string16(), this, true);
334 menu_button_->set_border(NULL);
335 }
336
337 views::GridLayout* layout = new views::GridLayout(this);
338 SetLayoutManager(layout);
339
340 views::ColumnSet* columns = layout->AddColumnSet(0);
341
342 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2);
343
344 // Notification Icon.
345 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
346 0, /* resize percent */
347 views::GridLayout::FIXED,
348 kNotificationIconWidth, kNotificationIconWidth);
349
350 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2);
351
352 // Notification message text.
353 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
354 100, /* resize percent */
355 views::GridLayout::USE_PREF, 0, 0);
356
357 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2);
358
359 // Close and menu buttons.
360 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
361 0, /* resize percent */
362 views::GridLayout::FIXED,
363 kWebNotificationButtonWidth,
364 kWebNotificationButtonWidth);
365
366 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2);
367
368 // Layout rows
369 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
370
371 layout->StartRow(0, 0);
372 layout->AddView(icon_, 1, 2);
373 layout->AddView(message_view, 1, 2);
374 layout->AddView(close_button_);
375
376 layout->StartRow(0, 0);
377 if (menu_button_) {
378 layout->SkipColumns(4);
379 layout->AddView(menu_button_);
380 }
381 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
382 }
383
384 // view::Views overrodes.
385 virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE {
386 tray_->OnClicked(notification_.id);
387 return true;
388 }
389
390 // Overridden from ButtonListener.
391 virtual void ButtonPressed(views::Button* sender,
392 const views::Event& event) OVERRIDE {
393 if (sender == close_button_)
394 tray_->RemoveNotification(notification_.id);
395 }
396
397 // Overridden from MenuButtonListener.
398 virtual void OnMenuButtonClicked(View* source, const gfx::Point& point) {
sadrul 2012/06/13 16:37:56 OVERRIDE
stevenjb 2012/06/13 19:05:02 Done.
399 if (source != menu_button_)
400 return;
401 WebNotificationMenuModel menu_model(tray_, notification_);
402 views::MenuModelAdapter menu_model_adapter(&menu_model);
403 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu());
404
405 gfx::Point screen_location;
406 views::View::ConvertPointToScreen(menu_button_, &screen_location);
407 ignore_result(menu_runner.RunMenuAt(
408 source->GetWidget()->GetTopLevelWidget(),
409 menu_button_,
410 gfx::Rect(screen_location, menu_button_->size()),
411 views::MenuItemView::TOPRIGHT,
412 views::MenuRunner::HAS_MNEMONICS));
413 }
414
415 private:
416 WebNotificationTray* tray_;
417 WebNotification notification_;
418 views::ImageView* icon_;
419 views::MenuButton* menu_button_;
420 views::ImageButton* close_button_;
421
422 DISALLOW_COPY_AND_ASSIGN(WebNotificationView);
423 };
424
425 // The view for the buttons at the bottom of the web notification tray.
426 class WebNotificationButtonView : public TrayPopupTextButtonContainer,
427 public views::ButtonListener {
428 public:
429 explicit WebNotificationButtonView(WebNotificationTray* tray)
430 : tray_(tray),
431 settings_button_(NULL),
432 close_all_button_(NULL) {
433 set_background(views::Background::CreateBackgroundPainter(
434 true,
435 views::Painter::CreateVerticalGradient(
436 kHeaderBackgroundColorLight,
437 kHeaderBackgroundColorDark)));
438 set_border(views::Border::CreateSolidSidedBorder(
439 2, 0, 0, 0, ash::kBorderDarkColor));
440
441 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
442 settings_button_ = new TrayPopupTextButton(
443 this, rb.GetLocalizedString(IDS_ASH_WEB_NOTFICATION_TRAY_SETTINGS));
444 AddTextButton(settings_button_);
445
446 close_all_button_ = new TrayPopupTextButton(
447 this, rb.GetLocalizedString(IDS_ASH_WEB_NOTFICATION_TRAY_CLOSE_ALL));
448 AddTextButton(close_all_button_);
449 }
450
451 virtual ~WebNotificationButtonView() {
452 }
453
454 // Overridden from ButtonListener.
455 virtual void ButtonPressed(views::Button* sender,
456 const views::Event& event) OVERRIDE {
457 if (sender == settings_button_)
458 tray_->ShowSettings("");
459 else if (sender == close_all_button_)
460 tray_->RemoveAllNotifications();
461 }
462
463 private:
464 WebNotificationTray* tray_;
465 TrayPopupTextButton* settings_button_;
466 TrayPopupTextButton* close_all_button_;
sadrul 2012/06/13 16:37:56 DISALLOW_COPY...
stevenjb 2012/06/13 19:05:02 Done.
467 };
468
469 } // namespace internal
470
471 using internal::WebNotificationList;
472 using internal::WebNotificationView;
473
474 class WebNotificationTray::BubbleContentsView : public views::View {
475 public:
476 explicit BubbleContentsView(WebNotificationTray* tray)
477 : tray_(tray) {
478 SetLayoutManager(
479 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
480 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
481
482 scroll_content_ = new views::View;
483 scroll_content_->SetLayoutManager(
484 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
485 scroller_ = new internal::FixedSizedScrollView;
486 scroller_->SetContentsView(scroll_content_);
487 AddChildView(scroller_);
488
489 button_view_ = new internal::WebNotificationButtonView(tray);
490 AddChildView(button_view_);
491 }
492
493 void Update(const WebNotificationList::Notifications& notifications) {
494 scroll_content_->RemoveAllChildViews(true);
495 for (WebNotificationList::Notifications::const_iterator iter =
496 notifications.begin(); iter != notifications.end(); ++iter) {
497 WebNotificationView* view = new WebNotificationView(tray_, *iter);
498 scroll_content_->AddChildView(view);
499 }
500 SizeScrollContent();
501 scroller_->Layout();
502 Layout();
503 PreferredSizeChanged();
504 SchedulePaint();
505 }
506
507 private:
508 void SizeScrollContent() {
509 gfx::Size scroll_size = scroll_content_->GetPreferredSize();
510 int button_height = button_view_->GetPreferredSize().height();
511 int scroll_height = std::min(
512 std::max(scroll_size.height(),
513 kWebNotificationBubbleMinHeight - button_height),
514 kWebNotificationBubbleMaxHeight - button_height);
515 scroll_size.set_height(scroll_height);
516 scroller_->set_fixed_size(scroll_size);
517 }
518
519 WebNotificationTray* tray_;
520 internal::FixedSizedScrollView* scroller_;
521 views::View* scroll_content_;
522 internal::WebNotificationButtonView* button_view_;
523
524 DISALLOW_COPY_AND_ASSIGN(BubbleContentsView);
525 };
526
527 class WebNotificationTray::Bubble : public internal::TrayBubbleView::Host {
528 public:
529 explicit Bubble(WebNotificationTray* tray) : tray_(tray),
sadrul 2012/06/13 16:37:56 Perhaps move these in the next line to match with
stevenjb 2012/06/13 19:05:02 Done.
530 bubble_view_(NULL),
531 bubble_widget_(NULL),
532 contents_view_(NULL) {
533 views::View* anchor = tray->tray_container();
534 views::BubbleBorder::ArrowLocation arrow_location;
535 int arrow_offset = 0;
536 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
537 arrow_location = views::BubbleBorder::BOTTOM_RIGHT;
538 arrow_offset = anchor->GetContentsBounds().width() / 2;
539 } else if (tray_->shelf_alignment() == SHELF_ALIGNMENT_LEFT) {
540 arrow_location = views::BubbleBorder::LEFT_BOTTOM;
541 } else {
542 arrow_location = views::BubbleBorder::RIGHT_BOTTOM;
543 }
544 bubble_view_ = new internal::TrayBubbleView(
545 anchor, arrow_location, this, false, kWebNotificationWidth);
546 bubble_view_->SetMaxHeight(kWebNotificationBubbleMaxHeight);
547
548 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_);
sadrul 2012/06/13 16:37:56 Do you need to unset bubble_widget_ when the widge
stevenjb 2012/06/13 19:05:02 Yes... I'm not sure how that might happen, but we
549
550 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
551 bubble_widget_->non_client_view()->frame_view()->set_background(NULL);
552 bubble_view_->SetBubbleBorder(arrow_offset);
553
554 contents_view_ = new BubbleContentsView(tray);
555 bubble_view_->AddChildView(contents_view_);
556
557 Update();
558 bubble_view_->Show();
559 }
560
561 virtual ~Bubble() {
562 if (bubble_view_)
563 bubble_view_->reset_host();
564 if (bubble_widget_)
565 bubble_widget_->Close();
566 }
567
568 // Overridden from TrayBubbleView::Host.
569 virtual void BubbleViewDestroyed() OVERRIDE {
570 }
571
572 virtual gfx::Rect GetAnchorRect() const OVERRIDE {
573 gfx::Rect anchor_rect = tray_->tray_container()->GetScreenBounds();
574 return anchor_rect;
575 }
576
577 virtual void OnMouseEnteredView() OVERRIDE {
578 }
579
580 virtual void OnMouseExitedView() OVERRIDE {
581 }
582
583 void Update() {
sadrul 2012/06/13 16:37:56 Move these two functions before the overridden met
stevenjb 2012/06/13 19:05:02 Done.
584 contents_view_->Update(tray_->notification_list()->notifications());
585 bubble_view_->Layout();
586 bubble_view_->SchedulePaint();
587 }
588
589 views::Widget* bubble_widget() const { return bubble_widget_; }
590
591 private:
592 WebNotificationTray* tray_;
593 internal::TrayBubbleView* bubble_view_;
594 views::Widget* bubble_widget_;
595 BubbleContentsView* contents_view_;
sadrul 2012/06/13 16:37:56 DISALLOW_COPY_..
stevenjb 2012/06/13 19:05:02 Done.
596 };
597
598 WebNotificationTray::WebNotificationTray(
599 internal::StatusAreaWidget* status_area_widget)
600 : status_area_widget_(status_area_widget),
601 notification_list_(new WebNotificationList()),
602 tray_container_(NULL),
603 icon_(NULL),
604 delegate_(NULL) {
605 tray_container_ = new views::View;
606 tray_container_->set_border(views::Border::CreateEmptyBorder(
607 kTrayBorder, kTrayBorder, kTrayBorder, kTrayBorder));
608 SetShelfAlignment(shelf_alignment());
609
610 icon_ = new views::ImageView;
611 tray_container_->AddChildView(icon_);
612 UpdateIcon(); // Hides the tray initially.
613
614 SetContents(tray_container_);
615
616 Shell::GetInstance()->AddEnvEventFilter(this);
sadrul 2012/06/13 16:37:56 The event-filtering stuff is very similar to the s
stevenjb 2012/06/13 19:05:02 Agreed.
617 }
618
619 WebNotificationTray::~WebNotificationTray() {
620 Shell::GetInstance()->RemoveEnvEventFilter(this);
621 }
622
623 void WebNotificationTray::SetDelegate(Delegate* delegate) {
624 DCHECK(!delegate_);
625 delegate_ = delegate;
626 }
627
628 void WebNotificationTray::AddNotification(const std::string& id,
629 const string16& title,
630 const string16& message,
631 const string16& source,
632 const std::string& extension) {
633 notification_list_->AddNotification(id, title, message, source, extension);
634 UpdateIcon();
635 if (bubble()) {
636 bubble_->Update();
637 } else {
638 status_area_widget_->ShowWebNotificationBubble(
639 internal::StatusAreaWidget::NON_USER_ACTION);
640 }
641 }
642
643 void WebNotificationTray::UpdateNotification(const std::string& id,
644 const string16& title,
645 const string16& message) {
646 notification_list_->UpdateNotificationMessage(id, title, message);
647 if (bubble())
648 bubble_->Update();
649 }
650
651 void WebNotificationTray::RemoveNotification(const std::string& id) {
652 if (!notification_list_->RemoveNotification(id))
653 return;
654 if (delegate_)
655 delegate_->NotificationRemoved(id);
656 UpdateBubbleAndIcon();
657 }
658
659 void WebNotificationTray::RemoveAllNotifications() {
660 const WebNotificationList::Notifications& notifications =
661 notification_list_->notifications();
662 if (delegate_) {
663 for (WebNotificationList::Notifications::const_iterator loopiter
sadrul 2012/06/13 16:37:56 perhaps move 'loopiter' in the next line
stevenjb 2012/06/13 19:05:02 Moved the = instead to be more consistent with mul
664 = notifications.begin(); loopiter != notifications.end();) {
665 WebNotificationList::Notifications::const_iterator curiter = loopiter++;
666 std::string notification_id = curiter->id;
667 // May call RemoveNotification and erase curiter.
668 delegate_->NotificationRemoved(notification_id);
669 }
670 }
671 notification_list_->RemoveAllNotifications();
672 UpdateBubbleAndIcon();
673 }
674
675 void WebNotificationTray::SetNotificationImage(const std::string& id,
676 const gfx::ImageSkia& image) {
677 if (!notification_list_->SetNotificationImage(id, image))
678 return;
679 if (bubble())
680 bubble_->Update();
681 }
682
683 void WebNotificationTray::DisableByExtension(const std::string& id) {
684 // When we disable notifications, we remove any existing matching
685 // notifications to avoid adding complicated UI to re-enable the source.
686 notification_list_->RemoveNotificationsByExtension(id);
687 UpdateBubbleAndIcon();
688 if (delegate_)
689 delegate_->DisableExtension(id);
690 }
691
692 void WebNotificationTray::DisableByUrl(const std::string& id) {
693 // See comment for DisableByExtension.
694 notification_list_->RemoveNotificationsBySource(id);
695 UpdateBubbleAndIcon();
696 if (delegate_)
697 delegate_->DisableNotificationsFromSource(id);
698 }
699
700 void WebNotificationTray::ShowBubble() {
701 if (bubble())
702 return;
703 bubble_.reset(new Bubble(this));
704 }
705
706 void WebNotificationTray::HideBubble() {
707 bubble_.reset();
708 }
709
710 void WebNotificationTray::ShowSettings(const std::string& id) {
711 if (delegate_)
712 delegate_->ShowSettings(id);
713 }
714
715 void WebNotificationTray::OnClicked(const std::string& id) {
716 if (delegate_)
717 delegate_->OnClicked(id);
718 }
719
720 bool WebNotificationTray::PreHandleKeyEvent(aura::Window* target,
721 aura::KeyEvent* event) {
sadrul 2012/06/13 16:37:56 indent is off (and in lines 726, 733)
stevenjb 2012/06/13 19:05:02 Done.
722 return false;
723 }
724
725 bool WebNotificationTray::PreHandleMouseEvent(aura::Window* target,
726 aura::MouseEvent* event) {
727 if (event->type() == ui::ET_MOUSE_PRESSED)
728 return ProcessLocatedEvent(*event);
729 return false;
730 }
731
732 ui::TouchStatus WebNotificationTray::PreHandleTouchEvent(aura::Window* target,
733 aura::TouchEvent* event) {
734 if (event->type() != ui::ET_TOUCH_PRESSED)
735 return ui::TOUCH_STATUS_UNKNOWN;
736 if (ProcessLocatedEvent(*event))
737 return ui::TOUCH_STATUS_END;
738 return ui::TOUCH_STATUS_UNKNOWN;
739 }
740
741 ui::GestureStatus WebNotificationTray::PreHandleGestureEvent(
742 aura::Window* target,
743 aura::GestureEvent* event) {
744 return ui::GESTURE_STATUS_UNKNOWN;
745 }
746
747 void WebNotificationTray::SetShelfAlignment(ShelfAlignment alignment) {
748 internal::TrayBackgroundView::SetShelfAlignment(alignment);
749 tray_container_->SetLayoutManager(new views::BoxLayout(
750 alignment == SHELF_ALIGNMENT_BOTTOM ?
751 views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
752 0, 0, 0));
753 }
754
755 bool WebNotificationTray::PerformAction(const views::Event& event) {
756 if (bubble()) {
757 status_area_widget_->HideWebNotificationBubble();
758 } else {
759 status_area_widget_->ShowWebNotificationBubble(
760 internal::StatusAreaWidget::USER_ACTION);
761 }
762 return true;
763 }
764
765 int WebNotificationTray::GetNotificationCount() const {
766 return notification_list()->notifications().size();
767 }
768
769 void WebNotificationTray::UpdateIcon() {
770 int count = GetNotificationCount();
771 if (count == 0) {
772 SetVisible(false);
773 } else {
774 icon_->SetImage(gfx::ImageSkia(GetNotificationImage(count)));
775 SetVisible(true);
776 }
777 PreferredSizeChanged();
778 }
779
780 void WebNotificationTray::UpdateBubbleAndIcon() {
781 UpdateIcon();
782 if (!bubble())
783 return;
784 if (GetNotificationCount() == 0)
785 status_area_widget_->HideWebNotificationBubble();
786 else
787 bubble_->Update();
788 }
789
790 bool WebNotificationTray::ProcessLocatedEvent(const aura::LocatedEvent& event) {
791 if (!bubble())
792 return false;
793 gfx::Rect bounds =
794 bubble_->bubble_widget()->GetNativeWindow()->GetBoundsInRootWindow();
795 if (bounds.Contains(event.root_location()))
796 return false;
797 status_area_widget_->HideWebNotificationBubble();
798 // If the event occurred in the tray widget, don't process the click.
799 bounds = GetWidget()->GetNativeWindow()->GetBoundsInRootWindow();
800 if (bounds.Contains(event.root_location()))
801 return true;
802 return false;
803 }
804
805 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698