summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornoms@chromium.org <noms@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-30 09:08:54 +0000
committernoms@chromium.org <noms@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-30 09:08:54 +0000
commitb13771f5c813f78233b9f5d64dc60012d988f615 (patch)
tree9992cb1f53a4028dd75f181bf7e2a835d96e3a91
parent72bf30c4e2872d3d58f3b14ea0fd4217528a3086 (diff)
downloadchromium_src-b13771f5c813f78233b9f5d64dc60012d988f615.zip
chromium_src-b13771f5c813f78233b9f5d64dc60012d988f615.tar.gz
chromium_src-b13771f5c813f78233b9f5d64dc60012d988f615.tar.bz2
[Mac] UI fixes to the new avatar bubble.
- the bottom options buttons get a blue background when hovered over - corrected the spacing between a button's image and its title. - s/makeAccountButtonWithRect/accountButtonWithRect/g to be consistent with the other control-making methods. Screenshot: https://drive.google.com/file/d/0B1B1Up4p2NRMeERscUNleHNMWWc/edit?usp=sharing BUG=324036 Review URL: https://codereview.chromium.org/132903016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247910 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm210
1 files changed, 144 insertions, 66 deletions
diff --git a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
index 2bbdf0c..461aa30 100644
--- a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
@@ -48,6 +48,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/text_elider.h"
+#include "ui/native_theme/native_theme.h"
namespace {
@@ -65,6 +66,8 @@ const CGFloat kTextFontSize = 12.0;
const CGFloat kProfileButtonHeight = 30;
const int kOverlayHeight = 20; // Height of the "Change" avatar photo overlay.
const int kBezelThickness = 3; // Width of the bezel on an NSButton.
+const int kImageTitleSpacing = 10;
+const int kBlueButtonHeight = 30;
// Minimum size for embedded sign in pages as defined in Gaia.
const CGFloat kMinGaiaViewWidth = 320;
@@ -99,9 +102,6 @@ NSString* ElideEmail(const std::string& email, CGFloat width) {
// Class that listens to changes to the OAuth2Tokens for the active profile, or
// changes to the avatar menu model.
-// TODO(noms): The avatar menu model changes can only be triggered by modifying
-// the name or avatar for the active profile, but this is not currently
-// implemented.
class ActiveProfileObserverBridge : public AvatarMenuObserver,
public OAuth2TokenService::Observer {
public:
@@ -145,7 +145,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
DISALLOW_COPY_AND_ASSIGN(ActiveProfileObserverBridge);
};
-
// A custom button that has a transparent backround.
@interface TransparentBackgroundButton : NSButton
@end
@@ -339,12 +338,91 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
[profileNameTextField_ becomeFirstResponder];
}
-- (NSString*)profileName {
- return [self title];
+@end
+
+// Custom button cell that adds a left padding before the button image, and
+// a custom spacing between the button image and title.
+@interface CustomPaddingImageButtonCell : NSButtonCell {
+ @private
+ // Padding between the left margin of the button and the cell image.
+ int leftMarginSpacing_;
+ // Spacing between the cell image and title.
+ int imageTitleSpacing_;
+}
+
+- (id)initWithLeftMarginSpacing:(int)leftMarginSpacing
+ imageTitleSpacing:(int)imageTitleSpacing;
+@end
+
+@implementation CustomPaddingImageButtonCell
+- (id)initWithLeftMarginSpacing:(int)leftMarginSpacing
+ imageTitleSpacing:(int)imageTitleSpacing {
+ if ((self = [super init])) {
+ leftMarginSpacing_ = leftMarginSpacing;
+ imageTitleSpacing_ = imageTitleSpacing;
+ }
+ return self;
+}
+
+- (NSRect)drawTitle:(NSAttributedString*)title
+ withFrame:(NSRect)frame
+ inView:(NSView*)controlView {
+ // The title frame origin isn't aware of the left margin spacing added
+ // in -drawImage, so it must be added when drawing the title as well.
+ frame.origin.x += leftMarginSpacing_ + imageTitleSpacing_;
+ return [super drawTitle:title withFrame:frame inView:controlView];
+}
+
+- (void)drawImage:(NSImage*)image
+ withFrame:(NSRect)frame
+ inView:(NSView*)controlView {
+ frame.origin.x = leftMarginSpacing_;
+ [super drawImage:image withFrame:frame inView:controlView];
+}
+
+- (NSSize)cellSize {
+ NSSize buttonSize = [super cellSize];
+ buttonSize.width += leftMarginSpacing_ + imageTitleSpacing_;
+ return buttonSize;
+}
+
+@end
+
+// A custom button that allows for setting a background color when hovered over.
+@interface BackgroundColorHoverButton : HoverButton
+@end
+
+@implementation BackgroundColorHoverButton
+- (id)initWithFrame:(NSRect)frameRect {
+ if ((self = [super initWithFrame:frameRect])) {
+ [self setBordered:NO];
+ [self setFont:[NSFont labelFontOfSize:kTextFontSize]];
+ [self setButtonType:NSMomentaryChangeButton];
+
+ base::scoped_nsobject<CustomPaddingImageButtonCell> cell(
+ [[CustomPaddingImageButtonCell alloc]
+ initWithLeftMarginSpacing:kHorizontalSpacing
+ imageTitleSpacing:kImageTitleSpacing]);
+ [self setCell:cell.get()];
+ }
+ return self;
+}
+
+- (void)setHoverState:(HoverState)state {
+ [super setHoverState:state];
+ bool isHighlighted = ([self hoverState] != kHoverStateNone);
+ NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor(
+ ui::NativeTheme::instance()->GetSystemColor(isHighlighted?
+ ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor :
+ ui::NativeTheme::kColorId_MenuBackgroundColor));
+
+ [[self cell] setBackgroundColor:backgroundColor];
}
+
@end
-@interface ProfileChooserController (Private)
+
+@interface ProfileChooserController ()
// Creates the main profile card for the profile |item| at the top of
// the bubble.
- (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item;
@@ -372,12 +450,12 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Creates the Gaia sign-in/add account view.
- (NSView*)createGaiaEmbeddedView;
-// Creates a generic button with text given by |textResourceId|, an icon
-// given by |imageResourceId| and with |action|.
-- (NSButton*)buttonWithRect:(NSRect)rect
- textResourceId:(int)textResourceId
- imageResourceId:(int)imageResourceId
- action:(SEL)action;
+// Creates a button with text given by |textResourceId|, an icon given by
+// |imageResourceId| and with |action|.
+- (NSButton*)hoverButtonWithRect:(NSRect)rect
+ textResourceId:(int)textResourceId
+ imageResourceId:(int)imageResourceId
+ action:(SEL)action;
// Creates a generic link button with |title| and an |action| positioned at
// |frameOrigin|.
@@ -387,9 +465,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Creates an email account button with |title|. If |canBeDeleted| is YES, then
// the button is clickable and has a remove icon.
-- (NSButton*)makeAccountButtonWithRect:(NSRect)rect
- title:(const std::string&)title
- canBeDeleted:(BOOL)canBeDeleted;
+- (NSButton*)accountButtonWithRect:(NSRect)rect
+ title:(const std::string&)title
+ canBeDeleted:(BOOL)canBeDeleted;
- (void)dealloc;
@@ -537,16 +615,16 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// |yOffset| is the next position at which to draw in |contentView|
// coordinates.
- CGFloat yOffset = kVerticalSpacing;
- NSRect viewRect = NSMakeRect(kHorizontalSpacing, yOffset, contentsWidth, 0);
+ CGFloat yOffset = kSmallVerticalSpacing;
// Guest / Add Person / View All Persons buttons.
- NSView* optionsView = [self createOptionsViewWithRect:viewRect];
+ NSView* optionsView = [self createOptionsViewWithRect:
+ NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:optionsView];
- yOffset = NSMaxY([optionsView frame]) + kVerticalSpacing;
+ yOffset = NSMaxY([optionsView frame]) + kSmallVerticalSpacing;
- NSBox* separator = [self separatorWithFrame:NSMakeRect(
- 0, yOffset, contentsWidthWithSpacing, 0)];
+ NSBox* separator = [self separatorWithFrame:
+ NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:separator];
yOffset = NSMaxY([separator frame]) + kVerticalSpacing;
@@ -565,15 +643,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
if ([otherProfiles.get() count] > 0)
yOffset += kSmallVerticalSpacing;
} else if (viewToDisplay == ACCOUNT_MANAGEMENT_VIEW) {
- // Reuse the same view area as for the option buttons.
- viewRect.origin.y = yOffset;
- NSView* currentProfileAccountsView =
- [self createCurrentProfileAccountsView:viewRect];
+ NSView* currentProfileAccountsView = [self createCurrentProfileAccountsView:
+ NSMakeRect(kHorizontalSpacing, yOffset, contentsWidth, 0)];
[contentView addSubview:currentProfileAccountsView];
yOffset = NSMaxY([currentProfileAccountsView frame]) + kVerticalSpacing;
- NSBox* accountsSeparator = [self separatorWithFrame:NSMakeRect(
- 0, yOffset, contentsWidthWithSpacing, 0)];
+ NSBox* accountsSeparator = [self separatorWithFrame:
+ NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:accountsSeparator];
yOffset = NSMaxY([accountsSeparator frame]) + kVerticalSpacing;
}
@@ -701,12 +777,17 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex);
base::scoped_nsobject<NSButton> profileButton([[NSButton alloc]
initWithFrame:NSZeroRect]);
+ base::scoped_nsobject<CustomPaddingImageButtonCell> cell(
+ [[CustomPaddingImageButtonCell alloc]
+ initWithLeftMarginSpacing:0
+ imageTitleSpacing:kImageTitleSpacing]);
+ [profileButton setCell:cell.get()];
- // TODO(noms): Increase the spacing between the icon and the text to 10px;
[profileButton setTitle:base::SysUTF16ToNSString(item.name)];
[profileButton setImage:CreateProfileImage(
item.icon, kSmallImageSide).ToNSImage()];
[profileButton setImagePosition:NSImageLeft];
+ [profileButton setAlignment:NSLeftTextAlignment];
[profileButton setBordered:NO];
[profileButton setFont:[NSFont labelFontOfSize:kTitleFontSize]];
[profileButton setTag:itemIndex];
@@ -718,41 +799,38 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
}
- (NSView*)createOptionsViewWithRect:(NSRect)rect {
- CGFloat yOffset = 0;
- base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
-
+ NSRect viewRect = NSMakeRect(0, 0, rect.size.width, kBlueButtonHeight);
NSButton* allUsersButton =
- [self buttonWithRect:NSMakeRect(0, yOffset, 0, 0)
- textResourceId:IDS_PROFILES_ALL_PEOPLE_BUTTON
- imageResourceId:IDR_ICON_PROFILES_ADD_USER
- action:@selector(showUserManager:)];
- yOffset = NSMaxY([allUsersButton frame]) + kSmallVerticalSpacing;
+ [self hoverButtonWithRect:viewRect
+ textResourceId:IDS_PROFILES_ALL_PEOPLE_BUTTON
+ imageResourceId:IDR_ICON_PROFILES_ADD_USER
+ action:@selector(showUserManager:)];
+ viewRect.origin.y = NSMaxY([allUsersButton frame]);
NSButton* addUserButton =
- [self buttonWithRect:NSMakeRect(0, yOffset, 0, 0)
- textResourceId:IDS_PROFILES_ADD_PERSON_BUTTON
- imageResourceId:IDR_ICON_PROFILES_ADD_USER
- action:@selector(addNewProfile:)];
- yOffset = NSMaxY([addUserButton frame]) + kSmallVerticalSpacing;
+ [self hoverButtonWithRect:viewRect
+ textResourceId:IDS_PROFILES_ADD_PERSON_BUTTON
+ imageResourceId:IDR_ICON_PROFILES_ADD_USER
+ action:@selector(addNewProfile:)];
+ viewRect.origin.y = NSMaxY([addUserButton frame]);
int guestButtonText = isGuestSession_ ? IDS_PROFILES_EXIT_GUEST_BUTTON :
IDS_PROFILES_GUEST_BUTTON;
SEL guestButtonAction = isGuestSession_ ? @selector(exitGuestProfile:) :
@selector(switchToGuestProfile:);
NSButton* guestButton =
- [self buttonWithRect:NSMakeRect(0, yOffset, 0, 0)
- textResourceId:guestButtonText
- imageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST
- action:guestButtonAction];
- yOffset = NSMaxY([guestButton frame]);
-
+ [self hoverButtonWithRect:viewRect
+ textResourceId:guestButtonText
+ imageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST
+ action:guestButtonAction];
+ rect.size.height = NSMaxY([guestButton frame]);
+ base::scoped_nsobject<NSView> container([[NSView alloc]
+ initWithFrame:rect]);
[container setSubviews:@[allUsersButton, addUserButton, guestButton]];
- [container setFrameSize:NSMakeSize(NSWidth([container frame]), yOffset)];
return container.autorelease();
}
- (NSView*)createCurrentProfileAccountsView:(NSRect)rect {
- const CGFloat kBlueButtonHeight = 30;
const CGFloat kAccountButtonHeight = 15;
const AvatarMenu::Item& item =
@@ -797,9 +875,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
for (size_t i = 0; i < accounts.size(); ++i) {
// Save the original email address, as the button text could be elided.
currentProfileAccounts_[i] = accounts[i];
- NSButton* accountButton = [self makeAccountButtonWithRect:rect
- title:accounts[i]
- canBeDeleted:true];
+ NSButton* accountButton = [self accountButtonWithRect:rect
+ title:accounts[i]
+ canBeDeleted:true];
[accountButton setTag:i];
[container addSubview:accountButton];
rect.origin.y = NSMaxY([accountButton frame]) + kSmallVerticalSpacing;
@@ -810,9 +888,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// TODO(rogerta): we still need to further differentiate the primary account
// from the others in the UI, so more work is likely required here:
// crbug.com/311124.
- NSButton* accountButton = [self makeAccountButtonWithRect:rect
- title:primaryAccount
- canBeDeleted:false];
+ NSButton* accountButton = [self accountButtonWithRect:rect
+ title:primaryAccount
+ canBeDeleted:false];
[container addSubview:accountButton];
[container setFrameSize:NSMakeSize(NSWidth([container frame]),
NSMaxY([accountButton frame]))];
@@ -836,21 +914,21 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return webview;
}
-- (NSButton*)buttonWithRect:(NSRect)rect
- textResourceId:(int)textResourceId
- imageResourceId:(int)imageResourceId
- action:(SEL)action {
- base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]);
+- (NSButton*)hoverButtonWithRect:(NSRect)rect
+ textResourceId:(int)textResourceId
+ imageResourceId:(int)imageResourceId
+ action:(SEL)action {
+ base::scoped_nsobject<BackgroundColorHoverButton> button(
+ [[BackgroundColorHoverButton alloc] initWithFrame:rect]);
- // TODO(noms): Increase the spacing between the icon and the text to 10px;
[button setTitle:l10n_util::GetNSString(textResourceId)];
[button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
imageResourceId).ToNSImage()];
[button setImagePosition:NSImageLeft];
+ [button setAlignment:NSLeftTextAlignment];
[button setBordered:NO];
[button setTarget:self];
[button setAction:action];
- [button sizeToFit];
return button.autorelease();
}
@@ -875,9 +953,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return link.autorelease();
}
-- (NSButton*)makeAccountButtonWithRect:(NSRect)rect
- title:(const std::string&)title
- canBeDeleted:(BOOL)canBeDeleted {
+- (NSButton*)accountButtonWithRect:(NSRect)rect
+ title:(const std::string&)title
+ canBeDeleted:(BOOL)canBeDeleted {
base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]);
[button setTitle:ElideEmail(title, rect.size.width)];
[button setAlignment:NSLeftTextAlignment];