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 { |