| 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 #import "chrome/browser/ui/cocoa/extensions/browser_action_button.h" | 5 #import "chrome/browser/ui/cocoa/extensions/browser_action_button.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 } // anonymous namespace | 43 } // anonymous namespace |
| 44 | 44 |
| 45 // A helper class to bridge the asynchronous Skia bitmap loading mechanism to | 45 // A helper class to bridge the asynchronous Skia bitmap loading mechanism to |
| 46 // the extension's button. | 46 // the extension's button. |
| 47 class ExtensionImageTrackerBridge : public content::NotificationObserver, | 47 class ExtensionImageTrackerBridge : public content::NotificationObserver, |
| 48 public ImageLoadingTracker::Observer { | 48 public ImageLoadingTracker::Observer { |
| 49 public: | 49 public: |
| 50 ExtensionImageTrackerBridge(BrowserActionButton* owner, | 50 ExtensionImageTrackerBridge(BrowserActionButton* owner, |
| 51 const Extension* extension) | 51 const Extension* extension) |
| 52 : owner_(owner), | 52 : owner_(owner), |
| 53 tracker_(this) { | 53 tracker_(this), |
| 54 browser_action_(extension->browser_action()) { |
| 54 // The Browser Action API does not allow the default icon path to be | 55 // The Browser Action API does not allow the default icon path to be |
| 55 // changed at runtime, so we can load this now and cache it. | 56 // changed at runtime, so we can load this now and cache it. |
| 56 std::string path = extension->browser_action()->default_icon_path(); | 57 std::string path = extension->browser_action()->default_icon_path(); |
| 57 if (!path.empty()) { | 58 if (!path.empty()) { |
| 58 tracker_.LoadImage(extension, extension->GetResource(path), | 59 tracker_.LoadImage(extension, extension->GetResource(path), |
| 59 gfx::Size(Extension::kBrowserActionIconMaxSize, | 60 gfx::Size(Extension::kBrowserActionIconMaxSize, |
| 60 Extension::kBrowserActionIconMaxSize), | 61 Extension::kBrowserActionIconMaxSize), |
| 61 ImageLoadingTracker::DONT_CACHE); | 62 ImageLoadingTracker::DONT_CACHE); |
| 62 } else { | |
| 63 // Set the icon to be the default extensions icon. | |
| 64 SkBitmap bm = *ResourceBundle::GetSharedInstance().GetBitmapNamed( | |
| 65 IDR_EXTENSIONS_FAVICON); | |
| 66 [owner_ setDefaultIcon:gfx::SkBitmapToNSImage(bm)]; | |
| 67 [owner_ updateState]; | |
| 68 } | 63 } |
| 69 registrar_.Add( | 64 registrar_.Add( |
| 70 this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, | 65 this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, |
| 71 content::Source<ExtensionAction>(extension->browser_action())); | 66 content::Source<ExtensionAction>(browser_action_)); |
| 72 } | 67 } |
| 73 | 68 |
| 74 ~ExtensionImageTrackerBridge() {} | 69 ~ExtensionImageTrackerBridge() {} |
| 75 | 70 |
| 71 const ExtensionAction::PathToIconCache& loaded_icons() const { |
| 72 return loaded_icons_; |
| 73 } |
| 74 |
| 76 // ImageLoadingTracker::Observer implementation. | 75 // ImageLoadingTracker::Observer implementation. |
| 77 void OnImageLoaded(const gfx::Image& image, | 76 void OnImageLoaded(const gfx::Image& image, |
| 78 const std::string& extension_id, | 77 const std::string& extension_id, |
| 79 int index) OVERRIDE { | 78 int index) OVERRIDE { |
| 80 if (!image.IsEmpty()) | 79 if (!image.IsEmpty()) |
| 81 [owner_ setDefaultIcon:image.ToNSImage()]; | 80 loaded_icons_[browser_action_->default_icon_path()] = image; |
| 82 [owner_ updateState]; | 81 [owner_ updateState]; |
| 83 } | 82 } |
| 84 | 83 |
| 85 // Overridden from content::NotificationObserver. | 84 // Overridden from content::NotificationObserver. |
| 86 void Observe(int type, | 85 void Observe(int type, |
| 87 const content::NotificationSource& source, | 86 const content::NotificationSource& source, |
| 88 const content::NotificationDetails& details) { | 87 const content::NotificationDetails& details) { |
| 89 if (type == chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED) | 88 if (type == chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED) |
| 90 [owner_ updateState]; | 89 [owner_ updateState]; |
| 91 else | 90 else |
| 92 NOTREACHED(); | 91 NOTREACHED(); |
| 93 } | 92 } |
| 94 | 93 |
| 95 private: | 94 private: |
| 96 // Weak. Owns us. | 95 // Weak. Owns us. |
| 97 BrowserActionButton* owner_; | 96 BrowserActionButton* owner_; |
| 98 | 97 |
| 99 // Loads the button's icons for us on the file thread. | 98 // Loads the button's icons for us on the file thread. |
| 100 ImageLoadingTracker tracker_; | 99 ImageLoadingTracker tracker_; |
| 101 | 100 |
| 101 // The browser action whose images we're loading. |
| 102 const ExtensionAction* const browser_action_; |
| 103 |
| 104 // Icons loaded from paths. Currently just the browser action's default icon. |
| 105 ExtensionAction::PathToIconCache loaded_icons_; |
| 106 |
| 102 // Used for registering to receive notifications and automatic clean up. | 107 // Used for registering to receive notifications and automatic clean up. |
| 103 content::NotificationRegistrar registrar_; | 108 content::NotificationRegistrar registrar_; |
| 104 | 109 |
| 105 DISALLOW_COPY_AND_ASSIGN(ExtensionImageTrackerBridge); | 110 DISALLOW_COPY_AND_ASSIGN(ExtensionImageTrackerBridge); |
| 106 }; | 111 }; |
| 107 | 112 |
| 108 @interface BrowserActionCell (Internals) | 113 @interface BrowserActionCell (Internals) |
| 109 - (void)drawBadgeWithinFrame:(NSRect)frame; | 114 - (void)drawBadgeWithinFrame:(NSRect)frame; |
| 110 @end | 115 @end |
| 111 | 116 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 self, NSViewAnimationTargetKey, | 239 self, NSViewAnimationTargetKey, |
| 235 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey, | 240 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey, |
| 236 [NSValue valueWithRect:frameRect], NSViewAnimationEndFrameKey, | 241 [NSValue valueWithRect:frameRect], NSViewAnimationEndFrameKey, |
| 237 nil]; | 242 nil]; |
| 238 [moveAnimation_ setViewAnimations: | 243 [moveAnimation_ setViewAnimations: |
| 239 [NSArray arrayWithObject:animationDictionary]]; | 244 [NSArray arrayWithObject:animationDictionary]]; |
| 240 [moveAnimation_ startAnimation]; | 245 [moveAnimation_ startAnimation]; |
| 241 } | 246 } |
| 242 } | 247 } |
| 243 | 248 |
| 244 - (void)setDefaultIcon:(NSImage*)image { | |
| 245 defaultIcon_.reset([image retain]); | |
| 246 } | |
| 247 | |
| 248 - (void)setTabSpecificIcon:(NSImage*)image { | |
| 249 tabSpecificIcon_.reset([image retain]); | |
| 250 } | |
| 251 | |
| 252 - (void)updateState { | 249 - (void)updateState { |
| 253 if (tabId_ < 0) | 250 if (tabId_ < 0) |
| 254 return; | 251 return; |
| 255 | 252 |
| 256 std::string tooltip = extension_->browser_action()->GetTitle(tabId_); | 253 std::string tooltip = extension_->browser_action()->GetTitle(tabId_); |
| 257 if (tooltip.empty()) { | 254 if (tooltip.empty()) { |
| 258 [self setToolTip:nil]; | 255 [self setToolTip:nil]; |
| 259 } else { | 256 } else { |
| 260 [self setToolTip:base::SysUTF8ToNSString(tooltip)]; | 257 [self setToolTip:base::SysUTF8ToNSString(tooltip)]; |
| 261 } | 258 } |
| 262 | 259 |
| 263 SkBitmap image = extension_->browser_action()->GetIcon(tabId_); | 260 gfx::Image image = extension_->browser_action()->GetIcon( |
| 264 if (!image.isNull()) { | 261 tabId_, imageLoadingBridge_->loaded_icons()); |
| 265 [self setTabSpecificIcon:gfx::SkBitmapToNSImage(image)]; | 262 if (!image.IsEmpty()) |
| 266 [self setImage:tabSpecificIcon_]; | 263 [self setImage:image.ToNSImage()]; |
| 267 } else if (defaultIcon_) { | |
| 268 [self setImage:defaultIcon_]; | |
| 269 } | |
| 270 | 264 |
| 271 [[self cell] setTabId:tabId_]; | 265 [[self cell] setTabId:tabId_]; |
| 272 | 266 |
| 273 bool enabled = extension_->browser_action()->GetIsVisible(tabId_); | 267 bool enabled = extension_->browser_action()->GetIsVisible(tabId_); |
| 274 [self setEnabled:enabled ? YES : NO]; | 268 [self setEnabled:enabled ? YES : NO]; |
| 275 | 269 |
| 276 [self setNeedsDisplay:YES]; | 270 [self setNeedsDisplay:YES]; |
| 277 } | 271 } |
| 278 | 272 |
| 279 - (BOOL)isAnimating { | 273 - (BOOL)isAnimating { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 } | 316 } |
| 323 | 317 |
| 324 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 318 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 325 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | 319 gfx::ScopedNSGraphicsContextSaveGState scopedGState; |
| 326 [super drawInteriorWithFrame:cellFrame inView:controlView]; | 320 [super drawInteriorWithFrame:cellFrame inView:controlView]; |
| 327 cellFrame.origin.y += kBrowserActionBadgeOriginYOffset; | 321 cellFrame.origin.y += kBrowserActionBadgeOriginYOffset; |
| 328 [self drawBadgeWithinFrame:cellFrame]; | 322 [self drawBadgeWithinFrame:cellFrame]; |
| 329 } | 323 } |
| 330 | 324 |
| 331 @end | 325 @end |
| OLD | NEW |