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

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

Powered by Google App Engine
This is Rietveld 408576698