OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "browser_actions_controller.h" | 5 #import "browser_actions_controller.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "app/gfx/canvas_paint.h" | 9 #include "app/gfx/canvas_paint.h" |
10 #include "base/sys_string_conversions.h" | 10 #include "base/sys_string_conversions.h" |
11 #include "chrome/browser/browser.h" | 11 #include "chrome/browser/browser.h" |
| 12 #include "chrome/browser/cocoa/extensions/extension_action_context_menu.h" |
12 #include "chrome/browser/cocoa/extensions/extension_popup_controller.h" | 13 #include "chrome/browser/cocoa/extensions/extension_popup_controller.h" |
13 #include "chrome/browser/cocoa/toolbar_button_cell.h" | 14 #include "chrome/browser/cocoa/toolbar_button_cell.h" |
14 #include "chrome/browser/extensions/extension_browser_event_router.h" | 15 #include "chrome/browser/extensions/extension_browser_event_router.h" |
15 #include "chrome/browser/extensions/extensions_service.h" | 16 #include "chrome/browser/extensions/extensions_service.h" |
16 #include "chrome/browser/extensions/extension_tabs_module.h" | 17 #include "chrome/browser/extensions/extension_tabs_module.h" |
17 #include "chrome/browser/extensions/image_loading_tracker.h" | 18 #include "chrome/browser/extensions/image_loading_tracker.h" |
18 #include "chrome/browser/profile.h" | 19 #include "chrome/browser/profile.h" |
19 #include "chrome/browser/tab_contents/tab_contents.h" | 20 #include "chrome/browser/tab_contents/tab_contents.h" |
20 #include "chrome/common/notification_observer.h" | 21 #include "chrome/common/notification_observer.h" |
21 #include "chrome/common/notification_registrar.h" | 22 #include "chrome/common/notification_registrar.h" |
22 #include "skia/ext/skia_utils_mac.h" | 23 #include "skia/ext/skia_utils_mac.h" |
23 | 24 |
24 static const CGFloat kBrowserActionBadgeOriginYOffset = -4; | 25 static const CGFloat kBrowserActionBadgeOriginYOffset = 5; |
25 | 26 |
26 // Since the container is the maximum height of the toolbar, we have to move the | 27 // Since the container is the maximum height of the toolbar, we have to move the |
27 // buttons up by this amount in order to have them look vertically centered | 28 // buttons up by this amount in order to have them look vertically centered |
28 // within the toolbar. | 29 // within the toolbar. |
29 static const CGFloat kBrowserActionOriginYOffset = 5; | 30 static const CGFloat kBrowserActionOriginYOffset = 5; |
30 | 31 |
31 // The size of each button on the toolbar. | 32 // The size of each button on the toolbar. |
32 static const CGFloat kBrowserActionHeight = 27; | 33 static const CGFloat kBrowserActionHeight = 27; |
33 extern const CGFloat kBrowserActionWidth = 29; | 34 extern const CGFloat kBrowserActionWidth = 29; |
34 | 35 |
35 // The padding between browser action buttons. | 36 // The padding between browser action buttons. |
36 extern const CGFloat kBrowserActionButtonPadding = 3; | 37 extern const CGFloat kBrowserActionButtonPadding = 3; |
37 | 38 |
38 NSString* const kBrowserActionsChangedNotification = @"BrowserActionsChanged"; | 39 NSString* const kBrowserActionsChangedNotification = @"BrowserActionsChanged"; |
39 | 40 |
40 @interface BrowserActionBadgeView : NSView { | 41 @interface BrowserActionCell : ToolbarButtonCell { |
41 @private | 42 @private |
42 // The current tab ID used when drawing the badge. | 43 // The current tab ID used when drawing the cell. |
43 int tabId_; | 44 int tabId_; |
44 | 45 |
45 // The action we're drawing the badge for. Weak. | 46 // The action we're drawing the cell for. Weak. |
46 ExtensionAction* extensionAction_; | 47 ExtensionAction* extensionAction_; |
47 } | 48 } |
48 | 49 |
49 @property(readwrite, nonatomic) int tabId; | 50 @property(readwrite, nonatomic) int tabId; |
50 @property(readwrite, nonatomic) ExtensionAction* extensionAction; | 51 @property(readwrite, nonatomic) ExtensionAction* extensionAction; |
51 | 52 |
52 @end | 53 @end |
53 | 54 |
54 @implementation BrowserActionBadgeView | 55 @implementation BrowserActionCell |
55 | 56 |
56 - (void)drawRect:(NSRect)dirtyRect { | 57 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
| 58 [super drawWithFrame:cellFrame inView:controlView]; |
| 59 |
57 // CanvasPaint draws its content to the current NSGraphicsContext in its | 60 // CanvasPaint draws its content to the current NSGraphicsContext in its |
58 // destructor. If anything needs to be drawn afterwards, then enclose this | 61 // destructor. If anything needs to be drawn afterwards, then enclose this |
59 // in a nested block. | 62 // in a nested block. |
60 NSRect badgeBounds = [self bounds]; | 63 cellFrame.origin.y += kBrowserActionBadgeOriginYOffset; |
61 badgeBounds.origin.y += kBrowserActionBadgeOriginYOffset; | 64 gfx::CanvasPaint canvas(cellFrame, false); |
62 gfx::CanvasPaint canvas(badgeBounds, false); | |
63 canvas.set_composite_alpha(true); | 65 canvas.set_composite_alpha(true); |
64 gfx::Rect boundingRect(NSRectToCGRect(badgeBounds)); | 66 gfx::Rect boundingRect(NSRectToCGRect(cellFrame)); |
65 extensionAction_->PaintBadge(&canvas, boundingRect, tabId_); | 67 extensionAction_->PaintBadge(&canvas, boundingRect, tabId_); |
66 } | 68 } |
67 | 69 |
68 @synthesize tabId = tabId_; | 70 @synthesize tabId = tabId_; |
69 @synthesize extensionAction = extensionAction_; | 71 @synthesize extensionAction = extensionAction_; |
70 | 72 |
71 @end | 73 @end |
72 | 74 |
73 class ExtensionImageTrackerBridge; | 75 class ExtensionImageTrackerBridge; |
74 | 76 |
75 @interface BrowserActionButton : NSButton { | 77 @interface BrowserActionButton : NSButton { |
76 @private | 78 @private |
77 scoped_ptr<ExtensionImageTrackerBridge> imageLoadingBridge_; | 79 scoped_ptr<ExtensionImageTrackerBridge> imageLoadingBridge_; |
78 | 80 |
79 scoped_nsobject<NSImage> defaultIcon_; | 81 scoped_nsobject<NSImage> defaultIcon_; |
80 | 82 |
81 scoped_nsobject<NSImage> tabSpecificIcon_; | 83 scoped_nsobject<NSImage> tabSpecificIcon_; |
82 | 84 |
83 scoped_nsobject<NSView> badgeView_; | |
84 | |
85 // The extension for this button. Weak. | 85 // The extension for this button. Weak. |
86 Extension* extension_; | 86 Extension* extension_; |
87 | 87 |
88 // Weak. Owns us. | 88 // Weak. Owns us. |
89 BrowserActionsController* controller_; | 89 BrowserActionsController* controller_; |
90 } | 90 } |
91 | 91 |
92 - (id)initWithExtension:(Extension*)extension | 92 - (id)initWithExtension:(Extension*)extension |
93 controller:(BrowserActionsController*)controller | 93 controller:(BrowserActionsController*)controller |
94 xOffset:(int)xOffset; | 94 xOffset:(int)xOffset; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 ImageLoadingTracker* tracker_; | 155 ImageLoadingTracker* tracker_; |
156 | 156 |
157 // Used for registering to receive notifications and automatic clean up. | 157 // Used for registering to receive notifications and automatic clean up. |
158 NotificationRegistrar registrar_; | 158 NotificationRegistrar registrar_; |
159 | 159 |
160 DISALLOW_COPY_AND_ASSIGN(ExtensionImageTrackerBridge); | 160 DISALLOW_COPY_AND_ASSIGN(ExtensionImageTrackerBridge); |
161 }; | 161 }; |
162 | 162 |
163 @implementation BrowserActionButton | 163 @implementation BrowserActionButton |
164 | 164 |
| 165 + (Class)cellClass { |
| 166 return [BrowserActionCell class]; |
| 167 } |
| 168 |
165 - (id)initWithExtension:(Extension*)extension | 169 - (id)initWithExtension:(Extension*)extension |
166 controller:(BrowserActionsController*)controller | 170 controller:(BrowserActionsController*)controller |
167 xOffset:(int)xOffset { | 171 xOffset:(int)xOffset { |
168 NSRect frame = NSMakeRect(xOffset, | 172 NSRect frame = NSMakeRect(xOffset, |
169 kBrowserActionOriginYOffset, | 173 kBrowserActionOriginYOffset, |
170 kBrowserActionWidth, | 174 kBrowserActionWidth, |
171 kBrowserActionHeight); | 175 kBrowserActionHeight); |
172 if ((self = [super initWithFrame:frame])) { | 176 if ((self = [super initWithFrame:frame])) { |
173 ToolbarButtonCell* cell = [[[ToolbarButtonCell alloc] init] autorelease]; | 177 BrowserActionCell* cell = [[[BrowserActionCell alloc] init] autorelease]; |
174 // [NSButton setCell:] warns to NOT use setCell: other than in the | 178 // [NSButton setCell:] warns to NOT use setCell: other than in the |
175 // initializer of a control. However, we are using a basic | 179 // initializer of a control. However, we are using a basic |
176 // NSButton whose initializer does not take an NSCell as an | 180 // NSButton whose initializer does not take an NSCell as an |
177 // object. To honor the assumed semantics, we do nothing with | 181 // object. To honor the assumed semantics, we do nothing with |
178 // NSButton between alloc/init and setCell:. | 182 // NSButton between alloc/init and setCell:. |
179 [self setCell:cell]; | 183 [self setCell:cell]; |
| 184 [cell setTabId:[controller currentTabId]]; |
| 185 [cell setExtensionAction:extension->browser_action()]; |
| 186 |
180 [self setTitle:@""]; | 187 [self setTitle:@""]; |
181 [self setButtonType:NSMomentaryChangeButton]; | 188 [self setButtonType:NSMomentaryChangeButton]; |
182 [self setShowsBorderOnlyWhileMouseInside:YES]; | 189 [self setShowsBorderOnlyWhileMouseInside:YES]; |
183 | 190 |
184 [self setTarget:controller]; | 191 [self setTarget:controller]; |
185 [self setAction:@selector(browserActionClicked:)]; | 192 [self setAction:@selector(browserActionClicked:)]; |
186 | 193 |
| 194 [self setMenu:[[[ExtensionActionContextMenu alloc] |
| 195 initWithExtension:extension] autorelease]]; |
| 196 |
187 extension_ = extension; | 197 extension_ = extension; |
188 controller_ = controller; | 198 controller_ = controller; |
189 imageLoadingBridge_.reset(new ExtensionImageTrackerBridge(self, extension)); | 199 imageLoadingBridge_.reset(new ExtensionImageTrackerBridge(self, extension)); |
190 | 200 |
191 NSRect badgeFrame = [self bounds]; | |
192 badgeView_.reset([[BrowserActionBadgeView alloc] initWithFrame:badgeFrame]); | |
193 [badgeView_ setTabId:[controller currentTabId]]; | |
194 [badgeView_ setExtensionAction:extension->browser_action()]; | |
195 [self addSubview:badgeView_]; | |
196 | |
197 [self updateState]; | 201 [self updateState]; |
198 } | 202 } |
199 | 203 |
200 return self; | 204 return self; |
201 } | 205 } |
202 | 206 |
203 - (void)setDefaultIcon:(NSImage*)image { | 207 - (void)setDefaultIcon:(NSImage*)image { |
204 defaultIcon_.reset([image retain]); | 208 defaultIcon_.reset([image retain]); |
205 } | 209 } |
206 | 210 |
(...skipping 14 matching lines...) Expand all Loading... |
221 } | 225 } |
222 | 226 |
223 SkBitmap image = extension_->browser_action()->GetIcon(tabId); | 227 SkBitmap image = extension_->browser_action()->GetIcon(tabId); |
224 if (!image.isNull()) { | 228 if (!image.isNull()) { |
225 [self setTabSpecificIcon:gfx::SkBitmapToNSImage(image)]; | 229 [self setTabSpecificIcon:gfx::SkBitmapToNSImage(image)]; |
226 [self setImage:tabSpecificIcon_]; | 230 [self setImage:tabSpecificIcon_]; |
227 } else if (defaultIcon_) { | 231 } else if (defaultIcon_) { |
228 [self setImage:defaultIcon_]; | 232 [self setImage:defaultIcon_]; |
229 } | 233 } |
230 | 234 |
231 [badgeView_ setTabId:tabId]; | 235 [[self cell] setTabId:tabId]; |
232 | 236 |
233 [self setNeedsDisplay:YES]; | 237 [self setNeedsDisplay:YES]; |
234 } | 238 } |
235 | 239 |
236 @synthesize extension = extension_; | 240 @synthesize extension = extension_; |
237 | 241 |
238 @end | 242 @end |
239 | 243 |
240 @interface BrowserActionsController(Private) | 244 @interface BrowserActionsController(Private) |
241 | 245 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 return -1; | 467 return -1; |
464 | 468 |
465 return selected_tab->controller().session_id().id(); | 469 return selected_tab->controller().session_id().id(); |
466 } | 470 } |
467 | 471 |
468 - (NSButton*)buttonWithIndex:(int)index { | 472 - (NSButton*)buttonWithIndex:(int)index { |
469 return [buttonOrder_ objectAtIndex:(NSUInteger)index]; | 473 return [buttonOrder_ objectAtIndex:(NSUInteger)index]; |
470 } | 474 } |
471 | 475 |
472 @end | 476 @end |
OLD | NEW |