Update Mac password generation autofill popup to match latest mocks.

Screenshots available on the bug.

BUG=394303

Review URL: https://codereview.chromium.org/487193003

Cr-Commit-Position: refs/heads/master@{#291389}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291389 0039d316-1c4b-4281-b951-d872f2087c98
parent bfaf1a9e
...@@ -22,6 +22,9 @@ class PasswordGenerationPopupController : public AutofillPopupViewDelegate { ...@@ -22,6 +22,9 @@ class PasswordGenerationPopupController : public AutofillPopupViewDelegate {
// Spacing between the border of the popup and any text. // Spacing between the border of the popup and any text.
static const int kHorizontalPadding = 10; static const int kHorizontalPadding = 10;
// Desired height of the password section.
static const int kPopupPasswordSectionHeight = 62;
// Called by the view when the saved passwords link is clicked. // Called by the view when the saved passwords link is clicked.
virtual void OnSavedPasswordsLinkClicked() = 0; virtual void OnSavedPasswordsLinkClicked() = 0;
......
...@@ -9,8 +9,7 @@ ...@@ -9,8 +9,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h" #import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h"
#include "ui/base/cocoa/window_size_constants.h" #include "ui/gfx/size.h"
#include "ui/gfx/rect.h"
namespace autofill { namespace autofill {
...@@ -36,8 +35,7 @@ void PasswordGenerationPopupViewBridge::Show() { ...@@ -36,8 +35,7 @@ void PasswordGenerationPopupViewBridge::Show() {
} }
gfx::Size PasswordGenerationPopupViewBridge::GetPreferredSizeOfPasswordView() { gfx::Size PasswordGenerationPopupViewBridge::GetPreferredSizeOfPasswordView() {
// TODO(gcasto): Implement this function. return gfx::Size(NSSizeToCGSize([view_ preferredSize]));
return gfx::Size();
} }
void PasswordGenerationPopupViewBridge::UpdateBoundsAndRedrawPopup() { void PasswordGenerationPopupViewBridge::UpdateBoundsAndRedrawPopup() {
...@@ -50,8 +48,7 @@ void PasswordGenerationPopupViewBridge::PasswordSelectionUpdated() { ...@@ -50,8 +48,7 @@ void PasswordGenerationPopupViewBridge::PasswordSelectionUpdated() {
bool PasswordGenerationPopupViewBridge::IsPointInPasswordBounds( bool PasswordGenerationPopupViewBridge::IsPointInPasswordBounds(
const gfx::Point& point) { const gfx::Point& point) {
// TODO(gcasto): Implement this function. return [view_ isPointInPasswordBounds:NSPointFromCGPoint(point.ToCGPoint())];
return true;
} }
PasswordGenerationPopupView* PasswordGenerationPopupView::Create( PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "chrome/browser/ui/autofill/password_generation_popup_controller.h" #include "chrome/browser/ui/autofill/password_generation_popup_controller.h"
#import "chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.h" #import "chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.h"
...@@ -23,9 +24,12 @@ class AutofillPopupController; ...@@ -23,9 +24,12 @@ class AutofillPopupController;
// The cross-platform controller for this view. // The cross-platform controller for this view.
__weak autofill::PasswordGenerationPopupController* controller_; __weak autofill::PasswordGenerationPopupController* controller_;
__weak NSTextField* passwordField_; base::scoped_nsobject<NSView> passwordSection_;
__weak NSTextField* passwordSubtextField_; base::scoped_nsobject<NSTextField> passwordField_;
__weak HyperlinkTextView* helpTextView_; base::scoped_nsobject<NSTextField> passwordTitleField_;
base::scoped_nsobject<NSImageView> keyIcon_;
base::scoped_nsobject<NSBox> divider_;
base::scoped_nsobject<HyperlinkTextView> helpTextView_;
} }
// Designated initializer. // Designated initializer.
...@@ -33,10 +37,17 @@ class AutofillPopupController; ...@@ -33,10 +37,17 @@ class AutofillPopupController;
(autofill::PasswordGenerationPopupController*)controller (autofill::PasswordGenerationPopupController*)controller
frame:(NSRect)frame; frame:(NSRect)frame;
// Determines whether |point| falls inside the password section of the popup.
// |point| needs to be in the popup's coordinate system.
- (BOOL)isPointInPasswordBounds:(NSPoint)point;
// Informs the view that its controller has been (or will imminently be) // Informs the view that its controller has been (or will imminently be)
// destroyed. // destroyed.
- (void)controllerDestroyed; - (void)controllerDestroyed;
// The preferred size for the popup.
- (NSSize)preferredSize;
@end @end
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_COCOA_H_ #endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_COCOA_H_
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h" #import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h"
#include <cmath>
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
...@@ -14,6 +16,7 @@ ...@@ -14,6 +16,7 @@
#import "chrome/browser/ui/cocoa/hyperlink_text_view.h" #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
#import "chrome/browser/ui/cocoa/l10n_util.h" #import "chrome/browser/ui/cocoa/l10n_util.h"
#include "components/autofill/core/browser/popup_item_ids.h" #include "components/autofill/core/browser/popup_item_ids.h"
#include "grit/theme_resources.h"
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/font_list.h" #include "ui/gfx/font_list.h"
...@@ -24,11 +27,19 @@ ...@@ -24,11 +27,19 @@
#include "ui/gfx/text_constants.h" #include "ui/gfx/text_constants.h"
using autofill::AutofillPopupView; using autofill::AutofillPopupView;
using autofill::PasswordGenerationPopupController;
using autofill::PasswordGenerationPopupView; using autofill::PasswordGenerationPopupView;
using base::scoped_nsobject; using base::scoped_nsobject;
namespace { namespace {
// The height of the divider between the password and help sections, in pixels.
const CGFloat kDividerHeight = 1;
// The amount of whitespace, in pixels, between lines of text in the password
// section.
const CGFloat kPasswordSectionVerticalSeparation = 5;
NSColor* DividerColor() { NSColor* DividerColor() {
return gfx::SkColorToCalibratedNSColor( return gfx::SkColorToCalibratedNSColor(
PasswordGenerationPopupView::kDividerColor); PasswordGenerationPopupView::kDividerColor);
...@@ -65,30 +76,52 @@ NSColor* HelpLinkColor() { ...@@ -65,30 +76,52 @@ NSColor* HelpLinkColor() {
if (self = [super initWithDelegate:controller frame:frame]) { if (self = [super initWithDelegate:controller frame:frame]) {
controller_ = controller; controller_ = controller;
passwordField_ = [self textFieldWithText:controller_->password() passwordSection_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
color:[self nameColor] [self addSubview:passwordSection_];
alignment:NSLeftTextAlignment];
[self addSubview:passwordField_]; passwordField_.reset(
[[self textFieldWithText:controller_->password()
passwordSubtextField_ = [self textFieldWithText:controller_->SuggestedText() attributes:[self passwordAttributes]] retain]);
color:[self subtextColor] [passwordSection_ addSubview:passwordField_];
alignment:NSRightTextAlignment];
[self addSubview:passwordSubtextField_]; passwordTitleField_.reset(
[[self textFieldWithText:controller_->SuggestedText()
scoped_nsobject<HyperlinkTextView> helpTextView( attributes:[self passwordTitleAttributes]] retain]);
[[HyperlinkTextView alloc] initWithFrame:NSZeroRect]); [passwordSection_ addSubview:passwordTitleField_];
[helpTextView setMessage:base::SysUTF16ToNSString(controller_->HelpText())
withFont:[self textFont] keyIcon_.reset([[NSImageView alloc] initWithFrame:NSZeroRect]);
messageColor:HelpTextColor()]; NSImage* keyImage = ResourceBundle::GetSharedInstance()
[helpTextView addLinkRange:controller_->HelpTextLinkRange().ToNSRange() .GetImageNamed(IDR_GENERATE_PASSWORD_KEY)
withName:@"" .ToNSImage();
linkColor:HelpLinkColor()]; [keyIcon_ setImage:keyImage];
[helpTextView setDelegate:self]; [passwordSection_ addSubview:keyIcon_];
[[helpTextView textContainer] setLineFragmentPadding:0.0f];
[helpTextView setVerticallyResizable:YES]; divider_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
[self addSubview:helpTextView]; [divider_ setBoxType:NSBoxCustom];
helpTextView_ = helpTextView.get(); [divider_ setBorderType:NSLineBorder];
} [divider_ setBorderColor:DividerColor()];
[self addSubview:divider_];
helpTextView_.reset([[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
[helpTextView_ setMessage:base::SysUTF16ToNSString(controller_->HelpText())
withFont:[self textFont]
messageColor:HelpTextColor()];
[helpTextView_ addLinkRange:controller_->HelpTextLinkRange().ToNSRange()
withName:@""
linkColor:HelpLinkColor()];
[helpTextView_ setDelegate:self];
[helpTextView_ setDrawsBackground:YES];
[helpTextView_ setBackgroundColor:HelpTextBackgroundColor()];
[helpTextView_
setTextContainerInset:NSMakeSize(controller_->kHorizontalPadding,
controller_->kHelpVerticalPadding)];
// Remove the underlining.
NSTextStorage* text = [helpTextView_ textStorage];
[text addAttribute:NSUnderlineStyleAttributeName
value:@(NSUnderlineStyleNone)
range:controller_->HelpTextLinkRange().ToNSRange()];
[self addSubview:helpTextView_];
}
return self; return self;
} }
...@@ -96,6 +129,8 @@ NSColor* HelpLinkColor() { ...@@ -96,6 +129,8 @@ NSColor* HelpLinkColor() {
#pragma mark NSView implementation: #pragma mark NSView implementation:
- (void)drawRect:(NSRect)dirtyRect { - (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// If the view is in the process of being destroyed, don't bother drawing. // If the view is in the process of being destroyed, don't bother drawing.
if (!controller_) if (!controller_)
return; return;
...@@ -104,30 +139,120 @@ NSColor* HelpLinkColor() { ...@@ -104,30 +139,120 @@ NSColor* HelpLinkColor() {
if (controller_->password_selected()) { if (controller_->password_selected()) {
// Draw a highlight under the suggested password. // Draw a highlight under the suggested password.
NSRect highlightBounds = [self passwordBounds]; NSRect highlightBounds = [passwordSection_ frame];
[[self highlightColor] set]; [[self highlightColor] set];
[NSBezierPath fillRect:highlightBounds]; [NSBezierPath fillRect:highlightBounds];
} }
// Render the background of the help text.
[HelpTextBackgroundColor() set];
[NSBezierPath fillRect:[self helpBounds]];
// Render the divider.
[DividerColor() set];
[NSBezierPath fillRect:[self dividerBounds]];
} }
#pragma mark Public API: #pragma mark Public API:
- (NSSize)preferredSize {
const NSSize passwordTitleSize =
[base::SysUTF16ToNSString(controller_->SuggestedText())
sizeWithAttributes:@{ NSFontAttributeName : [self boldFont] }];
const NSSize passwordSize = [base::SysUTF16ToNSString(controller_->password())
sizeWithAttributes:@{ NSFontAttributeName : [self textFont] }];
CGFloat width =
autofill::kPopupBorderThickness +
controller_->kHorizontalPadding +
[[keyIcon_ image] size].width +
controller_->kHorizontalPadding +
std::max(passwordSize.width, passwordTitleSize.width) +
controller_->kHorizontalPadding +
autofill::kPopupBorderThickness;
width = std::max(width, (CGFloat)controller_->GetMinimumWidth());
CGFloat height =
autofill::kPopupBorderThickness +
controller_->kHelpVerticalPadding +
[self helpSizeForPopupWidth:width].height +
controller_->kHelpVerticalPadding +
autofill::kPopupBorderThickness;
if (controller_->display_password())
height += controller_->kPopupPasswordSectionHeight;
return NSMakeSize(width, height);
}
- (void)updateBoundsAndRedrawPopup { - (void)updateBoundsAndRedrawPopup {
[self positionView:passwordField_ inRect:[self passwordBounds]]; const CGFloat popupWidth = controller_->popup_bounds().width();
[self positionView:passwordSubtextField_ inRect:[self passwordBounds]]; const CGFloat contentWidth =
[self positionView:helpTextView_ inRect:[self helpBounds]]; popupWidth - (2 * autofill::kPopupBorderThickness);
const CGFloat contentHeight = controller_->popup_bounds().height() -
(2 * autofill::kPopupBorderThickness);
if (controller_->display_password()) {
// The password can change while the bubble is shown: If the user has
// 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];
// Lay out the password section, which includes the key icon, the title, and
// the suggested password.
[passwordSection_
setFrame:NSMakeRect(autofill::kPopupBorderThickness,
autofill::kPopupBorderThickness,
contentWidth,
controller_->kPopupPasswordSectionHeight)];
// The key icon falls to the left of the title and password.
const NSSize imageSize = [[keyIcon_ image] size];
const CGFloat keyX = controller_->kHorizontalPadding;
const CGFloat keyY =
std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
(imageSize.height / 2.0));
[keyIcon_ setFrameOrigin:NSMakePoint(keyX, keyY)];
[keyIcon_ sizeToFit];
// The title and password fall to the right of the key icon and are centered
// vertically as a group with some padding in between.
[passwordTitleField_ sizeToFit];
[passwordField_ sizeToFit];
const CGFloat groupHeight = NSHeight([passwordField_ frame]) +
kPasswordSectionVerticalSeparation +
NSHeight([passwordTitleField_ frame]);
const CGFloat groupX =
NSMaxX([keyIcon_ frame]) + controller_->kHorizontalPadding;
const CGFloat groupY =
std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
(groupHeight / 2.0));
[passwordField_ setFrameOrigin:NSMakePoint(groupX, groupY)];
const CGFloat titleY = groupY +
NSHeight([passwordField_ frame]) +
kPasswordSectionVerticalSeparation;
[passwordTitleField_ setFrameOrigin:NSMakePoint(groupX, titleY)];
// Layout the divider, which falls immediately below the password section.
const CGFloat dividerX = autofill::kPopupBorderThickness;
const CGFloat dividerY = NSMaxY([passwordSection_ frame]);
NSRect dividerFrame =
NSMakeRect(dividerX, dividerY, contentWidth, kDividerHeight);
[divider_ setFrame:dividerFrame];
}
// Layout the help section beneath the divider (if applicable, otherwise
// beneath the border).
const CGFloat helpX = autofill::kPopupBorderThickness;
const CGFloat helpY = controller_->display_password()
? NSMaxY([divider_ frame])
: autofill::kPopupBorderThickness;
const CGFloat helpHeight = contentHeight -
NSHeight([passwordSection_ frame]) -
NSHeight([divider_ frame]);
[helpTextView_ setFrame:NSMakeRect(helpX, helpY, contentWidth, helpHeight)];
[super updateBoundsAndRedrawPopup]; [super updateBoundsAndRedrawPopup];
} }
- (BOOL)isPointInPasswordBounds:(NSPoint)point {
return NSPointInRect(point, [passwordSection_ frame]);
}
- (void)controllerDestroyed { - (void)controllerDestroyed {
controller_ = NULL; controller_ = NULL;
[super delegateDestroyed]; [super delegateDestroyed];
...@@ -144,27 +269,45 @@ NSColor* HelpLinkColor() { ...@@ -144,27 +269,45 @@ NSColor* HelpLinkColor() {
#pragma mark Private helpers: #pragma mark Private helpers:
- (NSTextField*)textFieldWithText:(const base::string16&)text - (void)updatePassword {
color:(NSColor*)color base::scoped_nsobject<NSMutableAttributedString> updatedPassword(
alignment:(NSTextAlignment)alignment { [[NSMutableAttributedString alloc]
initWithString:base::SysUTF16ToNSString(controller_->password())
attributes:[self passwordAttributes]]);
[passwordField_ setAttributedStringValue:updatedPassword];
}
- (NSDictionary*)passwordTitleAttributes {
scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
[[NSMutableParagraphStyle alloc] init]); [[NSMutableParagraphStyle alloc] init]);
[paragraphStyle setAlignment:alignment]; [paragraphStyle setAlignment:NSLeftTextAlignment];
return @{
NSFontAttributeName : [self boldFont],
NSForegroundColorAttributeName : [self nameColor],
NSParagraphStyleAttributeName : paragraphStyle.autorelease()
};
}
NSDictionary* textAttributes = @{ - (NSDictionary*)passwordAttributes {
scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
[[NSMutableParagraphStyle alloc] init]);
[paragraphStyle setAlignment:NSLeftTextAlignment];
return @{
NSFontAttributeName : [self textFont], NSFontAttributeName : [self textFont],
NSForegroundColorAttributeName : color, NSForegroundColorAttributeName : [self nameColor],
NSParagraphStyleAttributeName : paragraphStyle NSParagraphStyleAttributeName : paragraphStyle.autorelease()
}; };
}
- (NSTextField*)textFieldWithText:(const base::string16&)text
attributes:(NSDictionary*)attributes {
NSTextField* textField =
[[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
scoped_nsobject<NSAttributedString> attributedString( scoped_nsobject<NSAttributedString> attributedString(
[[NSAttributedString alloc] [[NSAttributedString alloc]
initWithString:base::SysUTF16ToNSString(text) initWithString:base::SysUTF16ToNSString(text)
attributes:textAttributes]); attributes:attributes]);
[textField setAttributedStringValue:attributedString.autorelease()];
NSTextField* textField =
[[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
[textField setAttributedStringValue:attributedString];
[textField setEditable:NO]; [textField setEditable:NO];
[textField setSelectable:NO]; [textField setSelectable:NO];
[textField setDrawsBackground:NO]; [textField setDrawsBackground:NO];
...@@ -172,31 +315,25 @@ NSColor* HelpLinkColor() { ...@@ -172,31 +315,25 @@ NSColor* HelpLinkColor() {
return textField; return textField;
} }
- (void)positionView:(NSView*)view inRect:(NSRect)bounds { - (NSSize)helpSizeForPopupWidth:(CGFloat)width {
NSRect frame = NSInsetRect(bounds, controller_->kHorizontalPadding, 0); const CGFloat helpWidth = width -
[view setFrame:frame]; 2 * controller_->kHorizontalPadding -
2 * autofill::kPopupBorderThickness;
// Center the text vertically within the bounds. const NSSize size = NSMakeSize(helpWidth, MAXFLOAT);
NSSize delta = cocoa_l10n_util::WrapOrSizeToFit(view); NSRect textFrame = [base::SysUTF16ToNSString(controller_->HelpText())
[view setFrameOrigin: boundingRectWithSize:size
NSInsetRect(frame, 0, floor(-delta.height/2)).origin]; options:NSLineBreakByWordWrapping |
} NSStringDrawingUsesLineFragmentOrigin
attributes:@{ NSFontAttributeName : [self textFont] }];
- (NSRect)passwordBounds { return textFrame.size;
return NSZeroRect;
}
- (NSRect)helpBounds {
return NSZeroRect;
} }
- (NSRect)dividerBounds { - (NSFont*)boldFont {
return NSZeroRect; return [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
} }
- (NSFont*)textFont { - (NSFont*)textFont {
return ResourceBundle::GetSharedInstance().GetFontList( return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
ResourceBundle::SmallFont).GetPrimaryFont().GetNativeFont();
} }
@end @end
...@@ -25,7 +25,6 @@ namespace { ...@@ -25,7 +25,6 @@ namespace {
// The amount of whitespace that is present when there is no padding. Used // The amount of whitespace that is present when there is no padding. Used
// to get the proper spacing in the help section. // to get the proper spacing in the help section.
const int kHelpVerticalOffset = 5; const int kHelpVerticalOffset = 5;
const int kPasswordSectionHeight = 62;
// Wrapper around just the text portions of the generation UI (password and // Wrapper around just the text portions of the generation UI (password and
// prompting text). // prompting text).
...@@ -173,7 +172,8 @@ gfx::Size PasswordGenerationPopupViewViews::GetPreferredSizeOfPasswordView() { ...@@ -173,7 +172,8 @@ gfx::Size PasswordGenerationPopupViewViews::GetPreferredSizeOfPasswordView() {
int height = kPopupBorderThickness; int height = kPopupBorderThickness;
if (controller_->display_password()) { if (controller_->display_password()) {
// Add divider height as well. // Add divider height as well.
height += kPasswordSectionHeight + 1; height +=
PasswordGenerationPopupController::kPopupPasswordSectionHeight + 1;
} }
int width = controller_->GetMinimumWidth(); int width = controller_->GetMinimumWidth();
int popup_width = width - 2 * kPopupBorderThickness; int popup_width = width - 2 * kPopupBorderThickness;
...@@ -217,7 +217,10 @@ void PasswordGenerationPopupViewViews::Layout() { ...@@ -217,7 +217,10 @@ void PasswordGenerationPopupViewViews::Layout() {
// it), but it can't change the other way around. // it), but it can't change the other way around.
CreatePasswordView(); CreatePasswordView();
password_view_->SetBounds( password_view_->SetBounds(
kPopupBorderThickness, y, popup_width, kPasswordSectionHeight); kPopupBorderThickness,
y,
popup_width,
PasswordGenerationPopupController::kPopupPasswordSectionHeight);
divider_bounds_ = divider_bounds_ =
gfx::Rect(kPopupBorderThickness, password_view_->bounds().bottom(), gfx::Rect(kPopupBorderThickness, password_view_->bounds().bottom(),
popup_width, 1); popup_width, 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment