OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "ash/system/web_notification/web_notification_tray.h" | 5 #include "ash/system/web_notification/web_notification_tray.h" |
6 | 6 |
7 #include "ash/system/status_area_widget.h" | 7 #include "ash/system/status_area_widget.h" |
| 8 #include "ash/system/tray/system_tray.h" |
8 #include "ash/system/tray/tray_bubble_view.h" | 9 #include "ash/system/tray/tray_bubble_view.h" |
9 #include "ash/system/tray/tray_constants.h" | 10 #include "ash/system/tray/tray_constants.h" |
10 #include "ash/system/tray/tray_views.h" | 11 #include "ash/system/tray/tray_views.h" |
11 #include "base/bind.h" | 12 #include "base/bind.h" |
12 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/stringprintf.h" |
| 15 #include "base/timer.h" |
| 16 #include "base/utf_string_conversions.h" |
13 #include "grit/ash_strings.h" | 17 #include "grit/ash_strings.h" |
14 #include "grit/ui_resources.h" | 18 #include "grit/ui_resources.h" |
15 #include "ui/aura/window.h" | 19 #include "ui/aura/window.h" |
16 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
17 #include "ui/base/models/simple_menu_model.h" | 21 #include "ui/base/models/simple_menu_model.h" |
18 #include "ui/base/resource/resource_bundle.h" | 22 #include "ui/base/resource/resource_bundle.h" |
19 #include "ui/gfx/image/image_skia_operations.h" | 23 #include "ui/gfx/image/image_skia_operations.h" |
20 #include "ui/views/controls/button/button.h" | 24 #include "ui/views/controls/button/button.h" |
21 #include "ui/views/controls/button/menu_button.h" | 25 #include "ui/views/controls/button/menu_button.h" |
22 #include "ui/views/controls/button/menu_button_listener.h" | 26 #include "ui/views/controls/button/menu_button_listener.h" |
23 #include "ui/views/controls/label.h" | 27 #include "ui/views/controls/label.h" |
24 #include "ui/views/controls/menu/menu_model_adapter.h" | 28 #include "ui/views/controls/menu/menu_model_adapter.h" |
25 #include "ui/views/controls/menu/menu_runner.h" | 29 #include "ui/views/controls/menu/menu_runner.h" |
26 #include "ui/views/layout/box_layout.h" | 30 #include "ui/views/layout/box_layout.h" |
27 #include "ui/views/layout/fill_layout.h" | 31 #include "ui/views/layout/fill_layout.h" |
28 #include "ui/views/layout/grid_layout.h" | 32 #include "ui/views/layout/grid_layout.h" |
29 #include "ui/views/painter.h" | 33 #include "ui/views/painter.h" |
30 #include "ui/views/widget/widget_observer.h" | 34 #include "ui/views/widget/widget_observer.h" |
31 | 35 |
32 namespace { | 36 namespace { |
33 | 37 |
34 // Tray constants | 38 // Tray constants |
35 const int kTrayContainerVeritcalPaddingBottomAlignment = 3; | 39 const int kTrayContainerVeritcalPaddingBottomAlignment = 3; |
36 const int kTrayContainerHorizontalPaddingBottomAlignment = 1; | 40 const int kTrayContainerHorizontalPaddingBottomAlignment = 1; |
37 const int kTrayContainerVerticalPaddingVerticalAlignment = 1; | 41 const int kTrayContainerVerticalPaddingVerticalAlignment = 1; |
38 const int kTrayContainerHorizontalPaddingVerticalAlignment = 0; | 42 const int kTrayContainerHorizontalPaddingVerticalAlignment = 0; |
39 const int kPaddingFromLeftEdgeOfSystemTrayBottomAlignment = 8; | 43 const int kPaddingFromLeftEdgeOfSystemTrayBottomAlignment = 8; |
40 const int kPaddingFromTopEdgeOfSystemTrayVerticalAlignment = 10; | 44 const int kPaddingFromTopEdgeOfSystemTrayVerticalAlignment = 10; |
41 const int kNotificationImageIconWidth = 40; | 45 const int kTrayWidth = 40; |
42 const int kNotificationImageIconHeight = 25; | 46 const int kTrayHeight = 32; |
43 const int kNotificationImageIconInset = 4; | 47 const int kTraySideWidth = 32; |
| 48 const int kTraySideHeight = 24; |
44 | 49 |
45 // Web Notification Bubble constants | 50 // Web Notification Bubble constants |
46 const int kWebNotificationBubbleMinHeight = 80; | 51 const int kWebNotificationBubbleMinHeight = 80; |
47 const int kWebNotificationBubbleMaxHeight = 480; | 52 const int kWebNotificationBubbleMaxHeight = 480; |
48 // Delay laying out the Bubble until all notifications have been added and icons | 53 // Delay laying out the Bubble until all notifications have been added and icons |
49 // have had a chance to load. | 54 // have had a chance to load. |
50 const int kUpdateDelayMs = 50; | 55 const int kUpdateDelayMs = 50; |
51 // Limit the number of visible notifications. | 56 // Limit the number of visible notifications. |
52 const int kMaxVisibleNotifications = 100; | 57 const int kMaxVisibleNotifications = 100; |
| 58 const int kAutocloseDelaySeconds = 5; |
53 | 59 |
54 // Individual notifications constants | 60 // Individual notifications constants |
55 const int kWebNotificationWidth = 320; | 61 const int kWebNotificationWidth = 320; |
56 const int kWebNotificationButtonWidth = 32; | 62 const int kWebNotificationButtonWidth = 32; |
57 const int kWebNotificationIconSize = 40; | 63 const int kWebNotificationIconSize = 40; |
58 | 64 |
59 // Menu constants | 65 // Menu constants |
60 const int kTogglePermissionCommand = 0; | 66 const int kTogglePermissionCommand = 0; |
61 const int kToggleExtensionCommand = 1; | 67 const int kToggleExtensionCommand = 1; |
62 const int kShowSettingsCommand = 2; | 68 const int kShowSettingsCommand = 2; |
63 | 69 |
64 // The image has three icons: 1 notifiaction, 2 notifications, and 3+. | 70 std::string GetNotificationText(int notification_count) { |
65 gfx::ImageSkia GetNotificationImage(int notification_count) { | 71 if (notification_count >= 100) |
66 const gfx::ImageSkia* image = ui::ResourceBundle::GetSharedInstance(). | 72 return "99+"; |
67 GetImageSkiaNamed(IDR_AURA_UBER_TRAY_WEB_NOTIFICATON); | 73 return base::StringPrintf("%d", notification_count); |
68 int image_index = notification_count - 1; | |
69 image_index = std::max(0, std::min(image_index, 2)); | |
70 // The original width of the image looks too big, so we need to inset | |
71 // it somewhat. | |
72 gfx::Rect region( | |
73 kNotificationImageIconInset, | |
74 image_index * kNotificationImageIconHeight, | |
75 kNotificationImageIconWidth - 2 * kNotificationImageIconInset, | |
76 kNotificationImageIconHeight); | |
77 return gfx::ImageSkiaOperations::ExtractSubset(*image, region); | |
78 } | 74 } |
79 | 75 |
80 } // namespace | 76 } // namespace |
81 | 77 |
82 namespace ash { | 78 namespace ash { |
83 | 79 |
84 namespace internal { | 80 namespace internal { |
85 | 81 |
86 struct WebNotification { | 82 struct WebNotification { |
87 WebNotification(const std::string& i, | 83 WebNotification(const std::string& i, |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 tray_->RemoveAllNotifications(); | 473 tray_->RemoveAllNotifications(); |
478 } | 474 } |
479 | 475 |
480 private: | 476 private: |
481 WebNotificationTray* tray_; | 477 WebNotificationTray* tray_; |
482 TrayPopupTextButton* close_all_button_; | 478 TrayPopupTextButton* close_all_button_; |
483 | 479 |
484 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView); | 480 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView); |
485 }; | 481 }; |
486 | 482 |
487 } // namespace internal | 483 class WebContentsView : public views::View { |
| 484 public: |
| 485 WebContentsView() {} |
| 486 virtual ~WebContentsView() {} |
488 | 487 |
489 using internal::TrayBubbleView; | 488 virtual void Update( |
490 using internal::WebNotificationList; | 489 const WebNotificationList::Notifications& notifications) = 0; |
491 using internal::WebNotificationView; | |
492 | 490 |
493 class WebNotificationTray::BubbleContentsView : public views::View { | 491 private: |
| 492 DISALLOW_COPY_AND_ASSIGN(WebContentsView); |
| 493 }; |
| 494 |
| 495 class MessageCenterContentsView : public WebContentsView { |
494 public: | 496 public: |
495 explicit BubbleContentsView(WebNotificationTray* tray) | 497 explicit MessageCenterContentsView(WebNotificationTray* tray) |
496 : tray_(tray) { | 498 : tray_(tray) { |
497 set_border(views::Border::CreateSolidSidedBorder( | 499 set_border(views::Border::CreateSolidSidedBorder( |
498 1, 1, 1, 1, ash::kBorderDarkColor)); | 500 1, 1, 1, 1, ash::kBorderDarkColor)); |
499 | 501 |
500 SetLayoutManager( | 502 SetLayoutManager( |
501 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | 503 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
502 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); | 504 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
503 | 505 |
504 scroll_content_ = new views::View; | 506 scroll_content_ = new views::View; |
505 scroll_content_->SetLayoutManager( | 507 scroll_content_->SetLayoutManager( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 scroll_size.set_height(scroll_height); | 540 scroll_size.set_height(scroll_height); |
539 scroller_->SetFixedSize(scroll_size); | 541 scroller_->SetFixedSize(scroll_size); |
540 scroller_->SizeToPreferredSize(); | 542 scroller_->SizeToPreferredSize(); |
541 } | 543 } |
542 | 544 |
543 WebNotificationTray* tray_; | 545 WebNotificationTray* tray_; |
544 internal::FixedSizedScrollView* scroller_; | 546 internal::FixedSizedScrollView* scroller_; |
545 views::View* scroll_content_; | 547 views::View* scroll_content_; |
546 internal::WebNotificationButtonView* button_view_; | 548 internal::WebNotificationButtonView* button_view_; |
547 | 549 |
548 DISALLOW_COPY_AND_ASSIGN(BubbleContentsView); | 550 DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView); |
549 }; | 551 }; |
550 | 552 |
| 553 class WebNotificationContentsView : public WebContentsView { |
| 554 public: |
| 555 explicit WebNotificationContentsView(WebNotificationTray* tray) |
| 556 : tray_(tray) { |
| 557 set_border(views::Border::CreateSolidSidedBorder( |
| 558 1, 1, 1, 1, ash::kBorderDarkColor)); |
| 559 |
| 560 SetLayoutManager( |
| 561 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
| 562 set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
| 563 |
| 564 content_ = new views::View; |
| 565 content_->SetLayoutManager( |
| 566 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
| 567 AddChildView(content_); |
| 568 } |
| 569 |
| 570 void Update(const WebNotificationList::Notifications& notifications) { |
| 571 content_->RemoveAllChildViews(true); |
| 572 WebNotificationList::Notifications::const_iterator iter = |
| 573 notifications.begin(); |
| 574 WebNotificationView* view = new WebNotificationView(tray_, *iter); |
| 575 content_->AddChildView(view); |
| 576 GetWidget()->GetRootView()->SchedulePaint(); |
| 577 } |
| 578 |
| 579 private: |
| 580 WebNotificationTray* tray_; |
| 581 views::View* content_; |
| 582 |
| 583 DISALLOW_COPY_AND_ASSIGN(WebNotificationContentsView); |
| 584 }; |
| 585 |
| 586 } // namespace internal |
| 587 |
| 588 using internal::TrayBubbleView; |
| 589 using internal::WebNotificationList; |
| 590 using internal::WebContentsView; |
| 591 |
551 class WebNotificationTray::Bubble : public TrayBubbleView::Host, | 592 class WebNotificationTray::Bubble : public TrayBubbleView::Host, |
552 public views::WidgetObserver { | 593 public views::WidgetObserver { |
553 public: | 594 public: |
554 explicit Bubble(WebNotificationTray* tray) | 595 enum BubbleType { |
| 596 BUBBLE_TYPE_MESAGE_CENTER, |
| 597 BUBBLE_TYPE_NOTIFICATION |
| 598 }; |
| 599 |
| 600 Bubble(WebNotificationTray* tray, BubbleType bubble_type) |
555 : tray_(tray), | 601 : tray_(tray), |
| 602 bubble_type_(bubble_type), |
556 bubble_view_(NULL), | 603 bubble_view_(NULL), |
557 bubble_widget_(NULL), | 604 bubble_widget_(NULL), |
558 contents_view_(NULL), | 605 contents_view_(NULL), |
559 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 606 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
560 views::View* anchor = tray->tray_container(); | 607 views::View* anchor = tray->tray_container(); |
561 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, | 608 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, |
562 tray->shelf_alignment()); | 609 tray->shelf_alignment()); |
563 init_params.bubble_width = kWebNotificationWidth; | 610 init_params.bubble_width = kWebNotificationWidth; |
564 init_params.max_height = kWebNotificationBubbleMaxHeight; | 611 if (bubble_type == BUBBLE_TYPE_MESAGE_CENTER) { |
| 612 init_params.max_height = kWebNotificationBubbleMaxHeight; |
| 613 } else { |
| 614 init_params.arrow_color = kBackgroundColor; |
| 615 init_params.close_on_deactivate = false; |
| 616 } |
565 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { | 617 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
566 gfx::Point bounds(anchor->width() / 2, 0); | 618 gfx::Point bounds(anchor->width() / 2, 0); |
567 ConvertPointToWidget(anchor, &bounds); | 619 ConvertPointToWidget(anchor, &bounds); |
568 init_params.arrow_offset = bounds.x(); | 620 init_params.arrow_offset = bounds.x(); |
569 } | 621 } |
570 bubble_view_ = TrayBubbleView::Create(anchor, this, init_params); | 622 bubble_view_ = TrayBubbleView::Create(anchor, this, init_params); |
571 | 623 |
572 contents_view_ = new BubbleContentsView(tray); | 624 if (bubble_type == BUBBLE_TYPE_MESAGE_CENTER) |
| 625 contents_view_ = new internal::MessageCenterContentsView(tray); |
| 626 else |
| 627 contents_view_ = new internal::WebNotificationContentsView(tray); |
573 bubble_view_->AddChildView(contents_view_); | 628 bubble_view_->AddChildView(contents_view_); |
574 | 629 |
575 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); | 630 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); |
576 bubble_widget_->AddObserver(this); | 631 bubble_widget_->AddObserver(this); |
577 | 632 |
578 InitializeAndShowBubble(bubble_widget_, bubble_view_, tray_); | 633 InitializeAndShowBubble(bubble_widget_, bubble_view_, tray_); |
579 | 634 |
580 ScheduleUpdate(); | 635 ScheduleUpdate(); |
581 } | 636 } |
582 | 637 |
583 virtual ~Bubble() { | 638 virtual ~Bubble() { |
584 if (bubble_view_) | 639 if (bubble_view_) |
585 bubble_view_->reset_host(); | 640 bubble_view_->reset_host(); |
586 if (bubble_widget_) { | 641 if (bubble_widget_) { |
587 bubble_widget_->RemoveObserver(this); | 642 bubble_widget_->RemoveObserver(this); |
588 bubble_widget_->Close(); | 643 bubble_widget_->Close(); |
589 } | 644 } |
590 } | 645 } |
591 | 646 |
592 void ScheduleUpdate() { | 647 void ScheduleUpdate() { |
| 648 StartAutoCloseTimer(); |
| 649 |
593 weak_ptr_factory_.InvalidateWeakPtrs(); // Cancel any pending update. | 650 weak_ptr_factory_.InvalidateWeakPtrs(); // Cancel any pending update. |
594 MessageLoop::current()->PostDelayedTask( | 651 MessageLoop::current()->PostDelayedTask( |
595 FROM_HERE, | 652 FROM_HERE, |
596 base::Bind(&WebNotificationTray::Bubble::UpdateBubbleView, | 653 base::Bind(&WebNotificationTray::Bubble::UpdateBubbleView, |
597 weak_ptr_factory_.GetWeakPtr()), | 654 weak_ptr_factory_.GetWeakPtr()), |
598 base::TimeDelta::FromMilliseconds(kUpdateDelayMs)); | 655 base::TimeDelta::FromMilliseconds(kUpdateDelayMs)); |
599 } | 656 } |
600 | 657 |
601 views::Widget* bubble_widget() const { return bubble_widget_; } | 658 views::Widget* bubble_widget() const { return bubble_widget_; } |
602 | 659 |
603 // Overridden from TrayBubbleView::Host. | 660 // Overridden from TrayBubbleView::Host. |
604 virtual void BubbleViewDestroyed() OVERRIDE { | 661 virtual void BubbleViewDestroyed() OVERRIDE { |
605 bubble_view_ = NULL; | 662 bubble_view_ = NULL; |
606 contents_view_ = NULL; | 663 contents_view_ = NULL; |
607 } | 664 } |
608 | 665 |
609 virtual void OnMouseEnteredView() OVERRIDE { | 666 virtual void OnMouseEnteredView() OVERRIDE { |
| 667 StopAutoCloseTimer(); |
610 } | 668 } |
611 | 669 |
612 virtual void OnMouseExitedView() OVERRIDE { | 670 virtual void OnMouseExitedView() OVERRIDE { |
| 671 StartAutoCloseTimer(); |
613 } | 672 } |
614 | 673 |
615 virtual void OnClickedOutsideView() OVERRIDE { | 674 virtual void OnClickedOutsideView() OVERRIDE { |
616 // May delete |this|. | 675 // May delete |this|. |
617 tray_->status_area_widget()->HideWebNotificationBubble(); | 676 tray_->HideMessageCenterBubble(); |
618 } | 677 } |
619 | 678 |
620 // Overridden from views::WidgetObserver: | 679 // Overridden from views::WidgetObserver: |
621 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE { | 680 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE { |
622 CHECK_EQ(bubble_widget_, widget); | 681 CHECK_EQ(bubble_widget_, widget); |
623 bubble_widget_ = NULL; | 682 bubble_widget_ = NULL; |
624 tray_->HideBubble(); // Will destroy |this|. | 683 tray_->HideBubble(this); // Will destroy |this|. |
625 } | 684 } |
626 | 685 |
627 private: | 686 private: |
628 void UpdateBubbleView() { | 687 void UpdateBubbleView() { |
629 contents_view_->Update(tray_->notification_list()->notifications()); | 688 const WebNotificationList::Notifications& notifications = |
| 689 tray_->notification_list()->notifications(); |
| 690 if (notifications.size() == 0) { |
| 691 tray_->HideBubble(this); // deletes |this|! |
| 692 return; |
| 693 } |
| 694 contents_view_->Update(notifications); |
630 bubble_view_->Show(); | 695 bubble_view_->Show(); |
631 bubble_view_->UpdateBubble(); | 696 bubble_view_->UpdateBubble(); |
632 } | 697 } |
633 | 698 |
| 699 void StartAutoCloseTimer() { |
| 700 if (bubble_type_ != BUBBLE_TYPE_NOTIFICATION) |
| 701 return; |
| 702 autoclose_.Start(FROM_HERE, |
| 703 base::TimeDelta::FromSeconds(kAutocloseDelaySeconds), |
| 704 this, &Bubble::OnAutoClose); |
| 705 } |
| 706 |
| 707 void StopAutoCloseTimer() { |
| 708 autoclose_.Stop(); |
| 709 } |
| 710 |
| 711 void OnAutoClose() { |
| 712 tray_->HideBubble(this); // deletes |this|! |
| 713 } |
| 714 |
634 WebNotificationTray* tray_; | 715 WebNotificationTray* tray_; |
| 716 BubbleType bubble_type_; |
635 TrayBubbleView* bubble_view_; | 717 TrayBubbleView* bubble_view_; |
636 views::Widget* bubble_widget_; | 718 views::Widget* bubble_widget_; |
637 BubbleContentsView* contents_view_; | 719 WebContentsView* contents_view_; |
| 720 base::OneShotTimer<Bubble> autoclose_; |
638 base::WeakPtrFactory<Bubble> weak_ptr_factory_; | 721 base::WeakPtrFactory<Bubble> weak_ptr_factory_; |
639 | 722 |
640 DISALLOW_COPY_AND_ASSIGN(Bubble); | 723 DISALLOW_COPY_AND_ASSIGN(Bubble); |
641 }; | 724 }; |
642 | 725 |
643 WebNotificationTray::WebNotificationTray( | 726 WebNotificationTray::WebNotificationTray( |
644 internal::StatusAreaWidget* status_area_widget) | 727 internal::StatusAreaWidget* status_area_widget) |
645 : status_area_widget_(status_area_widget), | 728 : internal::TrayBackgroundView(status_area_widget), |
646 notification_list_(new WebNotificationList()), | 729 notification_list_(new WebNotificationList()), |
647 tray_container_(NULL), | 730 count_label_(NULL), |
648 icon_(NULL), | |
649 delegate_(NULL), | 731 delegate_(NULL), |
650 show_bubble_on_unlock_(false) { | 732 show_message_center_on_unlock_(false), |
651 tray_container_ = new views::View; | 733 unread_count_(0) { |
652 SetShelfAlignment(shelf_alignment()); | 734 count_label_ = new views::Label(UTF8ToUTF16("0")); |
| 735 internal::SetupLabelForTray(count_label_); |
| 736 gfx::Font font = count_label_->font(); |
| 737 count_label_->SetFont(font.DeriveFont(0, font.GetStyle() & ~gfx::Font::BOLD)); |
| 738 count_label_->SetHorizontalAlignment(views::Label::ALIGN_CENTER); |
653 | 739 |
654 icon_ = new views::ImageView; | 740 tray_container()->set_size(gfx::Size(kTrayWidth, kTrayHeight)); |
655 tray_container_->AddChildView(icon_); | 741 tray_container()->AddChildView(count_label_); |
656 UpdateIcon(); // Hides the tray initially. | |
657 | 742 |
658 SetContents(tray_container_); | 743 UpdateTray(); |
659 } | 744 } |
660 | 745 |
661 WebNotificationTray::~WebNotificationTray() { | 746 WebNotificationTray::~WebNotificationTray() { |
662 } | 747 } |
663 | 748 |
664 void WebNotificationTray::SetDelegate(Delegate* delegate) { | 749 void WebNotificationTray::SetDelegate(Delegate* delegate) { |
665 DCHECK(!delegate_); | 750 DCHECK(!delegate_); |
666 delegate_ = delegate; | 751 delegate_ = delegate; |
667 } | 752 } |
668 | 753 |
669 void WebNotificationTray::AddNotification(const std::string& id, | 754 void WebNotificationTray::AddNotification(const std::string& id, |
670 const string16& title, | 755 const string16& title, |
671 const string16& message, | 756 const string16& message, |
672 const string16& display_source, | 757 const string16& display_source, |
673 const std::string& extension_id) { | 758 const std::string& extension_id) { |
674 notification_list_->AddNotification( | 759 notification_list_->AddNotification( |
675 id, title, message, display_source, extension_id); | 760 id, title, message, display_source, extension_id); |
676 UpdateIcon(); | 761 if (!message_center_bubble()) |
677 if (bubble()) { | 762 ++unread_count_; |
678 bubble_->ScheduleUpdate(); | 763 UpdateTrayAndBubble(); |
679 } else { | 764 if (!message_center_bubble()) |
680 status_area_widget_->ShowWebNotificationBubble( | 765 ShowNotificationBubble(); |
681 internal::StatusAreaWidget::NON_USER_ACTION); | |
682 } | |
683 } | 766 } |
684 | 767 |
685 void WebNotificationTray::UpdateNotification(const std::string& id, | 768 void WebNotificationTray::UpdateNotification(const std::string& id, |
686 const string16& title, | 769 const string16& title, |
687 const string16& message) { | 770 const string16& message) { |
688 notification_list_->UpdateNotificationMessage(id, title, message); | 771 notification_list_->UpdateNotificationMessage(id, title, message); |
689 if (bubble()) | 772 UpdateTrayAndBubble(); |
690 bubble_->ScheduleUpdate(); | |
691 } | 773 } |
692 | 774 |
693 void WebNotificationTray::RemoveNotification(const std::string& id) { | 775 void WebNotificationTray::RemoveNotification(const std::string& id) { |
694 if (!notification_list_->RemoveNotification(id)) | 776 if (!notification_list_->RemoveNotification(id)) |
695 return; | 777 return; |
696 if (delegate_) | 778 if (delegate_) |
697 delegate_->NotificationRemoved(id); | 779 delegate_->NotificationRemoved(id); |
698 UpdateBubbleAndIcon(); | 780 UpdateTrayAndBubble(); |
699 } | 781 } |
700 | 782 |
701 void WebNotificationTray::RemoveAllNotifications() { | 783 void WebNotificationTray::RemoveAllNotifications() { |
702 const WebNotificationList::Notifications& notifications = | 784 const WebNotificationList::Notifications& notifications = |
703 notification_list_->notifications(); | 785 notification_list_->notifications(); |
704 if (delegate_) { | 786 if (delegate_) { |
705 for (WebNotificationList::Notifications::const_iterator loopiter = | 787 for (WebNotificationList::Notifications::const_iterator loopiter = |
706 notifications.begin(); | 788 notifications.begin(); |
707 loopiter != notifications.end(); ) { | 789 loopiter != notifications.end(); ) { |
708 WebNotificationList::Notifications::const_iterator curiter = loopiter++; | 790 WebNotificationList::Notifications::const_iterator curiter = loopiter++; |
709 std::string notification_id = curiter->id; | 791 std::string notification_id = curiter->id; |
710 // May call RemoveNotification and erase curiter. | 792 // May call RemoveNotification and erase curiter. |
711 delegate_->NotificationRemoved(notification_id); | 793 delegate_->NotificationRemoved(notification_id); |
712 } | 794 } |
713 } | 795 } |
714 notification_list_->RemoveAllNotifications(); | 796 notification_list_->RemoveAllNotifications(); |
715 UpdateBubbleAndIcon(); | 797 UpdateTrayAndBubble(); |
716 } | 798 } |
717 | 799 |
718 void WebNotificationTray::SetNotificationImage(const std::string& id, | 800 void WebNotificationTray::SetNotificationImage(const std::string& id, |
719 const gfx::ImageSkia& image) { | 801 const gfx::ImageSkia& image) { |
720 if (!notification_list_->SetNotificationImage(id, image)) | 802 if (!notification_list_->SetNotificationImage(id, image)) |
721 return; | 803 return; |
722 if (bubble()) | 804 UpdateTrayAndBubble(); |
723 bubble_->ScheduleUpdate(); | |
724 } | 805 } |
725 | 806 |
726 void WebNotificationTray::DisableByExtension(const std::string& id) { | 807 void WebNotificationTray::DisableByExtension(const std::string& id) { |
727 // When we disable notifications, we remove any existing matching | 808 // When we disable notifications, we remove any existing matching |
728 // notifications to avoid adding complicated UI to re-enable the source. | 809 // notifications to avoid adding complicated UI to re-enable the source. |
729 notification_list_->RemoveNotificationsByExtension(id); | 810 notification_list_->RemoveNotificationsByExtension(id); |
730 UpdateBubbleAndIcon(); | 811 UpdateTrayAndBubble(); |
731 if (delegate_) | 812 if (delegate_) |
732 delegate_->DisableExtension(id); | 813 delegate_->DisableExtension(id); |
733 } | 814 } |
734 | 815 |
735 void WebNotificationTray::DisableByUrl(const std::string& id) { | 816 void WebNotificationTray::DisableByUrl(const std::string& id) { |
736 // See comment for DisableByExtension. | 817 // See comment for DisableByExtension. |
737 notification_list_->RemoveNotificationsBySource(id); | 818 notification_list_->RemoveNotificationsBySource(id); |
738 UpdateBubbleAndIcon(); | 819 UpdateTrayAndBubble(); |
739 if (delegate_) | 820 if (delegate_) |
740 delegate_->DisableNotificationsFromSource(id); | 821 delegate_->DisableNotificationsFromSource(id); |
741 } | 822 } |
742 | 823 |
743 void WebNotificationTray::ShowBubble() { | 824 void WebNotificationTray::ShowMessageCenterBubble() { |
744 if (status_area_widget_->login_status() == user::LOGGED_IN_LOCKED) { | 825 if (status_area_widget()->login_status() == user::LOGGED_IN_LOCKED) |
745 show_bubble_on_unlock_ = true; | |
746 return; | 826 return; |
747 } | 827 unread_count_ = 0; |
748 if (bubble()) | 828 UpdateTray(); |
| 829 if (message_center_bubble()) |
749 return; | 830 return; |
750 bubble_.reset(new Bubble(this)); | 831 if (GetNotificationCount() == 0) |
| 832 return; |
| 833 notification_bubble_.reset(); |
| 834 message_center_bubble_.reset( |
| 835 new Bubble(this, Bubble::BUBBLE_TYPE_MESAGE_CENTER)); |
| 836 status_area_widget()->SetHideSystemNotifications(true); |
751 } | 837 } |
752 | 838 |
753 void WebNotificationTray::HideBubble() { | 839 void WebNotificationTray::HideMessageCenterBubble() { |
754 bubble_.reset(); | 840 message_center_bubble_.reset(); |
755 show_bubble_on_unlock_ = false; | 841 show_message_center_on_unlock_ = false; |
| 842 status_area_widget()->SetHideSystemNotifications(false); |
| 843 } |
| 844 |
| 845 void WebNotificationTray::ShowNotificationBubble() { |
| 846 if (status_area_widget()->login_status() == user::LOGGED_IN_LOCKED) |
| 847 return; |
| 848 if (message_center_bubble()) |
| 849 return; |
| 850 if (!status_area_widget()->ShouldShowNonSystemNotifications()) |
| 851 return; |
| 852 UpdateTray(); |
| 853 notification_bubble_.reset( |
| 854 new Bubble(this, Bubble::BUBBLE_TYPE_NOTIFICATION)); |
| 855 } |
| 856 |
| 857 void WebNotificationTray::HideNotificationBubble() { |
| 858 notification_bubble_.reset(); |
756 } | 859 } |
757 | 860 |
758 void WebNotificationTray::UpdateAfterLoginStatusChange( | 861 void WebNotificationTray::UpdateAfterLoginStatusChange( |
759 user::LoginStatus login_status) { | 862 user::LoginStatus login_status) { |
760 if (login_status == user::LOGGED_IN_LOCKED) { | 863 if (login_status == user::LOGGED_IN_LOCKED) { |
761 if (bubble()) { | 864 if (message_center_bubble()) { |
762 HideBubble(); | 865 message_center_bubble_.reset(); |
763 show_bubble_on_unlock_ = true; | 866 show_message_center_on_unlock_ = true; |
764 } | 867 } |
765 } else if (show_bubble_on_unlock_) { | 868 if (notification_bubble()) |
766 ShowBubble(); | 869 notification_bubble_.reset(); |
767 show_bubble_on_unlock_ = false; | 870 } else { |
| 871 if (show_message_center_on_unlock_) |
| 872 ShowMessageCenterBubble(); |
| 873 show_message_center_on_unlock_ = false; |
768 } | 874 } |
769 UpdateIcon(); | 875 UpdateTray(); |
770 } | 876 } |
771 | 877 |
772 void WebNotificationTray::ShowSettings(const std::string& id) { | 878 void WebNotificationTray::ShowSettings(const std::string& id) { |
773 if (delegate_) | 879 if (delegate_) |
774 delegate_->ShowSettings(id); | 880 delegate_->ShowSettings(id); |
775 } | 881 } |
776 | 882 |
777 void WebNotificationTray::OnClicked(const std::string& id) { | 883 void WebNotificationTray::OnClicked(const std::string& id) { |
778 if (delegate_) | 884 if (delegate_) |
779 delegate_->OnClicked(id); | 885 delegate_->OnClicked(id); |
780 } | 886 } |
781 | 887 |
782 void WebNotificationTray::SetShelfAlignment(ShelfAlignment alignment) { | 888 void WebNotificationTray::SetShelfAlignment(ShelfAlignment alignment) { |
| 889 if (alignment == shelf_alignment()) |
| 890 return; |
783 internal::TrayBackgroundView::SetShelfAlignment(alignment); | 891 internal::TrayBackgroundView::SetShelfAlignment(alignment); |
784 SetTrayContainerBorder(); | 892 if (alignment == SHELF_ALIGNMENT_BOTTOM) |
785 SetBorder(); | 893 tray_container()->set_size(gfx::Size(kTrayWidth, kTrayHeight)); |
786 tray_container_->SetLayoutManager(new views::BoxLayout( | 894 else |
787 alignment == SHELF_ALIGNMENT_BOTTOM ? | 895 tray_container()->set_size(gfx::Size(kTraySideWidth, kTraySideHeight)); |
788 views::BoxLayout::kHorizontal : views::BoxLayout::kVertical, | |
789 0, 0, 0)); | |
790 // Destroy any existing bubble so that it will be rebuilt correctly. | 896 // Destroy any existing bubble so that it will be rebuilt correctly. |
791 bubble_.reset(); | 897 message_center_bubble_.reset(); |
| 898 notification_bubble_.reset(); |
792 } | 899 } |
793 | 900 |
794 bool WebNotificationTray::PerformAction(const views::Event& event) { | 901 bool WebNotificationTray::PerformAction(const views::Event& event) { |
795 if (bubble()) { | 902 if (message_center_bubble()) |
796 status_area_widget_->HideWebNotificationBubble(); | 903 HideMessageCenterBubble(); |
797 } else { | 904 else |
798 status_area_widget_->ShowWebNotificationBubble( | 905 ShowMessageCenterBubble(); |
799 internal::StatusAreaWidget::USER_ACTION); | |
800 } | |
801 return true; | 906 return true; |
802 } | 907 } |
803 | 908 |
804 void WebNotificationTray::SetBorder() { | |
805 // Change the border padding for different shelf alignment. | |
806 // This affects the position of the web notification tray. | |
807 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { | |
808 set_border(views::Border::CreateEmptyBorder(0, 0, | |
809 kPaddingFromBottomOfScreenBottomAlignment, | |
810 kPaddingFromLeftEdgeOfSystemTrayBottomAlignment)); | |
811 } else if (shelf_alignment() == SHELF_ALIGNMENT_LEFT) { | |
812 set_border(views::Border::CreateEmptyBorder(0, | |
813 kPaddingFromOuterEdgeOfLauncherVerticalAlignment, | |
814 kPaddingFromTopEdgeOfSystemTrayVerticalAlignment, | |
815 kPaddingFromInnerEdgeOfLauncherVerticalAlignment)); | |
816 } else { | |
817 set_border(views::Border::CreateEmptyBorder(0, | |
818 kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
819 kPaddingFromTopEdgeOfSystemTrayVerticalAlignment, | |
820 kPaddingFromOuterEdgeOfLauncherVerticalAlignment)); | |
821 } | |
822 } | |
823 | |
824 void WebNotificationTray::SetTrayContainerBorder() { | |
825 // Adjust the size of web notification tray dark background by adding | |
826 // additional empty border. | |
827 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { | |
828 tray_container_->set_border(views::Border::CreateEmptyBorder( | |
829 kTrayContainerVeritcalPaddingBottomAlignment, | |
830 kTrayContainerHorizontalPaddingBottomAlignment, | |
831 kTrayContainerVeritcalPaddingBottomAlignment, | |
832 kTrayContainerHorizontalPaddingBottomAlignment)); | |
833 } else { | |
834 tray_container_->set_border(views::Border::CreateEmptyBorder( | |
835 kTrayContainerVerticalPaddingVerticalAlignment, | |
836 kTrayContainerHorizontalPaddingVerticalAlignment, | |
837 kTrayContainerVerticalPaddingVerticalAlignment, | |
838 kTrayContainerHorizontalPaddingVerticalAlignment)); | |
839 } | |
840 } | |
841 | |
842 int WebNotificationTray::GetNotificationCount() const { | 909 int WebNotificationTray::GetNotificationCount() const { |
843 return notification_list()->notifications().size(); | 910 return notification_list()->notifications().size(); |
844 } | 911 } |
845 | 912 |
846 void WebNotificationTray::UpdateIcon() { | 913 void WebNotificationTray::UpdateTray() { |
847 int count = GetNotificationCount(); | 914 count_label_->SetText(UTF8ToUTF16(GetNotificationText(unread_count_))); |
848 if (count == 0 || | 915 Layout(); |
849 status_area_widget_->login_status() == user::LOGGED_IN_LOCKED) { | 916 SchedulePaint(); |
850 SetVisible(false); | |
851 } else { | |
852 icon_->SetImage(GetNotificationImage(count)); | |
853 SetVisible(true); | |
854 } | |
855 PreferredSizeChanged(); | |
856 } | 917 } |
857 | 918 |
858 void WebNotificationTray::UpdateBubbleAndIcon() { | 919 void WebNotificationTray::UpdateTrayAndBubble() { |
859 UpdateIcon(); | 920 UpdateTray(); |
860 if (!bubble()) | 921 if (GetNotificationCount() == 0) { |
| 922 HideMessageCenterBubble(); |
| 923 notification_bubble_.reset(); |
861 return; | 924 return; |
862 if (GetNotificationCount() == 0) | 925 } |
863 status_area_widget_->HideWebNotificationBubble(); | 926 if (message_center_bubble()) |
864 else | 927 message_center_bubble()->ScheduleUpdate(); |
865 bubble_->ScheduleUpdate(); | 928 if (notification_bubble()) |
| 929 notification_bubble()->ScheduleUpdate(); |
| 930 } |
| 931 |
| 932 void WebNotificationTray::HideBubble(Bubble* bubble) { |
| 933 if (bubble == message_center_bubble()) { |
| 934 HideMessageCenterBubble(); |
| 935 } else if (bubble == notification_bubble()) { |
| 936 notification_bubble_.reset(); |
| 937 } |
866 } | 938 } |
867 | 939 |
868 } // namespace ash | 940 } // namespace ash |
OLD | NEW |