Chromium Code Reviews| Index: chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm |
| diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm |
| index a8a85fdc74e95a18c14aa2f3dad1cb9f3c4f0ab9..bf4e390b4708328ce9a6b41287793adcb3d1ca0f 100644 |
| --- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm |
| +++ b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm |
| @@ -14,6 +14,7 @@ |
| #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" |
| #import "chrome/browser/ui/cocoa/l10n_util.h" |
| #include "components/autofill/core/browser/popup_item_ids.h" |
| +#include "grit/theme_resources.h" |
| #include "skia/ext/skia_utils_mac.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/font_list.h" |
| @@ -24,11 +25,19 @@ |
| #include "ui/gfx/text_constants.h" |
| using autofill::AutofillPopupView; |
| +using autofill::PasswordGenerationPopupController; |
| using autofill::PasswordGenerationPopupView; |
| using base::scoped_nsobject; |
| namespace { |
| +const CGFloat kDividerWidth = 1; |
| +const CGFloat kPasswordSectionVerticalSeparation = 5; |
|
Ilya Sherman
2014/08/19 22:32:17
nit: Please document these, including units.
dconnelly
2014/08/20 17:07:06
Done.
|
| + |
| +CGFloat MidY(NSRect frame) { |
| + return (NSMaxY(frame) + NSMinY(frame)) / 2.0; |
|
Ilya Sherman
2014/08/19 22:32:17
Any particular reason not to just use NSMidY?
dconnelly
2014/08/20 17:07:06
Amusingly, I googled for it and only found crap, b
|
| +} |
| + |
| NSColor* DividerColor() { |
| return gfx::SkColorToCalibratedNSColor( |
| PasswordGenerationPopupView::kDividerColor); |
| @@ -67,13 +76,19 @@ NSColor* HelpLinkColor() { |
| passwordField_ = [self textFieldWithText:controller_->password() |
| color:[self nameColor] |
| + font:[self textFont] |
| alignment:NSLeftTextAlignment]; |
| [self addSubview:passwordField_]; |
| - passwordSubtextField_ = [self textFieldWithText:controller_->SuggestedText() |
| - color:[self subtextColor] |
| - alignment:NSRightTextAlignment]; |
| - [self addSubview:passwordSubtextField_]; |
| + passwordTitleField_ = [self textFieldWithText:controller_->SuggestedText() |
| + color:[self nameColor] |
| + font:[self boldFont] |
| + alignment:NSLeftTextAlignment]; |
| + [self addSubview:passwordTitleField_]; |
| + |
| + keyIcon_ = ResourceBundle::GetSharedInstance() |
|
groby-ooo-7-16
2014/08/19 23:32:18
There's nothing retaining keyIcon_ - it can (and w
dconnelly
2014/08/20 17:07:05
Done.
|
| + .GetImageNamed(IDR_GENERATE_PASSWORD_KEY) |
| + .ToNSImage(); |
| scoped_nsobject<HyperlinkTextView> helpTextView( |
| [[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); |
| @@ -84,8 +99,14 @@ NSColor* HelpLinkColor() { |
| withName:@"" |
| linkColor:HelpLinkColor()]; |
| [helpTextView setDelegate:self]; |
| + // Remove the underlining. |
| [[helpTextView textContainer] setLineFragmentPadding:0.0f]; |
|
Ilya Sherman
2014/08/19 22:32:17
Is this still needed, in addition to the code you
dconnelly
2014/08/20 17:07:06
Done.
|
| [helpTextView setVerticallyResizable:YES]; |
| + [helpTextView setLinkTextAttributes:nil]; |
|
groby-ooo-7-16
2014/08/19 23:32:18
setLinkTextAttributes:nil does nothing for Hyperli
dconnelly
2014/08/20 17:07:06
Done.
|
| + NSTextStorage* text = [helpTextView textStorage]; |
| + [text addAttribute:NSUnderlineStyleAttributeName |
| + value:[NSNumber numberWithInt:NSUnderlineStyleNone] |
| + range:controller_->HelpTextLinkRange().ToNSRange()]; |
|
groby-ooo-7-16
2014/08/19 23:32:18
Is this cleared with UI review? HyperlinkTextView
dconnelly
2014/08/20 17:07:06
This came from UI mocks: https://code.google.com/p
|
| [self addSubview:helpTextView]; |
| helpTextView_ = helpTextView.get(); |
|
groby-ooo-7-16
2014/08/19 23:32:18
Why? Why not make helpTextView_ a scoped_nsobject?
dconnelly
2014/08/20 17:07:06
Agreed. I've now converted all the __weak pointer
|
| } |
| @@ -102,32 +123,80 @@ NSColor* HelpLinkColor() { |
| [self drawBackgroundAndBorder]; |
| + const CGFloat width = |
| + NSWidth(NSRectFromCGRect(controller_->popup_bounds().ToCGRect())); |
| + |
| if (controller_->password_selected()) { |
| // Draw a highlight under the suggested password. |
| - NSRect highlightBounds = [self passwordBounds]; |
| + NSRect highlightBounds = [self passwordSectionBoundsForWidth:width]; |
| [[self highlightColor] set]; |
| [NSBezierPath fillRect:highlightBounds]; |
| } |
| // Render the background of the help text. |
| [HelpTextBackgroundColor() set]; |
| - [NSBezierPath fillRect:[self helpBounds]]; |
| + [NSBezierPath fillRect:[self helpBoundsForWidth:width]]; |
|
groby-ooo-7-16
2014/08/19 23:32:18
Why not just set a background color on the help te
dconnelly
2014/08/20 17:07:06
Done.
|
| // Render the divider. |
| [DividerColor() set]; |
|
groby-ooo-7-16
2014/08/19 23:32:17
Usually, you draw dividers by just having an NSBox
dconnelly
2014/08/20 17:07:06
You can't change its color that way. I've replaced
|
| - [NSBezierPath fillRect:[self dividerBounds]]; |
| + [NSBezierPath fillRect:[self dividerBoundsForWidth:width]]; |
| + |
| + // Render the key icon. |
| + [keyIcon_ drawInRect:[self iconBoundsForWidth:width] |
|
groby-ooo-7-16
2014/08/19 23:32:18
Can you use an NSImageView instead?
dconnelly
2014/08/20 17:07:05
Done.
|
| + fromRect:{ NSZeroPoint, [keyIcon_ size] } |
|
groby-ooo-7-16
2014/08/19 23:32:18
Passing in NSZeroRect automatically specifies the
dconnelly
2014/08/20 17:07:05
Done.
|
| + operation:NSCompositeSourceOver |
| + fraction:1.0 |
| + respectFlipped:YES |
| + hints:nil]; |
| } |
| #pragma mark Public API: |
| -- (void)updateBoundsAndRedrawPopup { |
| - [self positionView:passwordField_ inRect:[self passwordBounds]]; |
| - [self positionView:passwordSubtextField_ inRect:[self passwordBounds]]; |
| - [self positionView:helpTextView_ inRect:[self helpBounds]]; |
| +- (NSSize)preferredSize { |
| + const CGFloat popupWidth = controller_->GetMinimumWidth(); |
| + NSRect helpBounds = [self helpBoundsForWidth:popupWidth]; |
| + CGFloat height = |
| + (controller_->display_password() |
| + ? NSHeight([self passwordSectionBoundsForWidth:popupWidth]) |
| + : 0) + |
| + NSHeight([self dividerBoundsForWidth:popupWidth]) + NSHeight(helpBounds) + |
| + 2 * autofill::kPopupBorderThickness; |
| + return NSMakeSize(popupWidth + 2 * autofill::kPopupBorderThickness, height); |
| +} |
| + |
| +- (void)updatePassword { |
| + [self setText:controller_->password() |
| + color:[self nameColor] |
| + font:[self textFont] |
| + alignment:NSLeftTextAlignment |
| + forField:passwordField_]; |
|
Ilya Sherman
2014/08/19 22:32:17
Is it not possible to update the text without need
dconnelly
2014/08/20 17:07:05
I thought not, but I found a way. Done.
|
| +} |
| +- (void)updateBoundsAndRedrawPopup { |
| + const CGFloat width = |
| + NSWidth(NSRectFromCGRect(controller_->popup_bounds().ToCGRect())); |
|
groby-ooo-7-16
2014/08/19 23:32:18
Just width = controller->popup_bounds().width()
N
dconnelly
2014/08/20 17:07:05
Done.
|
| + // The password can change while the bubble is shown: if the user has |
|
Ilya Sherman
2014/08/19 22:32:17
nit: "if" -> "If"
dconnelly
2014/08/20 17:07:06
TIL. Done.
|
| + // accepted the password and then selects the form again and starts deleting |
| + // the password, the field will be initially invisible and then become |
| + // visible. |
| + [self updatePassword]; |
|
Ilya Sherman
2014/08/19 22:32:17
nit: Can this be moved into the if-stmt below?
dconnelly
2014/08/20 17:07:05
Done.
|
| + if (controller_->display_password()) { |
| + [self positionView:passwordTitleField_ |
| + inRect:[self passwordSectionTitleBoundsForWidth:width]]; |
| + [self positionView:passwordField_ |
| + inRect:[self passwordBoundsForWidth:width]]; |
| + } |
| + [self positionView:helpTextView_ inRect:[self helpBoundsForWidth:width]]; |
| [super updateBoundsAndRedrawPopup]; |
| } |
| +- (BOOL)isPointInPasswordBounds:(CGPoint)point { |
| + const CGFloat width = |
| + NSWidth(NSRectFromCGRect(controller_->popup_bounds().ToCGRect())); |
| + return CGRectContainsPoint( |
| + NSRectToCGRect([self passwordSectionBoundsForWidth:width]), point); |
|
Ilya Sherman
2014/08/19 22:32:17
Can you use NSPointInRect instead? (In general, N
dconnelly
2014/08/20 17:07:05
Done.
|
| +} |
| + |
| - (void)controllerDestroyed { |
| controller_ = NULL; |
| [super delegateDestroyed]; |
| @@ -144,15 +213,17 @@ NSColor* HelpLinkColor() { |
| #pragma mark Private helpers: |
| -- (NSTextField*)textFieldWithText:(const base::string16&)text |
| - color:(NSColor*)color |
| - alignment:(NSTextAlignment)alignment { |
| +- (void)setText:(const base::string16&)text |
| + color:(NSColor*)color |
| + font:(NSFont*)font |
| + alignment:(NSTextAlignment)alignment |
| + forField:(NSTextField*)field { |
|
groby-ooo-7-16
2014/08/19 23:32:17
This seem overkill, but I'm not sure how many diff
dconnelly
2014/08/20 17:07:06
Done.
|
| scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( |
| [[NSMutableParagraphStyle alloc] init]); |
| [paragraphStyle setAlignment:alignment]; |
| NSDictionary* textAttributes = @{ |
| - NSFontAttributeName : [self textFont], |
| + NSFontAttributeName : font, |
| NSForegroundColorAttributeName : color, |
| NSParagraphStyleAttributeName : paragraphStyle |
| }; |
| @@ -162,9 +233,20 @@ NSColor* HelpLinkColor() { |
| initWithString:base::SysUTF16ToNSString(text) |
| attributes:textAttributes]); |
| + [field setAttributedStringValue:attributedString]; |
| +} |
| + |
| +- (NSTextField*)textFieldWithText:(const base::string16&)text |
| + color:(NSColor*)color |
| + font:(NSFont*)font |
| + alignment:(NSTextAlignment)alignment { |
| NSTextField* textField = |
| [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease]; |
| - [textField setAttributedStringValue:attributedString]; |
| + [self setText:text |
| + color:color |
| + font:font |
| + alignment:alignment |
| + forField:textField]; |
| [textField setEditable:NO]; |
| [textField setSelectable:NO]; |
| [textField setDrawsBackground:NO]; |
| @@ -182,16 +264,99 @@ NSColor* HelpLinkColor() { |
| NSInsetRect(frame, 0, floor(-delta.height/2)).origin]; |
| } |
| -- (NSRect)passwordBounds { |
| - return NSZeroRect; |
| +- (NSRect)passwordSectionBoundsForWidth:(CGFloat)width { |
|
groby-ooo-7-16
2014/08/19 23:32:18
Using bounds in the name is confusing. Usually, [s
dconnelly
2014/08/20 17:07:06
I think all this is confusing, so I've removed the
|
| + if (!controller_->display_password()) |
| + return NSZeroRect; |
| + return NSMakeRect( |
| + autofill::kPopupBorderThickness, |
| + autofill::kPopupBorderThickness, |
| + width - 2 * autofill::kPopupBorderThickness, |
| + PasswordGenerationPopupController::kPopupPasswordSectionHeight); |
| +} |
| + |
| +- (NSSize)sizeOfSingleLineString:(const base::string16&)string |
| + withFont:(NSFont*)font { |
| + NSRect textFrame = [base::SysUTF16ToNSString(string) |
| + boundingRectWithSize:NSMakeSize(MAXFLOAT, MAXFLOAT) |
| + options:0 |
| + attributes:@{ NSFontAttributeName : font }]; |
| + return textFrame.size; |
|
Ilya Sherman
2014/08/19 22:32:17
I feel like this code must already exist somewhere
dconnelly
2014/08/20 17:07:06
Done.
|
| +} |
| + |
| +- (NSRect)passwordSectionTitleBoundsForWidth:(CGFloat)width { |
| + if (!controller_->display_password()) |
| + return NSZeroRect; |
| + NSRect passwordSectionBounds = [self passwordSectionBoundsForWidth:width]; |
| + NSSize passwordSize = [self sizeOfSingleLineString:controller_->password() |
| + withFont:[self boldFont]]; |
| + const CGFloat y = MidY(passwordSectionBounds) - |
| + (kPasswordSectionVerticalSeparation / 2.0) - |
|
groby-ooo-7-16
2014/08/19 23:32:18
Be careful with rounding. Currently, kPasswordSect
dconnelly
2014/08/20 17:07:05
Done.
|
| + passwordSize.height; |
|
groby-ooo-7-16
2014/08/19 23:32:18
You seem to just care about the height of the text
dconnelly
2014/08/20 17:07:06
It's deprecated. I think this should be fine, as t
|
| + const CGFloat x = NSMaxX([self iconBoundsForWidth:width]); |
| + return NSMakeRect( |
| + x, y, NSWidth(passwordSectionBounds) - x, passwordSize.height); |
| +} |
| + |
| +- (NSRect)passwordBoundsForWidth:(CGFloat)width { |
| + NSRect passwordSectionBounds = [self passwordSectionBoundsForWidth:width]; |
| + NSSize titleSize = [self sizeOfSingleLineString:controller_->SuggestedText() |
| + withFont:[self textFont]]; |
| + const CGFloat y = MidY(passwordSectionBounds) + |
| + (kPasswordSectionVerticalSeparation / 2.0); |
| + const CGFloat x = NSMaxX([self iconBoundsForWidth:width]); |
| + return NSMakeRect(x, y, NSWidth(passwordSectionBounds) - x, titleSize.height); |
| +} |
| + |
| +- (NSRect)dividerBoundsForWidth:(CGFloat)width { |
| + if (!controller_->display_password()) |
| + return NSZeroRect; |
| + return NSMakeRect(autofill::kPopupBorderThickness, |
| + NSMaxY([self passwordSectionBoundsForWidth:width]), |
| + width - 2 * autofill::kPopupBorderThickness, |
| + kDividerWidth); |
|
groby-ooo-7-16
2014/08/19 23:32:18
Why is the last param kDividerWidth? Shouldn't tha
dconnelly
2014/08/20 17:07:06
Poor naming. I was thinking of the line as having
|
| +} |
| + |
| +- (NSRect)helpBoundsForWidth:(CGFloat)width { |
| + NSSize size = |
| + NSMakeSize(width - 2 * autofill::kPopupBorderThickness, MAXFLOAT); |
| + NSStringDrawingOptions options = |
| + NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin; |
| + NSDictionary* attributes = @{ NSFontAttributeName : [self textFont] }; |
| + NSRect textFrame = [base::SysUTF16ToNSString(controller_->HelpText()) |
| + boundingRectWithSize:size |
| + options:options |
| + attributes:attributes]; |
|
groby-ooo-7-16
2014/08/19 23:32:18
Ideally, you don't want to compute field sizes at
dconnelly
2014/08/20 17:07:05
Done.
|
| + const int verticalPadding = |
| + autofill::PasswordGenerationPopupController::kHelpVerticalPadding; |
| + size.height = NSHeight(textFrame) + 2 * verticalPadding; |
| + |
| + // The help section falls immediately above and to the right of the border. |
| + NSPoint origin = NSMakePoint(autofill::kPopupBorderThickness, |
| + controller_->display_password() |
| + ? NSMaxY([self dividerBoundsForWidth:width]) |
| + : autofill::kPopupBorderThickness); |
| + |
| + return { origin, size }; |
| } |
| -- (NSRect)helpBounds { |
| - return NSZeroRect; |
| +- (NSRect)iconBoundsForWidth:(CGFloat)width { |
| + if (!controller_->display_password()) |
| + return NSZeroRect; |
| + NSRect passwordSectionBounds = [self passwordSectionBoundsForWidth:width]; |
| + CGFloat passwordMidY = MidY(passwordSectionBounds); |
| + NSSize iconSize = [keyIcon_ size]; |
| + return NSMakeRect(PasswordGenerationPopupController::kHorizontalPadding, |
| + passwordMidY - (iconSize.height / 2.0), |
| + iconSize.width, |
| + iconSize.height); |
| } |
| -- (NSRect)dividerBounds { |
| - return NSZeroRect; |
| +- (NSFont*)boldFont { |
| + return ResourceBundle::GetSharedInstance() |
|
groby-ooo-7-16
2014/08/19 23:32:18
Fonts grabbed with DeriveWithStyle don't always lo
dconnelly
2014/08/20 17:07:06
Done.
|
| + .GetFontList(ResourceBundle::SmallFont) |
| + .DeriveWithStyle(gfx::Font::BOLD) |
| + .GetPrimaryFont() |
| + .GetNativeFont(); |
| } |
| - (NSFont*)textFont { |