Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: chrome/browser/cocoa/extensions/browser_actions_controller.mm

Issue 595017: [Mac] Use the ExtensionToolbarModel for ordering of the Browser Actions. Prep... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Remove redundant profile object. Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #include "chrome/browser/browser.h" 10 #include "chrome/browser/browser.h"
11 #include "chrome/browser/cocoa/extensions/browser_action_button.h" 11 #include "chrome/browser/cocoa/extensions/browser_action_button.h"
12 #include "chrome/browser/cocoa/extensions/browser_actions_container_view.h" 12 #include "chrome/browser/cocoa/extensions/browser_actions_container_view.h"
13 #include "chrome/browser/cocoa/extensions/extension_popup_controller.h" 13 #include "chrome/browser/cocoa/extensions/extension_popup_controller.h"
14 #include "chrome/browser/extensions/extension_browser_event_router.h" 14 #include "chrome/browser/extensions/extension_browser_event_router.h"
15 #include "chrome/browser/extensions/extension_toolbar_model.h"
15 #include "chrome/browser/extensions/extensions_service.h" 16 #include "chrome/browser/extensions/extensions_service.h"
16 #include "chrome/browser/profile.h" 17 #include "chrome/browser/profile.h"
17 #include "chrome/browser/tab_contents/tab_contents.h" 18 #include "chrome/browser/tab_contents/tab_contents.h"
18 #include "chrome/common/notification_observer.h" 19 #include "chrome/common/notification_observer.h"
19 #include "chrome/common/notification_registrar.h" 20 #include "chrome/common/notification_registrar.h"
20 21
21 // The padding between browser action buttons. 22 // The padding between browser action buttons.
22 extern const CGFloat kBrowserActionButtonPadding = 3; 23 extern const CGFloat kBrowserActionButtonPadding = 3;
23 24
24 NSString* const kBrowserActionsChangedNotification = @"BrowserActionsChanged"; 25 NSString* const kBrowserActionsChangedNotification = @"BrowserActionsChanged";
25 26
26 @interface BrowserActionsController(Private) 27 @interface BrowserActionsController(Private)
27 - (void)createActionButtonForExtension:(Extension*)extension; 28 - (void)createActionButtonForExtension:(Extension*)extension
29 withIndex:(int)index;
28 - (void)removeActionButtonForExtension:(Extension*)extension; 30 - (void)removeActionButtonForExtension:(Extension*)extension;
29 - (void)repositionActionButtons; 31 - (void)repositionActionButtons;
30 - (int)currentTabId; 32 - (int)currentTabId;
31 @end 33 @end
32 34
33 // A helper class to proxy extension notifications to the view controller's 35 // A helper class to proxy extension notifications to the view controller's
34 // appropriate methods. 36 // appropriate methods.
35 class ExtensionsServiceObserverBridge : public NotificationObserver { 37 class ExtensionsServiceObserverBridge : public NotificationObserver,
38 public ExtensionToolbarModel::Observer {
36 public: 39 public:
37 ExtensionsServiceObserverBridge(BrowserActionsController* owner, 40 ExtensionsServiceObserverBridge(BrowserActionsController* owner,
38 Profile* profile) : owner_(owner) { 41 Profile* profile) : owner_(owner) {
39 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
40 Source<Profile>(profile));
41 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
42 Source<Profile>(profile));
43 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
44 Source<Profile>(profile));
45 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, 42 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
46 Source<Profile>(profile)); 43 Source<Profile>(profile));
47 } 44 }
48 45
49 // Runs |owner_|'s method corresponding to the event type received from the
50 // notification system.
51 // Overridden from NotificationObserver. 46 // Overridden from NotificationObserver.
52 void Observe(NotificationType type, 47 void Observe(NotificationType type,
53 const NotificationSource& source, 48 const NotificationSource& source,
54 const NotificationDetails& details) { 49 const NotificationDetails& details) {
55 switch (type.value) { 50 switch (type.value) {
56 case NotificationType::EXTENSION_LOADED: {
57 Extension* extension = Details<Extension>(details).ptr();
58 [owner_ createActionButtonForExtension:extension];
59 [owner_ browserActionVisibilityHasChanged];
60 break;
61 }
62 case NotificationType::EXTENSION_UNLOADED:
63 case NotificationType::EXTENSION_UNLOADED_DISABLED: {
64 Extension* extension = Details<Extension>(details).ptr();
65 [owner_ removeActionButtonForExtension:extension];
66 [owner_ browserActionVisibilityHasChanged];
67 break;
68 }
69 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: { 51 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
70 ExtensionPopupController* popup = [ExtensionPopupController popup]; 52 ExtensionPopupController* popup = [ExtensionPopupController popup];
71 if (popup && ![popup isClosing]) 53 if (popup && ![popup isClosing])
72 [popup close]; 54 [popup close];
73 55
74 break; 56 break;
75 } 57 }
76 default: 58 default:
77 NOTREACHED() << L"Unexpected notification"; 59 NOTREACHED() << L"Unexpected notification";
78 } 60 }
79 } 61 }
80 62
63 // ExtensionToolbarModel::Observer implementation.
64 void BrowserActionAdded(Extension* extension, int index) {
65 [owner_ createActionButtonForExtension:extension withIndex:index];
66 }
67
68 void BrowserActionRemoved(Extension* extension) {
69 [owner_ removeActionButtonForExtension:extension];
70 }
71
81 private: 72 private:
82 // The object we need to inform when we get a notification. Weak. Owns us. 73 // The object we need to inform when we get a notification. Weak. Owns us.
83 BrowserActionsController* owner_; 74 BrowserActionsController* owner_;
84 75
85 // Used for registering to receive notifications and automatic clean up. 76 // Used for registering to receive notifications and automatic clean up.
86 NotificationRegistrar registrar_; 77 NotificationRegistrar registrar_;
87 78
88 DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceObserverBridge); 79 DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceObserverBridge);
89 }; 80 };
90 81
91 @implementation BrowserActionsController 82 @implementation BrowserActionsController
92 83
93 - (id)initWithBrowser:(Browser*)browser 84 - (id)initWithBrowser:(Browser*)browser
94 containerView:(BrowserActionsContainerView*)container { 85 containerView:(BrowserActionsContainerView*)container {
95 DCHECK(browser && container); 86 DCHECK(browser && container);
96 87
97 if ((self = [super init])) { 88 if ((self = [super init])) {
98 browser_ = browser; 89 browser_ = browser;
99 profile_ = browser->profile(); 90 profile_ = browser->profile();
91 observer_.reset(new ExtensionsServiceObserverBridge(self, profile_));
92 ExtensionsService* extensionsService = profile_->GetExtensionsService();
93 if (!extensionsService) { // |extensionsService| can be NULL in Incognito.
Erik does not do reviews 2010/02/10 16:57:41 FYI, this is going to change soon (see http://code
94 toolbarModel_ = NULL;
95 } else {
96 toolbarModel_ = extensionsService->toolbar_model();
97 toolbarModel_->AddObserver(observer_.get());
98 }
100 99
101 containerView_ = container; 100 containerView_ = container;
102 [containerView_ setHidden:YES]; 101 [containerView_ setHidden:YES];
103 observer_.reset(new ExtensionsServiceObserverBridge(self, profile_)); 102
104 buttons_.reset([[NSMutableDictionary alloc] init]); 103 buttons_.reset([[NSMutableDictionary alloc] init]);
105 buttonOrder_.reset([[NSMutableArray alloc] init]); 104 buttonOrder_.reset([[NSMutableArray alloc] init]);
106 } 105 }
107 106
108 return self; 107 return self;
109 } 108 }
110 109
111 - (void)dealloc { 110 - (void)dealloc {
111 if (toolbarModel_)
112 toolbarModel_->RemoveObserver(observer_.get());
113
112 [[NSNotificationCenter defaultCenter] removeObserver:self]; 114 [[NSNotificationCenter defaultCenter] removeObserver:self];
113 [super dealloc]; 115 [super dealloc];
114 } 116 }
115 117
116 - (void)update { 118 - (void)update {
117 for (BrowserActionButton* button in [buttons_ allValues]) { 119 for (BrowserActionButton* button in [buttons_ allValues]) {
118 [button setTabId:[self currentTabId]]; 120 [button setTabId:[self currentTabId]];
119 [button updateState]; 121 [button updateState];
120 } 122 }
121 } 123 }
122 124
123 - (void)browserActionVisibilityHasChanged {
124 [containerView_ setNeedsDisplay:YES];
125 }
126
127 - (void)createButtons { 125 - (void)createButtons {
128 ExtensionsService* extensionsService = profile_->GetExtensionsService(); 126 // No extensions in incognito mode.
129 if (!extensionsService) // |extensionsService| can be NULL in Incognito. 127 if (!toolbarModel_)
130 return; 128 return;
131 129
132 for (size_t i = 0; i < extensionsService->extensions()->size(); ++i) { 130 int i = 0;
133 Extension* extension = extensionsService->GetExtensionById( 131 for (ExtensionList::iterator iter = toolbarModel_->begin();
134 extensionsService->extensions()->at(i)->id(), false); 132 iter != toolbarModel_->end(); ++iter) {
135 if (extension->browser_action()) { 133 [self createActionButtonForExtension:*iter withIndex:i++];
136 [self createActionButtonForExtension:extension];
137 }
138 } 134 }
139 } 135 }
140 136
141 - (void)createActionButtonForExtension:(Extension*)extension { 137 - (void)createActionButtonForExtension:(Extension*)extension
138 withIndex:(int)index {
142 if (!extension->browser_action()) 139 if (!extension->browser_action())
143 return; 140 return;
144 141
145 if ([buttons_ count] == 0) { 142 // Show the container if it's the first button. Otherwise it will be shown
146 // Only call if we're adding our first button, otherwise it will be shown 143 // already.
147 // already. 144 if ([buttons_ count] == 0)
148 [containerView_ setHidden:NO]; 145 [containerView_ setHidden:NO];
149 }
150 146
151 int xOffset = 147 BrowserActionButton* newButton = [[[BrowserActionButton alloc]
152 [buttons_ count] * (kBrowserActionWidth + kBrowserActionButtonPadding); 148 initWithExtension:extension
153 BrowserActionButton* newButton = 149 profile:profile_
154 [[[BrowserActionButton alloc] initWithExtension:extension 150 tabId:[self currentTabId]] autorelease];
155 tabId:[self currentTabId]
156 xOffset:xOffset] autorelease];
157 [newButton setTarget:self]; 151 [newButton setTarget:self];
158 [newButton setAction:@selector(browserActionClicked:)]; 152 [newButton setAction:@selector(browserActionClicked:)];
159 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); 153 NSString* buttonKey = base::SysUTF8ToNSString(extension->id());
160 [buttons_ setObject:newButton forKey:buttonKey]; 154 [buttons_ setObject:newButton forKey:buttonKey];
161 [buttonOrder_ addObject:newButton]; 155 [buttonOrder_ insertObject:newButton atIndex:index];
162 [containerView_ addSubview:newButton]; 156 [containerView_ addSubview:newButton];
157 [self repositionActionButtons];
163 158
164 [[NSNotificationCenter defaultCenter] 159 [[NSNotificationCenter defaultCenter]
165 postNotificationName:kBrowserActionsChangedNotification object:self]; 160 postNotificationName:kBrowserActionsChangedNotification object:self];
161 [containerView_ setNeedsDisplay:YES];
Erik does not do reviews 2010/02/10 16:57:41 I thought adding and removing subviews always set
Bons 2010/02/10 17:52:30 I don't see anything in the docs, but also, we wan
166 } 162 }
167 163
168 - (void)removeActionButtonForExtension:(Extension*)extension { 164 - (void)removeActionButtonForExtension:(Extension*)extension {
169 if (!extension->browser_action()) 165 if (!extension->browser_action())
170 return; 166 return;
171 167
172 NSString* buttonKey = base::SysUTF8ToNSString(extension->id()); 168 NSString* buttonKey = base::SysUTF8ToNSString(extension->id());
173 169
174 BrowserActionButton* button = [buttons_ objectForKey:buttonKey]; 170 BrowserActionButton* button = [buttons_ objectForKey:buttonKey];
175 if (!button) { 171 if (!button) {
176 NOTREACHED(); 172 NOTREACHED();
177 return; 173 return;
178 } 174 }
179 [button removeFromSuperview]; 175 [button removeFromSuperview];
180 [buttons_ removeObjectForKey:buttonKey]; 176 [buttons_ removeObjectForKey:buttonKey];
181 [buttonOrder_ removeObject:button]; 177 [buttonOrder_ removeObject:button];
182 if ([buttons_ count] == 0) { 178 if ([buttons_ count] == 0) {
183 // No more buttons? Hide the container. 179 // No more buttons? Hide the container.
184 [containerView_ setHidden:YES]; 180 [containerView_ setHidden:YES];
185 } else { 181 } else {
186 // repositionActionButtons only needs to be called if removing a browser
187 // action button because adding one will always append to the end of the
188 // container, while removing one may require that those to the right of it
189 // be shifted to the left.
190 [self repositionActionButtons]; 182 [self repositionActionButtons];
191 } 183 }
192 [[NSNotificationCenter defaultCenter] 184 [[NSNotificationCenter defaultCenter]
193 postNotificationName:kBrowserActionsChangedNotification object:self]; 185 postNotificationName:kBrowserActionsChangedNotification object:self];
186 [containerView_ setNeedsDisplay:YES];
194 } 187 }
195 188
196 - (void)repositionActionButtons { 189 - (void)repositionActionButtons {
197 for (NSUInteger i = 0; i < [buttonOrder_ count]; ++i) { 190 for (NSUInteger i = 0; i < [buttonOrder_ count]; ++i) {
198 CGFloat xOffset = i * (kBrowserActionWidth + kBrowserActionButtonPadding); 191 CGFloat xOffset = i * (kBrowserActionWidth + kBrowserActionButtonPadding);
199 BrowserActionButton* button = [buttonOrder_ objectAtIndex:i]; 192 BrowserActionButton* button = [buttonOrder_ objectAtIndex:i];
200 NSRect buttonFrame = [button frame]; 193 NSRect buttonFrame = [button frame];
201 buttonFrame.origin.x = xOffset; 194 buttonFrame.origin.x = xOffset;
202 [button setFrame:buttonFrame]; 195 [button setFrame:buttonFrame];
203 } 196 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 } 260 }
268 NOTREACHED(); 261 NOTREACHED();
269 return nil; 262 return nil;
270 } 263 }
271 264
272 - (NSButton*)buttonWithIndex:(int)index { 265 - (NSButton*)buttonWithIndex:(int)index {
273 return [buttonOrder_ objectAtIndex:(NSUInteger)index]; 266 return [buttonOrder_ objectAtIndex:(NSUInteger)index];
274 } 267 }
275 268
276 @end 269 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698