Index: chrome/browser/ui/cocoa/browser/avatar_base_controller.mm |
diff --git a/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..85fa8b4faf5569fe713ffb3e3d1a8254d0c6890b |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm |
@@ -0,0 +1,163 @@ |
+// 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/avatar_base_controller.h" |
+ |
+#include "chrome/app/chrome_command_ids.h" |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/profiles/profile_info_cache_observer.h" |
+#include "chrome/browser/profiles/profile_info_util.h" |
+#include "chrome/browser/profiles/profile_manager.h" |
+#include "chrome/browser/profiles/profile_metrics.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/base_bubble_controller.h" |
+#import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h" |
+#import "chrome/browser/ui/cocoa/browser/profile_chooser_controller.h" |
+#import "chrome/browser/ui/cocoa/browser_window_controller.h" |
+#include "chrome/common/profile_management_switches.h" |
+#include "ui/base/resource/resource_bundle.h" |
+ |
+// Space between the avatar icon and the avatar menu bubble. |
+const CGFloat kMenuYOffsetAdjust = 1.0; |
+ |
+@interface AvatarBaseController (Private) |
+// Shows the avatar bubble. |
+- (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 ProfileInfoUpdateObserver : public ProfileInfoCacheObserver { |
+ public: |
+ ProfileInfoUpdateObserver(AvatarBaseController* avatarButton) |
+ : avatarButton_(avatarButton) { |
+ g_browser_process->profile_manager()-> |
+ GetProfileInfoCache().AddObserver(this); |
+ } |
+ |
+ virtual ~ProfileInfoUpdateObserver() { |
+ g_browser_process->profile_manager()-> |
+ GetProfileInfoCache().RemoveObserver(this); |
+ } |
+ |
+ // ProfileInfoCacheObserver: |
+ virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE { |
+ [avatarButton_ updateAvatarButtonAndLayoutParent:YES]; |
+ } |
+ |
+ virtual void OnProfileWasRemoved( |
+ const base::FilePath& profile_path, |
+ const base::string16& profile_name) OVERRIDE { |
+ [avatarButton_ updateAvatarButtonAndLayoutParent:YES]; |
+ } |
+ |
+ virtual void OnProfileNameChanged( |
+ const base::FilePath& profile_path, |
+ const base::string16& old_profile_name) OVERRIDE { |
+ [avatarButton_ updateAvatarButtonAndLayoutParent:YES]; |
+ } |
+ |
+ virtual void OnProfileAvatarChanged( |
+ const base::FilePath& profile_path) OVERRIDE { |
+ [avatarButton_ updateAvatarButtonAndLayoutParent:YES]; |
+ } |
+ |
+ private: |
+ AvatarBaseController* avatarButton_; // Weak; owns this. |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ProfileInfoUpdateObserver); |
+}; |
+ |
+@implementation AvatarBaseController |
+ |
+- (id)initWithBrowser:(Browser*)browser { |
+ if ((self = [super init])) { |
+ browser_ = browser; |
+ profileInfoObserver_.reset(new ProfileInfoUpdateObserver(self)); |
+ } |
+ return self; |
+} |
+ |
+- (void)dealloc { |
+ [[NSNotificationCenter defaultCenter] |
+ removeObserver:self |
+ name:NSWindowWillCloseNotification |
+ object:[menuController_ window]]; |
+ [super dealloc]; |
+} |
+ |
+- (NSButton*)buttonView { |
+ CHECK(button_.get()); // Subclasses must set this. |
+ 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]) - kMenuYOffsetAdjust); |
+ point = [anchor convertPoint:point toView:nil]; |
+ point = [[anchor window] convertBaseToScreen:point]; |
+ |
+ // |menuController_| will automatically release itself on close. |
+ if (switches::IsNewProfileManagement()) { |
+ menuController_ = |
+ [[ProfileChooserController alloc] initWithBrowser:browser_ |
+ anchoredAt:point]; |
+ } else { |
+ menuController_ = |
+ [[AvatarMenuBubbleController 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_EQ(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 { |
+ NOTREACHED(); |
+} |
+ |
+- (BaseBubbleController*)menuController { |
+ return menuController_; |
+} |
+ |
+@end |
+ |