Commit b13771f5 authored by noms@chromium.org's avatar noms@chromium.org

[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
parent 72bf30c4
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
#include "ui/gfx/text_elider.h" #include "ui/gfx/text_elider.h"
#include "ui/native_theme/native_theme.h"
namespace { namespace {
...@@ -65,6 +66,8 @@ const CGFloat kTextFontSize = 12.0; ...@@ -65,6 +66,8 @@ const CGFloat kTextFontSize = 12.0;
const CGFloat kProfileButtonHeight = 30; const CGFloat kProfileButtonHeight = 30;
const int kOverlayHeight = 20; // Height of the "Change" avatar photo overlay. const int kOverlayHeight = 20; // Height of the "Change" avatar photo overlay.
const int kBezelThickness = 3; // Width of the bezel on an NSButton. 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. // Minimum size for embedded sign in pages as defined in Gaia.
const CGFloat kMinGaiaViewWidth = 320; const CGFloat kMinGaiaViewWidth = 320;
...@@ -99,9 +102,6 @@ NSString* ElideEmail(const std::string& email, CGFloat width) { ...@@ -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 // Class that listens to changes to the OAuth2Tokens for the active profile, or
// changes to the avatar menu model. // 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, class ActiveProfileObserverBridge : public AvatarMenuObserver,
public OAuth2TokenService::Observer { public OAuth2TokenService::Observer {
public: public:
...@@ -145,7 +145,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -145,7 +145,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
DISALLOW_COPY_AND_ASSIGN(ActiveProfileObserverBridge); DISALLOW_COPY_AND_ASSIGN(ActiveProfileObserverBridge);
}; };
// A custom button that has a transparent backround. // A custom button that has a transparent backround.
@interface TransparentBackgroundButton : NSButton @interface TransparentBackgroundButton : NSButton
@end @end
...@@ -339,12 +338,91 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -339,12 +338,91 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
[profileNameTextField_ becomeFirstResponder]; [profileNameTextField_ becomeFirstResponder];
} }
- (NSString*)profileName { @end
return [self title];
// 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 @end
@interface ProfileChooserController (Private) // 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 ()
// Creates the main profile card for the profile |item| at the top of // Creates the main profile card for the profile |item| at the top of
// the bubble. // the bubble.
- (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item; - (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item;
...@@ -372,9 +450,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -372,9 +450,9 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Creates the Gaia sign-in/add account view. // Creates the Gaia sign-in/add account view.
- (NSView*)createGaiaEmbeddedView; - (NSView*)createGaiaEmbeddedView;
// Creates a generic button with text given by |textResourceId|, an icon // Creates a button with text given by |textResourceId|, an icon given by
// given by |imageResourceId| and with |action|. // |imageResourceId| and with |action|.
- (NSButton*)buttonWithRect:(NSRect)rect - (NSButton*)hoverButtonWithRect:(NSRect)rect
textResourceId:(int)textResourceId textResourceId:(int)textResourceId
imageResourceId:(int)imageResourceId imageResourceId:(int)imageResourceId
action:(SEL)action; action:(SEL)action;
...@@ -387,7 +465,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -387,7 +465,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Creates an email account button with |title|. If |canBeDeleted| is YES, then // Creates an email account button with |title|. If |canBeDeleted| is YES, then
// the button is clickable and has a remove icon. // the button is clickable and has a remove icon.
- (NSButton*)makeAccountButtonWithRect:(NSRect)rect - (NSButton*)accountButtonWithRect:(NSRect)rect
title:(const std::string&)title title:(const std::string&)title
canBeDeleted:(BOOL)canBeDeleted; canBeDeleted:(BOOL)canBeDeleted;
...@@ -537,16 +615,16 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -537,16 +615,16 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// |yOffset| is the next position at which to draw in |contentView| // |yOffset| is the next position at which to draw in |contentView|
// coordinates. // coordinates.
CGFloat yOffset = kVerticalSpacing; CGFloat yOffset = kSmallVerticalSpacing;
NSRect viewRect = NSMakeRect(kHorizontalSpacing, yOffset, contentsWidth, 0);
// Guest / Add Person / View All Persons buttons. // Guest / Add Person / View All Persons buttons.
NSView* optionsView = [self createOptionsViewWithRect:viewRect]; NSView* optionsView = [self createOptionsViewWithRect:
NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:optionsView]; [contentView addSubview:optionsView];
yOffset = NSMaxY([optionsView frame]) + kVerticalSpacing; yOffset = NSMaxY([optionsView frame]) + kSmallVerticalSpacing;
NSBox* separator = [self separatorWithFrame:NSMakeRect( NSBox* separator = [self separatorWithFrame:
0, yOffset, contentsWidthWithSpacing, 0)]; NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:separator]; [contentView addSubview:separator];
yOffset = NSMaxY([separator frame]) + kVerticalSpacing; yOffset = NSMaxY([separator frame]) + kVerticalSpacing;
...@@ -565,15 +643,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -565,15 +643,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
if ([otherProfiles.get() count] > 0) if ([otherProfiles.get() count] > 0)
yOffset += kSmallVerticalSpacing; yOffset += kSmallVerticalSpacing;
} else if (viewToDisplay == ACCOUNT_MANAGEMENT_VIEW) { } else if (viewToDisplay == ACCOUNT_MANAGEMENT_VIEW) {
// Reuse the same view area as for the option buttons. NSView* currentProfileAccountsView = [self createCurrentProfileAccountsView:
viewRect.origin.y = yOffset; NSMakeRect(kHorizontalSpacing, yOffset, contentsWidth, 0)];
NSView* currentProfileAccountsView =
[self createCurrentProfileAccountsView:viewRect];
[contentView addSubview:currentProfileAccountsView]; [contentView addSubview:currentProfileAccountsView];
yOffset = NSMaxY([currentProfileAccountsView frame]) + kVerticalSpacing; yOffset = NSMaxY([currentProfileAccountsView frame]) + kVerticalSpacing;
NSBox* accountsSeparator = [self separatorWithFrame:NSMakeRect( NSBox* accountsSeparator = [self separatorWithFrame:
0, yOffset, contentsWidthWithSpacing, 0)]; NSMakeRect(0, yOffset, contentsWidthWithSpacing, 0)];
[contentView addSubview:accountsSeparator]; [contentView addSubview:accountsSeparator];
yOffset = NSMaxY([accountsSeparator frame]) + kVerticalSpacing; yOffset = NSMaxY([accountsSeparator frame]) + kVerticalSpacing;
} }
...@@ -701,12 +777,17 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -701,12 +777,17 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex); const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex);
base::scoped_nsobject<NSButton> profileButton([[NSButton alloc] base::scoped_nsobject<NSButton> profileButton([[NSButton alloc]
initWithFrame:NSZeroRect]); 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 setTitle:base::SysUTF16ToNSString(item.name)];
[profileButton setImage:CreateProfileImage( [profileButton setImage:CreateProfileImage(
item.icon, kSmallImageSide).ToNSImage()]; item.icon, kSmallImageSide).ToNSImage()];
[profileButton setImagePosition:NSImageLeft]; [profileButton setImagePosition:NSImageLeft];
[profileButton setAlignment:NSLeftTextAlignment];
[profileButton setBordered:NO]; [profileButton setBordered:NO];
[profileButton setFont:[NSFont labelFontOfSize:kTitleFontSize]]; [profileButton setFont:[NSFont labelFontOfSize:kTitleFontSize]];
[profileButton setTag:itemIndex]; [profileButton setTag:itemIndex];
...@@ -718,41 +799,38 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -718,41 +799,38 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
} }
- (NSView*)createOptionsViewWithRect:(NSRect)rect { - (NSView*)createOptionsViewWithRect:(NSRect)rect {
CGFloat yOffset = 0; NSRect viewRect = NSMakeRect(0, 0, rect.size.width, kBlueButtonHeight);
base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
NSButton* allUsersButton = NSButton* allUsersButton =
[self buttonWithRect:NSMakeRect(0, yOffset, 0, 0) [self hoverButtonWithRect:viewRect
textResourceId:IDS_PROFILES_ALL_PEOPLE_BUTTON textResourceId:IDS_PROFILES_ALL_PEOPLE_BUTTON
imageResourceId:IDR_ICON_PROFILES_ADD_USER imageResourceId:IDR_ICON_PROFILES_ADD_USER
action:@selector(showUserManager:)]; action:@selector(showUserManager:)];
yOffset = NSMaxY([allUsersButton frame]) + kSmallVerticalSpacing; viewRect.origin.y = NSMaxY([allUsersButton frame]);
NSButton* addUserButton = NSButton* addUserButton =
[self buttonWithRect:NSMakeRect(0, yOffset, 0, 0) [self hoverButtonWithRect:viewRect
textResourceId:IDS_PROFILES_ADD_PERSON_BUTTON textResourceId:IDS_PROFILES_ADD_PERSON_BUTTON
imageResourceId:IDR_ICON_PROFILES_ADD_USER imageResourceId:IDR_ICON_PROFILES_ADD_USER
action:@selector(addNewProfile:)]; action:@selector(addNewProfile:)];
yOffset = NSMaxY([addUserButton frame]) + kSmallVerticalSpacing; viewRect.origin.y = NSMaxY([addUserButton frame]);
int guestButtonText = isGuestSession_ ? IDS_PROFILES_EXIT_GUEST_BUTTON : int guestButtonText = isGuestSession_ ? IDS_PROFILES_EXIT_GUEST_BUTTON :
IDS_PROFILES_GUEST_BUTTON; IDS_PROFILES_GUEST_BUTTON;
SEL guestButtonAction = isGuestSession_ ? @selector(exitGuestProfile:) : SEL guestButtonAction = isGuestSession_ ? @selector(exitGuestProfile:) :
@selector(switchToGuestProfile:); @selector(switchToGuestProfile:);
NSButton* guestButton = NSButton* guestButton =
[self buttonWithRect:NSMakeRect(0, yOffset, 0, 0) [self hoverButtonWithRect:viewRect
textResourceId:guestButtonText textResourceId:guestButtonText
imageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST imageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST
action:guestButtonAction]; action:guestButtonAction];
yOffset = NSMaxY([guestButton frame]); rect.size.height = NSMaxY([guestButton frame]);
base::scoped_nsobject<NSView> container([[NSView alloc]
initWithFrame:rect]);
[container setSubviews:@[allUsersButton, addUserButton, guestButton]]; [container setSubviews:@[allUsersButton, addUserButton, guestButton]];
[container setFrameSize:NSMakeSize(NSWidth([container frame]), yOffset)];
return container.autorelease(); return container.autorelease();
} }
- (NSView*)createCurrentProfileAccountsView:(NSRect)rect { - (NSView*)createCurrentProfileAccountsView:(NSRect)rect {
const CGFloat kBlueButtonHeight = 30;
const CGFloat kAccountButtonHeight = 15; const CGFloat kAccountButtonHeight = 15;
const AvatarMenu::Item& item = const AvatarMenu::Item& item =
...@@ -797,7 +875,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -797,7 +875,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
for (size_t i = 0; i < accounts.size(); ++i) { for (size_t i = 0; i < accounts.size(); ++i) {
// Save the original email address, as the button text could be elided. // Save the original email address, as the button text could be elided.
currentProfileAccounts_[i] = accounts[i]; currentProfileAccounts_[i] = accounts[i];
NSButton* accountButton = [self makeAccountButtonWithRect:rect NSButton* accountButton = [self accountButtonWithRect:rect
title:accounts[i] title:accounts[i]
canBeDeleted:true]; canBeDeleted:true];
[accountButton setTag:i]; [accountButton setTag:i];
...@@ -810,7 +888,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -810,7 +888,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// TODO(rogerta): we still need to further differentiate the primary account // TODO(rogerta): we still need to further differentiate the primary account
// from the others in the UI, so more work is likely required here: // from the others in the UI, so more work is likely required here:
// crbug.com/311124. // crbug.com/311124.
NSButton* accountButton = [self makeAccountButtonWithRect:rect NSButton* accountButton = [self accountButtonWithRect:rect
title:primaryAccount title:primaryAccount
canBeDeleted:false]; canBeDeleted:false];
[container addSubview:accountButton]; [container addSubview:accountButton];
...@@ -836,21 +914,21 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -836,21 +914,21 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return webview; return webview;
} }
- (NSButton*)buttonWithRect:(NSRect)rect - (NSButton*)hoverButtonWithRect:(NSRect)rect
textResourceId:(int)textResourceId textResourceId:(int)textResourceId
imageResourceId:(int)imageResourceId imageResourceId:(int)imageResourceId
action:(SEL)action { action:(SEL)action {
base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]); 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 setTitle:l10n_util::GetNSString(textResourceId)];
[button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( [button setImage:ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
imageResourceId).ToNSImage()]; imageResourceId).ToNSImage()];
[button setImagePosition:NSImageLeft]; [button setImagePosition:NSImageLeft];
[button setAlignment:NSLeftTextAlignment];
[button setBordered:NO]; [button setBordered:NO];
[button setTarget:self]; [button setTarget:self];
[button setAction:action]; [button setAction:action];
[button sizeToFit];
return button.autorelease(); return button.autorelease();
} }
...@@ -875,7 +953,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver, ...@@ -875,7 +953,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return link.autorelease(); return link.autorelease();
} }
- (NSButton*)makeAccountButtonWithRect:(NSRect)rect - (NSButton*)accountButtonWithRect:(NSRect)rect
title:(const std::string&)title title:(const std::string&)title
canBeDeleted:(BOOL)canBeDeleted { canBeDeleted:(BOOL)canBeDeleted {
base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]); base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment