1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/autofill/autofill_account_chooser.h"
7 #include "base/strings/sys_string_conversions.h"
8 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
9 #include "chrome/browser/ui/chrome_style.h"
10 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
11 #import "chrome/browser/ui/cocoa/autofill/down_arrow_popup_menu_cell.h"
12 #import "chrome/browser/ui/cocoa/menu_button.h"
13 #include "skia/ext/skia_utils_mac.h"
14 #import "ui/base/cocoa/controls/hyperlink_button_cell.h"
15 #include "ui/base/models/menu_model.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/resources/grit/ui_resources.h"
19 #pragma mark Helper functions
21 // Adds an item with the specified properties to |menu|.
22 void AddMenuItem(NSMenu *menu, id target, SEL selector, NSString* title,
23 int tag, bool enabled, bool checked) {
25 [menu addItem:[NSMenuItem separatorItem]];
29 base::scoped_nsobject<NSMenuItem> item(
30 [[NSMenuItem alloc] initWithTitle:title
35 [item setTarget:target];
37 [item setState:NSOnState];
38 [item setEnabled:enabled];
41 #pragma mark AutofillAccountChooser
43 @interface AutofillAccountChooser (Private)
44 - (void)performLayout;
47 @implementation AutofillAccountChooser
49 - (id)initWithFrame:(NSRect)frame
50 delegate:(autofill::AutofillDialogViewDelegate*)delegate {
51 if ((self = [super initWithFrame:frame])) {
54 icon_.reset([[NSImageView alloc] initWithFrame:NSZeroRect]);
55 [icon_ setImageFrameStyle:NSImageFrameNone];
57 link_.reset([[HyperlinkButtonCell buttonWithString:
58 base::SysUTF16ToNSString(delegate_->SignInLinkText())] retain]);
59 [link_ setAction:@selector(linkClicked:)];
60 [link_ setTarget:self];
61 [[link_ cell] setUnderlineOnHover:YES];
62 [[link_ cell] setTextColor:
63 gfx::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())];
65 popup_.reset([[MenuButton alloc] initWithFrame:NSZeroRect]);
66 base::scoped_nsobject<DownArrowPopupMenuCell> popupCell(
67 [[DownArrowPopupMenuCell alloc] initTextCell:@""]);
68 [popup_ setCell:popupCell];
70 [popup_ setOpenMenuOnClick:YES];
71 [popup_ setBordered:NO];
72 [popup_ setShowsBorderOnlyWhileMouseInside:NO];
73 NSImage* popupImage = ui::ResourceBundle::GetSharedInstance().
74 GetNativeImageNamed(IDR_MENU_DROPARROW).ToNSImage();
75 [popupCell setImage:popupImage
76 forButtonState:image_button_cell::kDefaultState];
78 base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
79 [menu setAutoenablesItems:NO];
80 [popup_ setAttachedMenu:menu];
82 [self setSubviews:@[link_, popup_, icon_]];
88 - (void)optionsMenuChanged:(id)sender {
89 ui::MenuModel* menuModel = delegate_->MenuModelForAccountChooser();
91 menuModel->ActivatedAt([sender tag]);
94 - (void)linkClicked:(id)sender {
95 delegate_->SignInLinkClicked();
99 [self setHidden:!delegate_->ShouldShowAccountChooser()];
101 NSImage* iconImage = delegate_->AccountChooserImage().AsNSImage();
102 [icon_ setImage:iconImage];
105 NSString* popupTitle =
106 base::SysUTF16ToNSString(delegate_->AccountChooserText());
107 [popup_ setTitle:popupTitle];
109 NSString* linkTitle =
110 base::SysUTF16ToNSString(delegate_->SignInLinkText());
111 [link_ setTitle:linkTitle];
114 NSMenu* accountMenu = [popup_ attachedMenu];
115 [accountMenu removeAllItems];
116 // See menu_button.h for documentation on why this is needed.
117 [accountMenu addItemWithTitle:@"" action:nil keyEquivalent:@""];
118 ui::MenuModel* model = delegate_->MenuModelForAccountChooser();
120 for (int i = 0; i < model->GetItemCount(); ++i) {
121 AddMenuItem(accountMenu,
123 @selector(optionsMenuChanged:),
124 base::SysUTF16ToNSString(model->GetLabelAt(i)),
126 model->IsEnabledAt(i),
127 model->IsItemCheckedAt(i));
131 bool showLink = !model;
132 [popup_ setHidden:showLink];
133 [link_ setHidden:!showLink];
135 [self performLayout];
138 - (void)performLayout {
139 NSRect bounds = [self bounds];
141 NSControl* activeControl = [link_ isHidden] ? popup_.get() : link_.get();
142 [activeControl sizeToFit];
143 NSRect frame = [activeControl frame];
144 frame.origin.x = NSMaxX(bounds) - NSWidth(frame);
145 [activeControl setFrame:frame];
147 [icon_ setFrameSize:[[icon_ image] size]];
148 frame.origin.x -= NSWidth([icon_ frame]) + autofill::kAroundTextPadding;
149 [icon_ setFrameOrigin:frame.origin];