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

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

Issue 117533002: [Mac] Redesign of the avatar menu button (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix tabstrip width Created 6 years, 11 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 2014 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/browser/new_avatar_button_controller.h"
6
7 #include "base/strings/sys_string_conversions.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/profiles/profile_metrics.h"
11 #include "chrome/browser/profiles/profiles_state.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.h"
14 #include "chrome/browser/ui/browser_window.h"
15 #import "chrome/browser/ui/cocoa/browser/profile_chooser_controller.h"
16 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
17 #include "content/public/browser/notification_service.h"
18 #include "grit/generated_resources.h"
19 #include "grit/theme_resources.h"
20 #include "ui/base/l10n/l10n_util_mac.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/text_elider.h"
23
24 namespace {
25
26 NSString* GetElidedProfileName(const base::string16& name) {
27 // Maximum characters the button can be before the text will get elided.
28 const int kMaxCharactersToDisplay = 15;
29
30 gfx::FontList font_list = ui::ResourceBundle::GetSharedInstance().GetFontList(
31 ui::ResourceBundle::BaseFont);
32 return base::SysUTF16ToNSString(gfx::ElideText(
33 name,
34 font_list,
35 font_list.GetExpectedTextWidth(kMaxCharactersToDisplay),
36 gfx::ELIDE_AT_END));
37 }
38
39 } // namespace
40
41 @interface NewAvatarButtonController (Private)
42 // Shows the ProfileMenuController.
43 - (IBAction)buttonClicked:(id)sender;
44
45 - (void)bubbleWillClose:(NSNotification*)notif;
46
47 // Updates the profile name displayed by the avatar button. If |layoutParent| is
48 // yes, then the BrowserWindowController is notified to relayout the subviews,
49 // as the button needs to be repositioned.
50 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent;
51 @end
52
53 class ProfileInfoUpdateObserverBridge : public content::NotificationObserver {
Nico 2014/01/07 23:20:33 In general, we try to not use notifications in new
noms (inactive) 2014/01/08 15:05:31 I can also make this an AvatarMenuObserver (like t
54 public:
55 ProfileInfoUpdateObserverBridge(NewAvatarButtonController* avatarButton)
56 : avatarButton_(avatarButton) {
57 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
58 content::NotificationService::AllSources());
59 }
60
61 virtual ~ProfileInfoUpdateObserverBridge() {
62 registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
63 content::NotificationService::AllSources());
Nico 2014/01/07 23:20:33 Do you need to do this? I thought the point of Not
64 }
65
66 // content::NotificationObserver:
67 virtual void Observe(int type,
68 const content::NotificationSource& source,
69 const content::NotificationDetails& details) OVERRIDE {
70 switch (type) {
71 case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
72 [avatarButton_ updateAvatarButtonAndLayoutParent:YES];
73 break;
74 default:
75 NOTREACHED();
76 break;
77 }
78 }
79
80 private:
81 content::NotificationRegistrar registrar_;
82
83 NewAvatarButtonController* avatarButton_; // Weak; owns this.
84
85 DISALLOW_COPY_AND_ASSIGN(ProfileInfoUpdateObserverBridge);
86 };
87
88 @implementation NewAvatarButtonController
89
90 - (id)initWithBrowser:(Browser*)browser {
91 if ((self = [super init])) {
92 browser_ = browser;
93 profileInfoObserver_.reset(new ProfileInfoUpdateObserverBridge(self));
94
95 base::scoped_nsobject<NSView> container([[NSView alloc]
96 initWithFrame:NSZeroRect]);
97 [self setView:container];
98
99 button_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
100 [button_ setBezelStyle:NSTexturedRoundedBezelStyle];
101 [button_ setImage:ui::ResourceBundle::GetSharedInstance().
102 GetNativeImageNamed(IDR_APP_DROPARROW).ToNSImage()];
103 [button_ setImagePosition:NSImageRight];
104 [button_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
105 [button_ setTarget:self];
106 [button_ setAction:@selector(buttonClicked:)];
107
108 [self updateAvatarButtonAndLayoutParent:NO];
109
110 [[self view] addSubview:button_];
Nico 2014/01/07 23:20:33 Since this is the only view, can button_ just be t
noms (inactive) 2014/01/08 15:05:31 Not really. The only reason I added the container
111 }
112 return self;
113 }
114
115 - (void)dealloc {
116 [[NSNotificationCenter defaultCenter]
117 removeObserver:self
118 name:NSWindowWillCloseNotification
119 object:[menuController_ window]];
120 [super dealloc];
121 }
122
123 - (NSButton*)buttonView {
124 return button_.get();
125 }
126
127 - (void)showAvatarBubble:(NSView*)anchor {
128 if (menuController_)
129 return;
130
131 DCHECK(chrome::IsCommandEnabled(browser_, IDC_SHOW_AVATAR_MENU));
132
133 NSWindowController* wc =
134 [browser_->window()->GetNativeWindow() windowController];
135 if ([wc isKindOfClass:[BrowserWindowController class]]) {
136 [static_cast<BrowserWindowController*>(wc)
137 lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
138 }
139
140 NSPoint point = NSMakePoint(NSMidX([anchor bounds]),
141 NSMaxY([anchor bounds]));
142 point = [anchor convertPoint:point toView:nil];
143 point = [[anchor window] convertBaseToScreen:point];
144
145 menuController_ = [[ProfileChooserController alloc] initWithBrowser:browser_
146 anchoredAt:point];
147 [[NSNotificationCenter defaultCenter]
148 addObserver:self
149 selector:@selector(bubbleWillClose:)
150 name:NSWindowWillCloseNotification
151 object:[menuController_ window]];
152 [menuController_ showWindow:self];
153
154 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::ICON_AVATAR_BUBBLE);
155 }
156
157 - (IBAction)buttonClicked:(id)sender {
158 DCHECK(sender == button_.get());
159 [self showAvatarBubble:button_];
160 }
161
162 - (void)bubbleWillClose:(NSNotification*)notif {
163 NSWindowController* wc =
164 [browser_->window()->GetNativeWindow() windowController];
165 if ([wc isKindOfClass:[BrowserWindowController class]]) {
166 [static_cast<BrowserWindowController*>(wc)
167 releaseBarVisibilityForOwner:self withAnimation:YES delay:NO];
168 }
169 menuController_ = nil;
170 }
171
172 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent {
173 [button_ setTitle:GetElidedProfileName(
174 profiles::GetActiveProfileDisplayName(browser_))];
175 [button_ sizeToFit];
176
177 // Resize the container.
178 [[self view] setFrameSize:[button_ frame].size];
179 [button_ setFrameOrigin:NSMakePoint(0, 0)];
180
181 if (layoutParent) {
182 // Because the width of the button might have changed, the parent browser
183 // frame needs to recalculate the button bounds and redraw it.
184 [[BrowserWindowController
185 browserWindowControllerForWindow:browser_->window()->GetNativeWindow()]
186 layoutSubviews];
187 }
188 }
189
190 - (ProfileChooserController*)menuController {
191 return menuController_;
192 }
193
194 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698