| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 | 6 |
| 7 #import "chrome/browser/ui/cocoa/profiles/profile_chooser_controller.h" | 7 #import "chrome/browser/ui/cocoa/profiles/profile_chooser_controller.h" |
| 8 | 8 |
| 9 #include "base/mac/bundle_locations.h" | 9 #include "base/mac/bundle_locations.h" |
| 10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 #include "ui/base/l10n/l10n_util_mac.h" | 58 #include "ui/base/l10n/l10n_util_mac.h" |
| 59 #include "ui/base/resource/resource_bundle.h" | 59 #include "ui/base/resource/resource_bundle.h" |
| 60 #include "ui/gfx/image/image.h" | 60 #include "ui/gfx/image/image.h" |
| 61 #include "ui/gfx/text_elider.h" | 61 #include "ui/gfx/text_elider.h" |
| 62 #include "ui/native_theme/native_theme.h" | 62 #include "ui/native_theme/native_theme.h" |
| 63 | 63 |
| 64 namespace { | 64 namespace { |
| 65 | 65 |
| 66 // Constants taken from the Windows/Views implementation at: | 66 // Constants taken from the Windows/Views implementation at: |
| 67 // chrome/browser/ui/views/profile_chooser_view.cc | 67 // chrome/browser/ui/views/profile_chooser_view.cc |
| 68 const int kLargeImageSide = 64; | 68 const int kLargeImageSide = 88; |
| 69 const int kSmallImageSide = 32; | 69 const int kSmallImageSide = 32; |
| 70 const CGFloat kFixedMenuWidth = 250; | 70 const CGFloat kFixedMenuWidth = 250; |
| 71 | 71 |
| 72 const CGFloat kVerticalSpacing = 20.0; | 72 const CGFloat kVerticalSpacing = 16.0; |
| 73 const CGFloat kSmallVerticalSpacing = 10.0; | 73 const CGFloat kSmallVerticalSpacing = 10.0; |
| 74 const CGFloat kHorizontalSpacing = 20.0; | 74 const CGFloat kHorizontalSpacing = 16.0; |
| 75 const CGFloat kTitleFontSize = 15.0; | 75 const CGFloat kTitleFontSize = 15.0; |
| 76 const CGFloat kTextFontSize = 12.0; | 76 const CGFloat kTextFontSize = 12.0; |
| 77 const CGFloat kProfileButtonHeight = 30; | 77 const CGFloat kProfileButtonHeight = 30; |
| 78 const int kOverlayHeight = 20; // Height of the "Change" avatar photo overlay. | 78 const int kOverlayHeight = 20; // Height of the "Change" avatar photo overlay. |
| 79 const int kBezelThickness = 3; // Width of the bezel on an NSButton. | 79 const int kBezelThickness = 3; // Width of the bezel on an NSButton. |
| 80 const int kImageTitleSpacing = 10; | 80 const int kImageTitleSpacing = 10; |
| 81 const int kBlueButtonHeight = 30; | 81 const int kBlueButtonHeight = 30; |
| 82 | 82 |
| 83 // Fixed size for embedded sign in pages as defined in Gaia. | 83 // Fixed size for embedded sign in pages as defined in Gaia. |
| 84 const CGFloat kFixedGaiaViewWidth = 360; | 84 const CGFloat kFixedGaiaViewWidth = 360; |
| 85 const CGFloat kFixedGaiaViewHeight = 400; | 85 const CGFloat kFixedGaiaViewHeight = 400; |
| 86 | 86 |
| 87 // Fixed size for the account removal view. | 87 // Fixed size for the account removal view. |
| 88 const CGFloat kFixedAccountRemovalViewWidth = 280; | 88 const CGFloat kFixedAccountRemovalViewWidth = 280; |
| 89 | 89 |
| 90 // Maximum number of times to show the tutorial in the profile avatar bubble. | 90 // Maximum number of times to show the tutorial in the profile avatar bubble. |
| 91 const int kProfileAvatarTutorialShowMax = 5; | 91 const int kProfileAvatarTutorialShowMax = 5; |
| 92 | 92 |
| 93 // The tag number for the primary account. | 93 // The tag number for the primary account. |
| 94 const int kPrimaryProfileTag = -1; | 94 const int kPrimaryProfileTag = -1; |
| 95 | 95 |
| 96 gfx::Image CreateProfileImage(const gfx::Image& icon, int imageSize) { | 96 gfx::Image CreateProfileImage(const gfx::Image& icon, int imageSize) { |
| 97 return profiles::GetSizedAvatarIconWithBorder( | 97 return profiles::GetSizedAvatarIcon( |
| 98 icon, true /* image is a square */, | 98 icon, true /* image is a square */, |
| 99 imageSize + profiles::kAvatarIconPadding, | 99 imageSize + profiles::kAvatarIconPadding, |
| 100 imageSize + profiles::kAvatarIconPadding); | 100 imageSize + profiles::kAvatarIconPadding); |
| 101 } | 101 } |
| 102 | 102 |
| 103 // Updates the window size and position. | 103 // Updates the window size and position. |
| 104 void SetWindowSize(NSWindow* window, NSSize size) { | 104 void SetWindowSize(NSWindow* window, NSSize size) { |
| 105 NSRect frame = [window frame]; | 105 NSRect frame = [window frame]; |
| 106 frame.origin.x += frame.size.width - size.width; | 106 frame.origin.x += frame.size.width - size.width; |
| 107 frame.origin.y += frame.size.height - size.height; | 107 frame.origin.y += frame.size.height - size.height; |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 @implementation EditableProfileNameButton | 476 @implementation EditableProfileNameButton |
| 477 - (id)initWithFrame:(NSRect)frameRect | 477 - (id)initWithFrame:(NSRect)frameRect |
| 478 profile:(Profile*)profile | 478 profile:(Profile*)profile |
| 479 profileName:(NSString*)profileName | 479 profileName:(NSString*)profileName |
| 480 editingAllowed:(BOOL)editingAllowed { | 480 editingAllowed:(BOOL)editingAllowed { |
| 481 if ((self = [super initWithFrame:frameRect])) { | 481 if ((self = [super initWithFrame:frameRect])) { |
| 482 profile_ = profile; | 482 profile_ = profile; |
| 483 | 483 |
| 484 [self setBordered:NO]; | 484 [self setBordered:NO]; |
| 485 [self setFont:[NSFont labelFontOfSize:kTitleFontSize]]; | 485 [self setFont:[NSFont labelFontOfSize:kTitleFontSize]]; |
| 486 [self setAlignment:NSLeftTextAlignment]; | 486 [self setAlignment:NSCenterTextAlignment]; |
| 487 [[self cell] setLineBreakMode:NSLineBreakByTruncatingTail]; | 487 [[self cell] setLineBreakMode:NSLineBreakByTruncatingTail]; |
| 488 [self setTitle:profileName]; | 488 [self setTitle:profileName]; |
| 489 | 489 |
| 490 if (editingAllowed) { | 490 if (editingAllowed) { |
| 491 // Show an "edit" pencil icon when hovering over. | 491 // Show an "edit" pencil icon when hovering over. In the default state, |
| 492 // we need to create an empty placeholder of the correct size, so that |
| 493 // the text doesn't jump around when the hovered icon appears. |
| 492 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | 494 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 493 [self setHoverImage: | 495 NSImage* hoverImage = rb->GetNativeImageNamed( |
| 494 rb->GetNativeImageNamed(IDR_ICON_PROFILES_EDIT_HOVER).AsNSImage()]; | 496 IDR_ICON_PROFILES_EDIT_HOVER).AsNSImage(); |
| 497 NSImage* placeholder = [[NSImage alloc] initWithSize:[hoverImage size]]; |
| 498 [self setDefaultImage:placeholder]; |
| 499 [self setHoverImage:hoverImage]; |
| 495 [self setAlternateImage: | 500 [self setAlternateImage: |
| 496 rb->GetNativeImageNamed(IDR_ICON_PROFILES_EDIT_PRESSED).AsNSImage()]; | 501 rb->GetNativeImageNamed(IDR_ICON_PROFILES_EDIT_PRESSED).AsNSImage()]; |
| 497 [self setImagePosition:NSImageRight]; | 502 [self setImagePosition:NSImageRight]; |
| 498 [self setTarget:self]; | 503 [self setTarget:self]; |
| 499 [self setAction:@selector(showEditableView:)]; | 504 [self setAction:@selector(showEditableView:)]; |
| 500 | 505 |
| 501 // We need to subtract the width of the bezel from the frame rect, so that | 506 // We need to subtract the width of the bezel from the frame rect, so that |
| 502 // the textfield can take the exact same space as the button. | 507 // the textfield can take the exact same space as the button. |
| 503 frameRect.size.height -= 2 * kBezelThickness; | 508 frameRect.size.height -= 2 * kBezelThickness; |
| 504 frameRect.origin = NSMakePoint(0, kBezelThickness); | 509 frameRect.origin = NSMakePoint(0, kBezelThickness); |
| 505 profileNameTextField_.reset( | 510 profileNameTextField_.reset( |
| 506 [[NSTextField alloc] initWithFrame:frameRect]); | 511 [[NSTextField alloc] initWithFrame:frameRect]); |
| 507 [profileNameTextField_ setStringValue:profileName]; | 512 [profileNameTextField_ setStringValue:profileName]; |
| 508 [profileNameTextField_ setFont:[NSFont labelFontOfSize:kTitleFontSize]]; | 513 [profileNameTextField_ setFont:[NSFont labelFontOfSize:kTitleFontSize]]; |
| 509 [profileNameTextField_ setEditable:YES]; | 514 [profileNameTextField_ setEditable:YES]; |
| 510 [profileNameTextField_ setDrawsBackground:YES]; | 515 [profileNameTextField_ setDrawsBackground:YES]; |
| 511 [profileNameTextField_ setBezeled:YES]; | 516 [profileNameTextField_ setBezeled:YES]; |
| 517 [profileNameTextField_ setAlignment:NSCenterTextAlignment]; |
| 512 [[profileNameTextField_ cell] setWraps:NO]; | 518 [[profileNameTextField_ cell] setWraps:NO]; |
| 513 [[profileNameTextField_ cell] setLineBreakMode: | 519 [[profileNameTextField_ cell] setLineBreakMode: |
| 514 NSLineBreakByTruncatingTail]; | 520 NSLineBreakByTruncatingTail]; |
| 515 [profileNameTextField_ setDelegate:self]; | 521 [profileNameTextField_ setDelegate:self]; |
| 516 [self addSubview:profileNameTextField_]; | 522 [self addSubview:profileNameTextField_]; |
| 517 | 523 |
| 518 // Hide the textfield until the user clicks on the button. | 524 // Hide the textfield until the user clicks on the button. |
| 519 [profileNameTextField_ setHidden:YES]; | 525 [profileNameTextField_ setHidden:YES]; |
| 520 } | 526 } |
| 521 } | 527 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 | 591 |
| 586 - (NSSize)cellSize { | 592 - (NSSize)cellSize { |
| 587 NSSize buttonSize = [super cellSize]; | 593 NSSize buttonSize = [super cellSize]; |
| 588 buttonSize.width += leftMarginSpacing_ + imageTitleSpacing_; | 594 buttonSize.width += leftMarginSpacing_ + imageTitleSpacing_; |
| 589 return buttonSize; | 595 return buttonSize; |
| 590 } | 596 } |
| 591 | 597 |
| 592 @end | 598 @end |
| 593 | 599 |
| 594 // A custom button that allows for setting a background color when hovered over. | 600 // A custom button that allows for setting a background color when hovered over. |
| 595 @interface BackgroundColorHoverButton : HoverImageButton | 601 @interface BackgroundColorHoverButton : HoverImageButton { |
| 602 @private |
| 603 base::scoped_nsobject<NSColor> backgroundColor_; |
| 604 base::scoped_nsobject<NSColor> hoverColor_; |
| 605 } |
| 596 @end | 606 @end |
| 597 | 607 |
| 598 @implementation BackgroundColorHoverButton | 608 @implementation BackgroundColorHoverButton |
| 599 - (id)initWithFrame:(NSRect)frameRect { | 609 |
| 610 - (id)initWithFrame:(NSRect)frameRect |
| 611 imageTitleSpacing:(int)imageTitleSpacing |
| 612 backgroundColor:(NSColor*)backgroundColor { |
| 600 if ((self = [super initWithFrame:frameRect])) { | 613 if ((self = [super initWithFrame:frameRect])) { |
| 614 backgroundColor_.reset([backgroundColor retain]); |
| 615 hoverColor_.reset([gfx::SkColorToCalibratedNSColor( |
| 616 ui::NativeTheme::instance()->GetSystemColor( |
| 617 ui::NativeTheme::kColorId_ButtonHoverBackgroundColor)) retain]); |
| 618 |
| 601 [self setBordered:NO]; | 619 [self setBordered:NO]; |
| 602 [self setFont:[NSFont labelFontOfSize:kTextFontSize]]; | 620 [self setFont:[NSFont labelFontOfSize:kTextFontSize]]; |
| 603 [self setButtonType:NSMomentaryChangeButton]; | 621 [self setButtonType:NSMomentaryChangeButton]; |
| 604 | 622 |
| 605 base::scoped_nsobject<CustomPaddingImageButtonCell> cell( | 623 base::scoped_nsobject<CustomPaddingImageButtonCell> cell( |
| 606 [[CustomPaddingImageButtonCell alloc] | 624 [[CustomPaddingImageButtonCell alloc] |
| 607 initWithLeftMarginSpacing:kHorizontalSpacing | 625 initWithLeftMarginSpacing:kHorizontalSpacing |
| 608 imageTitleSpacing:kImageTitleSpacing]); | 626 imageTitleSpacing:imageTitleSpacing]); |
| 609 [cell setLineBreakMode:NSLineBreakByTruncatingTail]; | 627 [cell setLineBreakMode:NSLineBreakByTruncatingTail]; |
| 610 [self setCell:cell.get()]; | 628 [self setCell:cell.get()]; |
| 611 } | 629 } |
| 612 return self; | 630 return self; |
| 613 } | 631 } |
| 614 | 632 |
| 615 - (void)setHoverState:(HoverState)state { | 633 - (void)setHoverState:(HoverState)state { |
| 616 [super setHoverState:state]; | 634 [super setHoverState:state]; |
| 617 bool isHighlighted = ([self hoverState] != kHoverStateNone); | 635 bool isHighlighted = ([self hoverState] != kHoverStateNone); |
| 618 | 636 |
| 619 NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor( | 637 NSColor* backgroundColor = isHighlighted ? hoverColor_ : backgroundColor_; |
| 620 ui::NativeTheme::instance()->GetSystemColor(isHighlighted? | |
| 621 ui::NativeTheme::kColorId_MenuSeparatorColor : | |
| 622 ui::NativeTheme::kColorId_DialogBackground)); | |
| 623 | |
| 624 [[self cell] setBackgroundColor:backgroundColor]; | 638 [[self cell] setBackgroundColor:backgroundColor]; |
| 625 } | 639 } |
| 626 | 640 |
| 627 @end | 641 @end |
| 628 | 642 |
| 629 // A custom view with the given background color. | 643 // A custom view with the given background color. |
| 630 @interface BackgroundColorView : NSView { | 644 @interface BackgroundColorView : NSView { |
| 631 @private | 645 @private |
| 632 base::scoped_nsobject<NSColor> backgroundColor_; | 646 base::scoped_nsobject<NSColor> backgroundColor_; |
| 633 } | 647 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 // out the feature. Otherwise, it notifies the user that the feature has been | 680 // out the feature. Otherwise, it notifies the user that the feature has been |
| 667 // enabled if needed. | 681 // enabled if needed. |
| 668 - (NSView*)buildPreviewTutorialIfNeeded:(const AvatarMenu::Item&)item; | 682 - (NSView*)buildPreviewTutorialIfNeeded:(const AvatarMenu::Item&)item; |
| 669 | 683 |
| 670 // Creates the main profile card for the profile |item| at the top of | 684 // Creates the main profile card for the profile |item| at the top of |
| 671 // the bubble. | 685 // the bubble. |
| 672 - (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item; | 686 - (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item; |
| 673 | 687 |
| 674 // Creates the possible links for the main profile card with profile |item|. | 688 // Creates the possible links for the main profile card with profile |item|. |
| 675 - (NSView*)createCurrentProfileLinksForItem:(const AvatarMenu::Item&)item | 689 - (NSView*)createCurrentProfileLinksForItem:(const AvatarMenu::Item&)item |
| 676 withXOffset:(CGFloat)xOffset; | 690 rect:(NSRect)rect; |
| 677 | 691 |
| 678 // Creates a main profile card for the guest user. | 692 // Creates a main profile card for the guest user. |
| 679 - (NSView*)createGuestProfileView; | 693 - (NSView*)createGuestProfileView; |
| 680 | 694 |
| 681 // Creates an item for the profile |itemIndex| that is used in the fast profile | 695 // Creates an item for the profile |itemIndex| that is used in the fast profile |
| 682 // switcher in the middle of the bubble. | 696 // switcher in the middle of the bubble. |
| 683 - (NSButton*)createOtherProfileView:(int)itemIndex; | 697 - (NSButton*)createOtherProfileView:(int)itemIndex; |
| 684 | 698 |
| 685 // Creates the "Not you" and Lock option buttons. | 699 // Creates the "Not you" and Lock option buttons. |
| 686 - (NSView*)createOptionsViewWithRect:(NSRect)rect | 700 - (NSView*)createOptionsViewWithRect:(NSRect)rect |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 } | 747 } |
| 734 | 748 |
| 735 - (IBAction)showUserManager:(id)sender { | 749 - (IBAction)showUserManager:(id)sender { |
| 736 profiles::ShowUserManagerMaybeWithTutorial(browser_->profile()); | 750 profiles::ShowUserManagerMaybeWithTutorial(browser_->profile()); |
| 737 } | 751 } |
| 738 | 752 |
| 739 - (IBAction)showAccountManagement:(id)sender { | 753 - (IBAction)showAccountManagement:(id)sender { |
| 740 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT]; | 754 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT]; |
| 741 } | 755 } |
| 742 | 756 |
| 757 - (IBAction)hideAccountManagement:(id)sender { |
| 758 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_PROFILE_CHOOSER]; |
| 759 } |
| 760 |
| 743 - (IBAction)lockProfile:(id)sender { | 761 - (IBAction)lockProfile:(id)sender { |
| 744 profiles::LockProfile(browser_->profile()); | 762 profiles::LockProfile(browser_->profile()); |
| 745 } | 763 } |
| 746 | 764 |
| 747 - (IBAction)showSigninPage:(id)sender { | 765 - (IBAction)showInlineSigninPage:(id)sender { |
| 748 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_GAIA_SIGNIN]; | 766 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_GAIA_SIGNIN]; |
| 749 } | 767 } |
| 750 | 768 |
| 769 - (IBAction)showTabbedSigninPage:(id)sender { |
| 770 chrome::ShowBrowserSignin(browser_, signin::SOURCE_MENU); |
| 771 } |
| 772 |
| 751 - (IBAction)addAccount:(id)sender { | 773 - (IBAction)addAccount:(id)sender { |
| 752 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT]; | 774 [self initMenuContentsWithView:BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT]; |
| 753 } | 775 } |
| 754 | 776 |
| 755 - (IBAction)navigateBackFromSigninPage:(id)sender { | 777 - (IBAction)navigateBackFromSigninPage:(id)sender { |
| 756 std::string primaryAccount = SigninManagerFactory::GetForProfile( | 778 std::string primaryAccount = SigninManagerFactory::GetForProfile( |
| 757 browser_->profile())->GetAuthenticatedUsername(); | 779 browser_->profile())->GetAuthenticatedUsername(); |
| 758 [self initMenuContentsWithView:primaryAccount.empty() ? | 780 [self initMenuContentsWithView:primaryAccount.empty() ? |
| 759 BUBBLE_VIEW_MODE_PROFILE_CHOOSER : BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT]; | 781 BUBBLE_VIEW_MODE_PROFILE_CHOOSER : BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT]; |
| 760 } | 782 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 enableLock = item.signed_in; | 903 enableLock = item.signed_in; |
| 882 } else { | 904 } else { |
| 883 [otherProfiles addObject:[self createOtherProfileView:i]]; | 905 [otherProfiles addObject:[self createOtherProfileView:i]]; |
| 884 } | 906 } |
| 885 } | 907 } |
| 886 if (!currentProfileView) // Guest windows don't have an active profile. | 908 if (!currentProfileView) // Guest windows don't have an active profile. |
| 887 currentProfileView = [self createGuestProfileView]; | 909 currentProfileView = [self createGuestProfileView]; |
| 888 | 910 |
| 889 // |yOffset| is the next position at which to draw in |contentView| | 911 // |yOffset| is the next position at which to draw in |contentView| |
| 890 // coordinates. | 912 // coordinates. |
| 891 CGFloat yOffset = kSmallVerticalSpacing; | 913 CGFloat yOffset = 0; |
| 892 | 914 |
| 893 // Option buttons. | 915 // Option buttons. Only available with the new profile management flag. |
| 894 NSView* optionsView = [self createOptionsViewWithRect: | 916 if (switches::IsNewProfileManagement()) { |
| 895 NSMakeRect(0, yOffset, kFixedMenuWidth, 0) | 917 NSRect rect = NSMakeRect(0, yOffset, kFixedMenuWidth, 0); |
| 896 enableLock:enableLock]; | 918 NSView* optionsView = [self createOptionsViewWithRect:rect |
| 897 [contentView addSubview:optionsView]; | 919 enableLock:enableLock]; |
| 898 yOffset = NSMaxY([optionsView frame]) + kSmallVerticalSpacing; | 920 [contentView addSubview:optionsView]; |
| 921 rect.origin.y = NSMaxY([optionsView frame]); |
| 899 | 922 |
| 900 NSBox* separator = [self separatorWithFrame: | 923 NSBox* separator = [self separatorWithFrame:rect]; |
| 901 NSMakeRect(0, yOffset, kFixedMenuWidth, 0)]; | 924 [contentView addSubview:separator]; |
| 902 [contentView addSubview:separator]; | 925 yOffset = NSMaxY([separator frame]); |
| 903 yOffset = NSMaxY([separator frame]) + kVerticalSpacing; | 926 } |
| 904 | 927 |
| 905 if (viewToDisplay == BUBBLE_VIEW_MODE_PROFILE_CHOOSER && | 928 if (viewToDisplay == BUBBLE_VIEW_MODE_PROFILE_CHOOSER && |
| 906 switches::IsFastUserSwitching()) { | 929 switches::IsFastUserSwitching()) { |
| 907 // Other profiles switcher. The profiles have already been sorted | 930 // Other profiles switcher. The profiles have already been sorted |
| 908 // by their y-coordinate, so they can be added in the existing order. | 931 // by their y-coordinate, so they can be added in the existing order. |
| 909 for (NSView *otherProfileView in otherProfiles.get()) { | 932 for (NSView *otherProfileView in otherProfiles.get()) { |
| 910 [otherProfileView setFrameOrigin:NSMakePoint(kHorizontalSpacing, | 933 [otherProfileView setFrameOrigin:NSMakePoint(0, yOffset)]; |
| 911 yOffset)]; | |
| 912 [contentView addSubview:otherProfileView]; | 934 [contentView addSubview:otherProfileView]; |
| 913 yOffset = NSMaxY([otherProfileView frame]) + kSmallVerticalSpacing; | 935 yOffset = NSMaxY([otherProfileView frame]); |
| 936 |
| 937 NSBox* separator = |
| 938 [self separatorWithFrame:NSMakeRect(0, yOffset, kFixedMenuWidth, 0)]; |
| 939 [contentView addSubview:separator]; |
| 940 yOffset = NSMaxY([separator frame]); |
| 914 } | 941 } |
| 915 | |
| 916 // If we displayed other profiles, ensure the spacing between the last item | |
| 917 // and the active profile card is the same as the spacing between the active | |
| 918 // profile card and the bottom of the bubble. | |
| 919 if ([otherProfiles.get() count] > 0) | |
| 920 yOffset += kSmallVerticalSpacing; | |
| 921 } else if (viewToDisplay == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) { | 942 } else if (viewToDisplay == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) { |
| 922 NSView* currentProfileAccountsView = [self createCurrentProfileAccountsView: | 943 NSView* currentProfileAccountsView = [self createCurrentProfileAccountsView: |
| 923 NSMakeRect(kHorizontalSpacing, | 944 NSMakeRect(0, yOffset, kFixedMenuWidth, 0)]; |
| 924 yOffset, | |
| 925 kFixedMenuWidth - 2 * kHorizontalSpacing, | |
| 926 0)]; | |
| 927 [contentView addSubview:currentProfileAccountsView]; | 945 [contentView addSubview:currentProfileAccountsView]; |
| 928 yOffset = NSMaxY([currentProfileAccountsView frame]) + kVerticalSpacing; | 946 yOffset = NSMaxY([currentProfileAccountsView frame]); |
| 929 | 947 |
| 930 NSBox* accountsSeparator = [self separatorWithFrame: | 948 NSBox* accountsSeparator = [self separatorWithFrame: |
| 931 NSMakeRect(0, yOffset, kFixedMenuWidth, 0)]; | 949 NSMakeRect(0, yOffset, kFixedMenuWidth, 0)]; |
| 932 [contentView addSubview:accountsSeparator]; | 950 [contentView addSubview:accountsSeparator]; |
| 933 yOffset = NSMaxY([accountsSeparator frame]) + kVerticalSpacing; | 951 yOffset = NSMaxY([accountsSeparator frame]); |
| 934 } | 952 } |
| 935 | 953 |
| 936 // Active profile card. | 954 // Active profile card. |
| 937 if (currentProfileView) { | 955 if (currentProfileView) { |
| 938 [currentProfileView setFrameOrigin:NSMakePoint(kHorizontalSpacing, | 956 yOffset += kVerticalSpacing; |
| 939 yOffset)]; | 957 [currentProfileView setFrameOrigin:NSMakePoint(0, yOffset)]; |
| 940 [contentView addSubview:currentProfileView]; | 958 [contentView addSubview:currentProfileView]; |
| 941 yOffset = NSMaxY([currentProfileView frame]) + kVerticalSpacing; | 959 yOffset = NSMaxY([currentProfileView frame]) + kVerticalSpacing; |
| 942 } | 960 } |
| 943 | 961 |
| 944 if (tutorialView) { | 962 if (tutorialView) { |
| 945 [tutorialView setFrameOrigin:NSMakePoint(0, yOffset)]; | 963 [tutorialView setFrameOrigin:NSMakePoint(0, yOffset)]; |
| 946 [contentView addSubview:tutorialView]; | 964 [contentView addSubview:tutorialView]; |
| 947 yOffset = NSMaxY([tutorialView frame]); | 965 yOffset = NSMaxY([tutorialView frame]); |
| 948 } else { | 966 } else { |
| 949 tutorialShowing_ = false; | 967 tutorialShowing_ = false; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 | 1101 |
| 1084 [containerWithCaret setFrameSize: | 1102 [containerWithCaret setFrameSize: |
| 1085 NSMakeSize(kFixedMenuWidth, NSMaxY([container frame]))]; | 1103 NSMakeSize(kFixedMenuWidth, NSMaxY([container frame]))]; |
| 1086 return containerWithCaret.autorelease(); | 1104 return containerWithCaret.autorelease(); |
| 1087 } | 1105 } |
| 1088 | 1106 |
| 1089 - (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item { | 1107 - (NSView*)createCurrentProfileView:(const AvatarMenu::Item&)item { |
| 1090 base::scoped_nsobject<NSView> container([[NSView alloc] | 1108 base::scoped_nsobject<NSView> container([[NSView alloc] |
| 1091 initWithFrame:NSZeroRect]); | 1109 initWithFrame:NSZeroRect]); |
| 1092 | 1110 |
| 1093 // Profile icon. | 1111 CGFloat xOffset = kHorizontalSpacing; |
| 1094 base::scoped_nsobject<EditableProfilePhoto> iconView( | 1112 CGFloat yOffset = 0; |
| 1095 [[EditableProfilePhoto alloc] | 1113 CGFloat availableTextWidth = kFixedMenuWidth - 2 * kHorizontalSpacing; |
| 1096 initWithFrame:NSMakeRect(0, 0, kLargeImageSide, kLargeImageSide) | |
| 1097 avatarMenu:avatarMenu_.get() | |
| 1098 profileIcon:item.icon | |
| 1099 editingAllowed:!isGuestSession_]); | |
| 1100 | 1114 |
| 1101 [container addSubview:iconView]; | 1115 // Profile options. This can be a link to the accounts view, the profile's |
| 1102 | 1116 // username for signed in users, or a "Sign in" button for local profiles. |
| 1103 CGFloat xOffset = NSMaxX([iconView frame]) + kHorizontalSpacing; | 1117 if (!isGuestSession_) { |
| 1104 CGFloat yOffset = kVerticalSpacing; | |
| 1105 if (!isGuestSession_ && viewMode_ == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) { | |
| 1106 NSView* linksContainer = | 1118 NSView* linksContainer = |
| 1107 [self createCurrentProfileLinksForItem:item withXOffset:xOffset]; | 1119 [self createCurrentProfileLinksForItem:item |
| 1120 rect:NSMakeRect(xOffset, yOffset, |
| 1121 availableTextWidth, |
| 1122 0)]; |
| 1108 [container addSubview:linksContainer]; | 1123 [container addSubview:linksContainer]; |
| 1109 yOffset = NSMaxY([linksContainer frame]); | 1124 yOffset = NSMaxY([linksContainer frame]); |
| 1110 } | 1125 } |
| 1111 | 1126 |
| 1112 // Profile name. | 1127 // Profile name, centered. |
| 1113 CGFloat availableTextWidth = | |
| 1114 kFixedMenuWidth - xOffset - 2 * kHorizontalSpacing; | |
| 1115 base::scoped_nsobject<EditableProfileNameButton> profileName( | 1128 base::scoped_nsobject<EditableProfileNameButton> profileName( |
| 1116 [[EditableProfileNameButton alloc] | 1129 [[EditableProfileNameButton alloc] |
| 1117 initWithFrame:NSMakeRect(xOffset, yOffset, | 1130 initWithFrame:NSMakeRect(xOffset, yOffset, |
| 1118 availableTextWidth, | 1131 availableTextWidth, |
| 1119 kProfileButtonHeight) | 1132 kProfileButtonHeight) |
| 1120 profile:browser_->profile() | 1133 profile:browser_->profile() |
| 1121 profileName:base::SysUTF16ToNSString( | 1134 profileName:base::SysUTF16ToNSString( |
| 1122 profiles::GetAvatarNameForProfile(browser_->profile())) | 1135 profiles::GetAvatarNameForProfile(browser_->profile())) |
| 1123 editingAllowed:!isGuestSession_]); | 1136 editingAllowed:!isGuestSession_]); |
| 1124 | 1137 |
| 1125 [container addSubview:profileName]; | 1138 [container addSubview:profileName]; |
| 1126 [container setFrameSize:NSMakeSize(kFixedMenuWidth, | 1139 yOffset = NSMaxY([profileName frame]); |
| 1127 NSHeight([iconView frame]))]; | 1140 |
| 1141 // Profile icon, centered. |
| 1142 xOffset = (kFixedMenuWidth - kLargeImageSide) / 2; |
| 1143 base::scoped_nsobject<EditableProfilePhoto> iconView( |
| 1144 [[EditableProfilePhoto alloc] |
| 1145 initWithFrame:NSMakeRect(xOffset, yOffset, |
| 1146 kLargeImageSide, kLargeImageSide) |
| 1147 avatarMenu:avatarMenu_.get() |
| 1148 profileIcon:item.icon |
| 1149 editingAllowed:!isGuestSession_]); |
| 1150 |
| 1151 [container addSubview:iconView]; |
| 1152 yOffset = NSMaxY([iconView frame]); |
| 1153 |
| 1154 [container setFrameSize:NSMakeSize(kFixedMenuWidth, yOffset)]; |
| 1128 return container.autorelease(); | 1155 return container.autorelease(); |
| 1129 } | 1156 } |
| 1130 | 1157 |
| 1131 - (NSView*)createCurrentProfileLinksForItem:(const AvatarMenu::Item&)item | 1158 - (NSView*)createCurrentProfileLinksForItem:(const AvatarMenu::Item&)item |
| 1132 withXOffset:(CGFloat)xOffset { | 1159 rect:(NSRect)rect { |
| 1133 base::scoped_nsobject<NSView> container([[NSView alloc] | 1160 base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]); |
| 1134 initWithFrame:NSZeroRect]); | |
| 1135 | 1161 |
| 1162 // Don't double-apply the left margin to the sub-views. |
| 1163 rect.origin.x = 0; |
| 1164 |
| 1165 // The available links depend on the type of profile that is active. |
| 1136 NSButton* link; | 1166 NSButton* link; |
| 1137 NSPoint frameOrigin = NSMakePoint(xOffset, kSmallVerticalSpacing); | |
| 1138 // The available links depend on the type of profile that is active. | |
| 1139 if (item.signed_in) { | 1167 if (item.signed_in) { |
| 1140 link = [self linkButtonWithTitle:l10n_util::GetNSString( | 1168 if (switches::IsNewProfileManagement()) { |
| 1141 IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON) | 1169 NSString* linkTitle = l10n_util::GetNSString( |
| 1142 frameOrigin:frameOrigin | 1170 viewMode_ == BUBBLE_VIEW_MODE_PROFILE_CHOOSER ? |
| 1143 action:@selector(showAccountManagement:)]; | 1171 IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON : |
| 1172 IDS_PROFILES_PROFILE_HIDE_MANAGE_ACCOUNTS_BUTTON); |
| 1173 SEL linkSelector = (viewMode_ == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) ? |
| 1174 @selector(showAccountManagement:) : @selector(hideAccountManagement:); |
| 1175 link = [self linkButtonWithTitle:linkTitle |
| 1176 frameOrigin:rect.origin |
| 1177 action:linkSelector]; |
| 1178 } else { |
| 1179 link = [self linkButtonWithTitle:base::SysUTF16ToNSString(item.sync_state) |
| 1180 frameOrigin:rect.origin |
| 1181 action:nil]; |
| 1182 [[link cell] setTextColor:[NSColor blackColor]]; |
| 1183 } |
| 1184 // -linkButtonWithTitle sizeToFit's the link, so re-stretch it so that it |
| 1185 // can be centered correctly in the view. |
| 1186 rect.size.height = NSMaxY([link frame]); |
| 1187 [link setFrame:rect]; |
| 1188 [link setAlignment:NSCenterTextAlignment]; |
| 1144 } else { | 1189 } else { |
| 1145 link = [self linkButtonWithTitle:l10n_util::GetNSStringFWithFixup( | 1190 rect.size.height = kBlueButtonHeight; |
| 1146 IDS_SYNC_START_SYNC_BUTTON_LABEL, | 1191 link = [[BlueLabelButton alloc] initWithFrame:rect]; |
| 1147 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)) | 1192 |
| 1148 frameOrigin:frameOrigin | 1193 // Manually elide the button text so that the contents fit inside the bubble |
| 1149 action:@selector(showSigninPage:)]; | 1194 // This is needed because the BlueLabelButton cell resets the style on |
| 1195 // every call to -cellSize, which prevents setting a custom lineBreakMode. |
| 1196 NSString* elidedButtonText = base::SysUTF16ToNSString(gfx::ElideText( |
| 1197 l10n_util::GetStringFUTF16( |
| 1198 IDS_SYNC_START_SYNC_BUTTON_LABEL, |
| 1199 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)), |
| 1200 ui::ResourceBundle::GetSharedInstance().GetFontList( |
| 1201 ui::ResourceBundle::BaseFont), |
| 1202 rect.size.width, |
| 1203 gfx::ELIDE_AT_END)); |
| 1204 |
| 1205 [link setTitle:elidedButtonText]; |
| 1206 [link setTarget:self]; |
| 1207 [link setAction:switches::IsNewProfileManagement() ? |
| 1208 @selector(showInlineSigninPage:) : @selector(showTabbedSigninPage:)]; |
| 1150 } | 1209 } |
| 1151 | 1210 |
| 1152 [container addSubview:link]; | 1211 [container addSubview:link]; |
| 1153 [container setFrameSize:NSMakeSize( | 1212 [container setFrameSize:rect.size]; |
| 1154 NSMaxX([link frame]), NSMaxY([link frame]) + kSmallVerticalSpacing)]; | |
| 1155 return container.autorelease(); | 1213 return container.autorelease(); |
| 1156 } | 1214 } |
| 1157 | 1215 |
| 1158 - (NSView*)createGuestProfileView { | 1216 - (NSView*)createGuestProfileView { |
| 1159 gfx::Image guestIcon = | 1217 gfx::Image guestIcon = |
| 1160 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 1218 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 1161 IDR_LOGIN_GUEST); | 1219 IDR_LOGIN_GUEST); |
| 1162 AvatarMenu::Item guestItem(std::string::npos, /* menu_index, not used */ | 1220 AvatarMenu::Item guestItem(std::string::npos, /* menu_index, not used */ |
| 1163 std::string::npos, /* profile_index, not used */ | 1221 std::string::npos, /* profile_index, not used */ |
| 1164 guestIcon); | 1222 guestIcon); |
| 1165 guestItem.active = true; | 1223 guestItem.active = true; |
| 1166 guestItem.name = base::SysNSStringToUTF16( | 1224 guestItem.name = base::SysNSStringToUTF16( |
| 1167 l10n_util::GetNSString(IDS_PROFILES_GUEST_PROFILE_NAME)); | 1225 l10n_util::GetNSString(IDS_PROFILES_GUEST_PROFILE_NAME)); |
| 1168 | 1226 |
| 1169 return [self createCurrentProfileView:guestItem]; | 1227 return [self createCurrentProfileView:guestItem]; |
| 1170 } | 1228 } |
| 1171 | 1229 |
| 1172 - (NSButton*)createOtherProfileView:(int)itemIndex { | 1230 - (NSButton*)createOtherProfileView:(int)itemIndex { |
| 1173 const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex); | 1231 const AvatarMenu::Item& item = avatarMenu_->GetItemAt(itemIndex); |
| 1174 base::scoped_nsobject<NSButton> profileButton([[NSButton alloc] | |
| 1175 initWithFrame:NSZeroRect]); | |
| 1176 base::scoped_nsobject<CustomPaddingImageButtonCell> cell( | |
| 1177 [[CustomPaddingImageButtonCell alloc] | |
| 1178 initWithLeftMarginSpacing:0 | |
| 1179 imageTitleSpacing:kImageTitleSpacing]); | |
| 1180 [profileButton setCell:cell.get()]; | |
| 1181 | 1232 |
| 1182 [[profileButton cell] setLineBreakMode:NSLineBreakByTruncatingTail]; | 1233 NSRect rect = NSMakeRect(0, 0, kFixedMenuWidth, |
| 1234 kBlueButtonHeight + kSmallVerticalSpacing); |
| 1235 base::scoped_nsobject<BackgroundColorHoverButton> profileButton( |
| 1236 [[BackgroundColorHoverButton alloc] |
| 1237 initWithFrame:rect |
| 1238 imageTitleSpacing:kImageTitleSpacing |
| 1239 backgroundColor:GetDialogBackgroundColor()]); |
| 1183 [profileButton setTitle:base::SysUTF16ToNSString(item.name)]; | 1240 [profileButton setTitle:base::SysUTF16ToNSString(item.name)]; |
| 1184 [profileButton setImage:CreateProfileImage( | 1241 [profileButton setDefaultImage:CreateProfileImage( |
| 1185 item.icon, kSmallImageSide).ToNSImage()]; | 1242 item.icon, kSmallImageSide).ToNSImage()]; |
| 1186 [profileButton setImagePosition:NSImageLeft]; | 1243 [profileButton setImagePosition:NSImageLeft]; |
| 1187 [profileButton setAlignment:NSLeftTextAlignment]; | 1244 [profileButton setAlignment:NSLeftTextAlignment]; |
| 1188 [profileButton setBordered:NO]; | 1245 [profileButton setBordered:NO]; |
| 1189 [profileButton setFont:[NSFont labelFontOfSize:kTitleFontSize]]; | |
| 1190 [profileButton setTag:itemIndex]; | 1246 [profileButton setTag:itemIndex]; |
| 1191 [profileButton setTarget:self]; | 1247 [profileButton setTarget:self]; |
| 1192 [profileButton setAction:@selector(switchToProfile:)]; | 1248 [profileButton setAction:@selector(switchToProfile:)]; |
| 1193 | 1249 |
| 1194 // Since the bubble is fixed width, we need to calculate the width available | |
| 1195 // for the profile name, as longer names will have to be elided. | |
| 1196 CGFloat availableTextWidth = kFixedMenuWidth - 2 * kHorizontalSpacing; | |
| 1197 [profileButton sizeToFit]; | |
| 1198 [profileButton setFrameSize:NSMakeSize(availableTextWidth, | |
| 1199 NSHeight([profileButton frame]))]; | |
| 1200 | |
| 1201 return profileButton.autorelease(); | 1250 return profileButton.autorelease(); |
| 1202 } | 1251 } |
| 1203 | 1252 |
| 1204 - (NSView*)createOptionsViewWithRect:(NSRect)rect | 1253 - (NSView*)createOptionsViewWithRect:(NSRect)rect |
| 1205 enableLock:(BOOL)enableLock { | 1254 enableLock:(BOOL)enableLock { |
| 1206 int widthOfLockButton = enableLock? 2 * kHorizontalSpacing + 12 : 0; | 1255 int widthOfLockButton = enableLock? 2 * kHorizontalSpacing + 12 : 0; |
| 1207 NSRect viewRect = NSMakeRect(0, 0, | 1256 NSRect viewRect = NSMakeRect(0, 0, |
| 1208 rect.size.width - widthOfLockButton, | 1257 rect.size.width - widthOfLockButton, |
| 1209 kBlueButtonHeight); | 1258 kBlueButtonHeight + kVerticalSpacing); |
| 1210 NSButton* notYouButton = | 1259 NSButton* notYouButton = |
| 1211 [self hoverButtonWithRect:viewRect | 1260 [self hoverButtonWithRect:viewRect |
| 1212 text:l10n_util::GetNSStringF( | 1261 text:l10n_util::GetNSStringF( |
| 1213 IDS_PROFILES_NOT_YOU_BUTTON, | 1262 IDS_PROFILES_NOT_YOU_BUTTON, |
| 1214 profiles::GetAvatarNameForProfile(browser_->profile())) | 1263 profiles::GetAvatarNameForProfile(browser_->profile())) |
| 1215 imageResourceId:IDR_ICON_PROFILES_MENU_AVATAR | 1264 imageResourceId:IDR_ICON_PROFILES_MENU_AVATAR |
| 1216 alternateImageResourceId:IDR_ICON_PROFILES_MENU_AVATAR | 1265 alternateImageResourceId:IDR_ICON_PROFILES_MENU_AVATAR |
| 1217 action:@selector(showUserManager:)]; | 1266 action:@selector(showUserManager:)]; |
| 1218 | 1267 |
| 1219 rect.size.height = NSMaxY([notYouButton frame]); | 1268 rect.size.height = NSMaxY([notYouButton frame]); |
| 1220 base::scoped_nsobject<NSView> container([[NSView alloc] | 1269 base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]); |
| 1221 initWithFrame:rect]); | |
| 1222 [container addSubview:notYouButton]; | 1270 [container addSubview:notYouButton]; |
| 1223 | 1271 |
| 1224 if (enableLock) { | 1272 if (enableLock) { |
| 1225 viewRect.origin.x = NSMaxX([notYouButton frame]); | 1273 viewRect.origin.x = NSMaxX([notYouButton frame]); |
| 1226 viewRect.size.width = widthOfLockButton; | 1274 viewRect.size.width = widthOfLockButton; |
| 1227 NSButton* lockButton = | 1275 NSButton* lockButton = |
| 1228 [self hoverButtonWithRect:viewRect | 1276 [self hoverButtonWithRect:viewRect |
| 1229 text:@"" | 1277 text:@"" |
| 1230 imageResourceId:IDR_ICON_PROFILES_MENU_LOCK | 1278 imageResourceId:IDR_ICON_PROFILES_MENU_LOCK |
| 1231 alternateImageResourceId:IDR_ICON_PROFILES_MENU_LOCK | 1279 alternateImageResourceId:IDR_ICON_PROFILES_MENU_LOCK |
| 1232 action:@selector(lockProfile:)]; | 1280 action:@selector(lockProfile:)]; |
| 1233 [container addSubview:lockButton]; | 1281 [container addSubview:lockButton]; |
| 1234 } | 1282 } |
| 1235 | 1283 |
| 1236 return container.autorelease(); | 1284 return container.autorelease(); |
| 1237 } | 1285 } |
| 1238 | 1286 |
| 1239 - (NSView*)createCurrentProfileAccountsView:(NSRect)rect { | 1287 - (NSView*)createCurrentProfileAccountsView:(NSRect)rect { |
| 1240 const CGFloat kAccountButtonHeight = 15; | 1288 const CGFloat kAccountButtonHeight = 34; |
| 1241 | 1289 |
| 1242 const AvatarMenu::Item& item = | 1290 const AvatarMenu::Item& item = |
| 1243 avatarMenu_->GetItemAt(avatarMenu_->GetActiveProfileIndex()); | 1291 avatarMenu_->GetItemAt(avatarMenu_->GetActiveProfileIndex()); |
| 1244 DCHECK(item.signed_in); | 1292 DCHECK(item.signed_in); |
| 1245 | 1293 |
| 1246 base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]); | 1294 NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor( |
| 1247 | 1295 profiles::kAvatarBubbleAccountsBackgroundColor); |
| 1248 NSRect viewRect = NSMakeRect(0, 0, rect.size.width, kBlueButtonHeight); | 1296 base::scoped_nsobject<NSView> container([[BackgroundColorView alloc] |
| 1249 base::scoped_nsobject<NSButton> addAccountsButton([[BlueLabelButton alloc] | 1297 initWithFrame:rect |
| 1250 initWithFrame:viewRect]); | 1298 withColor:backgroundColor]); |
| 1251 | 1299 |
| 1252 // Manually elide the button text so that the contents fit inside the bubble. | 1300 // Manually elide the button text so that the contents fit inside the bubble. |
| 1253 // This is needed because the BlueLabelButton cell resets the style on | 1301 // This is needed because the BlueLabelButton cell resets the style on |
| 1254 // every call to -cellSize, which prevents setting a custom lineBreakMode. | 1302 // every call to -cellSize, which prevents setting a custom lineBreakMode. |
| 1255 NSString* elidedButtonText = base::SysUTF16ToNSString(gfx::ElideText( | 1303 NSString* elidedButtonText = base::SysUTF16ToNSString(gfx::ElideText( |
| 1256 l10n_util::GetStringFUTF16( | 1304 l10n_util::GetStringFUTF16( |
| 1257 IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON, item.name), | 1305 IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON, item.name), |
| 1258 ui::ResourceBundle::GetSharedInstance().GetFontList( | 1306 ui::ResourceBundle::GetSharedInstance().GetFontList( |
| 1259 ui::ResourceBundle::BaseFont), | 1307 ui::ResourceBundle::BaseFont), |
| 1260 rect.size.width, | 1308 rect.size.width, |
| 1261 gfx::ELIDE_AT_END)); | 1309 gfx::ELIDE_AT_END)); |
| 1262 | 1310 |
| 1263 [addAccountsButton setTitle:elidedButtonText]; | 1311 NSButton* addAccountsButton = |
| 1264 [addAccountsButton setTarget:self]; | 1312 [self linkButtonWithTitle:elidedButtonText |
| 1265 [addAccountsButton setAction:@selector(addAccount:)]; | 1313 frameOrigin:NSMakePoint( |
| 1314 kHorizontalSpacing, kSmallVerticalSpacing) |
| 1315 action:@selector(addAccount:)]; |
| 1266 [container addSubview:addAccountsButton]; | 1316 [container addSubview:addAccountsButton]; |
| 1267 | 1317 |
| 1268 // Update the height of the email account buttons. This is needed so that the | 1318 NSView* accountEmails = [self createAccountsListWithRect:NSMakeRect( |
| 1269 // all the buttons span the entire width of the bubble. | 1319 0, kAccountButtonHeight, rect.size.width, kAccountButtonHeight)]; |
| 1270 viewRect.origin.y = NSMaxY([addAccountsButton frame]) + kVerticalSpacing; | 1320 [container addSubview:accountEmails]; |
| 1271 viewRect.size.height = kAccountButtonHeight; | |
| 1272 | 1321 |
| 1273 NSView* accountEmails = [self createAccountsListWithRect:viewRect]; | 1322 [container setFrameSize:NSMakeSize(rect.size.width, |
| 1274 [container addSubview:accountEmails]; | 1323 NSMaxY([accountEmails frame]))]; |
| 1275 [container setFrameSize:NSMakeSize( | |
| 1276 NSWidth([container frame]), NSMaxY([accountEmails frame]))]; | |
| 1277 return container.autorelease(); | 1324 return container.autorelease(); |
| 1278 } | 1325 } |
| 1279 | 1326 |
| 1280 - (NSView*)createAccountsListWithRect:(NSRect)rect { | 1327 - (NSView*)createAccountsListWithRect:(NSRect)rect { |
| 1281 base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]); | 1328 base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]); |
| 1282 currentProfileAccounts_.clear(); | 1329 currentProfileAccounts_.clear(); |
| 1283 | 1330 |
| 1284 Profile* profile = browser_->profile(); | 1331 Profile* profile = browser_->profile(); |
| 1285 std::string primaryAccount = | 1332 std::string primaryAccount = |
| 1286 SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedUsername(); | 1333 SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedUsername(); |
| 1287 DCHECK(!primaryAccount.empty()); | 1334 DCHECK(!primaryAccount.empty()); |
| 1288 std::vector<std::string>accounts = | 1335 std::vector<std::string>accounts = |
| 1289 profiles::GetSecondaryAccountsForProfile(profile, primaryAccount); | 1336 profiles::GetSecondaryAccountsForProfile(profile, primaryAccount); |
| 1290 | 1337 |
| 1291 rect.origin.y = 0; | 1338 rect.origin.y = 0; |
| 1292 for (size_t i = 0; i < accounts.size(); ++i) { | 1339 for (size_t i = 0; i < accounts.size(); ++i) { |
| 1293 // Save the original email address, as the button text could be elided. | 1340 // Save the original email address, as the button text could be elided. |
| 1294 currentProfileAccounts_[i] = accounts[i]; | 1341 currentProfileAccounts_[i] = accounts[i]; |
| 1295 NSButton* accountButton = [self accountButtonWithRect:rect | 1342 NSButton* accountButton = [self accountButtonWithRect:rect |
| 1296 title:accounts[i]]; | 1343 title:accounts[i]]; |
| 1297 [accountButton setTag:i]; | 1344 [accountButton setTag:i]; |
| 1298 [container addSubview:accountButton]; | 1345 [container addSubview:accountButton]; |
| 1299 rect.origin.y = NSMaxY([accountButton frame]) + kSmallVerticalSpacing; | 1346 rect.origin.y = NSMaxY([accountButton frame]); |
| 1300 } | 1347 } |
| 1301 | 1348 |
| 1302 // The primary account should always be listed first. | 1349 // The primary account should always be listed first. |
| 1303 NSButton* accountButton = [self accountButtonWithRect:rect | 1350 NSButton* accountButton = [self accountButtonWithRect:rect |
| 1304 title:primaryAccount]; | 1351 title:primaryAccount]; |
| 1305 [container addSubview:accountButton]; | 1352 [container addSubview:accountButton]; |
| 1306 [container setFrameSize:NSMakeSize(NSWidth([container frame]), | 1353 [container setFrameSize:NSMakeSize(NSWidth([container frame]), |
| 1307 NSMaxY([accountButton frame]))]; | 1354 NSMaxY([accountButton frame]))]; |
| 1308 [accountButton setTag:kPrimaryProfileTag]; | 1355 [accountButton setTag:kPrimaryProfileTag]; |
| 1309 return container.autorelease(); | 1356 return container.autorelease(); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 clickedOnLink:(id)link | 1474 clickedOnLink:(id)link |
| 1428 atIndex:(NSUInteger)charIndex { | 1475 atIndex:(NSUInteger)charIndex { |
| 1429 chrome::ShowSettings(browser_); | 1476 chrome::ShowSettings(browser_); |
| 1430 return YES; | 1477 return YES; |
| 1431 } | 1478 } |
| 1432 | 1479 |
| 1433 - (NSButton*)hoverButtonWithRect:(NSRect)rect | 1480 - (NSButton*)hoverButtonWithRect:(NSRect)rect |
| 1434 text:(NSString*)text | 1481 text:(NSString*)text |
| 1435 imageResourceId:(int)imageResourceId | 1482 imageResourceId:(int)imageResourceId |
| 1436 alternateImageResourceId:(int)alternateImageResourceId | 1483 alternateImageResourceId:(int)alternateImageResourceId |
| 1437 action:(SEL)action { | 1484 action:(SEL)action { |
| 1438 base::scoped_nsobject<BackgroundColorHoverButton> button( | 1485 base::scoped_nsobject<BackgroundColorHoverButton> button( |
| 1439 [[BackgroundColorHoverButton alloc] initWithFrame:rect]); | 1486 [[BackgroundColorHoverButton alloc] |
| 1487 initWithFrame:rect |
| 1488 imageTitleSpacing:kImageTitleSpacing |
| 1489 backgroundColor:GetDialogBackgroundColor()]); |
| 1440 | 1490 |
| 1441 [button setTitle:text]; | 1491 [button setTitle:text]; |
| 1442 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | 1492 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 1443 NSImage* alternateImage = rb->GetNativeImageNamed( | 1493 NSImage* alternateImage = rb->GetNativeImageNamed( |
| 1444 alternateImageResourceId).ToNSImage(); | 1494 alternateImageResourceId).ToNSImage(); |
| 1445 [button setDefaultImage:rb->GetNativeImageNamed(imageResourceId).ToNSImage()]; | 1495 [button setDefaultImage:rb->GetNativeImageNamed(imageResourceId).ToNSImage()]; |
| 1446 [button setHoverImage:alternateImage]; | 1496 [button setHoverImage:alternateImage]; |
| 1447 [button setPressedImage:alternateImage]; | 1497 [button setPressedImage:alternateImage]; |
| 1448 [button setImagePosition:NSImageLeft]; | 1498 [button setImagePosition:NSImageLeft]; |
| 1449 [button setAlignment:NSLeftTextAlignment]; | 1499 [button setAlignment:NSLeftTextAlignment]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1469 [link setTarget:self]; | 1519 [link setTarget:self]; |
| 1470 [link setAction:action]; | 1520 [link setAction:action]; |
| 1471 [link setFrameOrigin:frameOrigin]; | 1521 [link setFrameOrigin:frameOrigin]; |
| 1472 [link sizeToFit]; | 1522 [link sizeToFit]; |
| 1473 | 1523 |
| 1474 return link.autorelease(); | 1524 return link.autorelease(); |
| 1475 } | 1525 } |
| 1476 | 1526 |
| 1477 - (NSButton*)accountButtonWithRect:(NSRect)rect | 1527 - (NSButton*)accountButtonWithRect:(NSRect)rect |
| 1478 title:(const std::string&)title { | 1528 title:(const std::string&)title { |
| 1479 base::scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:rect]); | 1529 NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor( |
| 1530 profiles::kAvatarBubbleAccountsBackgroundColor); |
| 1531 base::scoped_nsobject<BackgroundColorHoverButton> button( |
| 1532 [[BackgroundColorHoverButton alloc] initWithFrame:rect |
| 1533 imageTitleSpacing:0 |
| 1534 backgroundColor:backgroundColor]); |
| 1535 |
| 1480 [button setTitle:ElideEmail(title, rect.size.width)]; | 1536 [button setTitle:ElideEmail(title, rect.size.width)]; |
| 1481 [button setAlignment:NSLeftTextAlignment]; | 1537 [button setAlignment:NSLeftTextAlignment]; |
| 1482 [button setBordered:NO]; | 1538 [button setBordered:NO]; |
| 1483 | |
| 1484 [button setImage:ui::ResourceBundle::GetSharedInstance(). | |
| 1485 GetNativeImageNamed(IDR_CLOSE_1).ToNSImage()]; | |
| 1486 [button setImagePosition:NSImageRight]; | |
| 1487 [button setTarget:self]; | 1539 [button setTarget:self]; |
| 1488 [button setAction:@selector(showAccountRemovalView:)]; | 1540 [button setAction:@selector(showAccountRemovalView:)]; |
| 1489 | 1541 |
| 1490 return button.autorelease(); | 1542 return button.autorelease(); |
| 1491 } | 1543 } |
| 1492 | 1544 |
| 1493 @end | 1545 @end |
| OLD | NEW |