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

Side by Side Diff: chrome/browser/ui/cocoa/profile_menu_controller.mm

Issue 229163004: [Mac] Move profile related UI from cocoa/browser to cocoa/profiles (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: oops forgot a comment Created 6 years, 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/profile_menu_controller.h"
6
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/profiles/avatar_menu.h"
11 #include "chrome/browser/profiles/avatar_menu_observer.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/profiles/profile_info_cache.h"
14 #include "chrome/browser/profiles/profile_info_interface.h"
15 #include "chrome/browser/profiles/profile_info_util.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/profiles/profile_metrics.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/browser/ui/browser_list_observer.h"
21 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
22 #include "grit/generated_resources.h"
23 #include "ui/base/l10n/l10n_util_mac.h"
24 #include "ui/gfx/image/image.h"
25
26 @interface ProfileMenuController (Private)
27 - (void)initializeMenu;
28 @end
29
30 namespace ProfileMenuControllerInternal {
31
32 class Observer : public chrome::BrowserListObserver,
33 public AvatarMenuObserver {
34 public:
35 Observer(ProfileMenuController* controller) : controller_(controller) {
36 BrowserList::AddObserver(this);
37 }
38
39 virtual ~Observer() {
40 BrowserList::RemoveObserver(this);
41 }
42
43 // chrome::BrowserListObserver:
44 virtual void OnBrowserAdded(Browser* browser) OVERRIDE {}
45 virtual void OnBrowserRemoved(Browser* browser) OVERRIDE {
46 [controller_ activeBrowserChangedTo:chrome::GetLastActiveBrowser()];
47 }
48 virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE {
49 [controller_ activeBrowserChangedTo:browser];
50 }
51
52 // AvatarMenuObserver:
53 virtual void OnAvatarMenuChanged(AvatarMenu* menu) OVERRIDE {
54 [controller_ rebuildMenu];
55 }
56
57 private:
58 ProfileMenuController* controller_; // Weak; owns this.
59 };
60
61 } // namespace ProfileMenuControllerInternal
62
63 ////////////////////////////////////////////////////////////////////////////////
64
65 @implementation ProfileMenuController
66
67 - (id)initWithMainMenuItem:(NSMenuItem*)item {
68 if ((self = [super init])) {
69 mainMenuItem_ = item;
70
71 base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:
72 l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME)]);
73 [mainMenuItem_ setSubmenu:menu];
74
75 // This object will be constructed as part of nib loading, which happens
76 // before the message loop starts and g_browser_process is available.
77 // Schedule this on the loop to do work when the browser is ready.
78 [self performSelector:@selector(initializeMenu)
79 withObject:nil
80 afterDelay:0];
81 }
82 return self;
83 }
84
85 - (IBAction)switchToProfileFromMenu:(id)sender {
86 menu_->SwitchToProfile([sender tag], false,
87 ProfileMetrics::SWITCH_PROFILE_MENU);
88 }
89
90 - (IBAction)switchToProfileFromDock:(id)sender {
91 // Explicitly bring to the foreground when taking action from the dock.
92 [NSApp activateIgnoringOtherApps:YES];
93 menu_->SwitchToProfile([sender tag], false,
94 ProfileMetrics::SWITCH_PROFILE_DOCK);
95 }
96
97 - (IBAction)editProfile:(id)sender {
98 menu_->EditProfile(menu_->GetActiveProfileIndex());
99 }
100
101 - (IBAction)newProfile:(id)sender {
102 menu_->AddNewProfile(ProfileMetrics::ADD_NEW_USER_MENU);
103 }
104
105 - (BOOL)insertItemsIntoMenu:(NSMenu*)menu
106 atOffset:(NSInteger)offset
107 fromDock:(BOOL)dock {
108 if (!menu_ || !menu_->ShouldShowAvatarMenu())
109 return NO;
110
111 if (dock) {
112 NSString* headerName =
113 l10n_util::GetNSStringWithFixup(IDS_PROFILES_OPTIONS_GROUP_NAME);
114 base::scoped_nsobject<NSMenuItem> header(
115 [[NSMenuItem alloc] initWithTitle:headerName
116 action:NULL
117 keyEquivalent:@""]);
118 [header setEnabled:NO];
119 [menu insertItem:header atIndex:offset++];
120 }
121
122 for (size_t i = 0; i < menu_->GetNumberOfItems(); ++i) {
123 const AvatarMenu::Item& itemData = menu_->GetItemAt(i);
124 NSString* name = base::SysUTF16ToNSString(itemData.name);
125 SEL action = dock ? @selector(switchToProfileFromDock:)
126 : @selector(switchToProfileFromMenu:);
127 NSMenuItem* item = [self createItemWithTitle:name
128 action:action];
129 [item setTag:itemData.menu_index];
130 if (dock) {
131 [item setIndentationLevel:1];
132 } else {
133 gfx::Image itemIcon = itemData.icon;
134 // The image might be too large and need to be resized (i.e. if this is
135 // a signed-in user using the GAIA profile photo).
136 if (itemIcon.Width() > profiles::kAvatarIconWidth ||
137 itemIcon.Height() > profiles::kAvatarIconHeight) {
138 itemIcon = profiles::GetAvatarIconForWebUI(itemIcon, true);
139 }
140 DCHECK(itemIcon.Width() <= profiles::kAvatarIconWidth);
141 DCHECK(itemIcon.Height() <= profiles::kAvatarIconHeight);
142 [item setImage:itemIcon.ToNSImage()];
143 [item setState:itemData.active ? NSOnState : NSOffState];
144 }
145 [menu insertItem:item atIndex:i + offset];
146 }
147
148 return YES;
149 }
150
151 - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
152 // In guest mode, chrome://settings isn't available, so disallow creating
153 // or editing a profile.
154 Profile* activeProfile = ProfileManager::GetLastUsedProfile();
155 if (activeProfile->IsGuestSession()) {
156 return [menuItem action] != @selector(newProfile:) &&
157 [menuItem action] != @selector(editProfile:);
158 }
159
160 const AvatarMenu::Item& itemData = menu_->GetItemAt(
161 menu_->GetActiveProfileIndex());
162 if ([menuItem action] == @selector(switchToProfileFromDock:) ||
163 [menuItem action] == @selector(switchToProfileFromMenu:)) {
164 if (!itemData.managed)
165 return YES;
166
167 return [menuItem tag] == static_cast<NSInteger>(itemData.menu_index);
168 }
169
170 if ([menuItem action] == @selector(newProfile:))
171 return !itemData.managed;
172
173 return YES;
174 }
175
176 // Private /////////////////////////////////////////////////////////////////////
177
178 - (NSMenu*)menu {
179 return [mainMenuItem_ submenu];
180 }
181
182 - (void)initializeMenu {
183 observer_.reset(new ProfileMenuControllerInternal::Observer(self));
184 menu_.reset(new AvatarMenu(
185 &g_browser_process->profile_manager()->GetProfileInfoCache(),
186 observer_.get(),
187 NULL));
188 menu_->RebuildMenu();
189
190 [[self menu] addItem:[NSMenuItem separatorItem]];
191
192 NSMenuItem* item = [self createItemWithTitle:
193 l10n_util::GetNSStringWithFixup(IDS_PROFILES_CUSTOMIZE_PROFILE)
194 action:@selector(editProfile:)];
195 [[self menu] addItem:item];
196
197 [[self menu] addItem:[NSMenuItem separatorItem]];
198 item = [self createItemWithTitle:l10n_util::GetNSStringWithFixup(
199 IDS_PROFILES_CREATE_NEW_PROFILE_OPTION)
200 action:@selector(newProfile:)];
201 [[self menu] addItem:item];
202
203 [self rebuildMenu];
204 }
205
206 // Notifies the controller that the active browser has changed and that the
207 // menu item and menu need to be updated to reflect that.
208 - (void)activeBrowserChangedTo:(Browser*)browser {
209 // Tell the menu that the browser has changed.
210 menu_->ActiveBrowserChanged(browser);
211
212 // If |browser| is NULL, it may be because the current profile was deleted
213 // and there are no other loaded profiles. In this case, calling
214 // |menu_->GetActiveProfileIndex()| may result in a profile being loaded,
215 // which is inappropriate to do on the UI thread.
216 //
217 // An early return provides the desired behavior:
218 // a) If the profile was deleted, the menu would have been rebuilt and no
219 // profile will have a check mark.
220 // b) If the profile was not deleted, but there is no active browser, then
221 // the previous profile will remain checked.
222 if (!browser)
223 return;
224
225 // In guest mode, there is no active menu item.
226 size_t activeProfileIndex = browser->profile()->IsGuestSession() ?
227 std::string::npos : menu_->GetActiveProfileIndex();
228
229 // Update the state for the menu items.
230 for (size_t i = 0; i < menu_->GetNumberOfItems(); ++i) {
231 size_t tag = menu_->GetItemAt(i).menu_index;
232 [[[self menu] itemWithTag:tag]
233 setState:activeProfileIndex == tag ? NSOnState : NSOffState];
234 }
235 }
236
237 - (void)rebuildMenu {
238 NSMenu* menu = [self menu];
239
240 for (NSMenuItem* item = [menu itemAtIndex:0];
241 ![item isSeparatorItem];
242 item = [menu itemAtIndex:0]) {
243 [menu removeItemAtIndex:0];
244 }
245
246 BOOL hasContent = [self insertItemsIntoMenu:menu atOffset:0 fromDock:NO];
247
248 [mainMenuItem_ setHidden:!hasContent];
249 }
250
251 - (NSMenuItem*)createItemWithTitle:(NSString*)title action:(SEL)sel {
252 base::scoped_nsobject<NSMenuItem> item(
253 [[NSMenuItem alloc] initWithTitle:title action:sel keyEquivalent:@""]);
254 [item setTarget:self];
255 return [item.release() autorelease];
256 }
257
258 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/profile_menu_controller.h ('k') | chrome/browser/ui/cocoa/profile_menu_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698