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

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: Make WebNotificationTray::Bubble a Widget::Observer; address nits 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& display_source,
99 const std::string& extension_id) {
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 = display_source;
106 iter->extension_id = extension_id;
107 } else {
108 notifications_.push_back(
109 WebNotification(id, title, message, display_source, extension_id));
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(
399 View* source, const gfx::Point& point) OVERRIDE {
400 if (source != menu_button_)
401 return;
402 WebNotificationMenuModel menu_model(tray_, notification_);
403 views::MenuModelAdapter menu_model_adapter(&menu_model);
404 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu());
405
406 gfx::Point screen_location;
407 views::View::ConvertPointToScreen(menu_button_, &screen_location);
408 ignore_result(menu_runner.RunMenuAt(
409 source->GetWidget()->GetTopLevelWidget(),
410 menu_button_,
411 gfx::Rect(screen_location, menu_button_->size()),
412 views::MenuItemView::TOPRIGHT,
413 views::MenuRunner::HAS_MNEMONICS));
414 }
415
416 private:
417 WebNotificationTray* tray_;
418 WebNotification notification_;
419 views::ImageView* icon_;
420 views::MenuButton* menu_button_;
421 views::ImageButton* close_button_;
422
423 DISALLOW_COPY_AND_ASSIGN(WebNotificationView);
424 };
425
426 // The view for the buttons at the bottom of the web notification tray.
427 class WebNotificationButtonView : public TrayPopupTextButtonContainer,
428 public views::ButtonListener {
429 public:
430 explicit WebNotificationButtonView(WebNotificationTray* tray)
431 : tray_(tray),
432 settings_button_(NULL),
433 close_all_button_(NULL) {
434 set_background(views::Background::CreateBackgroundPainter(
435 true,
436 views::Painter::CreateVerticalGradient(
437 kHeaderBackgroundColorLight,
438 kHeaderBackgroundColorDark)));
439 set_border(views::Border::CreateSolidSidedBorder(
440 2, 0, 0, 0, ash::kBorderDarkColor));
441
442 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
443 settings_button_ = new TrayPopupTextButton(
444 this, rb.GetLocalizedString(IDS_ASH_WEB_NOTFICATION_TRAY_SETTINGS));
445 AddTextButton(settings_button_);
446
447 close_all_button_ = new TrayPopupTextButton(
448 this, rb.GetLocalizedString(IDS_ASH_WEB_NOTFICATION_TRAY_CLOSE_ALL));
449 AddTextButton(close_all_button_);
450 }
451
452 virtual ~WebNotificationButtonView() {
453 }
454
455 // Overridden from ButtonListener.
456 virtual void ButtonPressed(views::Button* sender,
457 const views::Event& event) OVERRIDE {
458 if (sender == settings_button_)
459 tray_->ShowSettings("");
460 else if (sender == close_all_button_)
461 tray_->RemoveAllNotifications();
462 }
463
464 private:
465 WebNotificationTray* tray_;
466 TrayPopupTextButton* settings_button_;
467 TrayPopupTextButton* close_all_button_;
468
469 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView);
470 };
471
472 } // namespace internal
473
474 using internal::WebNotificationList;
475 using internal::WebNotificationView;
476
477 class WebNotificationTray::BubbleContentsView : public views::View {
478 public:
479 explicit BubbleContentsView(WebNotificationTray* tray)
480 : tray_(tray) {
481 SetLayoutManager(
482 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
483 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
484
485 scroll_content_ = new views::View;
486 scroll_content_->SetLayoutManager(
487 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
488 scroller_ = new internal::FixedSizedScrollView;
489 scroller_->SetContentsView(scroll_content_);
490 AddChildView(scroller_);
491
492 button_view_ = new internal::WebNotificationButtonView(tray);
493 AddChildView(button_view_);
494 }
495
496 void Update(const WebNotificationList::Notifications& notifications) {
497 scroll_content_->RemoveAllChildViews(true);
498 for (WebNotificationList::Notifications::const_iterator iter =
499 notifications.begin(); iter != notifications.end(); ++iter) {
500 WebNotificationView* view = new WebNotificationView(tray_, *iter);
501 scroll_content_->AddChildView(view);
502 }
503 SizeScrollContent();
504 scroller_->Layout();
505 Layout();
506 PreferredSizeChanged();
507 SchedulePaint();
508 }
509
510 private:
511 void SizeScrollContent() {
512 gfx::Size scroll_size = scroll_content_->GetPreferredSize();
513 int button_height = button_view_->GetPreferredSize().height();
514 int scroll_height = std::min(
515 std::max(scroll_size.height(),
516 kWebNotificationBubbleMinHeight - button_height),
517 kWebNotificationBubbleMaxHeight - button_height);
518 scroll_size.set_height(scroll_height);
519 scroller_->set_fixed_size(scroll_size);
520 }
521
522 WebNotificationTray* tray_;
523 internal::FixedSizedScrollView* scroller_;
524 views::View* scroll_content_;
525 internal::WebNotificationButtonView* button_view_;
526
527 DISALLOW_COPY_AND_ASSIGN(BubbleContentsView);
528 };
529
530 class WebNotificationTray::Bubble : public internal::TrayBubbleView::Host,
531 public views::Widget::Observer {
532 public:
533 explicit Bubble(WebNotificationTray* tray)
534 : tray_(tray),
535 bubble_view_(NULL),
536 bubble_widget_(NULL),
537 contents_view_(NULL) {
538 views::View* anchor = tray->tray_container();
539 views::BubbleBorder::ArrowLocation arrow_location;
540 int arrow_offset = 0;
541 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
542 arrow_location = views::BubbleBorder::BOTTOM_RIGHT;
543 arrow_offset = anchor->GetContentsBounds().width() / 2;
544 } else if (tray_->shelf_alignment() == SHELF_ALIGNMENT_LEFT) {
545 arrow_location = views::BubbleBorder::LEFT_BOTTOM;
546 } else {
547 arrow_location = views::BubbleBorder::RIGHT_BOTTOM;
548 }
549 bubble_view_ = new internal::TrayBubbleView(
550 anchor, arrow_location, this, false, kWebNotificationWidth);
551 bubble_view_->SetMaxHeight(kWebNotificationBubbleMaxHeight);
552
553 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_);
554
555 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
556 bubble_widget_->non_client_view()->frame_view()->set_background(NULL);
557 bubble_view_->SetBubbleBorder(arrow_offset);
558
559 bubble_widget_->AddObserver(this);
560
561 contents_view_ = new BubbleContentsView(tray);
562 bubble_view_->AddChildView(contents_view_);
563
564 Update();
565 bubble_view_->Show();
566 }
567
568 virtual ~Bubble() {
569 if (bubble_view_)
570 bubble_view_->reset_host();
571 if (bubble_widget_) {
572 bubble_widget_->RemoveObserver(this);
573 bubble_widget_->Close();
574 }
575 }
576
577 void Update() {
578 contents_view_->Update(tray_->notification_list()->notifications());
579 bubble_view_->Layout();
580 bubble_view_->SchedulePaint();
581 }
582
583 views::Widget* bubble_widget() const { return bubble_widget_; }
584
585 // Overridden from TrayBubbleView::Host.
586 virtual void BubbleViewDestroyed() OVERRIDE {
587 bubble_view_ = NULL;
588 contents_view_ = NULL;
589 }
590
591 virtual gfx::Rect GetAnchorRect() const OVERRIDE {
592 gfx::Rect anchor_rect = tray_->tray_container()->GetScreenBounds();
593 return anchor_rect;
594 }
595
596 virtual void OnMouseEnteredView() OVERRIDE {
597 }
598
599 virtual void OnMouseExitedView() OVERRIDE {
600 }
601
602 // Overridden from views::Widget::Observer.
603 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE {
stevenjb 2012/06/13 19:05:02 Added this.
604 CHECK_EQ(bubble_widget_, widget);
605 bubble_widget_ = NULL;
606 tray_->HideBubble(); // Will destroy |this|.
607 }
608
609 private:
610 WebNotificationTray* tray_;
611 internal::TrayBubbleView* bubble_view_;
612 views::Widget* bubble_widget_;
613 BubbleContentsView* contents_view_;
614
615 DISALLOW_COPY_AND_ASSIGN(Bubble);
616 };
617
618 WebNotificationTray::WebNotificationTray(
619 internal::StatusAreaWidget* status_area_widget)
620 : status_area_widget_(status_area_widget),
621 notification_list_(new WebNotificationList()),
622 tray_container_(NULL),
623 icon_(NULL),
624 delegate_(NULL) {
625 tray_container_ = new views::View;
626 tray_container_->set_border(views::Border::CreateEmptyBorder(
627 kTrayBorder, kTrayBorder, kTrayBorder, kTrayBorder));
628 SetShelfAlignment(shelf_alignment());
629
630 icon_ = new views::ImageView;
631 tray_container_->AddChildView(icon_);
632 UpdateIcon(); // Hides the tray initially.
633
634 SetContents(tray_container_);
635
636 Shell::GetInstance()->AddEnvEventFilter(this);
637 }
638
639 WebNotificationTray::~WebNotificationTray() {
640 Shell::GetInstance()->RemoveEnvEventFilter(this);
641 }
642
643 void WebNotificationTray::SetDelegate(Delegate* delegate) {
644 DCHECK(!delegate_);
645 delegate_ = delegate;
646 }
647
648 void WebNotificationTray::AddNotification(const std::string& id,
649 const string16& title,
650 const string16& message,
651 const string16& display_source,
652 const std::string& extension_id) {
653 notification_list_->AddNotification(
654 id, title, message, display_source, extension_id);
655 UpdateIcon();
656 if (bubble()) {
657 bubble_->Update();
658 } else {
659 status_area_widget_->ShowWebNotificationBubble(
660 internal::StatusAreaWidget::NON_USER_ACTION);
661 }
662 }
663
664 void WebNotificationTray::UpdateNotification(const std::string& id,
665 const string16& title,
666 const string16& message) {
667 notification_list_->UpdateNotificationMessage(id, title, message);
668 if (bubble())
669 bubble_->Update();
670 }
671
672 void WebNotificationTray::RemoveNotification(const std::string& id) {
673 if (!notification_list_->RemoveNotification(id))
674 return;
675 if (delegate_)
676 delegate_->NotificationRemoved(id);
677 UpdateBubbleAndIcon();
678 }
679
680 void WebNotificationTray::RemoveAllNotifications() {
681 const WebNotificationList::Notifications& notifications =
682 notification_list_->notifications();
683 if (delegate_) {
684 for (WebNotificationList::Notifications::const_iterator loopiter =
685 notifications.begin();
686 loopiter != notifications.end(); ) {
687 WebNotificationList::Notifications::const_iterator curiter = loopiter++;
688 std::string notification_id = curiter->id;
689 // May call RemoveNotification and erase curiter.
690 delegate_->NotificationRemoved(notification_id);
691 }
692 }
693 notification_list_->RemoveAllNotifications();
694 UpdateBubbleAndIcon();
695 }
696
697 void WebNotificationTray::SetNotificationImage(const std::string& id,
698 const gfx::ImageSkia& image) {
699 if (!notification_list_->SetNotificationImage(id, image))
700 return;
701 if (bubble())
702 bubble_->Update();
703 }
704
705 void WebNotificationTray::DisableByExtension(const std::string& id) {
706 // When we disable notifications, we remove any existing matching
707 // notifications to avoid adding complicated UI to re-enable the source.
708 notification_list_->RemoveNotificationsByExtension(id);
709 UpdateBubbleAndIcon();
710 if (delegate_)
711 delegate_->DisableExtension(id);
712 }
713
714 void WebNotificationTray::DisableByUrl(const std::string& id) {
715 // See comment for DisableByExtension.
716 notification_list_->RemoveNotificationsBySource(id);
717 UpdateBubbleAndIcon();
718 if (delegate_)
719 delegate_->DisableNotificationsFromSource(id);
720 }
721
722 void WebNotificationTray::ShowBubble() {
723 if (bubble())
724 return;
725 bubble_.reset(new Bubble(this));
726 }
727
728 void WebNotificationTray::HideBubble() {
729 bubble_.reset();
730 }
731
732 void WebNotificationTray::ShowSettings(const std::string& id) {
733 if (delegate_)
734 delegate_->ShowSettings(id);
735 }
736
737 void WebNotificationTray::OnClicked(const std::string& id) {
738 if (delegate_)
739 delegate_->OnClicked(id);
740 }
741
742 bool WebNotificationTray::PreHandleKeyEvent(aura::Window* target,
743 aura::KeyEvent* event) {
744 return false;
745 }
746
747 bool WebNotificationTray::PreHandleMouseEvent(aura::Window* target,
748 aura::MouseEvent* event) {
749 if (event->type() == ui::ET_MOUSE_PRESSED)
750 return ProcessLocatedEvent(*event);
751 return false;
752 }
753
754 ui::TouchStatus WebNotificationTray::PreHandleTouchEvent(
755 aura::Window* target,
756 aura::TouchEvent* event) {
757 if (event->type() != ui::ET_TOUCH_PRESSED)
758 return ui::TOUCH_STATUS_UNKNOWN;
759 if (ProcessLocatedEvent(*event))
760 return ui::TOUCH_STATUS_END;
761 return ui::TOUCH_STATUS_UNKNOWN;
762 }
763
764 ui::GestureStatus WebNotificationTray::PreHandleGestureEvent(
765 aura::Window* target,
766 aura::GestureEvent* event) {
767 return ui::GESTURE_STATUS_UNKNOWN;
768 }
769
770 void WebNotificationTray::SetShelfAlignment(ShelfAlignment alignment) {
771 internal::TrayBackgroundView::SetShelfAlignment(alignment);
772 tray_container_->SetLayoutManager(new views::BoxLayout(
773 alignment == SHELF_ALIGNMENT_BOTTOM ?
774 views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
775 0, 0, 0));
776 }
777
778 bool WebNotificationTray::PerformAction(const views::Event& event) {
779 if (bubble()) {
780 status_area_widget_->HideWebNotificationBubble();
781 } else {
782 status_area_widget_->ShowWebNotificationBubble(
783 internal::StatusAreaWidget::USER_ACTION);
784 }
785 return true;
786 }
787
788 int WebNotificationTray::GetNotificationCount() const {
789 return notification_list()->notifications().size();
790 }
791
792 void WebNotificationTray::UpdateIcon() {
793 int count = GetNotificationCount();
794 if (count == 0) {
795 SetVisible(false);
796 } else {
797 icon_->SetImage(gfx::ImageSkia(GetNotificationImage(count)));
798 SetVisible(true);
799 }
800 PreferredSizeChanged();
801 }
802
803 void WebNotificationTray::UpdateBubbleAndIcon() {
804 UpdateIcon();
805 if (!bubble())
806 return;
807 if (GetNotificationCount() == 0)
808 status_area_widget_->HideWebNotificationBubble();
809 else
810 bubble_->Update();
811 }
812
813 bool WebNotificationTray::ProcessLocatedEvent(const aura::LocatedEvent& event) {
814 if (!bubble())
815 return false;
816 gfx::Rect bounds =
817 bubble_->bubble_widget()->GetNativeWindow()->GetBoundsInRootWindow();
818 if (bounds.Contains(event.root_location()))
819 return false;
820 status_area_widget_->HideWebNotificationBubble();
821 // If the event occurred in the tray widget, don't process the click.
822 bounds = GetWidget()->GetNativeWindow()->GetBoundsInRootWindow();
823 if (bounds.Contains(event.root_location()))
824 return true;
825 return false;
826 }
827
828 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698