1 // Copyright 2015 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/passwords/credential_item_view.h"
9 #include "base/i18n/rtl.h"
10 #include "base/mac/foundation_util.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
13 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "grit/theme_resources.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h"
18 #include "ui/gfx/image/image_skia.h"
19 #include "ui/gfx/image/image_skia_util_mac.h"
22 const CGFloat kHorizontalPaddingBetweenAvatarAndLabels = 10.0f;
23 const CGFloat kVerticalPaddingBetweenLabels = 2.0f;
26 @interface CredentialItemView()
27 + (NSString*)upperLabelTextForForm:(const autofill::PasswordForm&)passwordForm
28 style:(password_manager_mac::CredentialItemStyle)
30 + (NSString*)lowerLabelTextForForm:
31 (const autofill::PasswordForm&)passwordForm;
32 + (NSTextField*)labelWithText:(NSString*)title;
33 @property(nonatomic, readonly) NSTextField* upperLabel;
34 @property(nonatomic, readonly) NSTextField* lowerLabel;
35 @property(nonatomic, readonly) NSImageView* avatarView;
38 @implementation CredentialItemView
40 @synthesize upperLabel = upperLabel_;
41 @synthesize lowerLabel = lowerLabel_;
42 @synthesize avatarView = avatarView_;
43 @synthesize passwordForm = passwordForm_;
44 @synthesize credentialType = credentialType_;
46 - (id)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
47 credentialType:(password_manager::CredentialType)credentialType
48 style:(password_manager_mac::CredentialItemStyle)style
49 delegate:(id<CredentialItemDelegate>)delegate {
50 if ((self = [super init])) {
51 passwordForm_ = passwordForm;
52 credentialType_ = credentialType;
55 // -----------------------------------------------
56 // | | John Q. Facebooker |
57 // | icon | john@somewhere.com |
58 // -----------------------------------------------
62 avatarView_ = [[[NSImageView alloc] initWithFrame:NSZeroRect] autorelease];
63 [avatarView_ setWantsLayer:YES];
64 [[avatarView_ layer] setCornerRadius:kAvatarImageSize / 2.0f];
65 [[avatarView_ layer] setMasksToBounds:YES];
66 [self addSubview:avatarView_];
68 NSString* upperLabelText =
69 [[self class] upperLabelTextForForm:passwordForm_ style:style];
70 upperLabel_ = [[self class] labelWithText:upperLabelText];
71 [self addSubview:upperLabel_];
73 NSString* lowerLabelText =
74 [[self class] lowerLabelTextForForm:passwordForm_];
76 lowerLabel_ = [[self class] labelWithText:lowerLabelText];
77 [self addSubview:lowerLabel_];
80 // Compute the heights and widths of everything, as the layout depends on
81 // these measurements.
82 const CGFloat labelsHeight = NSHeight([upperLabel_ frame]) +
83 NSHeight([lowerLabel_ frame]) +
84 kVerticalPaddingBetweenLabels;
85 const CGFloat height = std::max(labelsHeight, CGFloat(kAvatarImageSize));
87 kAvatarImageSize + kHorizontalPaddingBetweenAvatarAndLabels +
88 std::max(NSWidth([upperLabel_ frame]), NSWidth([lowerLabel_ frame]));
89 self.frame = NSMakeRect(0, 0, width, height);
91 // Lay out the views (RTL reverses the order horizontally).
93 const CGFloat avatarX = base::i18n::IsRTL() ? width - kAvatarImageSize : 0;
94 const CGFloat avatarY =
95 (kAvatarImageSize > height) ? 0 : (height - kAvatarImageSize) / 2.0f;
96 [avatarView_ setFrame:NSMakeRect(avatarX, avatarY, kAvatarImageSize,
99 const CGFloat lowerX =
101 ? NSMinX([avatarView_ frame]) -
102 kHorizontalPaddingBetweenAvatarAndLabels -
103 NSWidth([lowerLabel_ frame])
104 : NSMaxX([avatarView_ frame]) +
105 kHorizontalPaddingBetweenAvatarAndLabels;
106 const CGFloat lowerLabelY =
107 (labelsHeight > height) ? 0 : (height - labelsHeight) / 2.0f;
108 NSRect lowerFrame = [lowerLabel_ frame];
109 lowerFrame.origin = NSMakePoint(lowerX, lowerLabelY);
110 [lowerLabel_ setFrame:lowerFrame];
112 const CGFloat upperX = base::i18n::IsRTL()
113 ? NSMinX([avatarView_ frame]) -
114 kHorizontalPaddingBetweenAvatarAndLabels -
115 NSWidth([upperLabel_ frame])
116 : NSMaxX([avatarView_ frame]) +
117 kHorizontalPaddingBetweenAvatarAndLabels;
118 const CGFloat upperLabelY =
119 NSMaxY(lowerFrame) + kVerticalPaddingBetweenLabels;
120 NSRect upperFrame = [upperLabel_ frame];
121 upperFrame.origin = NSMakePoint(upperX, upperLabelY);
122 [upperLabel_ setFrame:upperFrame];
124 // Use a default avatar and fetch the custom one, if it exists.
125 [self updateAvatar:[[self class] defaultAvatar]];
126 if (passwordForm_.icon_url.is_valid())
127 [delegate_ fetchAvatar:passwordForm_.icon_url forView:self];
129 // When resizing, stick to the left (resp. right for RTL) edge.
130 const NSUInteger autoresizingMask =
131 (base::i18n::IsRTL() ? NSViewMinXMargin : NSViewMaxXMargin);
132 [avatarView_ setAutoresizingMask:autoresizingMask];
133 [lowerLabel_ setAutoresizingMask:autoresizingMask];
134 [upperLabel_ setAutoresizingMask:autoresizingMask];
135 [self setAutoresizingMask:NSViewWidthSizable];
141 - (void)updateAvatar:(NSImage*)avatar {
142 [avatarView_ setImage:avatar];
145 + (NSImage*)defaultAvatar {
146 return gfx::NSImageFromImageSkia(ScaleImageForAccountAvatar(
147 *ResourceBundle::GetSharedInstance()
148 .GetImageNamed(IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE)
152 + (NSString*)upperLabelTextForForm:(const autofill::PasswordForm&)passwordForm
153 style:(password_manager_mac::CredentialItemStyle)
155 base::string16 name = passwordForm.display_name.empty()
156 ? passwordForm.username_value
157 : passwordForm.display_name;
159 case password_manager_mac::CredentialItemStyle::ACCOUNT_CHOOSER:
160 return base::SysUTF16ToNSString(name);
161 case password_manager_mac::CredentialItemStyle::AUTO_SIGNIN:
162 return l10n_util::GetNSStringF(IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_TITLE,
169 + (NSString*)lowerLabelTextForForm:
170 (const autofill::PasswordForm&)passwordForm {
171 return passwordForm.display_name.empty()
173 : base::SysUTF16ToNSString(passwordForm.username_value);
176 + (NSTextField*)labelWithText:(NSString*)title {
178 [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
179 [label setBezeled:NO];
180 [label setDrawsBackground:NO];
181 [label setEditable:NO];
182 [label setSelectable:NO];
183 [label setStringValue:title];
184 [label setAlignment:base::i18n::IsRTL() ? NSRightTextAlignment
185 : NSLeftTextAlignment];