OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #import "chrome/browser/ui/cocoa/passwords/credential_item_view.h" | |
6 | |
7 #include <algorithm> | |
8 | |
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 "grit/theme_resources.h" | |
15 #include "ui/base/resource/resource_bundle.h" | |
16 #include "ui/gfx/image/image_skia.h" | |
17 #include "ui/gfx/image/image_skia_util_mac.h" | |
18 | |
19 namespace { | |
20 const CGFloat kVerticalPaddingBetweenCredentials = 10.0f; | |
21 const CGFloat kHorizontalPaddingBetweenAvatarAndLabels = 10.0f; | |
22 const CGFloat kVerticalPaddingBetweenLabels = 2.0f; | |
23 } // namespace | |
24 | |
25 // Custom button cell that draws nothing. | |
26 @interface CredentialItemViewCell : NSButtonCell | |
groby-ooo-7-16
2015/02/19 17:01:33
Are you sure you need an NSButton at all? :)
dconnelly
2015/02/20 15:36:06
Replaced all this handling and ListView stuff with
| |
27 @end | |
28 | |
29 @implementation CredentialItemViewCell | |
30 - (void)drawWithFrame:(CGRect)frame inView:(NSView*)view { | |
31 // Do nothing. | |
32 } | |
33 @end | |
34 | |
35 @interface CredentialItemView() | |
36 - (void)click:(id)sender; | |
37 @end | |
38 | |
39 @implementation CredentialItemView | |
40 | |
41 - (id)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm | |
42 credentialType:(password_manager::CredentialType)credentialType | |
43 delegate:(id<CredentialItemDelegate>)delegate { | |
44 if ((self = [super init])) { | |
45 passwordForm_ = passwordForm; | |
46 credentialType_ = credentialType; | |
47 delegate_ = delegate; | |
48 | |
49 // Forward clicks to the delegate. | |
50 [self setTarget:self]; | |
51 [self setAction:@selector(click:)]; | |
52 | |
53 // ----------------------------------------------- | |
54 // | | John Q. Facebooker | | |
55 // | icon | john@somewhere.com | | |
56 // ----------------------------------------------- | |
57 | |
58 // Create the views. | |
59 | |
60 avatarView_.reset([[NSImageView alloc] initWithFrame:CGRectZero]); | |
groby-ooo-7-16
2015/02/19 17:01:33
I vaguely recall the profile switcher does similar
dconnelly
2015/02/20 15:36:06
The profile switchers I see on trunk Chromium and
| |
61 [avatarView_ setWantsLayer:YES]; | |
62 [[avatarView_ layer] setCornerRadius:kAvatarImageSize / 2.0f]; | |
63 [[avatarView_ layer] setMasksToBounds:YES]; | |
64 [self addSubview:avatarView_]; | |
65 | |
66 if (!passwordForm_.display_name.empty()) { | |
67 nameLabel_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | |
68 [self addSubview:nameLabel_]; | |
69 [nameLabel_ setBezeled:NO]; | |
70 [nameLabel_ setDrawsBackground:NO]; | |
71 [nameLabel_ setEditable:NO]; | |
72 [nameLabel_ setSelectable:NO]; | |
73 [nameLabel_ | |
74 setStringValue:base::SysUTF16ToNSString(passwordForm_.display_name)]; | |
75 [nameLabel_ setAlignment:base::i18n::IsRTL() ? NSRightTextAlignment | |
76 : NSLeftTextAlignment]; | |
77 [nameLabel_ sizeToFit]; | |
78 } | |
79 | |
80 usernameLabel_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | |
81 [self addSubview:usernameLabel_]; | |
82 [usernameLabel_ setBezeled:NO]; | |
83 [usernameLabel_ setDrawsBackground:NO]; | |
84 [usernameLabel_ setEditable:NO]; | |
85 [usernameLabel_ setSelectable:NO]; | |
86 [usernameLabel_ | |
87 setStringValue:base::SysUTF16ToNSString(passwordForm_.username_value)]; | |
88 [usernameLabel_ setAlignment:base::i18n::IsRTL() ? NSRightTextAlignment | |
89 : NSLeftTextAlignment]; | |
90 [usernameLabel_ sizeToFit]; | |
91 | |
92 // Compute the heights and widths of everything, as the layout depends on | |
93 // these measurements. | |
94 const CGFloat labelsHeight = CGRectGetHeight([nameLabel_ frame]) + | |
95 CGRectGetHeight([usernameLabel_ frame]) + | |
96 kVerticalPaddingBetweenLabels; | |
97 const CGFloat height = std::max(labelsHeight, CGFloat(kAvatarImageSize)); | |
98 const CGFloat width = kAvatarImageSize + | |
99 kHorizontalPaddingBetweenAvatarAndLabels + | |
100 std::max(CGRectGetWidth([nameLabel_ frame]), | |
101 CGRectGetWidth([usernameLabel_ frame])); | |
102 self.frame = CGRectMake(0, 0, width, height); | |
103 | |
104 // Lay out the views (RTL reverses the order horizontally). | |
105 | |
106 const CGFloat avatarX = base::i18n::IsRTL() ? width - kAvatarImageSize : 0; | |
107 const CGFloat avatarY = | |
108 (kAvatarImageSize > height) ? 0 : (height - kAvatarImageSize) / 2.0f; | |
109 [avatarView_ setFrame:CGRectMake(avatarX, avatarY, kAvatarImageSize, | |
110 kAvatarImageSize)]; | |
111 | |
112 const CGFloat nameX = base::i18n::IsRTL() | |
113 ? NSMinX([avatarView_ frame]) - | |
114 kHorizontalPaddingBetweenAvatarAndLabels - | |
115 CGRectGetWidth([nameLabel_ frame]) | |
116 : NSMaxX([avatarView_ frame]) + | |
117 kHorizontalPaddingBetweenAvatarAndLabels; | |
118 const CGFloat nameLabelY = | |
119 (labelsHeight > height) ? 0 : (height - labelsHeight) / 2.0f; | |
120 CGRect nameFrame = [nameLabel_ frame]; | |
121 nameFrame.origin = CGPointMake(nameX, nameLabelY); | |
groby-ooo-7-16
2015/02/19 17:01:33
NSMakePoint
dconnelly
2015/02/20 15:36:06
Done.
| |
122 [nameLabel_ setFrame:nameFrame]; | |
123 | |
124 const CGFloat usernameX = | |
125 base::i18n::IsRTL() | |
126 ? NSMinX([avatarView_ frame]) - | |
127 kHorizontalPaddingBetweenAvatarAndLabels - | |
128 CGRectGetWidth([usernameLabel_ frame]) | |
groby-ooo-7-16
2015/02/19 17:01:33
NSWidth - you *do* love CG functions, don't you? ;
dconnelly
2015/02/20 15:36:06
Sorry, yeah, the iOS idioms are just stickier in m
| |
129 : NSMaxX([avatarView_ frame]) + | |
130 kHorizontalPaddingBetweenAvatarAndLabels; | |
131 const CGFloat usernameLabelY = | |
132 NSMaxY(nameFrame) + kVerticalPaddingBetweenLabels; | |
133 CGRect usernameFrame = [usernameLabel_ frame]; | |
134 usernameFrame.origin = CGPointMake(usernameX, usernameLabelY); | |
135 [usernameLabel_ setFrame:usernameFrame]; | |
136 | |
137 // Use a default avatar and fetch the custom one, if it exists. | |
138 [self updateAvatar:[[self class] defaultAvatar]]; | |
139 if (passwordForm_.avatar_url.is_valid()) | |
140 [delegate_ fetchAvatar:passwordForm_.avatar_url forView:self]; | |
141 | |
142 // When resizing, stick to the left (resp. right for RTL) edge. | |
143 const NSUInteger autoresizingMask = | |
144 (base::i18n::IsRTL() ? NSViewMinXMargin : NSViewMaxXMargin); | |
145 [avatarView_ setAutoresizingMask:autoresizingMask]; | |
146 [usernameLabel_ setAutoresizingMask:autoresizingMask]; | |
147 [nameLabel_ setAutoresizingMask:autoresizingMask]; | |
148 [self setAutoresizingMask:NSViewWidthSizable]; | |
149 } | |
150 | |
151 return self; | |
152 } | |
153 | |
154 - (void)updateAvatar:(NSImage*)avatar { | |
155 [avatarView_ setImage:avatar]; | |
156 } | |
157 | |
158 + (NSImage*)defaultAvatar { | |
159 return gfx::NSImageFromImageSkia(ScaleImageForAccountAvatar( | |
160 *ResourceBundle::GetSharedInstance() | |
161 .GetImageNamed(IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE) | |
162 .ToImageSkia())); | |
163 } | |
164 | |
165 + (Class)cellClass { | |
166 return [CredentialItemViewCell class]; | |
167 } | |
168 | |
169 - (void)click:(id)sender { | |
170 DCHECK_EQ(sender, self); | |
171 [delegate_ selectPasswordForm:passwordForm_ credentialType:credentialType_]; | |
172 } | |
173 | |
174 - (NSTextField*)nameLabel { | |
175 return nameLabel_.get(); | |
176 } | |
177 | |
178 - (NSTextField*)usernameLabel { | |
179 return usernameLabel_.get(); | |
180 } | |
181 | |
182 - (NSImageView*)avatarView { | |
183 return avatarView_.get(); | |
184 } | |
185 | |
186 @end | |
187 | |
188 @interface CredentialItemListView() | |
189 - (void)addCredentialItem:(CredentialItemView*)item; | |
190 @end | |
191 | |
192 @implementation CredentialItemListView | |
groby-ooo-7-16
2015/02/19 17:01:33
Question: Would this be better off as an NSTableVi
dconnelly
2015/02/20 15:36:06
You know, I've never written an NSTableView before
| |
193 | |
194 - (id)initWithItems:(NSArray*)items { | |
195 if ((self = [super initWithFrame:NSZeroRect])) { | |
196 for (CredentialItemView* item in items) | |
197 [self addCredentialItem:item]; | |
198 } | |
199 return self; | |
200 } | |
201 | |
202 - (void)addCredentialItem:(CredentialItemView*)item { | |
203 [self addSubview:item]; | |
204 | |
205 // Stack the credentials on top of each other. | |
groby-ooo-7-16
2015/02/19 17:01:33
Shorter (and hopefully clearer) version:
NSRect v
dconnelly
2015/02/20 15:36:06
TableView - removed all this
| |
206 const CGFloat y = | |
207 CGRectGetHeight([self frame]) + | |
208 ([[self subviews] count] > 1 ? kVerticalPaddingBetweenCredentials : 0.0f); | |
209 | |
210 // Update the size of the list view to accomodate the new item. | |
211 const CGFloat width = | |
212 std::max(CGRectGetWidth([self frame]), CGRectGetWidth([item frame])); | |
213 const CGFloat height = y + CGRectGetHeight([item frame]); | |
214 [self setFrameSize:CGSizeMake(width, height)]; | |
215 | |
216 const CGFloat x = 0; | |
groby-ooo-7-16
2015/02/19 17:01:33
You could replace the entire code block with
[item
dconnelly
2015/02/20 15:36:06
TableView - removed all this
| |
217 NSRect itemFrame = [item frame]; | |
218 itemFrame.size.width = width; | |
219 itemFrame.origin = CGPointMake(x, y); | |
220 [item setFrame:itemFrame]; | |
221 } | |
222 | |
223 - (NSArray*)items { | |
224 return [self subviews]; | |
225 } | |
226 | |
227 @end | |
OLD | NEW |