Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm

Issue 487193003: Update Mac password generation autofill popup to match latest mocks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h " 5 #import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h "
6 6
7 #include <cmath>
8
7 #include "base/logging.h" 9 #include "base/logging.h"
8 #include "base/strings/sys_string_conversions.h" 10 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/browser/ui/autofill/autofill_popup_controller.h" 11 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
10 #include "chrome/browser/ui/autofill/autofill_popup_view.h" 12 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
11 #include "chrome/browser/ui/autofill/popup_constants.h" 13 #include "chrome/browser/ui/autofill/popup_constants.h"
12 #include "chrome/browser/ui/chrome_style.h" 14 #include "chrome/browser/ui/chrome_style.h"
13 #include "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge .h" 15 #include "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge .h"
14 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" 16 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
15 #import "chrome/browser/ui/cocoa/l10n_util.h" 17 #import "chrome/browser/ui/cocoa/l10n_util.h"
16 #include "components/autofill/core/browser/popup_item_ids.h" 18 #include "components/autofill/core/browser/popup_item_ids.h"
19 #include "grit/theme_resources.h"
17 #include "skia/ext/skia_utils_mac.h" 20 #include "skia/ext/skia_utils_mac.h"
18 #include "ui/base/resource/resource_bundle.h" 21 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/font_list.h" 22 #include "ui/gfx/font_list.h"
20 #include "ui/gfx/image/image.h" 23 #include "ui/gfx/image/image.h"
21 #include "ui/gfx/point.h" 24 #include "ui/gfx/point.h"
22 #include "ui/gfx/range/range.h" 25 #include "ui/gfx/range/range.h"
23 #include "ui/gfx/rect.h" 26 #include "ui/gfx/rect.h"
24 #include "ui/gfx/text_constants.h" 27 #include "ui/gfx/text_constants.h"
25 28
26 using autofill::AutofillPopupView; 29 using autofill::AutofillPopupView;
30 using autofill::PasswordGenerationPopupController;
27 using autofill::PasswordGenerationPopupView; 31 using autofill::PasswordGenerationPopupView;
28 using base::scoped_nsobject; 32 using base::scoped_nsobject;
29 33
30 namespace { 34 namespace {
31 35
36 // The height of the divider between the password and help sections, in pixels.
37 const CGFloat kDividerHeight = 1;
38
39 // The amount of whitespace, in pixels, between lines of text in the password
40 // section.
41 const CGFloat kPasswordSectionVerticalSeparation = 5;
42
32 NSColor* DividerColor() { 43 NSColor* DividerColor() {
33 return gfx::SkColorToCalibratedNSColor( 44 return gfx::SkColorToCalibratedNSColor(
34 PasswordGenerationPopupView::kDividerColor); 45 PasswordGenerationPopupView::kDividerColor);
35 } 46 }
36 47
37 NSColor* HelpTextBackgroundColor() { 48 NSColor* HelpTextBackgroundColor() {
38 return gfx::SkColorToCalibratedNSColor( 49 return gfx::SkColorToCalibratedNSColor(
39 PasswordGenerationPopupView::kExplanatoryTextBackgroundColor); 50 PasswordGenerationPopupView::kExplanatoryTextBackgroundColor);
40 } 51 }
41 52
(...skipping 16 matching lines...) Expand all
58 NOTREACHED(); 69 NOTREACHED();
59 return nil; 70 return nil;
60 } 71 }
61 72
62 - (id)initWithController: 73 - (id)initWithController:
63 (autofill::PasswordGenerationPopupController*)controller 74 (autofill::PasswordGenerationPopupController*)controller
64 frame:(NSRect)frame { 75 frame:(NSRect)frame {
65 if (self = [super initWithDelegate:controller frame:frame]) { 76 if (self = [super initWithDelegate:controller frame:frame]) {
66 controller_ = controller; 77 controller_ = controller;
67 78
68 passwordField_ = [self textFieldWithText:controller_->password() 79 passwordSection_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
69 color:[self nameColor] 80 [self addSubview:passwordSection_];
70 alignment:NSLeftTextAlignment];
71 [self addSubview:passwordField_];
72 81
73 passwordSubtextField_ = [self textFieldWithText:controller_->SuggestedText() 82 passwordField_.reset(
74 color:[self subtextColor] 83 [[self textFieldWithText:controller_->password()
75 alignment:NSRightTextAlignment]; 84 attributes:[self passwordAttributes]] retain]);
76 [self addSubview:passwordSubtextField_]; 85 [passwordSection_ addSubview:passwordField_];
77 86
78 scoped_nsobject<HyperlinkTextView> helpTextView( 87 passwordTitleField_.reset(
79 [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); 88 [[self textFieldWithText:controller_->SuggestedText()
80 [helpTextView setMessage:base::SysUTF16ToNSString(controller_->HelpText()) 89 attributes:[self passwordTitleAttributes]] retain]);
81 withFont:[self textFont] 90 [passwordSection_ addSubview:passwordTitleField_];
82 messageColor:HelpTextColor()]; 91
83 [helpTextView addLinkRange:controller_->HelpTextLinkRange().ToNSRange() 92 keyIcon_.reset([[NSImageView alloc] initWithFrame:NSZeroRect]);
84 withName:@"" 93 NSImage* keyImage = ResourceBundle::GetSharedInstance()
85 linkColor:HelpLinkColor()]; 94 .GetImageNamed(IDR_GENERATE_PASSWORD_KEY)
86 [helpTextView setDelegate:self]; 95 .ToNSImage();
87 [[helpTextView textContainer] setLineFragmentPadding:0.0f]; 96 [keyIcon_ setImage:keyImage];
88 [helpTextView setVerticallyResizable:YES]; 97 [passwordSection_ addSubview:keyIcon_];
89 [self addSubview:helpTextView]; 98
90 helpTextView_ = helpTextView.get(); 99 divider_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
91 } 100 [divider_ setBoxType:NSBoxCustom];
101 [divider_ setBorderType:NSLineBorder];
102 [divider_ setBorderColor:DividerColor()];
103 [self addSubview:divider_];
104
105 helpTextView_.reset([[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
106 [helpTextView_ setMessage:base::SysUTF16ToNSString(controller_->HelpText())
107 withFont:[self textFont]
108 messageColor:HelpTextColor()];
109 [helpTextView_ addLinkRange:controller_->HelpTextLinkRange().ToNSRange()
110 withName:@""
111 linkColor:HelpLinkColor()];
112 [helpTextView_ setDelegate:self];
113 [helpTextView_ setDrawsBackground:YES];
114 [helpTextView_ setBackgroundColor:HelpTextBackgroundColor()];
115 [helpTextView_
116 setTextContainerInset:NSMakeSize(controller_->kHorizontalPadding,
117 controller_->kHelpVerticalPadding)];
118 // Remove the underlining.
119 NSTextStorage* text = [helpTextView_ textStorage];
120 [text addAttribute:NSUnderlineStyleAttributeName
121 value:@(NSUnderlineStyleNone)
122 range:controller_->HelpTextLinkRange().ToNSRange()];
123 [self addSubview:helpTextView_];
124 }
92 125
93 return self; 126 return self;
94 } 127 }
95 128
96 #pragma mark NSView implementation: 129 #pragma mark NSView implementation:
97 130
98 - (void)drawRect:(NSRect)dirtyRect { 131 - (void)drawRect:(NSRect)dirtyRect {
132 [super drawRect:dirtyRect];
133
99 // If the view is in the process of being destroyed, don't bother drawing. 134 // If the view is in the process of being destroyed, don't bother drawing.
100 if (!controller_) 135 if (!controller_)
101 return; 136 return;
102 137
103 [self drawBackgroundAndBorder]; 138 [self drawBackgroundAndBorder];
104 139
105 if (controller_->password_selected()) { 140 if (controller_->password_selected()) {
106 // Draw a highlight under the suggested password. 141 // Draw a highlight under the suggested password.
107 NSRect highlightBounds = [self passwordBounds]; 142 NSRect highlightBounds = [passwordSection_ frame];
108 [[self highlightColor] set]; 143 [[self highlightColor] set];
109 [NSBezierPath fillRect:highlightBounds]; 144 [NSBezierPath fillRect:highlightBounds];
110 } 145 }
111
112 // Render the background of the help text.
113 [HelpTextBackgroundColor() set];
114 [NSBezierPath fillRect:[self helpBounds]];
115
116 // Render the divider.
117 [DividerColor() set];
118 [NSBezierPath fillRect:[self dividerBounds]];
119 } 146 }
120 147
121 #pragma mark Public API: 148 #pragma mark Public API:
122 149
150 - (NSSize)preferredSize {
151 const NSSize passwordTitleSize =
152 [base::SysUTF16ToNSString(controller_->SuggestedText())
153 sizeWithAttributes:@{ NSFontAttributeName : [self boldFont] }];
154 const NSSize passwordSize = [base::SysUTF16ToNSString(controller_->password())
155 sizeWithAttributes:@{ NSFontAttributeName : [self textFont] }];
156
157 CGFloat width =
158 autofill::kPopupBorderThickness +
159 controller_->kHorizontalPadding +
160 [[keyIcon_ image] size].width +
161 controller_->kHorizontalPadding +
162 std::max(passwordSize.width, passwordTitleSize.width) +
163 controller_->kHorizontalPadding +
164 autofill::kPopupBorderThickness;
165
166 width = std::max(width, (CGFloat)controller_->GetMinimumWidth());
167
168 CGFloat height =
169 autofill::kPopupBorderThickness +
170 controller_->kHelpVerticalPadding +
171 [self helpSizeForPopupWidth:width].height +
172 controller_->kHelpVerticalPadding +
173 autofill::kPopupBorderThickness;
174
175 if (controller_->display_password())
176 height += controller_->kPopupPasswordSectionHeight;
177
178 return NSMakeSize(width, height);
179 }
180
123 - (void)updateBoundsAndRedrawPopup { 181 - (void)updateBoundsAndRedrawPopup {
124 [self positionView:passwordField_ inRect:[self passwordBounds]]; 182 const CGFloat popupWidth = controller_->popup_bounds().width();
125 [self positionView:passwordSubtextField_ inRect:[self passwordBounds]]; 183 const CGFloat contentWidth =
126 [self positionView:helpTextView_ inRect:[self helpBounds]]; 184 popupWidth - (2 * autofill::kPopupBorderThickness);
185 const CGFloat contentHeight = controller_->popup_bounds().height() -
186 (2 * autofill::kPopupBorderThickness);
187
188 if (controller_->display_password()) {
189 // The password can change while the bubble is shown: If the user has
190 // accepted the password and then selects the form again and starts deleting
191 // the password, the field will be initially invisible and then become
192 // visible.
193 [self updatePassword];
194
195 // Lay out the password section, which includes the key icon, the title, and
196 // the suggested password.
197 [passwordSection_
198 setFrame:NSMakeRect(autofill::kPopupBorderThickness,
199 autofill::kPopupBorderThickness,
200 contentWidth,
201 controller_->kPopupPasswordSectionHeight)];
202
203 // The key icon falls to the left of the title and password.
204 const NSSize imageSize = [[keyIcon_ image] size];
205 const CGFloat keyX = controller_->kHorizontalPadding;
206 const CGFloat keyY =
207 std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
208 (imageSize.height / 2.0));
209 [keyIcon_ setFrameOrigin:NSMakePoint(keyX, keyY)];
210 [keyIcon_ sizeToFit];
211
212 // The title and password fall to the right of the key icon and are centered
213 // vertically as a group with some padding in between.
214 [passwordTitleField_ sizeToFit];
215 [passwordField_ sizeToFit];
216 const CGFloat groupHeight = NSHeight([passwordField_ frame]) +
217 kPasswordSectionVerticalSeparation +
218 NSHeight([passwordTitleField_ frame]);
219 const CGFloat groupX =
220 NSMaxX([keyIcon_ frame]) + controller_->kHorizontalPadding;
221 const CGFloat groupY =
222 std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
223 (groupHeight / 2.0));
224 [passwordField_ setFrameOrigin:NSMakePoint(groupX, groupY)];
225 const CGFloat titleY = groupY +
226 NSHeight([passwordField_ frame]) +
227 kPasswordSectionVerticalSeparation;
228 [passwordTitleField_ setFrameOrigin:NSMakePoint(groupX, titleY)];
229
230 // Layout the divider, which falls immediately below the password section.
231 const CGFloat dividerX = autofill::kPopupBorderThickness;
232 const CGFloat dividerY = NSMaxY([passwordSection_ frame]);
233 NSRect dividerFrame =
234 NSMakeRect(dividerX, dividerY, contentWidth, kDividerHeight);
235 [divider_ setFrame:dividerFrame];
236 }
237
238 // Layout the help section beneath the divider (if applicable, otherwise
239 // beneath the border).
240 const CGFloat helpX = autofill::kPopupBorderThickness;
241 const CGFloat helpY = controller_->display_password()
242 ? NSMaxY([divider_ frame])
243 : autofill::kPopupBorderThickness;
244 const CGFloat helpHeight = contentHeight -
245 NSHeight([passwordSection_ frame]) -
246 NSHeight([divider_ frame]);
247 [helpTextView_ setFrame:NSMakeRect(helpX, helpY, contentWidth, helpHeight)];
127 248
128 [super updateBoundsAndRedrawPopup]; 249 [super updateBoundsAndRedrawPopup];
129 } 250 }
130 251
252 - (BOOL)isPointInPasswordBounds:(NSPoint)point {
253 return NSPointInRect(point, [passwordSection_ frame]);
254 }
255
131 - (void)controllerDestroyed { 256 - (void)controllerDestroyed {
132 controller_ = NULL; 257 controller_ = NULL;
133 [super delegateDestroyed]; 258 [super delegateDestroyed];
134 } 259 }
135 260
136 #pragma mark NSTextViewDelegate implementation: 261 #pragma mark NSTextViewDelegate implementation:
137 262
138 - (BOOL)textView:(NSTextView*)textView 263 - (BOOL)textView:(NSTextView*)textView
139 clickedOnLink:(id)link 264 clickedOnLink:(id)link
140 atIndex:(NSUInteger)charIndex { 265 atIndex:(NSUInteger)charIndex {
141 controller_->OnSavedPasswordsLinkClicked(); 266 controller_->OnSavedPasswordsLinkClicked();
142 return YES; 267 return YES;
143 } 268 }
144 269
145 #pragma mark Private helpers: 270 #pragma mark Private helpers:
146 271
147 - (NSTextField*)textFieldWithText:(const base::string16&)text 272 - (void)updatePassword {
148 color:(NSColor*)color 273 base::scoped_nsobject<NSMutableAttributedString> updatedPassword(
149 alignment:(NSTextAlignment)alignment { 274 [[NSMutableAttributedString alloc]
275 initWithString:base::SysUTF16ToNSString(controller_->password())
276 attributes:[self passwordAttributes]]);
277 [passwordField_ setAttributedStringValue:updatedPassword];
278 }
279
280 - (NSDictionary*)passwordTitleAttributes {
150 scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( 281 scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
151 [[NSMutableParagraphStyle alloc] init]); 282 [[NSMutableParagraphStyle alloc] init]);
152 [paragraphStyle setAlignment:alignment]; 283 [paragraphStyle setAlignment:NSLeftTextAlignment];
284 return @{
285 NSFontAttributeName : [self boldFont],
286 NSForegroundColorAttributeName : [self nameColor],
287 NSParagraphStyleAttributeName : paragraphStyle.autorelease()
288 };
289 }
153 290
154 NSDictionary* textAttributes = @{ 291 - (NSDictionary*)passwordAttributes {
292 scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
293 [[NSMutableParagraphStyle alloc] init]);
294 [paragraphStyle setAlignment:NSLeftTextAlignment];
295 return @{
155 NSFontAttributeName : [self textFont], 296 NSFontAttributeName : [self textFont],
156 NSForegroundColorAttributeName : color, 297 NSForegroundColorAttributeName : [self nameColor],
157 NSParagraphStyleAttributeName : paragraphStyle 298 NSParagraphStyleAttributeName : paragraphStyle.autorelease()
158 }; 299 };
300 }
159 301
302 - (NSTextField*)textFieldWithText:(const base::string16&)text
303 attributes:(NSDictionary*)attributes {
304 NSTextField* textField =
305 [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
160 scoped_nsobject<NSAttributedString> attributedString( 306 scoped_nsobject<NSAttributedString> attributedString(
161 [[NSAttributedString alloc] 307 [[NSAttributedString alloc]
162 initWithString:base::SysUTF16ToNSString(text) 308 initWithString:base::SysUTF16ToNSString(text)
163 attributes:textAttributes]); 309 attributes:attributes]);
164 310 [textField setAttributedStringValue:attributedString.autorelease()];
165 NSTextField* textField =
166 [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
167 [textField setAttributedStringValue:attributedString];
168 [textField setEditable:NO]; 311 [textField setEditable:NO];
169 [textField setSelectable:NO]; 312 [textField setSelectable:NO];
170 [textField setDrawsBackground:NO]; 313 [textField setDrawsBackground:NO];
171 [textField setBezeled:NO]; 314 [textField setBezeled:NO];
172 return textField; 315 return textField;
173 } 316 }
174 317
175 - (void)positionView:(NSView*)view inRect:(NSRect)bounds { 318 - (NSSize)helpSizeForPopupWidth:(CGFloat)width {
176 NSRect frame = NSInsetRect(bounds, controller_->kHorizontalPadding, 0); 319 const CGFloat helpWidth = width -
177 [view setFrame:frame]; 320 2 * controller_->kHorizontalPadding -
178 321 2 * autofill::kPopupBorderThickness;
179 // Center the text vertically within the bounds. 322 const NSSize size = NSMakeSize(helpWidth, MAXFLOAT);
180 NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view); 323 NSRect textFrame = [base::SysUTF16ToNSString(controller_->HelpText())
181 [view setFrameOrigin: 324 boundingRectWithSize:size
182 NSInsetRect(frame, 0, floor(-delta.height/2)).origin]; 325 options:NSLineBreakByWordWrapping |
326 NSStringDrawingUsesLineFragmentOrigin
327 attributes:@{ NSFontAttributeName : [self textFont] }];
328 return textFrame.size;
183 } 329 }
184 330
185 - (NSRect)passwordBounds { 331 - (NSFont*)boldFont {
186 return NSZeroRect; 332 return [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
187 }
188
189 - (NSRect)helpBounds {
190 return NSZeroRect;
191 }
192
193 - (NSRect)dividerBounds {
194 return NSZeroRect;
195 } 333 }
196 334
197 - (NSFont*)textFont { 335 - (NSFont*)textFont {
198 return ResourceBundle::GetSharedInstance().GetFontList( 336 return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
199 ResourceBundle::SmallFont).GetPrimaryFont().GetNativeFont();
200 } 337 }
201 338
202 @end 339 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698