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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/browser/new_avatar_button_controller.mm
diff --git a/chrome/browser/ui/cocoa/browser/new_avatar_button_controller.mm b/chrome/browser/ui/cocoa/browser/new_avatar_button_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..be1667db75752533780a43938de20734108395ac
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/new_avatar_button_controller.mm
@@ -0,0 +1,194 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/browser/new_avatar_button_controller.h"
+
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/browser/profile_chooser_controller.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "content/public/browser/notification_service.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/text_elider.h"
+
+namespace {
+
+NSString* GetElidedProfileName(const base::string16& name) {
+ // Maximum characters the button can be before the text will get elided.
+ const int kMaxCharactersToDisplay = 15;
+
+ gfx::FontList font_list = ui::ResourceBundle::GetSharedInstance().GetFontList(
+ ui::ResourceBundle::BaseFont);
+ return base::SysUTF16ToNSString(gfx::ElideText(
+ name,
+ font_list,
+ font_list.GetExpectedTextWidth(kMaxCharactersToDisplay),
+ gfx::ELIDE_AT_END));
+}
+
+} // namespace
+
+@interface NewAvatarButtonController (Private)
+// Shows the ProfileMenuController.
+- (IBAction)buttonClicked:(id)sender;
+
+- (void)bubbleWillClose:(NSNotification*)notif;
+
+// Updates the profile name displayed by the avatar button. If |layoutParent| is
+// yes, then the BrowserWindowController is notified to relayout the subviews,
+// as the button needs to be repositioned.
+- (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent;
+@end
+
+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
+ public:
+ ProfileInfoUpdateObserverBridge(NewAvatarButtonController* avatarButton)
+ : avatarButton_(avatarButton) {
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources());
+ }
+
+ virtual ~ProfileInfoUpdateObserverBridge() {
+ registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources());
Nico 2014/01/07 23:20:33 Do you need to do this? I thought the point of Not
+ }
+
+ // content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ switch (type) {
+ case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
+ [avatarButton_ updateAvatarButtonAndLayoutParent:YES];
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ private:
+ content::NotificationRegistrar registrar_;
+
+ NewAvatarButtonController* avatarButton_; // Weak; owns this.
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileInfoUpdateObserverBridge);
+};
+
+@implementation NewAvatarButtonController
+
+- (id)initWithBrowser:(Browser*)browser {
+ if ((self = [super init])) {
+ browser_ = browser;
+ profileInfoObserver_.reset(new ProfileInfoUpdateObserverBridge(self));
+
+ base::scoped_nsobject<NSView> container([[NSView alloc]
+ initWithFrame:NSZeroRect]);
+ [self setView:container];
+
+ button_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
+ [button_ setBezelStyle:NSTexturedRoundedBezelStyle];
+ [button_ setImage:ui::ResourceBundle::GetSharedInstance().
+ GetNativeImageNamed(IDR_APP_DROPARROW).ToNSImage()];
+ [button_ setImagePosition:NSImageRight];
+ [button_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
+ [button_ setTarget:self];
+ [button_ setAction:@selector(buttonClicked:)];
+
+ [self updateAvatarButtonAndLayoutParent:NO];
+
+ [[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
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:NSWindowWillCloseNotification
+ object:[menuController_ window]];
+ [super dealloc];
+}
+
+- (NSButton*)buttonView {
+ return button_.get();
+}
+
+- (void)showAvatarBubble:(NSView*)anchor {
+ if (menuController_)
+ return;
+
+ DCHECK(chrome::IsCommandEnabled(browser_, IDC_SHOW_AVATAR_MENU));
+
+ NSWindowController* wc =
+ [browser_->window()->GetNativeWindow() windowController];
+ if ([wc isKindOfClass:[BrowserWindowController class]]) {
+ [static_cast<BrowserWindowController*>(wc)
+ lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
+ }
+
+ NSPoint point = NSMakePoint(NSMidX([anchor bounds]),
+ NSMaxY([anchor bounds]));
+ point = [anchor convertPoint:point toView:nil];
+ point = [[anchor window] convertBaseToScreen:point];
+
+ menuController_ = [[ProfileChooserController alloc] initWithBrowser:browser_
+ anchoredAt:point];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(bubbleWillClose:)
+ name:NSWindowWillCloseNotification
+ object:[menuController_ window]];
+ [menuController_ showWindow:self];
+
+ ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::ICON_AVATAR_BUBBLE);
+}
+
+- (IBAction)buttonClicked:(id)sender {
+ DCHECK(sender == button_.get());
+ [self showAvatarBubble:button_];
+}
+
+- (void)bubbleWillClose:(NSNotification*)notif {
+ NSWindowController* wc =
+ [browser_->window()->GetNativeWindow() windowController];
+ if ([wc isKindOfClass:[BrowserWindowController class]]) {
+ [static_cast<BrowserWindowController*>(wc)
+ releaseBarVisibilityForOwner:self withAnimation:YES delay:NO];
+ }
+ menuController_ = nil;
+}
+
+- (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent {
+ [button_ setTitle:GetElidedProfileName(
+ profiles::GetActiveProfileDisplayName(browser_))];
+ [button_ sizeToFit];
+
+ // Resize the container.
+ [[self view] setFrameSize:[button_ frame].size];
+ [button_ setFrameOrigin:NSMakePoint(0, 0)];
+
+ if (layoutParent) {
+ // Because the width of the button might have changed, the parent browser
+ // frame needs to recalculate the button bounds and redraw it.
+ [[BrowserWindowController
+ browserWindowControllerForWindow:browser_->window()->GetNativeWindow()]
+ layoutSubviews];
+ }
+}
+
+- (ProfileChooserController*)menuController {
+ return menuController_;
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698