Chromium Code Reviews| Index: ash/system/web_notification/web_notification_tray.cc |
| diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..07e3b0e525df279950fa3421071f640869bb1a53 |
| --- /dev/null |
| +++ b/ash/system/web_notification/web_notification_tray.cc |
| @@ -0,0 +1,692 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "ash/system/web_notification/web_notification_tray.h" |
| + |
| +#include "ash/shell.h" |
| +#include "ash/system/tray/system_tray.h" |
| +#include "ash/system/tray/system_tray_bubble_view.h" |
| +#include "ash/system/tray/tray_constants.h" |
| +#include "ash/system/tray/tray_views.h" |
| +#include "grit/ash_strings.h" |
| +#include "grit/ui_resources.h" |
| +#include "grit/ui_resources_standard.h" |
| +#include "ui/aura/event.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "ui/base/models/simple_menu_model.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| +#include "ui/views/controls/button/button.h" |
| +#include "ui/views/controls/button/menu_button.h" |
| +#include "ui/views/controls/button/menu_button_listener.h" |
| +#include "ui/views/controls/label.h" |
| +#include "ui/views/controls/menu/menu_model_adapter.h" |
| +#include "ui/views/controls/menu/menu_runner.h" |
| +#include "ui/views/layout/box_layout.h" |
| +#include "ui/views/layout/fill_layout.h" |
| +#include "ui/views/layout/grid_layout.h" |
| + |
| +namespace { |
| + |
| +const int kIconBorder = 4; |
| +const int kImageWidth = 40; |
| +const int kImageHeight = 25; |
| +const int kWebNotificationBubbleMinHeight = 50; |
| +const int kWebNotificationBubbleMaxHeight = 400; |
| +const int kWebNotificationWidth = 400; |
| +const int kWebNotificationButtonWidth = 32; |
| + |
| +// The image has three icons: 1 notifiaction, 2 notifications, and 3+. |
| +SkBitmap GetNotificationImage(int notification_count) { |
| + SkBitmap image; |
| + gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| + IDR_AURA_UBER_TRAY_WEB_NOTIFICATON); |
| + |
| + int image_index = notification_count - 1; |
| + image_index = std::max(0, std::min(image_index, 2)); |
| + |
| + SkIRect region = SkIRect::MakeXYWH( |
| + 0, image_index * kImageHeight, kImageWidth, kImageHeight); |
| + all.ToSkBitmap()->extractSubset(&image, region); |
| + return image; |
| +} |
| + |
| +} // namespace |
| + |
| +namespace ash { |
| + |
| +namespace internal { |
| + |
| +struct WebNotification { |
| + WebNotification(const std::string& i, |
| + const string16& t, |
| + const string16& m, |
| + const string16& s, |
| + const std::string& e) : |
|
sadrul
2012/06/06 19:19:19
the ':' should be in the next line
stevenjb
2012/06/06 23:12:15
Done.
|
| + id(i), |
| + title(t), |
| + message(m), |
| + display_source(s), |
| + extension_id(e) { |
| + } |
| + std::string id; |
|
sadrul
2012/06/06 19:19:19
newline between 72/73
stevenjb
2012/06/06 23:12:15
Done.
|
| + string16 title; |
| + string16 message; |
| + string16 display_source; |
| + std::string extension_id; |
| + SkBitmap image; |
| +}; |
| + |
| +// A helper class to manage the list of notifications. |
| +class WebNotificationList { |
| + public: |
| + typedef std::list<WebNotification> Notifications; |
| + |
| + WebNotificationList() { |
| + } |
| + |
| + void AddNotification(const std::string& id, |
| + const string16& title, |
| + const string16& message, |
| + const string16& source, |
| + const std::string& extension) { |
| + Notifications::iterator iter = GetNotification(id); |
| + if (iter != notifications_.end()) { |
| + iter->title = title; |
| + iter->message = message; |
| + iter->display_source = source; |
| + iter->extension_id = extension; |
| + } else { |
| + notifications_.push_back( |
| + WebNotification(id, title, message, source, extension)); |
| + } |
| + } |
| + |
| + bool RemoveNotification(const std::string& id) { |
| + Notifications::iterator iter = GetNotification(id); |
| + if (iter == notifications_.end()) |
| + return false; |
| + notifications_.erase(iter); |
| + return true; |
| + } |
| + |
| + void RemoveNotificationsBySource(const std::string& id) { |
| + Notifications::iterator source_iter = GetNotification(id); |
| + if (source_iter == notifications_.end()) |
| + return; |
| + string16 display_source = source_iter->display_source; |
| + for (Notifications::iterator loopiter = notifications_.begin(); |
| + loopiter != notifications_.end(); ) { |
|
sadrul
2012/06/06 19:19:19
Can you just ++loopiter here instead of below?
..
stevenjb
2012/06/06 23:12:15
Correct.
|
| + Notifications::iterator curiter = loopiter++; |
| + if (curiter->display_source == display_source) |
| + notifications_.erase(curiter); |
| + } |
| + } |
| + |
| + void RemoveNotificationsByExtension(const std::string& id) { |
| + Notifications::iterator source_iter = GetNotification(id); |
| + if (source_iter == notifications_.end()) |
| + return; |
| + std::string extension_id = source_iter->extension_id; |
| + for (Notifications::iterator loopiter = notifications_.begin(); |
| + loopiter != notifications_.end(); ) { |
| + Notifications::iterator curiter = loopiter++; |
| + if (curiter->extension_id == extension_id) |
| + notifications_.erase(curiter); |
| + } |
| + } |
| + |
| + bool SetNotificationImage(const std::string& id, |
| + const SkBitmap& image) { |
| + Notifications::iterator iter = GetNotification(id); |
| + if (iter == notifications_.end()) |
| + return false; |
| + iter->image = image; |
| + return true; |
| + } |
| + |
| + const Notifications& notifications() const { return notifications_; } |
| + |
| + private: |
| + Notifications::iterator GetNotification(const std::string& id) { |
| + for (Notifications::iterator iter = notifications_.begin(); |
| + iter != notifications_.end(); ++iter) { |
| + if (iter->id == id) |
| + return iter; |
| + } |
| + return notifications_.end(); |
| + } |
| + |
| + Notifications notifications_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebNotificationList); |
| +}; |
| + |
| +// A simple view for the text (title and message) of a notification. |
| +class WebNotificationMessageView : public views::View { |
| + public: |
| + explicit WebNotificationMessageView(const WebNotification& notification) { |
| + views::Label* title = new views::Label(notification.title); |
| + title->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| + title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD)); |
| + views::Label* message = new views::Label(notification.message); |
| + message->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| + message->SetMultiLine(true); |
| + |
| + SetLayoutManager( |
| + new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
| + AddChildView(title); |
| + AddChildView(message); |
| + } |
| + |
| + virtual ~WebNotificationMessageView() { |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(WebNotificationMessageView); |
| +}; |
| + |
| +const int kTogglePermissionCommand = 0; |
| +const int kToggleExtensionCommand = 1; |
| +const int kShowSettingsCommand = 2; |
|
sadrul
2012/06/06 19:19:19
These could be in the anonymous namespace
stevenjb
2012/06/06 23:12:15
Done.
|
| + |
| +// A dropdown menu for notifications. |
| +class WebNotificationMenuModel : public ui::SimpleMenuModel, |
| + public ui::SimpleMenuModel::Delegate { |
| + public: |
| + explicit WebNotificationMenuModel(WebNotificationTray* tray, |
| + const WebNotification& notification) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), |
| + tray_(tray), |
| + notification_(notification) { |
| + // Add 'disable notifications' menu item. |
| + if (!notification.extension_id.empty()) { |
| + AddItem(kToggleExtensionCommand, |
| + GetLabelForCommandId(kToggleExtensionCommand)); |
| + } else if (!notification.display_source.empty()) { |
| + AddItem(kTogglePermissionCommand, |
| + GetLabelForCommandId(kTogglePermissionCommand)); |
| + } |
| + // Add settings menu item. |
| + if (!notification.display_source.empty()) { |
| + AddItem(kShowSettingsCommand, |
| + GetLabelForCommandId(kShowSettingsCommand)); |
| + } |
| + } |
| + |
| + virtual ~WebNotificationMenuModel() { |
| + } |
| + |
| + // Overridden from ui::SimpleMenuModel: |
| + virtual string16 GetLabelForCommandId(int command_id) const OVERRIDE { |
| + switch (command_id) { |
| + case kToggleExtensionCommand: |
| + return l10n_util::GetStringUTF16( |
| + IDS_ASH_WEB_NOTFICATION_TRAY_EXTENSIONS_DISABLE); |
| + case kTogglePermissionCommand: |
| + return l10n_util::GetStringFUTF16( |
| + IDS_ASH_WEB_NOTFICATION_TRAY_SITE_DISABLE, |
| + notification_.display_source); |
| + case kShowSettingsCommand: |
| + return l10n_util::GetStringUTF16( |
| + IDS_ASH_WEB_NOTFICATION_TRAY_SETTINGS); |
| + default: |
| + NOTREACHED(); |
| + } |
| + return string16(); |
| + } |
| + |
| + // Overridden from ui::SimpleMenuModel::Delegate: |
| + virtual bool IsCommandIdChecked(int command_id) const OVERRIDE { |
| + return false; |
| + } |
| + |
| + virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE { |
| + return true; |
| + } |
| + |
| + virtual bool GetAcceleratorForCommandId( |
| + int command_id, |
| + ui::Accelerator* accelerator) OVERRIDE { |
| + return false; |
| + } |
| + |
| + virtual void ExecuteCommand(int command_id) OVERRIDE { |
| + switch (command_id) { |
| + case kToggleExtensionCommand: |
| + tray_->DisableByExtension(notification_.id); |
| + break; |
| + case kTogglePermissionCommand: |
| + tray_->DisableByUrl(notification_.id); |
| + break; |
| + case kShowSettingsCommand: |
| + tray_->ShowSettings(notification_.id); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| + } |
| + |
| + private: |
| + WebNotificationTray* tray_; |
| + WebNotification notification_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebNotificationMenuModel); |
| +}; |
| + |
| +// The view for a notification entry (icon + message + buttons). |
| +class WebNotificationView : public views::View, |
| + public views::ButtonListener, |
| + public views::MenuButtonListener { |
| + public: |
| + WebNotificationView(WebNotificationTray* tray, |
| + const WebNotification& notification) |
| + : tray_(tray), |
| + notification_(notification), |
| + icon_(NULL), |
| + menu_button_(NULL), |
| + close_button_(NULL) { |
| + InitView(tray, notification); |
| + } |
| + |
| + virtual ~WebNotificationView() { |
| + } |
| + |
| + void InitView(WebNotificationTray* tray, |
| + const WebNotification& notification) { |
| + set_border(views::Border::CreateSolidSidedBorder( |
| + 1, 0, 0, 0, kBorderLightColor)); |
| + set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
| + |
| + icon_ = new views::ImageView; |
| + icon_->SetImage(notification.image); |
| + |
| + WebNotificationMessageView* message_view |
| + = new WebNotificationMessageView(notification); |
| + |
| + close_button_ = new views::ImageButton(this); |
| + close_button_->SetImage( |
| + views::CustomButton::BS_NORMAL, |
| + ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| + IDR_AURA_WINDOW_CLOSE)); |
| + |
| + menu_button_ = new views::MenuButton(NULL, string16(), this, true); |
| + menu_button_->set_border(NULL); |
| + |
| + views::GridLayout* layout = new views::GridLayout(this); |
| + SetLayoutManager(layout); |
| + |
| + views::ColumnSet* columns = layout->AddColumnSet(0); |
| + |
| + columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2); |
| + |
| + // Notification Icon. |
| + columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, |
| + 0, /* resize percent */ |
| + views::GridLayout::FIXED, |
| + kNotificationIconWidth, kNotificationIconWidth); |
| + |
| + columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2); |
| + |
| + // Notification message text. |
| + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
| + 100, /* resize percent */ |
| + views::GridLayout::USE_PREF, 0, 0); |
| + |
| + columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2); |
| + |
| + // Close and menu buttons. |
| + columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, |
| + 0, /* resize percent */ |
| + views::GridLayout::FIXED, |
| + kWebNotificationButtonWidth, |
| + kWebNotificationButtonWidth); |
| + |
| + columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2); |
| + |
| + // Layout rows |
| + layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems); |
| + |
| + layout->StartRow(0, 0); |
| + layout->AddView(icon_, 1, 2); |
| + layout->AddView(message_view, 1, 2); |
| + layout->AddView(close_button_); |
| + |
| + layout->StartRow(0, 0); |
| + layout->SkipColumns(4); |
| + layout->AddView(menu_button_); |
| + |
| + layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems); |
| + } |
| + |
| + // Overridden from ButtonListener. |
| + virtual void ButtonPressed(views::Button* sender, |
| + const views::Event& event) OVERRIDE { |
| + if (sender == close_button_) |
| + tray_->RemoveNotification(notification_.id); |
| + } |
| + |
| + // Overridden from MenuButtonListener. |
| + virtual void OnMenuButtonClicked(View* source, const gfx::Point& point) { |
| + if (source != menu_button_) |
| + return; |
| + WebNotificationMenuModel menu_model(tray_, notification_); |
| + views::MenuModelAdapter menu_model_adapter(&menu_model); |
| + views::MenuRunner menu_runner(menu_model_adapter.CreateMenu()); |
| + |
| + gfx::Point screen_location; |
| + views::View::ConvertPointToScreen(menu_button_, &screen_location); |
| + if (menu_runner.RunMenuAt( |
| + source->GetWidget()->GetTopLevelWidget(), |
| + menu_button_, |
| + gfx::Rect(screen_location, menu_button_->size()), |
| + views::MenuItemView::TOPRIGHT, |
| + views::MenuRunner::HAS_MNEMONICS) |
| + == views::MenuRunner::MENU_DELETED) { |
|
sadrul
2012/06/06 19:19:19
== should be in the line above
stevenjb
2012/06/06 23:12:15
Used ignore_result instead.
|
| + return; |
| + } |
| + } |
| + |
| + |
| + private: |
| + WebNotificationTray* tray_; |
| + WebNotification notification_; |
| + views::ImageView* icon_; |
| + views::MenuButton* menu_button_; |
| + views::ImageButton* close_button_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebNotificationView); |
| +}; |
| + |
| +} // namespace internal |
| + |
| +using internal::WebNotificationList; |
| +using internal::WebNotificationView; |
| + |
| +class WebNotificationTray::BubbleContentsView : public views::View { |
| + public: |
| + explicit BubbleContentsView(WebNotificationTray* tray) |
| + : tray_(tray) { |
| + SetLayoutManager(new views::FillLayout); |
| + set_background(views::Background::CreateSolidBackground(kBackgroundColor)); |
| + |
| + scroll_content_ = new views::View; |
| + scroll_content_->SetLayoutManager( |
| + new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); |
| + scroller_ = new internal::FixedSizedScrollView; |
| + scroller_->SetContentsView(scroll_content_); |
| + |
| + AddChildView(scroller_); |
| + } |
| + |
| + void Update(const WebNotificationList::Notifications& notifications) { |
| + scroll_content_->RemoveAllChildViews(true); |
| + for (WebNotificationList::Notifications::const_iterator iter = |
| + notifications.begin(); iter != notifications.end(); ++iter) { |
| + WebNotificationView* view = new WebNotificationView(tray_, *iter); |
| + scroll_content_->AddChildView(view); |
| + } |
| + scroller_->Layout(); |
| + SizeToPreferredSize(); |
| + Layout(); |
| + PreferredSizeChanged(); |
| + SchedulePaint(); |
| + } |
| + |
| + // views::View overrides. |
| + virtual gfx::Size GetPreferredSize() { |
| + gfx::Size preferred_size = scroll_content_->GetPreferredSize(); |
| + int height = std::min( |
| + std::max(preferred_size.height(), kWebNotificationBubbleMinHeight), |
| + kWebNotificationBubbleMaxHeight); |
| + preferred_size.set_height(height); |
| + return preferred_size; |
| + } |
| + |
| + private: |
| + WebNotificationTray* tray_; |
| + internal::FixedSizedScrollView* scroller_; |
| + views::View* scroll_content_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BubbleContentsView); |
| +}; |
| + |
| +class WebNotificationTray::Bubble |
| + : public internal::SystemTrayBubbleView::Host { |
| + public: |
| + explicit Bubble(WebNotificationTray* tray) : |
|
sadrul
2012/06/06 19:19:19
: should be in the next line
stevenjb
2012/06/06 23:12:15
Done.
|
| + tray_(tray), |
| + bubble_view_(NULL), |
| + bubble_widget_(NULL), |
| + contents_view_(NULL) { |
| + views::View* anchor = tray->tray_container(); |
| + views::BubbleBorder::ArrowLocation arrow_location; |
| + int arrow_offset = 0; |
| + if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
| + arrow_location = views::BubbleBorder::BOTTOM_RIGHT; |
| + arrow_offset = anchor->GetContentsBounds().width() / 2; |
| + } else if (tray_->shelf_alignment() == SHELF_ALIGNMENT_LEFT) { |
| + arrow_location = views::BubbleBorder::LEFT_BOTTOM; |
| + } else { |
| + arrow_location = views::BubbleBorder::RIGHT_BOTTOM; |
| + } |
| + bubble_view_ = new internal::SystemTrayBubbleView( |
| + anchor, arrow_location, this, false); |
| + bubble_view_->SetMaxHeight(kWebNotificationBubbleMaxHeight); |
| + bubble_view_->set_bubble_width(kWebNotificationWidth); |
| + |
| + bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); |
| + |
| + bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| + bubble_widget_->non_client_view()->frame_view()->set_background(NULL); |
| + bubble_view_->SetBubbleBorder(arrow_offset); |
| + |
| + contents_view_ = new BubbleContentsView(tray); |
| + bubble_view_->AddChildView(contents_view_); |
| + |
| + Update(); |
| + bubble_view_->Show(); |
| + |
| + // Don't show any system notifications while we are viewing web |
| + // notifications. As soon as the web notification tray looses focus, |
| + // this will be destroyed and any hidden or suppressed system notifications |
| + // will be displayed (see ~Bubble below). |
| + ash::Shell::GetInstance()->system_tray()->SetHideNotifications(true); |
| + } |
| + |
| + ~Bubble() { |
|
sadrul
2012/06/06 19:19:19
virtual?
stevenjb
2012/06/06 23:12:15
Oops! Done.
|
| + if (bubble_view_) |
| + bubble_view_->reset_host(); |
| + if (bubble_widget_) |
| + bubble_widget_->Close(); |
| + |
| + // Show any hidden or suppressed system notifications. |
| + ash::Shell::GetInstance()->system_tray()->SetHideNotifications(false); |
| + } |
| + |
| + // Overridden from SystemTrayBubbleView::Host. |
| + virtual void BubbleViewDestroyed() OVERRIDE { |
| + } |
| + |
| + virtual gfx::Rect GetAnchorRect() const OVERRIDE { |
| + gfx::Rect anchor_rect = tray_->tray_container()->GetScreenBounds(); |
| + return anchor_rect; |
| + } |
| + |
| + virtual void OnMouseEnteredView() OVERRIDE { |
| + } |
| + |
| + virtual void OnMoiseExitedView() OVERRIDE { |
| + } |
| + |
| + void Update() { |
| + contents_view_->Update(tray_->notification_list()->notifications()); |
| + bubble_view_->Layout(); |
| + bubble_view_->SchedulePaint(); |
| + } |
| + |
| + views::Widget* bubble_widget() const { return bubble_widget_; } |
| + |
| + private: |
| + WebNotificationTray* tray_; |
| + internal::SystemTrayBubbleView* bubble_view_; |
| + views::Widget* bubble_widget_; |
| + BubbleContentsView* contents_view_; |
| +}; |
| + |
| +WebNotificationTray::WebNotificationTray() |
| + : notification_list_(new WebNotificationList()), |
| + tray_container_(NULL), |
| + icon_(NULL), |
| + delegate_(NULL) { |
| + tray_container_ = new views::View; |
| + tray_container_->set_border(views::Border::CreateEmptyBorder( |
| + kIconBorder, kIconBorder, kIconBorder, kIconBorder)); |
| + SetShelfAlignment(shelf_alignment()); |
| + |
| + icon_ = new views::ImageView; |
| + tray_container_->AddChildView(icon_); |
| + UpdateIcon(); // Hides the tray initially. |
| + |
| + SetContents(tray_container_); |
| + |
| + Shell::GetInstance()->AddEnvEventFilter(this); |
| +} |
| + |
| +WebNotificationTray::~WebNotificationTray() { |
| + Shell::GetInstance()->RemoveEnvEventFilter(this); |
| +} |
| + |
| +bool WebNotificationTray::PreHandleKeyEvent(aura::Window* target, |
| + aura::KeyEvent* event) { |
| + return false; |
| +} |
| + |
| +bool WebNotificationTray::PreHandleMouseEvent(aura::Window* target, |
| + aura::MouseEvent* event) { |
| + if (event->type() == ui::ET_MOUSE_PRESSED) |
| + ProcessLocatedEvent(*event); |
| + return false; |
| +} |
| + |
| +ui::TouchStatus WebNotificationTray::PreHandleTouchEvent(aura::Window* target, |
| + aura::TouchEvent* event) { |
| + if (event->type() == ui::ET_TOUCH_PRESSED) |
| + ProcessLocatedEvent(*event); |
| + return ui::TOUCH_STATUS_UNKNOWN; |
| +} |
| + |
| +ui::GestureStatus WebNotificationTray::PreHandleGestureEvent( |
| + aura::Window* target, |
| + aura::GestureEvent* event) { |
| + return ui::GESTURE_STATUS_UNKNOWN; |
| +} |
| + |
| +void WebNotificationTray::SetShelfAlignment(ShelfAlignment alignment) { |
| + internal::TrayBackgroundView::SetShelfAlignment(alignment); |
| + tray_container_->SetLayoutManager(new views::BoxLayout( |
| + alignment == SHELF_ALIGNMENT_BOTTOM ? |
| + views::BoxLayout::kHorizontal : views::BoxLayout::kVertical, |
| + 0, 0, 0)); |
| +} |
| + |
| +bool WebNotificationTray::PerformAction(const views::Event& event) { |
| + if (bubble()) |
| + bubble_.reset(); |
| + else |
| + bubble_.reset(new Bubble(this)); |
| + return true; |
| +} |
| + |
| +void WebNotificationTray::SetDelegate(Delegate* delegate) { |
| + DCHECK(!delegate_); |
| + delegate_ = delegate; |
| +} |
| + |
| +void WebNotificationTray::AddNotification(const std::string& id, |
| + const string16& title, |
| + const string16& message, |
| + const string16& source, |
| + const std::string& extension) { |
| + notification_list_->AddNotification(id, title, message, source, extension); |
| + UpdateIcon(); |
| + if (bubble()) { |
| + bubble_->Update(); |
| + } else { |
| + // Only show the web notification bubble if the system tray is not shown. |
| + if (!ash::Shell::GetInstance()->system_tray()->IsBubbleVisible()) |
| + bubble_.reset(new Bubble(this)); |
|
sadrul
2012/06/06 19:19:19
This seems unfortunate. It would be nice to say 's
stevenjb
2012/06/06 23:12:15
I can put this in the status area. I was going to
|
| + } |
| +} |
| + |
| +void WebNotificationTray::RemoveNotification(const std::string& id) { |
| + if (!notification_list_->RemoveNotification(id)) |
| + return; |
| + if (delegate_) |
| + delegate_->NotificationRemoved(id); |
| + UpdateBubbleAndIcon(); |
| +} |
| + |
| +void WebNotificationTray::SetNotificationImage(const std::string& id, |
| + const SkBitmap& image) { |
| + if (notification_list_->SetNotificationImage(id, image)) { |
| + if (bubble()) |
|
sadrul
2012/06/06 19:19:19
if (notification_list_ ... && bubble())
bubble_-
stevenjb
2012/06/06 23:12:15
I personally dislike combining functions that do s
|
| + bubble_->Update(); |
| + } |
| +} |
| + |
| +void WebNotificationTray::DisableByExtension(const std::string& id) { |
| + notification_list_->RemoveNotificationsByExtension(id); |
| + UpdateBubbleAndIcon(); |
| + if (delegate_) |
| + delegate_->DisableExtension(id); |
| +} |
| + |
| +void WebNotificationTray::DisableByUrl(const std::string& id) { |
| + notification_list_->RemoveNotificationsBySource(id); |
| + UpdateBubbleAndIcon(); |
| + if (delegate_) |
| + delegate_->DisableNotificationsFromSource(id); |
| +} |
| + |
| +void WebNotificationTray::ShowSettings(const std::string& id) { |
| + if (delegate_) |
| + delegate_->ShowSettings(id); |
| +} |
| + |
| +int WebNotificationTray::GetNotificationCount() const { |
| + return notification_list()->notifications().size(); |
| +} |
| + |
| +void WebNotificationTray::UpdateIcon() { |
| + int count = GetNotificationCount(); |
| + if (count == 0) { |
| + SetVisible(false); |
| + } else { |
| + icon_->SetImage(GetNotificationImage(count)); |
| + SetVisible(true); |
| + } |
| + PreferredSizeChanged(); |
| +} |
| + |
| +void WebNotificationTray::UpdateBubbleAndIcon() { |
| + UpdateIcon(); |
| + if (bubble()) { |
| + if (GetNotificationCount() == 0) |
| + bubble_.reset(); |
| + else |
| + bubble_->Update(); |
| + } |
| +} |
| + |
| +void WebNotificationTray::ProcessLocatedEvent(const aura::LocatedEvent& event) { |
| + if (!bubble()) |
| + return; |
| + gfx::Rect bounds = |
| + bubble_->bubble_widget()->GetNativeWindow()->GetBoundsInRootWindow(); |
| + if (!bounds.Contains(event.root_location())) |
| + bubble_.reset(); |
| +} |
| + |
| +} // namespace ash |