Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
| 7 #include "base/strings/sys_string_conversions.h" | 7 #include "base/strings/sys_string_conversions.h" |
| 8 #include "chrome/browser/ui/autofill/autofill_dialog_models.h" | 8 #include "chrome/browser/ui/autofill/autofill_dialog_models.h" |
| 9 #include "chrome/browser/ui/autofill/autofill_dialog_types.h" | |
| 9 #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" | 10 #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" |
| 10 #import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h" | 11 #import "chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.h" |
| 11 #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h" | 12 #include "chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.h" |
| 12 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" | 13 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h" |
| 13 #include "chrome/browser/ui/chrome_style.h" | 14 #include "chrome/browser/ui/chrome_style.h" |
| 14 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_u tils.h" | 15 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_u tils.h" |
| 15 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sh eet.h" | 16 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sh eet.h" |
| 16 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_wi ndow.h" | 17 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_wi ndow.h" |
| 17 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" | 18 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" |
| 18 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
| 19 #include "grit/theme_resources.h" | 20 #include "grit/theme_resources.h" |
| 21 #include "skia/ext/skia_utils_mac.h" | |
| 20 #include "ui/base/cocoa/window_size_constants.h" | 22 #include "ui/base/cocoa/window_size_constants.h" |
| 21 #include "ui/base/l10n/l10n_util.h" | 23 #include "ui/base/l10n/l10n_util.h" |
| 22 | 24 |
| 23 namespace { | 25 namespace { |
| 24 | 26 |
| 25 const CGFloat kButtonGap = 6.0f; | 27 const CGFloat kButtonGap = 6.0f; |
| 26 const CGFloat kDialogContentMinWidth = 210.0f; | 28 const CGFloat kDialogContentMinWidth = 210.0f; |
| 27 const CGFloat kCvcInputWidth = 64.0f; | 29 const CGFloat kCvcInputWidth = 64.0f; |
| 28 const ui::ResourceBundle::FontStyle kProgressFontStyle = | 30 const ui::ResourceBundle::FontStyle kProgressFontStyle = |
| 29 chrome_style::kTitleFontStyle; | 31 chrome_style::kTitleFontStyle; |
| 32 const ui::ResourceBundle::FontStyle kErrorFontStyle = | |
| 33 chrome_style::kTextFontStyle; | |
| 30 | 34 |
| 31 } // namespace | 35 } // namespace |
| 32 | 36 |
| 33 namespace autofill { | 37 namespace autofill { |
| 34 | 38 |
| 35 // static | 39 // static |
| 36 CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( | 40 CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( |
| 37 CardUnmaskPromptController* controller) { | 41 CardUnmaskPromptController* controller) { |
| 38 return new CardUnmaskPromptViewBridge(controller); | 42 return new CardUnmaskPromptViewBridge(controller); |
| 39 } | 43 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 [view_controller_ setProgressOverlayText: | 81 [view_controller_ setProgressOverlayText: |
| 78 l10n_util::GetStringUTF16( | 82 l10n_util::GetStringUTF16( |
| 79 IDS_AUTOFILL_CARD_UNMASK_VERIFICATION_SUCCESS)]; | 83 IDS_AUTOFILL_CARD_UNMASK_VERIFICATION_SUCCESS)]; |
| 80 | 84 |
| 81 base::MessageLoop::current()->PostDelayedTask( | 85 base::MessageLoop::current()->PostDelayedTask( |
| 82 FROM_HERE, base::Bind(&CardUnmaskPromptViewBridge::PerformClose, | 86 FROM_HERE, base::Bind(&CardUnmaskPromptViewBridge::PerformClose, |
| 83 weak_ptr_factory_.GetWeakPtr()), | 87 weak_ptr_factory_.GetWeakPtr()), |
| 84 base::TimeDelta::FromSeconds(1)); | 88 base::TimeDelta::FromSeconds(1)); |
| 85 } else { | 89 } else { |
| 86 [view_controller_ setProgressOverlayText:base::string16()]; | 90 [view_controller_ setProgressOverlayText:base::string16()]; |
| 91 // TODO(bondd): Views version never hides |errorLabel_|. When Views decides | |
| 92 // when to hide it then do the same thing here. | |
| 93 [view_controller_ setRetriableErrorMessage:error_message]; | |
| 87 } | 94 } |
| 88 } | 95 } |
| 89 | 96 |
| 90 void CardUnmaskPromptViewBridge::OnConstrainedWindowClosed( | 97 void CardUnmaskPromptViewBridge::OnConstrainedWindowClosed( |
| 91 ConstrainedWindowMac* window) { | 98 ConstrainedWindowMac* window) { |
| 92 if (controller_) | 99 if (controller_) |
| 93 controller_->OnUnmaskDialogClosed(); | 100 controller_->OnUnmaskDialogClosed(); |
| 94 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 101 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 95 } | 102 } |
| 96 | 103 |
| 97 CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() { | 104 CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() { |
| 98 return controller_; | 105 return controller_; |
| 99 } | 106 } |
| 100 | 107 |
| 101 void CardUnmaskPromptViewBridge::PerformClose() { | 108 void CardUnmaskPromptViewBridge::PerformClose() { |
| 102 constrained_window_->CloseWebContentsModalDialog(); | 109 constrained_window_->CloseWebContentsModalDialog(); |
| 103 } | 110 } |
| 104 | 111 |
| 105 } // autofill | 112 } // autofill |
| 106 | 113 |
| 107 #pragma mark CardUnmaskPromptViewCocoa | 114 #pragma mark CardUnmaskPromptViewCocoa |
| 108 | 115 |
| 109 @implementation CardUnmaskPromptViewCocoa { | 116 @implementation CardUnmaskPromptViewCocoa { |
| 117 base::scoped_nsobject<NSView> inputRowView_; | |
| 118 base::scoped_nsobject<NSView> storageView_; | |
| 119 | |
| 120 base::scoped_nsobject<NSTextField> titleLabel_; | |
| 121 base::scoped_nsobject<NSTextField> instructionsLabel_; | |
| 110 base::scoped_nsobject<NSTextField> cvcInput_; | 122 base::scoped_nsobject<NSTextField> cvcInput_; |
| 111 base::scoped_nsobject<NSPopUpButton> monthPopup_; | 123 base::scoped_nsobject<NSPopUpButton> monthPopup_; |
| 112 base::scoped_nsobject<NSPopUpButton> yearPopup_; | 124 base::scoped_nsobject<NSPopUpButton> yearPopup_; |
| 125 base::scoped_nsobject<NSButton> cancelButton_; | |
| 113 base::scoped_nsobject<NSButton> verifyButton_; | 126 base::scoped_nsobject<NSButton> verifyButton_; |
| 114 base::scoped_nsobject<NSButton> storageCheckbox_; | 127 base::scoped_nsobject<NSButton> storageCheckbox_; |
| 115 base::scoped_nsobject<AutofillTooltipController> storageTooltip_; | 128 base::scoped_nsobject<AutofillTooltipController> storageTooltip_; |
| 116 base::scoped_nsobject<NSView> inputRow_; | 129 base::scoped_nsobject<NSTextField> errorLabel_; |
| 117 base::scoped_nsobject<NSTextField> progressOverlayText_; | 130 base::scoped_nsobject<NSTextField> progressOverlayLabel_; |
| 118 | 131 |
| 119 int monthPopupDefaultIndex_; | 132 int monthPopupDefaultIndex_; |
| 120 int yearPopupDefaultIndex_; | 133 int yearPopupDefaultIndex_; |
| 121 | 134 |
| 122 // Owns |self|. | 135 // Owns |self|. |
| 123 autofill::CardUnmaskPromptViewBridge* bridge_; | 136 autofill::CardUnmaskPromptViewBridge* bridge_; |
| 124 } | 137 } |
| 125 | 138 |
| 126 + (NSPopUpButton*)buildDatePopupWithModel:(ui::ComboboxModel&)model { | 139 + (NSPopUpButton*)buildDatePopupWithModel:(ui::ComboboxModel&)model { |
| 127 NSPopUpButton* popup = | 140 NSPopUpButton* popup = |
| 128 [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO]; | 141 [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO]; |
| 129 | 142 |
| 130 for (int i = 0; i < model.GetItemCount(); ++i) { | 143 for (int i = 0; i < model.GetItemCount(); ++i) { |
| 131 [popup addItemWithTitle:base::SysUTF16ToNSString(model.GetItemAt(i))]; | 144 [popup addItemWithTitle:base::SysUTF16ToNSString(model.GetItemAt(i))]; |
| 132 } | 145 } |
| 133 [popup sizeToFit]; | 146 [popup sizeToFit]; |
| 134 return popup; | 147 return popup; |
| 135 } | 148 } |
| 136 | 149 |
| 150 // Sets |textField|'s frame size to minimum dimensions needed to display its | |
| 151 // text without exceeding |width|. Text will wrap onto multiple lines if | |
| 152 // necessary. Frame width may end up being less than |width| if the text fits | |
| 153 // in a smaller area. | |
| 154 // TODO(bondd): Hoist this to ui/base/cocoa. | |
|
groby-ooo-7-16
2015/03/25 20:51:53
You can kill the TODO - see other CL re l10::SizeT
bondd
2015/03/26 00:05:10
Done.
| |
| 155 + (void)sizeTextField:(NSTextField*)textField toFitWidth:(CGFloat)width { | |
| 156 NSSize frameSize = | |
| 157 [[textField cell] cellSizeForBounds:NSMakeRect(0, 0, width, CGFLOAT_MAX)]; | |
| 158 [textField setFrameSize:frameSize]; | |
| 159 } | |
| 160 | |
| 137 // Set |view|'s frame to the minimum dimensions required to contain all of its | 161 // Set |view|'s frame to the minimum dimensions required to contain all of its |
| 138 // subviews. | 162 // subviews. |
| 139 + (void)sizeToFitView:(NSView*)view { | 163 + (void)sizeToFitView:(NSView*)view { |
| 140 NSRect frame = NSZeroRect; | 164 NSRect frame = NSZeroRect; |
| 141 for (NSView* child in [view subviews]) { | 165 for (NSView* child in [view subviews]) { |
| 142 frame = NSUnionRect(frame, [child frame]); | 166 frame = NSUnionRect(frame, [child frame]); |
| 143 } | 167 } |
| 144 [view setFrame:frame]; | 168 [view setFrame:frame]; |
| 145 } | 169 } |
| 146 | 170 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 161 | 185 |
| 162 return self; | 186 return self; |
| 163 } | 187 } |
| 164 | 188 |
| 165 - (void)setProgressOverlayText:(const base::string16&)text { | 189 - (void)setProgressOverlayText:(const base::string16&)text { |
| 166 if (!text.empty()) { | 190 if (!text.empty()) { |
| 167 NSAttributedString* attributedString = | 191 NSAttributedString* attributedString = |
| 168 constrained_window::GetAttributedLabelString( | 192 constrained_window::GetAttributedLabelString( |
| 169 SysUTF16ToNSString(text), kProgressFontStyle, NSCenterTextAlignment, | 193 SysUTF16ToNSString(text), kProgressFontStyle, NSCenterTextAlignment, |
| 170 NSLineBreakByWordWrapping); | 194 NSLineBreakByWordWrapping); |
| 171 [progressOverlayText_ setAttributedStringValue:attributedString]; | 195 [progressOverlayLabel_ setAttributedStringValue:attributedString]; |
| 172 } | 196 } |
| 173 | 197 |
| 174 [progressOverlayText_ setHidden:text.empty()]; | 198 [progressOverlayLabel_ setHidden:text.empty()]; |
| 175 [inputRow_ setHidden:!text.empty()]; | 199 [inputRowView_ setHidden:!text.empty()]; |
| 176 [self updateVerifyButtonEnabled]; | 200 [self updateVerifyButtonEnabled]; |
| 177 } | 201 } |
| 178 | 202 |
| 203 - (void)setRetriableErrorMessage:(const base::string16&)text { | |
| 204 NSAttributedString* attributedString = | |
| 205 constrained_window::GetAttributedLabelString( | |
| 206 SysUTF16ToNSString(text), kErrorFontStyle, NSNaturalTextAlignment, | |
| 207 NSLineBreakByWordWrapping); | |
| 208 [errorLabel_ setAttributedStringValue:attributedString]; | |
| 209 [self performLayoutAndDisplay:YES]; | |
| 210 } | |
| 211 | |
| 179 - (void)updateVerifyButtonEnabled { | 212 - (void)updateVerifyButtonEnabled { |
| 180 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); | 213 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); |
| 181 DCHECK(controller); | 214 DCHECK(controller); |
| 182 | 215 |
| 183 BOOL enable = | 216 BOOL enable = |
| 184 ![inputRow_ isHidden] && | 217 ![inputRowView_ isHidden] && |
| 185 controller->InputCvcIsValid( | 218 controller->InputCvcIsValid( |
| 186 base::SysNSStringToUTF16([cvcInput_ stringValue])) && | 219 base::SysNSStringToUTF16([cvcInput_ stringValue])) && |
| 187 (!monthPopup_ || | 220 (!monthPopup_ || |
| 188 [monthPopup_ indexOfSelectedItem] != monthPopupDefaultIndex_) && | 221 [monthPopup_ indexOfSelectedItem] != monthPopupDefaultIndex_) && |
| 189 (!yearPopup_ || | 222 (!yearPopup_ || |
| 190 [yearPopup_ indexOfSelectedItem] != yearPopupDefaultIndex_); | 223 [yearPopup_ indexOfSelectedItem] != yearPopupDefaultIndex_); |
| 191 | 224 |
| 192 [verifyButton_ setEnabled:enable]; | 225 [verifyButton_ setEnabled:enable]; |
| 193 } | 226 } |
| 194 | 227 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 213 | 246 |
| 214 // Called when text in CVC input field changes. | 247 // Called when text in CVC input field changes. |
| 215 - (void)controlTextDidChange:(NSNotification*)notification { | 248 - (void)controlTextDidChange:(NSNotification*)notification { |
| 216 [self updateVerifyButtonEnabled]; | 249 [self updateVerifyButtonEnabled]; |
| 217 } | 250 } |
| 218 | 251 |
| 219 - (base::scoped_nsobject<NSView>)createStorageViewWithController: | 252 - (base::scoped_nsobject<NSView>)createStorageViewWithController: |
| 220 (autofill::CardUnmaskPromptController*)controller { | 253 (autofill::CardUnmaskPromptController*)controller { |
| 221 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); | 254 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); |
| 222 | 255 |
| 223 // "Store card on this device" checkbox. | 256 // Add "Store card on this device" checkbox. |
| 224 storageCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); | 257 storageCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); |
| 225 [storageCheckbox_ setButtonType:NSSwitchButton]; | 258 [storageCheckbox_ setButtonType:NSSwitchButton]; |
| 226 [storageCheckbox_ | 259 [storageCheckbox_ |
| 227 setTitle:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( | 260 setTitle:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( |
| 228 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_CHECKBOX))]; | 261 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_CHECKBOX))]; |
| 229 [storageCheckbox_ | 262 [storageCheckbox_ |
| 230 setState:(controller->GetStoreLocallyStartState() ? NSOnState | 263 setState:(controller->GetStoreLocallyStartState() ? NSOnState |
| 231 : NSOffState)]; | 264 : NSOffState)]; |
| 232 [storageCheckbox_ sizeToFit]; | 265 [storageCheckbox_ sizeToFit]; |
| 233 [view addSubview:storageCheckbox_]; | 266 [view addSubview:storageCheckbox_]; |
| 234 | 267 |
| 235 // "?" icon with tooltip. | 268 // Add "?" icon with tooltip. |
| 236 storageTooltip_.reset([[AutofillTooltipController alloc] | 269 storageTooltip_.reset([[AutofillTooltipController alloc] |
| 237 initWithArrowLocation:info_bubble::kTopRight]); | 270 initWithArrowLocation:info_bubble::kTopRight]); |
| 238 [storageTooltip_ setImage:ui::ResourceBundle::GetSharedInstance() | 271 [storageTooltip_ setImage:ui::ResourceBundle::GetSharedInstance() |
| 239 .GetNativeImageNamed(IDR_AUTOFILL_TOOLTIP_ICON) | 272 .GetNativeImageNamed(IDR_AUTOFILL_TOOLTIP_ICON) |
| 240 .ToNSImage()]; | 273 .ToNSImage()]; |
| 241 [storageTooltip_ | 274 [storageTooltip_ |
| 242 setMessage:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( | 275 setMessage:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( |
| 243 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_TOOLTIP))]; | 276 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_TOOLTIP))]; |
| 244 [view addSubview:[storageTooltip_ view]]; | 277 [view addSubview:[storageTooltip_ view]]; |
| 245 [[storageTooltip_ view] | 278 [[storageTooltip_ view] setFrameOrigin: |
| 246 setFrameOrigin:NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap, | 279 NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap, 0)]; |
| 247 0)]; | |
| 248 | 280 |
| 249 [CardUnmaskPromptViewCocoa sizeToFitView:view]; | 281 [CardUnmaskPromptViewCocoa sizeToFitView:view]; |
| 250 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:view]; | 282 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:view]; |
| 251 return view; | 283 return view; |
| 252 } | 284 } |
| 253 | 285 |
| 286 // TODO(bondd): Add an ASCII diagram of the layout. | |
| 287 - (void)performLayoutAndDisplay:(BOOL)display { | |
| 288 // Calculate dialog content width. | |
| 289 CGFloat contentWidth = | |
| 290 std::max(NSWidth([titleLabel_ frame]), NSWidth([inputRowView_ frame])); | |
| 291 contentWidth = std::max(contentWidth, NSWidth([storageView_ frame])); | |
| 292 contentWidth = std::max(contentWidth, kDialogContentMinWidth); | |
| 293 | |
| 294 [storageView_ | |
| 295 setFrameOrigin:NSMakePoint(0, chrome_style::kClientBottomPadding)]; | |
| 296 | |
| 297 [verifyButton_ setFrameOrigin: | |
| 298 NSMakePoint(contentWidth - NSWidth([verifyButton_ frame]), | |
| 299 NSMaxY([storageView_ frame]) + chrome_style::kRowPadding)]; | |
| 300 | |
| 301 [cancelButton_ | |
| 302 setFrameOrigin:NSMakePoint(NSMinX([verifyButton_ frame]) - kButtonGap - | |
| 303 NSWidth([cancelButton_ frame]), | |
| 304 NSMinY([verifyButton_ frame]))]; | |
| 305 | |
| 306 [errorLabel_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton_ frame]) + | |
| 307 chrome_style::kRowPadding)]; | |
| 308 [CardUnmaskPromptViewCocoa sizeTextField:errorLabel_ toFitWidth:contentWidth]; | |
| 309 | |
| 310 [inputRowView_ setFrameOrigin:NSMakePoint(0, NSMaxY([errorLabel_ frame]) + | |
| 311 chrome_style::kRowPadding)]; | |
| 312 | |
| 313 [instructionsLabel_ | |
| 314 setFrameOrigin:NSMakePoint(0, NSMaxY([inputRowView_ frame]) + | |
| 315 chrome_style::kRowPadding)]; | |
| 316 [CardUnmaskPromptViewCocoa sizeTextField:instructionsLabel_ | |
| 317 toFitWidth:contentWidth]; | |
| 318 | |
| 319 [titleLabel_ | |
| 320 setFrameOrigin:NSMakePoint(0, NSMaxY([instructionsLabel_ frame]) + | |
| 321 chrome_style::kRowPadding)]; | |
| 322 | |
| 323 // Center progressOverlayLabel_ vertically within inputRowView_ frame. | |
| 324 CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance() | |
| 325 .GetFont(kProgressFontStyle) | |
| 326 .GetHeight(); | |
| 327 [progressOverlayLabel_ | |
| 328 setFrame:NSMakeRect(0, ceil(NSMidY([inputRowView_ frame]) - | |
| 329 progressHeight / 2.0), | |
| 330 contentWidth, progressHeight)]; | |
| 331 | |
| 332 // Set dialog size. | |
| 333 [[self view] | |
| 334 setFrameSize:NSMakeSize( | |
| 335 contentWidth + chrome_style::kHorizontalPadding * 2.0, | |
| 336 NSMaxY([titleLabel_ frame]) + | |
| 337 chrome_style::kTitleTopPadding)]; | |
| 338 | |
| 339 NSRect frameRect = | |
| 340 [[[self view] window] frameRectForContentRect:[[self view] frame]]; | |
| 341 [[[self view] window] setFrame:frameRect display:display]; | |
| 342 } | |
| 343 | |
| 254 - (void)loadView { | 344 - (void)loadView { |
| 255 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); | 345 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); |
| 256 DCHECK(controller); | 346 DCHECK(controller); |
| 257 | 347 |
| 258 base::scoped_nsobject<NSBox> mainView( | 348 base::scoped_nsobject<NSBox> mainView( |
| 259 [[NSBox alloc] initWithFrame:NSZeroRect]); | 349 [[NSBox alloc] initWithFrame:NSZeroRect]); |
| 260 [mainView setBoxType:NSBoxCustom]; | 350 [mainView setBoxType:NSBoxCustom]; |
| 261 [mainView setBorderType:NSNoBorder]; | 351 [mainView setBorderType:NSNoBorder]; |
| 262 [mainView setTitlePosition:NSNoTitle]; | 352 [mainView setTitlePosition:NSNoTitle]; |
| 263 [mainView | 353 [mainView |
| 264 setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)]; | 354 setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)]; |
| 265 | 355 |
| 266 inputRow_.reset([[NSView alloc] initWithFrame:NSZeroRect]); | 356 inputRowView_.reset([[NSView alloc] initWithFrame:NSZeroRect]); |
| 267 [mainView addSubview:inputRow_]; | 357 [mainView addSubview:inputRowView_]; |
| 268 | 358 |
| 269 base::scoped_nsobject<NSView> storageView( | 359 storageView_ = [self createStorageViewWithController:controller]; |
| 270 [self createStorageViewWithController:controller]); | 360 [mainView addSubview:storageView_]; |
| 271 [mainView addSubview:storageView]; | |
| 272 | 361 |
| 273 // Title label. | 362 progressOverlayLabel_.reset([constrained_window::CreateLabel() retain]); |
| 274 NSTextField* title = constrained_window::CreateLabel(); | 363 [progressOverlayLabel_ setHidden:YES]; |
| 364 [mainView addSubview:progressOverlayLabel_]; | |
| 365 | |
| 366 // Add title label. | |
| 367 titleLabel_.reset([constrained_window::CreateLabel() retain]); | |
| 275 NSAttributedString* titleString = | 368 NSAttributedString* titleString = |
| 276 constrained_window::GetAttributedLabelString( | 369 constrained_window::GetAttributedLabelString( |
| 277 SysUTF16ToNSString(controller->GetWindowTitle()), | 370 SysUTF16ToNSString(controller->GetWindowTitle()), |
| 278 chrome_style::kTitleFontStyle, NSNaturalTextAlignment, | 371 chrome_style::kTitleFontStyle, NSNaturalTextAlignment, |
| 279 NSLineBreakByWordWrapping); | 372 NSLineBreakByWordWrapping); |
| 280 [title setAttributedStringValue:titleString]; | 373 [titleLabel_ setAttributedStringValue:titleString]; |
| 281 [title sizeToFit]; | 374 [titleLabel_ sizeToFit]; |
| 282 [mainView addSubview:title]; | 375 [mainView addSubview:titleLabel_]; |
| 283 | 376 |
| 284 // Instructions label. | 377 // Add instructions label. |
| 285 NSTextField* instructions = constrained_window::CreateLabel(); | 378 instructionsLabel_.reset([constrained_window::CreateLabel() retain]); |
| 286 NSAttributedString* instructionsString = | 379 NSAttributedString* instructionsString = |
| 287 constrained_window::GetAttributedLabelString( | 380 constrained_window::GetAttributedLabelString( |
| 288 SysUTF16ToNSString(controller->GetInstructionsMessage()), | 381 SysUTF16ToNSString(controller->GetInstructionsMessage()), |
| 289 chrome_style::kTextFontStyle, NSNaturalTextAlignment, | 382 chrome_style::kTextFontStyle, NSNaturalTextAlignment, |
| 290 NSLineBreakByWordWrapping); | 383 NSLineBreakByWordWrapping); |
| 291 [instructions setAttributedStringValue:instructionsString]; | 384 [instructionsLabel_ setAttributedStringValue:instructionsString]; |
| 292 [mainView addSubview:instructions]; | 385 [mainView addSubview:instructionsLabel_]; |
| 293 | 386 |
| 294 // Expiration date. | 387 // Add expiration date. |
| 295 base::scoped_nsobject<NSView> expirationView; | 388 base::scoped_nsobject<NSView> expirationView; |
| 296 if (controller->ShouldRequestExpirationDate()) { | 389 if (controller->ShouldRequestExpirationDate()) { |
| 297 expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]); | 390 expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]); |
| 298 | 391 |
| 299 // Month. | 392 // Add expiration month. |
| 300 autofill::MonthComboboxModel monthModel; | 393 autofill::MonthComboboxModel monthModel; |
| 301 monthPopupDefaultIndex_ = monthModel.GetDefaultIndex(); | 394 monthPopupDefaultIndex_ = monthModel.GetDefaultIndex(); |
| 302 monthPopup_.reset( | 395 monthPopup_.reset( |
| 303 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:monthModel]); | 396 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:monthModel]); |
| 304 [monthPopup_ setTarget:self]; | 397 [monthPopup_ setTarget:self]; |
| 305 [monthPopup_ setAction:@selector(onExpirationDateChanged:)]; | 398 [monthPopup_ setAction:@selector(onExpirationDateChanged:)]; |
| 306 [expirationView addSubview:monthPopup_]; | 399 [expirationView addSubview:monthPopup_]; |
| 307 | 400 |
| 308 // Year. | 401 // Add expiration year. |
| 309 autofill::YearComboboxModel yearModel; | 402 autofill::YearComboboxModel yearModel; |
| 310 yearPopupDefaultIndex_ = yearModel.GetDefaultIndex(); | 403 yearPopupDefaultIndex_ = yearModel.GetDefaultIndex(); |
| 311 yearPopup_.reset( | 404 yearPopup_.reset( |
| 312 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:yearModel]); | 405 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:yearModel]); |
| 313 [yearPopup_ setTarget:self]; | 406 [yearPopup_ setTarget:self]; |
| 314 [yearPopup_ setAction:@selector(onExpirationDateChanged:)]; | 407 [yearPopup_ setAction:@selector(onExpirationDateChanged:)]; |
| 315 [expirationView addSubview:yearPopup_]; | 408 [expirationView addSubview:yearPopup_]; |
| 316 | 409 |
| 317 // Layout month and year within expirationView. | 410 // Layout month and year within expirationView. |
| 318 [yearPopup_ | 411 [yearPopup_ |
| 319 setFrameOrigin:NSMakePoint(NSMaxX([monthPopup_ frame]) + kButtonGap, | 412 setFrameOrigin:NSMakePoint(NSMaxX([monthPopup_ frame]) + kButtonGap, |
| 320 0)]; | 413 0)]; |
| 321 NSRect expirationFrame = | 414 NSRect expirationFrame = |
| 322 NSUnionRect([monthPopup_ frame], [yearPopup_ frame]); | 415 NSUnionRect([monthPopup_ frame], [yearPopup_ frame]); |
| 323 expirationFrame.size.width += kButtonGap; | 416 expirationFrame.size.width += kButtonGap; |
| 324 [expirationView setFrame:expirationFrame]; | 417 [expirationView setFrame:expirationFrame]; |
| 325 [inputRow_ addSubview:expirationView]; | 418 [inputRowView_ addSubview:expirationView]; |
| 326 } | 419 } |
| 327 | 420 |
| 328 // CVC text input. | 421 // Add CVC text input. |
| 329 cvcInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | 422 cvcInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
| 330 [[cvcInput_ cell] | 423 [[cvcInput_ cell] |
| 331 setPlaceholderString:l10n_util::GetNSString( | 424 setPlaceholderString:l10n_util::GetNSString( |
| 332 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)]; | 425 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)]; |
| 333 [[cvcInput_ cell] setScrollable:YES]; | 426 [[cvcInput_ cell] setScrollable:YES]; |
| 334 [cvcInput_ setDelegate:self]; | 427 [cvcInput_ setDelegate:self]; |
| 335 [cvcInput_ sizeToFit]; | 428 [cvcInput_ sizeToFit]; |
| 336 [cvcInput_ setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0, | 429 [cvcInput_ setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0, |
| 337 kCvcInputWidth, NSHeight([cvcInput_ frame]))]; | 430 kCvcInputWidth, NSHeight([cvcInput_ frame]))]; |
| 338 [inputRow_ addSubview:cvcInput_]; | 431 [inputRowView_ addSubview:cvcInput_]; |
| 339 | 432 |
| 340 // CVC image. | 433 // Add CVC image. |
| 341 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 434 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 342 NSImage* cvcImage = | 435 NSImage* cvcImage = |
| 343 rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage(); | 436 rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage(); |
| 344 base::scoped_nsobject<NSImageView> cvcImageView( | 437 base::scoped_nsobject<NSImageView> cvcImageView( |
| 345 [[NSImageView alloc] initWithFrame:NSZeroRect]); | 438 [[NSImageView alloc] initWithFrame:NSZeroRect]); |
| 346 [cvcImageView setImage:cvcImage]; | 439 [cvcImageView setImage:cvcImage]; |
| 347 [cvcImageView setFrameSize:[cvcImage size]]; | 440 [cvcImageView setFrameSize:[cvcImage size]]; |
| 348 [cvcImageView | 441 [cvcImageView |
| 349 setFrameOrigin:NSMakePoint(NSMaxX([cvcInput_ frame]) + kButtonGap, 0)]; | 442 setFrameOrigin:NSMakePoint(NSMaxX([cvcInput_ frame]) + kButtonGap, 0)]; |
| 350 [inputRow_ addSubview:cvcImageView]; | 443 [inputRowView_ addSubview:cvcImageView]; |
| 351 | 444 |
| 352 // Cancel button. | 445 // Add error message label. |
| 353 base::scoped_nsobject<NSButton> cancelButton( | 446 errorLabel_.reset([constrained_window::CreateLabel() retain]); |
| 447 [errorLabel_ | |
| 448 setTextColor:gfx::SkColorToCalibratedNSColor(autofill::kWarningColor)]; | |
| 449 [mainView addSubview:errorLabel_]; | |
| 450 | |
| 451 // Add cancel button. | |
| 452 cancelButton_.reset( | |
| 354 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 453 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
| 355 [cancelButton setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; | 454 [cancelButton_ setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; |
| 356 [cancelButton setKeyEquivalent:kKeyEquivalentEscape]; | 455 [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape]; |
| 357 [cancelButton setTarget:self]; | 456 [cancelButton_ setTarget:self]; |
| 358 [cancelButton setAction:@selector(onCancel:)]; | 457 [cancelButton_ setAction:@selector(onCancel:)]; |
| 359 [cancelButton sizeToFit]; | 458 [cancelButton_ sizeToFit]; |
| 360 [mainView addSubview:cancelButton]; | 459 [mainView addSubview:cancelButton_]; |
| 361 | 460 |
| 362 // Verify button. | 461 // Add verify button. |
| 363 verifyButton_.reset( | 462 verifyButton_.reset( |
| 364 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 463 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
| 365 // TODO(bondd): use l10n string. | 464 // TODO(bondd): use l10n string. |
| 366 [verifyButton_ setTitle:@"Verify"]; | 465 [verifyButton_ setTitle:@"Verify"]; |
| 367 [verifyButton_ setKeyEquivalent:kKeyEquivalentReturn]; | 466 [verifyButton_ setKeyEquivalent:kKeyEquivalentReturn]; |
| 368 [verifyButton_ setTarget:self]; | 467 [verifyButton_ setTarget:self]; |
| 369 [verifyButton_ setAction:@selector(onVerify:)]; | 468 [verifyButton_ setAction:@selector(onVerify:)]; |
| 370 [verifyButton_ sizeToFit]; | 469 [verifyButton_ sizeToFit]; |
| 371 [self updateVerifyButtonEnabled]; | 470 [self updateVerifyButtonEnabled]; |
| 372 [mainView addSubview:verifyButton_]; | 471 [mainView addSubview:verifyButton_]; |
| 373 | 472 |
| 374 // Layout inputRow_. | 473 // Layout inputRowView_. |
| 375 [CardUnmaskPromptViewCocoa sizeToFitView:inputRow_]; | 474 [CardUnmaskPromptViewCocoa sizeToFitView:inputRowView_]; |
| 376 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRow_]; | 475 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRowView_]; |
| 377 | |
| 378 // Calculate dialog content width. | |
| 379 CGFloat contentWidth = | |
| 380 std::max(NSWidth([title frame]), NSWidth([inputRow_ frame])); | |
| 381 contentWidth = std::max(contentWidth, NSWidth([storageView frame])); | |
| 382 contentWidth = std::max(contentWidth, kDialogContentMinWidth); | |
| 383 | |
| 384 // Layout mainView contents, starting at the bottom and moving up. | |
| 385 | |
| 386 [storageView | |
| 387 setFrameOrigin:NSMakePoint(0, chrome_style::kClientBottomPadding)]; | |
| 388 | |
| 389 // Verify and Cancel buttons. | |
| 390 [verifyButton_ | |
| 391 setFrameOrigin:NSMakePoint(contentWidth - NSWidth([verifyButton_ frame]), | |
| 392 NSMaxY([storageView frame]) + | |
| 393 chrome_style::kRowPadding)]; | |
| 394 | |
| 395 [cancelButton | |
| 396 setFrameOrigin:NSMakePoint(NSMinX([verifyButton_ frame]) - kButtonGap - | |
| 397 NSWidth([cancelButton frame]), | |
| 398 NSMinY([verifyButton_ frame]))]; | |
| 399 | |
| 400 // Input row. | |
| 401 [inputRow_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton frame]) + | |
| 402 chrome_style::kRowPadding)]; | |
| 403 | |
| 404 // Instruction label. | |
| 405 [instructions setFrameOrigin:NSMakePoint(0, NSMaxY([inputRow_ frame]) + | |
| 406 chrome_style::kRowPadding)]; | |
| 407 NSSize instructionsSize = [[instructions cell] | |
| 408 cellSizeForBounds:NSMakeRect(0, 0, contentWidth, CGFLOAT_MAX)]; | |
| 409 [instructions setFrameSize:instructionsSize]; | |
| 410 | |
| 411 // Title label. | |
| 412 [title setFrameOrigin:NSMakePoint(0, NSMaxY([instructions frame]) + | |
| 413 chrome_style::kRowPadding)]; | |
| 414 | |
| 415 // Dialog size. | |
| 416 [mainView | |
| 417 setFrameSize:NSMakeSize( | |
| 418 contentWidth + [mainView contentViewMargins].width * 2.0, | |
| 419 NSMaxY([title frame]) + chrome_style::kTitleTopPadding)]; | |
| 420 | |
| 421 // Add progress overlay. | |
| 422 progressOverlayText_.reset([constrained_window::CreateLabel() retain]); | |
| 423 CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance() | |
| 424 .GetFont(kProgressFontStyle) | |
| 425 .GetHeight(); | |
| 426 // Center the text vertically within inputRow_ frame. | |
| 427 [progressOverlayText_ setFrame:NSMakeRect(0, ceil(NSMidY([inputRow_ frame]) - | |
| 428 progressHeight / 2.0), | |
| 429 contentWidth, progressHeight)]; | |
| 430 [progressOverlayText_ setHidden:YES]; | |
| 431 [mainView addSubview:progressOverlayText_]; | |
| 432 | 476 |
| 433 [self setView:mainView]; | 477 [self setView:mainView]; |
| 478 [self performLayoutAndDisplay:NO]; | |
| 434 } | 479 } |
| 435 | 480 |
| 436 @end | 481 @end |
| OLD | NEW |