| Index: chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
|
| diff --git a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
|
| index ba5e6c62a33702b24044768134eb1c30e4e64c39..e461ce6a2b07992e0b7aa569b08c7c2ec3dce90d 100644
|
| --- a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
|
| +++ b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
|
| @@ -6,6 +6,7 @@
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/strings/sys_string_conversions.h"
|
| #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
|
| +#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
|
| #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h"
|
| #import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h"
|
| #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h"
|
| @@ -17,6 +18,7 @@
|
| #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
|
| #include "grit/generated_resources.h"
|
| #include "grit/theme_resources.h"
|
| +#include "skia/ext/skia_utils_mac.h"
|
| #include "ui/base/cocoa/window_size_constants.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
|
|
| @@ -27,6 +29,8 @@ const CGFloat kDialogContentMinWidth = 210.0f;
|
| const CGFloat kCvcInputWidth = 64.0f;
|
| const ui::ResourceBundle::FontStyle kProgressFontStyle =
|
| chrome_style::kTitleFontStyle;
|
| +const ui::ResourceBundle::FontStyle kErrorFontStyle =
|
| + chrome_style::kTextFontStyle;
|
|
|
| } // namespace
|
|
|
| @@ -84,6 +88,9 @@ void CardUnmaskPromptViewBridge::GotVerificationResult(
|
| base::TimeDelta::FromSeconds(1));
|
| } else {
|
| [view_controller_ setProgressOverlayText:base::string16()];
|
| + // TODO(bondd): Views version never hides |errorLabel_|. When Views decides
|
| + // when to hide it then do the same thing here.
|
| + [view_controller_ setRetriableErrorMessage:error_message];
|
| }
|
| }
|
|
|
| @@ -107,14 +114,20 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| #pragma mark CardUnmaskPromptViewCocoa
|
|
|
| @implementation CardUnmaskPromptViewCocoa {
|
| + base::scoped_nsobject<NSView> inputRowView_;
|
| + base::scoped_nsobject<NSView> storageView_;
|
| +
|
| + base::scoped_nsobject<NSTextField> titleLabel_;
|
| + base::scoped_nsobject<NSTextField> instructionsLabel_;
|
| base::scoped_nsobject<NSTextField> cvcInput_;
|
| base::scoped_nsobject<NSPopUpButton> monthPopup_;
|
| base::scoped_nsobject<NSPopUpButton> yearPopup_;
|
| + base::scoped_nsobject<NSButton> cancelButton_;
|
| base::scoped_nsobject<NSButton> verifyButton_;
|
| base::scoped_nsobject<NSButton> storageCheckbox_;
|
| base::scoped_nsobject<AutofillTooltipController> storageTooltip_;
|
| - base::scoped_nsobject<NSView> inputRow_;
|
| - base::scoped_nsobject<NSTextField> progressOverlayText_;
|
| + base::scoped_nsobject<NSTextField> errorLabel_;
|
| + base::scoped_nsobject<NSTextField> progressOverlayLabel_;
|
|
|
| int monthPopupDefaultIndex_;
|
| int yearPopupDefaultIndex_;
|
| @@ -134,6 +147,16 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| return popup;
|
| }
|
|
|
| +// Sets |textField|'s frame size to minimum dimensions needed to display its
|
| +// text without exceeding |width|. Text will wrap onto multiple lines if
|
| +// necessary. Frame width may end up being less than |width| if the text fits
|
| +// in a smaller area.
|
| ++ (void)sizeTextField:(NSTextField*)textField toFitWidth:(CGFloat)width {
|
| + NSSize frameSize =
|
| + [[textField cell] cellSizeForBounds:NSMakeRect(0, 0, width, CGFLOAT_MAX)];
|
| + [textField setFrameSize:frameSize];
|
| +}
|
| +
|
| // Set |view|'s frame to the minimum dimensions required to contain all of its
|
| // subviews.
|
| + (void)sizeToFitView:(NSView*)view {
|
| @@ -168,20 +191,29 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| constrained_window::GetAttributedLabelString(
|
| SysUTF16ToNSString(text), kProgressFontStyle, NSCenterTextAlignment,
|
| NSLineBreakByWordWrapping);
|
| - [progressOverlayText_ setAttributedStringValue:attributedString];
|
| + [progressOverlayLabel_ setAttributedStringValue:attributedString];
|
| }
|
|
|
| - [progressOverlayText_ setHidden:text.empty()];
|
| - [inputRow_ setHidden:!text.empty()];
|
| + [progressOverlayLabel_ setHidden:text.empty()];
|
| + [inputRowView_ setHidden:!text.empty()];
|
| [self updateVerifyButtonEnabled];
|
| }
|
|
|
| +- (void)setRetriableErrorMessage:(const base::string16&)text {
|
| + NSAttributedString* attributedString =
|
| + constrained_window::GetAttributedLabelString(
|
| + SysUTF16ToNSString(text), kErrorFontStyle, NSNaturalTextAlignment,
|
| + NSLineBreakByWordWrapping);
|
| + [errorLabel_ setAttributedStringValue:attributedString];
|
| + [self performLayoutAndDisplay:YES];
|
| +}
|
| +
|
| - (void)updateVerifyButtonEnabled {
|
| autofill::CardUnmaskPromptController* controller = bridge_->GetController();
|
| DCHECK(controller);
|
|
|
| BOOL enable =
|
| - ![inputRow_ isHidden] &&
|
| + ![inputRowView_ isHidden] &&
|
| controller->InputCvcIsValid(
|
| base::SysNSStringToUTF16([cvcInput_ stringValue])) &&
|
| (!monthPopup_ ||
|
| @@ -220,7 +252,7 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| (autofill::CardUnmaskPromptController*)controller {
|
| base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
|
|
|
| - // "Store card on this device" checkbox.
|
| + // Add "Store card on this device" checkbox.
|
| storageCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
|
| [storageCheckbox_ setButtonType:NSSwitchButton];
|
| [storageCheckbox_
|
| @@ -232,7 +264,7 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [storageCheckbox_ sizeToFit];
|
| [view addSubview:storageCheckbox_];
|
|
|
| - // "?" icon with tooltip.
|
| + // Add "?" icon with tooltip.
|
| storageTooltip_.reset([[AutofillTooltipController alloc]
|
| initWithArrowLocation:info_bubble::kTopRight]);
|
| [storageTooltip_ setImage:ui::ResourceBundle::GetSharedInstance()
|
| @@ -242,15 +274,72 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| setMessage:base::SysUTF16ToNSString(l10n_util::GetStringUTF16(
|
| IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_TOOLTIP))];
|
| [view addSubview:[storageTooltip_ view]];
|
| - [[storageTooltip_ view]
|
| - setFrameOrigin:NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap,
|
| - 0)];
|
| + [[storageTooltip_ view] setFrameOrigin:
|
| + NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap, 0)];
|
|
|
| [CardUnmaskPromptViewCocoa sizeToFitView:view];
|
| [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:view];
|
| return view;
|
| }
|
|
|
| +// TODO(bondd): Add an ASCII diagram of the layout.
|
| +- (void)performLayoutAndDisplay:(BOOL)display {
|
| + // Calculate dialog content width.
|
| + CGFloat contentWidth =
|
| + std::max(NSWidth([titleLabel_ frame]), NSWidth([inputRowView_ frame]));
|
| + contentWidth = std::max(contentWidth, NSWidth([storageView_ frame]));
|
| + contentWidth = std::max(contentWidth, kDialogContentMinWidth);
|
| +
|
| + [storageView_
|
| + setFrameOrigin:NSMakePoint(0, chrome_style::kClientBottomPadding)];
|
| +
|
| + [verifyButton_ setFrameOrigin:
|
| + NSMakePoint(contentWidth - NSWidth([verifyButton_ frame]),
|
| + NSMaxY([storageView_ frame]) + chrome_style::kRowPadding)];
|
| +
|
| + [cancelButton_
|
| + setFrameOrigin:NSMakePoint(NSMinX([verifyButton_ frame]) - kButtonGap -
|
| + NSWidth([cancelButton_ frame]),
|
| + NSMinY([verifyButton_ frame]))];
|
| +
|
| + [errorLabel_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton_ frame]) +
|
| + chrome_style::kRowPadding)];
|
| + [CardUnmaskPromptViewCocoa sizeTextField:errorLabel_ toFitWidth:contentWidth];
|
| +
|
| + [inputRowView_ setFrameOrigin:NSMakePoint(0, NSMaxY([errorLabel_ frame]) +
|
| + chrome_style::kRowPadding)];
|
| +
|
| + [instructionsLabel_
|
| + setFrameOrigin:NSMakePoint(0, NSMaxY([inputRowView_ frame]) +
|
| + chrome_style::kRowPadding)];
|
| + [CardUnmaskPromptViewCocoa sizeTextField:instructionsLabel_
|
| + toFitWidth:contentWidth];
|
| +
|
| + [titleLabel_
|
| + setFrameOrigin:NSMakePoint(0, NSMaxY([instructionsLabel_ frame]) +
|
| + chrome_style::kRowPadding)];
|
| +
|
| + // Center progressOverlayLabel_ vertically within inputRowView_ frame.
|
| + CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance()
|
| + .GetFont(kProgressFontStyle)
|
| + .GetHeight();
|
| + [progressOverlayLabel_
|
| + setFrame:NSMakeRect(0, ceil(NSMidY([inputRowView_ frame]) -
|
| + progressHeight / 2.0),
|
| + contentWidth, progressHeight)];
|
| +
|
| + // Set dialog size.
|
| + [[self view]
|
| + setFrameSize:NSMakeSize(
|
| + contentWidth + chrome_style::kHorizontalPadding * 2.0,
|
| + NSMaxY([titleLabel_ frame]) +
|
| + chrome_style::kTitleTopPadding)];
|
| +
|
| + NSRect frameRect =
|
| + [[[self view] window] frameRectForContentRect:[[self view] frame]];
|
| + [[[self view] window] setFrame:frameRect display:display];
|
| +}
|
| +
|
| - (void)loadView {
|
| autofill::CardUnmaskPromptController* controller = bridge_->GetController();
|
| DCHECK(controller);
|
| @@ -263,40 +352,43 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [mainView
|
| setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)];
|
|
|
| - inputRow_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
|
| - [mainView addSubview:inputRow_];
|
| + inputRowView_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
|
| + [mainView addSubview:inputRowView_];
|
| +
|
| + storageView_ = [self createStorageViewWithController:controller];
|
| + [mainView addSubview:storageView_];
|
|
|
| - base::scoped_nsobject<NSView> storageView(
|
| - [self createStorageViewWithController:controller]);
|
| - [mainView addSubview:storageView];
|
| + progressOverlayLabel_.reset([constrained_window::CreateLabel() retain]);
|
| + [progressOverlayLabel_ setHidden:YES];
|
| + [mainView addSubview:progressOverlayLabel_];
|
|
|
| - // Title label.
|
| - NSTextField* title = constrained_window::CreateLabel();
|
| + // Add title label.
|
| + titleLabel_.reset([constrained_window::CreateLabel() retain]);
|
| NSAttributedString* titleString =
|
| constrained_window::GetAttributedLabelString(
|
| SysUTF16ToNSString(controller->GetWindowTitle()),
|
| chrome_style::kTitleFontStyle, NSNaturalTextAlignment,
|
| NSLineBreakByWordWrapping);
|
| - [title setAttributedStringValue:titleString];
|
| - [title sizeToFit];
|
| - [mainView addSubview:title];
|
| + [titleLabel_ setAttributedStringValue:titleString];
|
| + [titleLabel_ sizeToFit];
|
| + [mainView addSubview:titleLabel_];
|
|
|
| - // Instructions label.
|
| - NSTextField* instructions = constrained_window::CreateLabel();
|
| + // Add instructions label.
|
| + instructionsLabel_.reset([constrained_window::CreateLabel() retain]);
|
| NSAttributedString* instructionsString =
|
| constrained_window::GetAttributedLabelString(
|
| SysUTF16ToNSString(controller->GetInstructionsMessage()),
|
| chrome_style::kTextFontStyle, NSNaturalTextAlignment,
|
| NSLineBreakByWordWrapping);
|
| - [instructions setAttributedStringValue:instructionsString];
|
| - [mainView addSubview:instructions];
|
| + [instructionsLabel_ setAttributedStringValue:instructionsString];
|
| + [mainView addSubview:instructionsLabel_];
|
|
|
| - // Expiration date.
|
| + // Add expiration date.
|
| base::scoped_nsobject<NSView> expirationView;
|
| if (controller->ShouldRequestExpirationDate()) {
|
| expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]);
|
|
|
| - // Month.
|
| + // Add expiration month.
|
| autofill::MonthComboboxModel monthModel;
|
| monthPopupDefaultIndex_ = monthModel.GetDefaultIndex();
|
| monthPopup_.reset(
|
| @@ -305,7 +397,7 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [monthPopup_ setAction:@selector(onExpirationDateChanged:)];
|
| [expirationView addSubview:monthPopup_];
|
|
|
| - // Year.
|
| + // Add expiration year.
|
| autofill::YearComboboxModel yearModel;
|
| yearPopupDefaultIndex_ = yearModel.GetDefaultIndex();
|
| yearPopup_.reset(
|
| @@ -322,10 +414,10 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| NSUnionRect([monthPopup_ frame], [yearPopup_ frame]);
|
| expirationFrame.size.width += kButtonGap;
|
| [expirationView setFrame:expirationFrame];
|
| - [inputRow_ addSubview:expirationView];
|
| + [inputRowView_ addSubview:expirationView];
|
| }
|
|
|
| - // CVC text input.
|
| + // Add CVC text input.
|
| cvcInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]);
|
| [[cvcInput_ cell]
|
| setPlaceholderString:l10n_util::GetNSString(
|
| @@ -335,9 +427,9 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [cvcInput_ sizeToFit];
|
| [cvcInput_ setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0,
|
| kCvcInputWidth, NSHeight([cvcInput_ frame]))];
|
| - [inputRow_ addSubview:cvcInput_];
|
| + [inputRowView_ addSubview:cvcInput_];
|
|
|
| - // CVC image.
|
| + // Add CVC image.
|
| ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| NSImage* cvcImage =
|
| rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage();
|
| @@ -347,19 +439,25 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [cvcImageView setFrameSize:[cvcImage size]];
|
| [cvcImageView
|
| setFrameOrigin:NSMakePoint(NSMaxX([cvcInput_ frame]) + kButtonGap, 0)];
|
| - [inputRow_ addSubview:cvcImageView];
|
| + [inputRowView_ addSubview:cvcImageView];
|
|
|
| - // Cancel button.
|
| - base::scoped_nsobject<NSButton> cancelButton(
|
| + // Add error message label.
|
| + errorLabel_.reset([constrained_window::CreateLabel() retain]);
|
| + [errorLabel_
|
| + setTextColor:gfx::SkColorToCalibratedNSColor(autofill::kWarningColor)];
|
| + [mainView addSubview:errorLabel_];
|
| +
|
| + // Add cancel button.
|
| + cancelButton_.reset(
|
| [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
|
| - [cancelButton setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
|
| - [cancelButton setKeyEquivalent:kKeyEquivalentEscape];
|
| - [cancelButton setTarget:self];
|
| - [cancelButton setAction:@selector(onCancel:)];
|
| - [cancelButton sizeToFit];
|
| - [mainView addSubview:cancelButton];
|
| -
|
| - // Verify button.
|
| + [cancelButton_ setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)];
|
| + [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape];
|
| + [cancelButton_ setTarget:self];
|
| + [cancelButton_ setAction:@selector(onCancel:)];
|
| + [cancelButton_ sizeToFit];
|
| + [mainView addSubview:cancelButton_];
|
| +
|
| + // Add verify button.
|
| verifyButton_.reset(
|
| [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]);
|
| // TODO(bondd): use l10n string.
|
| @@ -371,66 +469,12 @@ void CardUnmaskPromptViewBridge::PerformClose() {
|
| [self updateVerifyButtonEnabled];
|
| [mainView addSubview:verifyButton_];
|
|
|
| - // Layout inputRow_.
|
| - [CardUnmaskPromptViewCocoa sizeToFitView:inputRow_];
|
| - [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRow_];
|
| -
|
| - // Calculate dialog content width.
|
| - CGFloat contentWidth =
|
| - std::max(NSWidth([title frame]), NSWidth([inputRow_ frame]));
|
| - contentWidth = std::max(contentWidth, NSWidth([storageView frame]));
|
| - contentWidth = std::max(contentWidth, kDialogContentMinWidth);
|
| -
|
| - // Layout mainView contents, starting at the bottom and moving up.
|
| -
|
| - [storageView
|
| - setFrameOrigin:NSMakePoint(0, chrome_style::kClientBottomPadding)];
|
| -
|
| - // Verify and Cancel buttons.
|
| - [verifyButton_
|
| - setFrameOrigin:NSMakePoint(contentWidth - NSWidth([verifyButton_ frame]),
|
| - NSMaxY([storageView frame]) +
|
| - chrome_style::kRowPadding)];
|
| -
|
| - [cancelButton
|
| - setFrameOrigin:NSMakePoint(NSMinX([verifyButton_ frame]) - kButtonGap -
|
| - NSWidth([cancelButton frame]),
|
| - NSMinY([verifyButton_ frame]))];
|
| -
|
| - // Input row.
|
| - [inputRow_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton frame]) +
|
| - chrome_style::kRowPadding)];
|
| -
|
| - // Instruction label.
|
| - [instructions setFrameOrigin:NSMakePoint(0, NSMaxY([inputRow_ frame]) +
|
| - chrome_style::kRowPadding)];
|
| - NSSize instructionsSize = [[instructions cell]
|
| - cellSizeForBounds:NSMakeRect(0, 0, contentWidth, CGFLOAT_MAX)];
|
| - [instructions setFrameSize:instructionsSize];
|
| -
|
| - // Title label.
|
| - [title setFrameOrigin:NSMakePoint(0, NSMaxY([instructions frame]) +
|
| - chrome_style::kRowPadding)];
|
| -
|
| - // Dialog size.
|
| - [mainView
|
| - setFrameSize:NSMakeSize(
|
| - contentWidth + [mainView contentViewMargins].width * 2.0,
|
| - NSMaxY([title frame]) + chrome_style::kTitleTopPadding)];
|
| -
|
| - // Add progress overlay.
|
| - progressOverlayText_.reset([constrained_window::CreateLabel() retain]);
|
| - CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance()
|
| - .GetFont(kProgressFontStyle)
|
| - .GetHeight();
|
| - // Center the text vertically within inputRow_ frame.
|
| - [progressOverlayText_ setFrame:NSMakeRect(0, ceil(NSMidY([inputRow_ frame]) -
|
| - progressHeight / 2.0),
|
| - contentWidth, progressHeight)];
|
| - [progressOverlayText_ setHidden:YES];
|
| - [mainView addSubview:progressOverlayText_];
|
| + // Layout inputRowView_.
|
| + [CardUnmaskPromptViewCocoa sizeToFitView:inputRowView_];
|
| + [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRowView_];
|
|
|
| [self setView:mainView];
|
| + [self performLayoutAndDisplay:NO];
|
| }
|
|
|
| @end
|
|
|