Chromium Code Reviews| Index: chrome/browser/ui/views/status_icons/status_icon_chromeos.cc |
| diff --git a/chrome/browser/ui/views/status_icons/status_icon_chromeos.cc b/chrome/browser/ui/views/status_icons/status_icon_chromeos.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b2e82bf1318efe118ba2fe00f5ff247dd9211c71 |
| --- /dev/null |
| +++ b/chrome/browser/ui/views/status_icons/status_icon_chromeos.cc |
| @@ -0,0 +1,194 @@ |
| +// Copyright (c) 2011 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 "chrome/browser/ui/views/status_icons/status_icon_chromeos.h" |
| + |
| +#include "chrome/browser/chromeos/frame/browser_view.h" |
| +#include "chrome/browser/chromeos/status/status_area_button.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/browser_list.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "views/controls/menu/menu_delegate.h" |
| +#include "views/controls/menu/menu_model_adapter.h" |
| +#include "views/controls/menu/menu_runner.h" |
| +#include "views/controls/menu/view_menu_delegate.h" |
| + |
| +namespace { |
| + |
| +chromeos::BrowserView* GetBrowserView(Browser* browser) { |
| + chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>( |
| + BrowserView::GetBrowserViewForBrowser(browser)); |
|
stevenjb
2011/11/14 19:03:22
We should really put this in chromeos/frame/browse
Leandro Graciá Gil
2011/11/15 22:23:31
Done.
|
| + DCHECK(browser_view); |
| + return browser_view; |
| +} |
| + |
| +} // anonymous namespace |
| + |
| +class StatusIconChromeOS::NotificationTrayButton |
| + : public StatusAreaButton, |
| + public views::MenuDelegate, |
| + public views::ViewMenuDelegate { |
| + public: |
| + NotificationTrayButton(StatusIconChromeOS* status_icon, |
| + StatusAreaButton::Delegate* delegate) |
|
stevenjb
2011/11/14 19:03:22
nit: align parameters
Leandro Graciá Gil
2011/11/15 22:23:31
Done.
|
| + : StatusAreaButton(delegate, this), |
| + status_icon_(status_icon) { |
| + } |
| + virtual ~NotificationTrayButton() {} |
| + |
| + void SetImage(const SkBitmap& image) { |
| + SetIcon(image); |
| + SetVisible(true); |
| + PreferredSizeChanged(); |
| + SchedulePaint(); |
| + } |
| + |
| + void Hide() { |
| + SetVisible(false); |
| + SchedulePaint(); |
| + } |
| + |
| + // views::MenuButton overrides. |
| + virtual bool Activate() OVERRIDE { |
| + // All tray buttons are removed on status icon destruction. |
| + // This should never be called afterwards. |
| + bool retval = views::MenuButton::Activate(); |
| + status_icon_->Clicked(); |
| + return retval; |
| + } |
| + |
| + // views::ViewMenuDelegate implementation. |
| + virtual void RunMenu(views::View* source, const gfx::Point& pt) |
| + OVERRIDE { |
| + views::MenuRunner* menu_runner = status_icon_->menu_runner(); |
| + if (!menu_runner) |
| + return; |
| + |
| + gfx::Point screen_location; |
| + views::View::ConvertPointToScreen(source, &screen_location); |
| + gfx::Rect bounds(screen_location, source->size()); |
| + if (menu_runner->RunMenuAt( |
| + source->GetWidget()->GetTopLevelWidget(), this, bounds, |
| + views::MenuItemView::TOPRIGHT, views::MenuRunner::HAS_MNEMONICS) == |
| + views::MenuRunner::MENU_DELETED) |
| + return; |
|
stevenjb
2011/11/14 19:03:22
What is the purpose of the if statement here?
Leandro Graciá Gil
2011/11/15 22:23:31
RunMenuAt is defined using WARN_UNUSED_RESULT. So,
|
| + } |
| + |
| + private: |
| + StatusIconChromeOS* status_icon_; |
| +}; |
| + |
| +StatusIconChromeOS::StatusIconChromeOS() |
| + : last_image_(new SkBitmap()) { |
| + // This class adds a tray icon in all browser windows for Chrome OS. |
| + // Since the target of this API is to provide notification as much |
|
stevenjb
2011/11/14 19:03:22
This sentence isn't clear to me.
Leandro Graciá Gil
2011/11/15 22:23:31
Done.
|
| + // "permanent" as possible, this is the closest we can get since |
| + // there is no real system tray in Chrome OS, only browser windows. |
| + for (BrowserList::BrowserVector::const_iterator it = BrowserList::begin(); |
|
Andrew T Wilson (Slow)
2011/11/14 23:46:03
Just to verify - do we want this on all browser wi
Leandro Graciá Gil
2011/11/15 22:23:31
Yes, I have discussed this with the Chrome OS UI d
|
| + it != BrowserList::end(); ++it) { |
| + AddIconToBrowser(*it); |
| + } |
| + |
| + // Listen to all browser open/close events to keep our map up to date. |
| + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, |
| + content::NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, |
| + content::NotificationService::AllSources()); |
| +} |
| + |
| +StatusIconChromeOS::~StatusIconChromeOS() { |
| + for (TrayButtonMap::const_iterator it = tray_button_map_.begin(); |
| + it != tray_button_map_.end(); ++it) { |
| + it->first->RemoveTrayButton(it->second); |
| + } |
| +} |
| + |
| +void StatusIconChromeOS::Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + switch (type) { |
| + case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { |
| + Browser* browser = content::Source<Browser>(source).ptr(); |
| + AddIconToBrowser(browser); |
| + break; |
| + } |
| + |
| + case chrome::NOTIFICATION_BROWSER_CLOSED: { |
| + chromeos::BrowserView* browser_view = GetBrowserView( |
| + content::Source<Browser>(source).ptr()); |
| + tray_button_map_.erase(browser_view); |
| + break; |
| + } |
| + |
| + default: |
| + NOTREACHED(); |
| + } |
| +} |
| + |
| +void StatusIconChromeOS::AddIconToBrowser(Browser* browser) { |
| + chromeos::BrowserView* browser_view = GetBrowserView(browser); |
| + DCHECK(tray_button_map_.find(browser_view) == tray_button_map_.end()); |
|
stevenjb
2011/11/14 19:03:22
We should probably do more than a DCHECK here, sin
Leandro Graciá Gil
2011/11/15 22:23:31
Done.
|
| + |
| + NotificationTrayButton* tray_button = |
| + new NotificationTrayButton(this, browser_view); |
| + tray_button_map_[browser_view] = tray_button; |
| + browser_view->AddTrayButton(tray_button, false); |
| + if (!last_image_->empty()) |
| + tray_button->SetImage(*last_image_.get()); |
| +} |
| + |
| +void StatusIconChromeOS::SetImage(const SkBitmap& image) { |
| + if (image.isNull()) |
| + return; |
| + |
| + for (TrayButtonMap::const_iterator it = tray_button_map_.begin(); |
| + it != tray_button_map_.end(); ++it) { |
| + it->second->SetImage(image); |
| + } |
| + *last_image_.get() = image; |
| +} |
| + |
| +void StatusIconChromeOS::SetPressedImage(const SkBitmap& image) { |
| + // Not supported. Chrome OS shows the context menu on left clicks. |
| +} |
| + |
| +void StatusIconChromeOS::SetToolTip(const string16& tool_tip) { |
| + for (TrayButtonMap::const_iterator it = tray_button_map_.begin(); |
| + it != tray_button_map_.end(); ++it) { |
| + it->second->SetTooltipText(tool_tip); |
| + } |
| +} |
| + |
| +void StatusIconChromeOS::DisplayBalloon(const SkBitmap& icon, |
| + const string16& title, |
| + const string16& contents) { |
| + notification_.DisplayBalloon(icon, title, contents); |
| +} |
| + |
| +void StatusIconChromeOS::Clicked() { |
| + // Chrome OS shows the context menu on left button clicks, and this event |
| + // should only be dispatched when the click doesn't show the context menu. |
| + if (!menu_runner_.get()) |
| + DispatchClickEvent(); |
| +} |
| + |
| +void StatusIconChromeOS::UpdatePlatformContextMenu(ui::MenuModel* menu) { |
| + // If no items are passed, blow away our context menu. |
| + if (!menu) { |
| + context_menu_adapter_.reset(); |
| + menu_runner_.reset(); |
| + return; |
| + } |
| + |
| + // Create context menu with the new contents. |
| + views::MenuModelAdapter* adapter = new views::MenuModelAdapter(menu); |
| + context_menu_adapter_.reset(adapter); |
| + views::MenuItemView* menu_view = new views::MenuItemView(adapter); |
| + adapter->BuildMenu(menu_view); |
| + |
| + // menu_runner_ takes ownership of menu. |
| + menu_runner_.reset(new views::MenuRunner(menu_view)); |
| +} |