diff options
author | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-06 22:02:04 +0000 |
---|---|---|
committer | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-06 22:02:04 +0000 |
commit | ccb55cf5b25fd67078e51b924cf6e694d7374376 (patch) | |
tree | b04cd09754ea2cdc2ee6d333166de81688a97c8e /chrome/browser/cocoa | |
parent | 42695f09883e29aa167b79ad75263e3d611dce2d (diff) | |
download | chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.zip chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.tar.gz chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.tar.bz2 |
Initial implementation of status tray functionality (mac-only, currently).
Added Mac implementation of StatusIcon, and added a simple click callback that
displays the "extensions" tab when clicked on, to allow us to dogfood long-lived
extensions.
BUG=37375
Review URL: http://codereview.chromium.org/661454
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40847 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa')
3 files changed, 200 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/status_icons/status_icon_mac.h b/chrome/browser/cocoa/status_icons/status_icon_mac.h new file mode 100644 index 0000000..d606429 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac.h @@ -0,0 +1,48 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ +#define CHROME_BROWSER_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ + +#include <vector> + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#include "base/string16.h" +#include "chrome/browser/status_icons/status_icon.h" + +class SkBitmap; +@class NSStatusItem; +@class StatusItemController; + +class StatusIconMac : public StatusIcon { + public: + StatusIconMac(); + virtual ~StatusIconMac(); + + // Sets the image associated with this status icon. + virtual void SetImage(const SkBitmap& image); + + // Sets the hover text for this status icon. + virtual void SetToolTip(const string16& tool_tip); + + // Adds/removes a observer for status bar events. + virtual void AddObserver(StatusIcon::StatusIconObserver* observer); + virtual void RemoveObserver(StatusIcon::StatusIconObserver* observer); + + // Called back if the user clicks on the status bar icon. + void HandleClick(); + + private: + // Getter for item_ that allows lazy initialization. + NSStatusItem* item(); + scoped_nsobject<NSStatusItem> item_; + + scoped_nsobject<StatusItemController> controller_; + std::vector<StatusIcon::StatusIconObserver*> observers_; +}; + + +#endif // CHROME_BROWSER_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ diff --git a/chrome/browser/cocoa/status_icons/status_icon_mac.mm b/chrome/browser/cocoa/status_icons/status_icon_mac.mm new file mode 100644 index 0000000..201b6d4 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac.mm @@ -0,0 +1,95 @@ +// Copyright (c) 2010 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/cocoa/status_icons/status_icon_mac.h" + +#include "base/logging.h" +#include "base/sys_string_conversions.h" +#include "skia/ext/skia_utils_mac.h" +#include "third_party/skia/include/core/SkBitmap.h" + +@interface StatusItemController : NSObject { + StatusIconMac* statusIcon_; // weak +} +- initWithIcon:(StatusIconMac*)icon; +- (void)handleClick:(id)sender; + +@end // @interface StatusItemController + +@implementation StatusItemController + +- (id)initWithIcon:(StatusIconMac*)icon { + statusIcon_ = icon; + return self; +} + +- (void)handleClick:(id)sender { + // Pass along the click notification to our owner. + DCHECK(statusIcon_); + statusIcon_->HandleClick(); +} + +@end + +StatusIconMac::StatusIconMac() + : item_(NULL) { + controller_.reset([[StatusItemController alloc] initWithIcon:this]); +} + +StatusIconMac::~StatusIconMac() { + // Remove the status item from the status bar. + if (item_) + [[NSStatusBar systemStatusBar] removeStatusItem:item_]; +} + +NSStatusItem* StatusIconMac::item() { + if (!item_.get()) { + // Create a new status item. + item_.reset([[[NSStatusBar systemStatusBar] + statusItemWithLength:NSSquareStatusItemLength] retain]); + [item_ setEnabled:YES]; + [item_ setTarget:controller_]; + [item_ setAction:@selector(handleClick:)]; + } + return item_.get(); +} + +void StatusIconMac::SetImage(const SkBitmap& bitmap) { + if (!bitmap.isNull()) { + NSImage* image = gfx::SkBitmapToNSImage(bitmap); + if (image) + [item() setImage:image]; + } +} + +void StatusIconMac::SetToolTip(const string16& tool_tip) { + [item() setToolTip:base::SysUTF16ToNSString(tool_tip)]; +} + +void StatusIconMac::AddObserver(StatusIconObserver* observer) { + observers_.push_back(observer); +} + +void StatusIconMac::RemoveObserver(StatusIconObserver* observer) { + std::vector<StatusIconObserver*>::iterator iter = + std::find(observers_.begin(), observers_.end(), observer); + if (iter != observers_.end()) + observers_.erase(iter); +} + +void StatusIconMac::HandleClick() { + // Walk observers, call callback for each one. + for (std::vector<StatusIconObserver*>::const_iterator iter = + observers_.begin(); + iter != observers_.end(); + ++iter) { + StatusIconObserver* observer = *iter; + observer->OnClicked(); + } +} + +// static factory method +StatusIcon* StatusIcon::Create() { + return new StatusIconMac(); +} diff --git a/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm b/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm new file mode 100644 index 0000000..4a7b284 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm @@ -0,0 +1,57 @@ +// Copyright (c) 2010 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 "app/resource_bundle.h" +#include "base/string_util.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/browser/cocoa/status_icons/status_icon_mac.h" +#include "grit/browser_resources.h" +#include "grit/theme_resources.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +class SkBitmap; + +class MockStatusIconObserver : public StatusIcon::StatusIconObserver { + public: + MOCK_METHOD0(OnClicked, void()); +}; + +class StatusIconMacTest : public CocoaTest { +}; + +TEST_F(StatusIconMacTest, Create) { + // Create an icon, set the tool tip, then shut it down (checks for leaks). + scoped_ptr<StatusIcon> icon(new StatusIconMac()); + SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_STATUS_TRAY_ICON); + icon->SetImage(*bitmap); + icon->SetToolTip(ASCIIToUTF16("tool tip")); +} + +TEST_F(StatusIconMacTest, ObserverAdd) { + // Make sure that observers are invoked when we click items. + StatusIconMac icon; + MockStatusIconObserver observer, observer2; + EXPECT_CALL(observer, OnClicked()).Times(2); + EXPECT_CALL(observer2, OnClicked()); + icon.AddObserver(&observer); + icon.HandleClick(); + icon.AddObserver(&observer2); + icon.HandleClick(); + icon.RemoveObserver(&observer); + icon.RemoveObserver(&observer2); +} + +TEST_F(StatusIconMacTest, ObserverRemove) { + // Make sure that observers are no longer invoked after they are removed. + StatusIconMac icon; + MockStatusIconObserver observer; + EXPECT_CALL(observer, OnClicked()); + icon.AddObserver(&observer); + icon.HandleClick(); + icon.RemoveObserver(&observer); + icon.HandleClick(); +} + |