Commit 48a0519f authored by bondd's avatar bondd Committed by Commit bot

Autofill OSX: Add PermanentErrorMessage box and label.

Adds red permanent error message banner between title and instructions.
Error messages passed to
CardUnmaskPromptViewBridge::GotVerificationResult() with
allow_retry == false are displayed. The banner is hidden until an error
message is passed to GotVerificationResult().

Note that the red banner does not extend to the full width of the dialog
(see screenshot attached to bug). Extending to the full dialog width
requires significant refactoring of the layout code, so I'm doing it in
two parts. This CL adds the banner functionality, and a separate CL will
fix the layout.

Dialog will re-layout to fit entire message if a multiline message is
set.

Also adds an ASCII art diagram of the dialog layout.

Screenshot attached to bug: https://code.google.com/p/chromium/issues/detail?id=448572#c15

BUG=448572

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

Cr-Commit-Position: refs/heads/master@{#322441}
parent 7da6a47d
...@@ -56,6 +56,7 @@ class CardUnmaskPromptViewBridge : public CardUnmaskPromptView, ...@@ -56,6 +56,7 @@ class CardUnmaskPromptViewBridge : public CardUnmaskPromptView,
- (void)setProgressOverlayText:(const base::string16&)text; - (void)setProgressOverlayText:(const base::string16&)text;
- (void)setRetriableErrorMessage:(const base::string16&)text; - (void)setRetriableErrorMessage:(const base::string16&)text;
- (void)setPermanentErrorMessage:(const base::string16&)text;
@end @end
......
...@@ -8,14 +8,15 @@ ...@@ -8,14 +8,15 @@
#include "chrome/browser/ui/autofill/autofill_dialog_models.h" #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
#include "chrome/browser/ui/autofill/autofill_dialog_types.h" #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
#include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h"
#include "chrome/browser/ui/chrome_style.h"
#import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h" #import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h"
#include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h" #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
#include "chrome/browser/ui/chrome_style.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h" #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h" #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h" #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h"
#import "chrome/browser/ui/cocoa/key_equivalent_constants.h" #import "chrome/browser/ui/cocoa/key_equivalent_constants.h"
#import "chrome/browser/ui/cocoa/l10n_util.h"
#include "grit/generated_resources.h" #include "grit/generated_resources.h"
#include "grit/theme_resources.h" #include "grit/theme_resources.h"
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
...@@ -27,6 +28,8 @@ namespace { ...@@ -27,6 +28,8 @@ namespace {
const CGFloat kButtonGap = 6.0f; const CGFloat kButtonGap = 6.0f;
const CGFloat kDialogContentMinWidth = 210.0f; const CGFloat kDialogContentMinWidth = 210.0f;
const CGFloat kCvcInputWidth = 64.0f; const CGFloat kCvcInputWidth = 64.0f;
const SkColor kPermanentErrorTextColor = SK_ColorWHITE;
const SkColor kPermanentErrorBackgroundColor = SkColorSetRGB(0xd3, 0x2f, 0x2f);
const ui::ResourceBundle::FontStyle kProgressFontStyle = const ui::ResourceBundle::FontStyle kProgressFontStyle =
chrome_style::kTitleFontStyle; chrome_style::kTitleFontStyle;
const ui::ResourceBundle::FontStyle kErrorFontStyle = const ui::ResourceBundle::FontStyle kErrorFontStyle =
...@@ -88,9 +91,14 @@ void CardUnmaskPromptViewBridge::GotVerificationResult( ...@@ -88,9 +91,14 @@ void CardUnmaskPromptViewBridge::GotVerificationResult(
base::TimeDelta::FromSeconds(1)); base::TimeDelta::FromSeconds(1));
} else { } else {
[view_controller_ setProgressOverlayText:base::string16()]; [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. if (allow_retry) {
[view_controller_ setRetriableErrorMessage:error_message]; // 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];
} else {
[view_controller_ setPermanentErrorMessage:error_message];
}
} }
} }
...@@ -114,10 +122,12 @@ void CardUnmaskPromptViewBridge::PerformClose() { ...@@ -114,10 +122,12 @@ void CardUnmaskPromptViewBridge::PerformClose() {
#pragma mark CardUnmaskPromptViewCocoa #pragma mark CardUnmaskPromptViewCocoa
@implementation CardUnmaskPromptViewCocoa { @implementation CardUnmaskPromptViewCocoa {
base::scoped_nsobject<NSBox> permanentErrorBox_;
base::scoped_nsobject<NSView> inputRowView_; base::scoped_nsobject<NSView> inputRowView_;
base::scoped_nsobject<NSView> storageView_; base::scoped_nsobject<NSView> storageView_;
base::scoped_nsobject<NSTextField> titleLabel_; base::scoped_nsobject<NSTextField> titleLabel_;
base::scoped_nsobject<NSTextField> permanentErrorLabel_;
base::scoped_nsobject<NSTextField> instructionsLabel_; base::scoped_nsobject<NSTextField> instructionsLabel_;
base::scoped_nsobject<NSTextField> cvcInput_; base::scoped_nsobject<NSTextField> cvcInput_;
base::scoped_nsobject<NSPopUpButton> monthPopup_; base::scoped_nsobject<NSPopUpButton> monthPopup_;
...@@ -147,16 +157,6 @@ void CardUnmaskPromptViewBridge::PerformClose() { ...@@ -147,16 +157,6 @@ void CardUnmaskPromptViewBridge::PerformClose() {
return popup; 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 // Set |view|'s frame to the minimum dimensions required to contain all of its
// subviews. // subviews.
+ (void)sizeToFitView:(NSView*)view { + (void)sizeToFitView:(NSView*)view {
...@@ -208,6 +208,36 @@ void CardUnmaskPromptViewBridge::PerformClose() { ...@@ -208,6 +208,36 @@ void CardUnmaskPromptViewBridge::PerformClose() {
[self performLayoutAndDisplay:YES]; [self performLayoutAndDisplay:YES];
} }
- (void)setPermanentErrorMessage:(const base::string16&)text {
if (!text.empty()) {
if (!permanentErrorBox_) {
permanentErrorBox_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
[permanentErrorBox_ setBoxType:NSBoxCustom];
[permanentErrorBox_ setBorderType:NSNoBorder];
[permanentErrorBox_ setTitlePosition:NSNoTitle];
[permanentErrorBox_ setFillColor:gfx::SkColorToCalibratedNSColor(
kPermanentErrorBackgroundColor)];
permanentErrorLabel_.reset([constrained_window::CreateLabel() retain]);
[permanentErrorLabel_ setAutoresizingMask:NSViewWidthSizable];
[permanentErrorLabel_ setTextColor:gfx::SkColorToCalibratedNSColor(
kPermanentErrorTextColor)];
[permanentErrorBox_ addSubview:permanentErrorLabel_];
[[self view] addSubview:permanentErrorBox_];
}
NSAttributedString* attributedString =
constrained_window::GetAttributedLabelString(
SysUTF16ToNSString(text), kErrorFontStyle, NSNaturalTextAlignment,
NSLineBreakByWordWrapping);
[permanentErrorLabel_ setAttributedStringValue:attributedString];
}
[permanentErrorBox_ setHidden:text.empty()];
[self setRetriableErrorMessage:base::string16()];
}
- (void)updateVerifyButtonEnabled { - (void)updateVerifyButtonEnabled {
autofill::CardUnmaskPromptController* controller = bridge_->GetController(); autofill::CardUnmaskPromptController* controller = bridge_->GetController();
DCHECK(controller); DCHECK(controller);
...@@ -282,7 +312,25 @@ void CardUnmaskPromptViewBridge::PerformClose() { ...@@ -282,7 +312,25 @@ void CardUnmaskPromptViewBridge::PerformClose() {
return view; return view;
} }
// TODO(bondd): Add an ASCII diagram of the layout. // +------------------------------------------------+
// | titleLabel_ (Single line.) |
// |------------------------------------------------|
// | permanentErrorBox_ (Multiline, may be hidden.) |
// |------------------------------------------------|
// | instructionsLabel_ (Multiline.) |
// |------------------------------------------------|
// | monthPopup_ yearPopup_ cvcInput_ cvcImage |
// | (All enclosed in inputRowView_. Month and |
// | year may be hidden.) |
// |------------------------------------------------|
// | errorLabel_ (Multiline. Always takes up space |
// | for one line even if empty.) |
// |------------------------------------------------|
// | [Cancel] [Verify] |
// |------------------------------------------------|
// | storageCheckbox_ storageTooltip_ |
// | (Both enclosed in storageView_.) |
// +------------------------------------------------+
- (void)performLayoutAndDisplay:(BOOL)display { - (void)performLayoutAndDisplay:(BOOL)display {
// Calculate dialog content width. // Calculate dialog content width.
CGFloat contentWidth = CGFloat contentWidth =
...@@ -302,22 +350,29 @@ void CardUnmaskPromptViewBridge::PerformClose() { ...@@ -302,22 +350,29 @@ void CardUnmaskPromptViewBridge::PerformClose() {
NSWidth([cancelButton_ frame]), NSWidth([cancelButton_ frame]),
NSMinY([verifyButton_ frame]))]; NSMinY([verifyButton_ frame]))];
[errorLabel_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton_ frame]) + [errorLabel_ setFrame:NSMakeRect(0, NSMaxY([cancelButton_ frame]) +
chrome_style::kRowPadding)]; chrome_style::kRowPadding,
[CardUnmaskPromptViewCocoa sizeTextField:errorLabel_ toFitWidth:contentWidth]; contentWidth, 0)];
cocoa_l10n_util::WrapOrSizeToFit(errorLabel_);
[inputRowView_ setFrameOrigin:NSMakePoint(0, NSMaxY([errorLabel_ frame]) + [inputRowView_ setFrameOrigin:NSMakePoint(0, NSMaxY([errorLabel_ frame]) +
chrome_style::kRowPadding)]; chrome_style::kRowPadding)];
[instructionsLabel_ [instructionsLabel_ setFrame:NSMakeRect(0, NSMaxY([inputRowView_ frame]) +
setFrameOrigin:NSMakePoint(0, NSMaxY([inputRowView_ frame]) + chrome_style::kRowPadding,
chrome_style::kRowPadding)]; contentWidth, 0)];
[CardUnmaskPromptViewCocoa sizeTextField:instructionsLabel_ cocoa_l10n_util::WrapOrSizeToFit(instructionsLabel_);
toFitWidth:contentWidth];
// Layout permanent error box.
CGFloat minY = NSMaxY([instructionsLabel_ frame]) + chrome_style::kRowPadding;
if (permanentErrorBox_ && ![permanentErrorBox_ isHidden]) {
[permanentErrorBox_ setFrame:NSMakeRect(0, minY, contentWidth, 0)];
cocoa_l10n_util::WrapOrSizeToFit(permanentErrorLabel_);
[permanentErrorBox_ sizeToFit];
minY = NSMaxY([permanentErrorBox_ frame]) + chrome_style::kRowPadding;
}
[titleLabel_ [titleLabel_ setFrameOrigin:NSMakePoint(0, minY)];
setFrameOrigin:NSMakePoint(0, NSMaxY([instructionsLabel_ frame]) +
chrome_style::kRowPadding)];
// Center progressOverlayLabel_ vertically within inputRowView_ frame. // Center progressOverlayLabel_ vertically within inputRowView_ frame.
CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance() CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance()
......
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