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 + (void)sizeTextField:(NSTextField*)textField toFitWidth:(CGFloat)width { |
| 155 NSSize frameSize = |
| 156 [[textField cell] cellSizeForBounds:NSMakeRect(0, 0, width, CGFLOAT_MAX)]; |
| 157 [textField setFrameSize:frameSize]; |
| 158 } |
| 159 |
137 // Set |view|'s frame to the minimum dimensions required to contain all of its | 160 // Set |view|'s frame to the minimum dimensions required to contain all of its |
138 // subviews. | 161 // subviews. |
139 + (void)sizeToFitView:(NSView*)view { | 162 + (void)sizeToFitView:(NSView*)view { |
140 NSRect frame = NSZeroRect; | 163 NSRect frame = NSZeroRect; |
141 for (NSView* child in [view subviews]) { | 164 for (NSView* child in [view subviews]) { |
142 frame = NSUnionRect(frame, [child frame]); | 165 frame = NSUnionRect(frame, [child frame]); |
143 } | 166 } |
144 [view setFrame:frame]; | 167 [view setFrame:frame]; |
145 } | 168 } |
146 | 169 |
(...skipping 14 matching lines...) Expand all Loading... |
161 | 184 |
162 return self; | 185 return self; |
163 } | 186 } |
164 | 187 |
165 - (void)setProgressOverlayText:(const base::string16&)text { | 188 - (void)setProgressOverlayText:(const base::string16&)text { |
166 if (!text.empty()) { | 189 if (!text.empty()) { |
167 NSAttributedString* attributedString = | 190 NSAttributedString* attributedString = |
168 constrained_window::GetAttributedLabelString( | 191 constrained_window::GetAttributedLabelString( |
169 SysUTF16ToNSString(text), kProgressFontStyle, NSCenterTextAlignment, | 192 SysUTF16ToNSString(text), kProgressFontStyle, NSCenterTextAlignment, |
170 NSLineBreakByWordWrapping); | 193 NSLineBreakByWordWrapping); |
171 [progressOverlayText_ setAttributedStringValue:attributedString]; | 194 [progressOverlayLabel_ setAttributedStringValue:attributedString]; |
172 } | 195 } |
173 | 196 |
174 [progressOverlayText_ setHidden:text.empty()]; | 197 [progressOverlayLabel_ setHidden:text.empty()]; |
175 [inputRow_ setHidden:!text.empty()]; | 198 [inputRowView_ setHidden:!text.empty()]; |
176 [self updateVerifyButtonEnabled]; | 199 [self updateVerifyButtonEnabled]; |
177 } | 200 } |
178 | 201 |
| 202 - (void)setRetriableErrorMessage:(const base::string16&)text { |
| 203 NSAttributedString* attributedString = |
| 204 constrained_window::GetAttributedLabelString( |
| 205 SysUTF16ToNSString(text), kErrorFontStyle, NSNaturalTextAlignment, |
| 206 NSLineBreakByWordWrapping); |
| 207 [errorLabel_ setAttributedStringValue:attributedString]; |
| 208 [self performLayoutAndDisplay:YES]; |
| 209 } |
| 210 |
179 - (void)updateVerifyButtonEnabled { | 211 - (void)updateVerifyButtonEnabled { |
180 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); | 212 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); |
181 DCHECK(controller); | 213 DCHECK(controller); |
182 | 214 |
183 BOOL enable = | 215 BOOL enable = |
184 ![inputRow_ isHidden] && | 216 ![inputRowView_ isHidden] && |
185 controller->InputCvcIsValid( | 217 controller->InputCvcIsValid( |
186 base::SysNSStringToUTF16([cvcInput_ stringValue])) && | 218 base::SysNSStringToUTF16([cvcInput_ stringValue])) && |
187 (!monthPopup_ || | 219 (!monthPopup_ || |
188 [monthPopup_ indexOfSelectedItem] != monthPopupDefaultIndex_) && | 220 [monthPopup_ indexOfSelectedItem] != monthPopupDefaultIndex_) && |
189 (!yearPopup_ || | 221 (!yearPopup_ || |
190 [yearPopup_ indexOfSelectedItem] != yearPopupDefaultIndex_); | 222 [yearPopup_ indexOfSelectedItem] != yearPopupDefaultIndex_); |
191 | 223 |
192 [verifyButton_ setEnabled:enable]; | 224 [verifyButton_ setEnabled:enable]; |
193 } | 225 } |
194 | 226 |
(...skipping 18 matching lines...) Expand all Loading... |
213 | 245 |
214 // Called when text in CVC input field changes. | 246 // Called when text in CVC input field changes. |
215 - (void)controlTextDidChange:(NSNotification*)notification { | 247 - (void)controlTextDidChange:(NSNotification*)notification { |
216 [self updateVerifyButtonEnabled]; | 248 [self updateVerifyButtonEnabled]; |
217 } | 249 } |
218 | 250 |
219 - (base::scoped_nsobject<NSView>)createStorageViewWithController: | 251 - (base::scoped_nsobject<NSView>)createStorageViewWithController: |
220 (autofill::CardUnmaskPromptController*)controller { | 252 (autofill::CardUnmaskPromptController*)controller { |
221 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); | 253 base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); |
222 | 254 |
223 // "Store card on this device" checkbox. | 255 // Add "Store card on this device" checkbox. |
224 storageCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); | 256 storageCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); |
225 [storageCheckbox_ setButtonType:NSSwitchButton]; | 257 [storageCheckbox_ setButtonType:NSSwitchButton]; |
226 [storageCheckbox_ | 258 [storageCheckbox_ |
227 setTitle:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( | 259 setTitle:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( |
228 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_CHECKBOX))]; | 260 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_CHECKBOX))]; |
229 [storageCheckbox_ | 261 [storageCheckbox_ |
230 setState:(controller->GetStoreLocallyStartState() ? NSOnState | 262 setState:(controller->GetStoreLocallyStartState() ? NSOnState |
231 : NSOffState)]; | 263 : NSOffState)]; |
232 [storageCheckbox_ sizeToFit]; | 264 [storageCheckbox_ sizeToFit]; |
233 [view addSubview:storageCheckbox_]; | 265 [view addSubview:storageCheckbox_]; |
234 | 266 |
235 // "?" icon with tooltip. | 267 // Add "?" icon with tooltip. |
236 storageTooltip_.reset([[AutofillTooltipController alloc] | 268 storageTooltip_.reset([[AutofillTooltipController alloc] |
237 initWithArrowLocation:info_bubble::kTopRight]); | 269 initWithArrowLocation:info_bubble::kTopRight]); |
238 [storageTooltip_ setImage:ui::ResourceBundle::GetSharedInstance() | 270 [storageTooltip_ setImage:ui::ResourceBundle::GetSharedInstance() |
239 .GetNativeImageNamed(IDR_AUTOFILL_TOOLTIP_ICON) | 271 .GetNativeImageNamed(IDR_AUTOFILL_TOOLTIP_ICON) |
240 .ToNSImage()]; | 272 .ToNSImage()]; |
241 [storageTooltip_ | 273 [storageTooltip_ |
242 setMessage:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( | 274 setMessage:base::SysUTF16ToNSString(l10n_util::GetStringUTF16( |
243 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_TOOLTIP))]; | 275 IDS_AUTOFILL_CARD_UNMASK_PROMPT_STORAGE_TOOLTIP))]; |
244 [view addSubview:[storageTooltip_ view]]; | 276 [view addSubview:[storageTooltip_ view]]; |
245 [[storageTooltip_ view] | 277 [[storageTooltip_ view] setFrameOrigin: |
246 setFrameOrigin:NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap, | 278 NSMakePoint(NSMaxX([storageCheckbox_ frame]) + kButtonGap, 0)]; |
247 0)]; | |
248 | 279 |
249 [CardUnmaskPromptViewCocoa sizeToFitView:view]; | 280 [CardUnmaskPromptViewCocoa sizeToFitView:view]; |
250 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:view]; | 281 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:view]; |
251 return view; | 282 return view; |
252 } | 283 } |
253 | 284 |
| 285 // TODO(bondd): Add an ASCII diagram of the layout. |
| 286 - (void)performLayoutAndDisplay:(BOOL)display { |
| 287 // Calculate dialog content width. |
| 288 CGFloat contentWidth = |
| 289 std::max(NSWidth([titleLabel_ frame]), NSWidth([inputRowView_ frame])); |
| 290 contentWidth = std::max(contentWidth, NSWidth([storageView_ frame])); |
| 291 contentWidth = std::max(contentWidth, kDialogContentMinWidth); |
| 292 |
| 293 [storageView_ |
| 294 setFrameOrigin:NSMakePoint(0, chrome_style::kClientBottomPadding)]; |
| 295 |
| 296 [verifyButton_ setFrameOrigin: |
| 297 NSMakePoint(contentWidth - NSWidth([verifyButton_ frame]), |
| 298 NSMaxY([storageView_ frame]) + chrome_style::kRowPadding)]; |
| 299 |
| 300 [cancelButton_ |
| 301 setFrameOrigin:NSMakePoint(NSMinX([verifyButton_ frame]) - kButtonGap - |
| 302 NSWidth([cancelButton_ frame]), |
| 303 NSMinY([verifyButton_ frame]))]; |
| 304 |
| 305 [errorLabel_ setFrameOrigin:NSMakePoint(0, NSMaxY([cancelButton_ frame]) + |
| 306 chrome_style::kRowPadding)]; |
| 307 [CardUnmaskPromptViewCocoa sizeTextField:errorLabel_ toFitWidth:contentWidth]; |
| 308 |
| 309 [inputRowView_ setFrameOrigin:NSMakePoint(0, NSMaxY([errorLabel_ frame]) + |
| 310 chrome_style::kRowPadding)]; |
| 311 |
| 312 [instructionsLabel_ |
| 313 setFrameOrigin:NSMakePoint(0, NSMaxY([inputRowView_ frame]) + |
| 314 chrome_style::kRowPadding)]; |
| 315 [CardUnmaskPromptViewCocoa sizeTextField:instructionsLabel_ |
| 316 toFitWidth:contentWidth]; |
| 317 |
| 318 [titleLabel_ |
| 319 setFrameOrigin:NSMakePoint(0, NSMaxY([instructionsLabel_ frame]) + |
| 320 chrome_style::kRowPadding)]; |
| 321 |
| 322 // Center progressOverlayLabel_ vertically within inputRowView_ frame. |
| 323 CGFloat progressHeight = ui::ResourceBundle::GetSharedInstance() |
| 324 .GetFont(kProgressFontStyle) |
| 325 .GetHeight(); |
| 326 [progressOverlayLabel_ |
| 327 setFrame:NSMakeRect(0, ceil(NSMidY([inputRowView_ frame]) - |
| 328 progressHeight / 2.0), |
| 329 contentWidth, progressHeight)]; |
| 330 |
| 331 // Set dialog size. |
| 332 [[self view] |
| 333 setFrameSize:NSMakeSize( |
| 334 contentWidth + chrome_style::kHorizontalPadding * 2.0, |
| 335 NSMaxY([titleLabel_ frame]) + |
| 336 chrome_style::kTitleTopPadding)]; |
| 337 |
| 338 NSRect frameRect = |
| 339 [[[self view] window] frameRectForContentRect:[[self view] frame]]; |
| 340 [[[self view] window] setFrame:frameRect display:display]; |
| 341 } |
| 342 |
254 - (void)loadView { | 343 - (void)loadView { |
255 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); | 344 autofill::CardUnmaskPromptController* controller = bridge_->GetController(); |
256 DCHECK(controller); | 345 DCHECK(controller); |
257 | 346 |
258 base::scoped_nsobject<NSBox> mainView( | 347 base::scoped_nsobject<NSBox> mainView( |
259 [[NSBox alloc] initWithFrame:NSZeroRect]); | 348 [[NSBox alloc] initWithFrame:NSZeroRect]); |
260 [mainView setBoxType:NSBoxCustom]; | 349 [mainView setBoxType:NSBoxCustom]; |
261 [mainView setBorderType:NSNoBorder]; | 350 [mainView setBorderType:NSNoBorder]; |
262 [mainView setTitlePosition:NSNoTitle]; | 351 [mainView setTitlePosition:NSNoTitle]; |
263 [mainView | 352 [mainView |
264 setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)]; | 353 setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, 0)]; |
265 | 354 |
266 inputRow_.reset([[NSView alloc] initWithFrame:NSZeroRect]); | 355 inputRowView_.reset([[NSView alloc] initWithFrame:NSZeroRect]); |
267 [mainView addSubview:inputRow_]; | 356 [mainView addSubview:inputRowView_]; |
268 | 357 |
269 base::scoped_nsobject<NSView> storageView( | 358 storageView_ = [self createStorageViewWithController:controller]; |
270 [self createStorageViewWithController:controller]); | 359 [mainView addSubview:storageView_]; |
271 [mainView addSubview:storageView]; | |
272 | 360 |
273 // Title label. | 361 progressOverlayLabel_.reset([constrained_window::CreateLabel() retain]); |
274 NSTextField* title = constrained_window::CreateLabel(); | 362 [progressOverlayLabel_ setHidden:YES]; |
| 363 [mainView addSubview:progressOverlayLabel_]; |
| 364 |
| 365 // Add title label. |
| 366 titleLabel_.reset([constrained_window::CreateLabel() retain]); |
275 NSAttributedString* titleString = | 367 NSAttributedString* titleString = |
276 constrained_window::GetAttributedLabelString( | 368 constrained_window::GetAttributedLabelString( |
277 SysUTF16ToNSString(controller->GetWindowTitle()), | 369 SysUTF16ToNSString(controller->GetWindowTitle()), |
278 chrome_style::kTitleFontStyle, NSNaturalTextAlignment, | 370 chrome_style::kTitleFontStyle, NSNaturalTextAlignment, |
279 NSLineBreakByWordWrapping); | 371 NSLineBreakByWordWrapping); |
280 [title setAttributedStringValue:titleString]; | 372 [titleLabel_ setAttributedStringValue:titleString]; |
281 [title sizeToFit]; | 373 [titleLabel_ sizeToFit]; |
282 [mainView addSubview:title]; | 374 [mainView addSubview:titleLabel_]; |
283 | 375 |
284 // Instructions label. | 376 // Add instructions label. |
285 NSTextField* instructions = constrained_window::CreateLabel(); | 377 instructionsLabel_.reset([constrained_window::CreateLabel() retain]); |
286 NSAttributedString* instructionsString = | 378 NSAttributedString* instructionsString = |
287 constrained_window::GetAttributedLabelString( | 379 constrained_window::GetAttributedLabelString( |
288 SysUTF16ToNSString(controller->GetInstructionsMessage()), | 380 SysUTF16ToNSString(controller->GetInstructionsMessage()), |
289 chrome_style::kTextFontStyle, NSNaturalTextAlignment, | 381 chrome_style::kTextFontStyle, NSNaturalTextAlignment, |
290 NSLineBreakByWordWrapping); | 382 NSLineBreakByWordWrapping); |
291 [instructions setAttributedStringValue:instructionsString]; | 383 [instructionsLabel_ setAttributedStringValue:instructionsString]; |
292 [mainView addSubview:instructions]; | 384 [mainView addSubview:instructionsLabel_]; |
293 | 385 |
294 // Expiration date. | 386 // Add expiration date. |
295 base::scoped_nsobject<NSView> expirationView; | 387 base::scoped_nsobject<NSView> expirationView; |
296 if (controller->ShouldRequestExpirationDate()) { | 388 if (controller->ShouldRequestExpirationDate()) { |
297 expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]); | 389 expirationView.reset([[NSView alloc] initWithFrame:NSZeroRect]); |
298 | 390 |
299 // Month. | 391 // Add expiration month. |
300 autofill::MonthComboboxModel monthModel; | 392 autofill::MonthComboboxModel monthModel; |
301 monthPopupDefaultIndex_ = monthModel.GetDefaultIndex(); | 393 monthPopupDefaultIndex_ = monthModel.GetDefaultIndex(); |
302 monthPopup_.reset( | 394 monthPopup_.reset( |
303 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:monthModel]); | 395 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:monthModel]); |
304 [monthPopup_ setTarget:self]; | 396 [monthPopup_ setTarget:self]; |
305 [monthPopup_ setAction:@selector(onExpirationDateChanged:)]; | 397 [monthPopup_ setAction:@selector(onExpirationDateChanged:)]; |
306 [expirationView addSubview:monthPopup_]; | 398 [expirationView addSubview:monthPopup_]; |
307 | 399 |
308 // Year. | 400 // Add expiration year. |
309 autofill::YearComboboxModel yearModel; | 401 autofill::YearComboboxModel yearModel; |
310 yearPopupDefaultIndex_ = yearModel.GetDefaultIndex(); | 402 yearPopupDefaultIndex_ = yearModel.GetDefaultIndex(); |
311 yearPopup_.reset( | 403 yearPopup_.reset( |
312 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:yearModel]); | 404 [CardUnmaskPromptViewCocoa buildDatePopupWithModel:yearModel]); |
313 [yearPopup_ setTarget:self]; | 405 [yearPopup_ setTarget:self]; |
314 [yearPopup_ setAction:@selector(onExpirationDateChanged:)]; | 406 [yearPopup_ setAction:@selector(onExpirationDateChanged:)]; |
315 [expirationView addSubview:yearPopup_]; | 407 [expirationView addSubview:yearPopup_]; |
316 | 408 |
317 // Layout month and year within expirationView. | 409 // Layout month and year within expirationView. |
318 [yearPopup_ | 410 [yearPopup_ |
319 setFrameOrigin:NSMakePoint(NSMaxX([monthPopup_ frame]) + kButtonGap, | 411 setFrameOrigin:NSMakePoint(NSMaxX([monthPopup_ frame]) + kButtonGap, |
320 0)]; | 412 0)]; |
321 NSRect expirationFrame = | 413 NSRect expirationFrame = |
322 NSUnionRect([monthPopup_ frame], [yearPopup_ frame]); | 414 NSUnionRect([monthPopup_ frame], [yearPopup_ frame]); |
323 expirationFrame.size.width += kButtonGap; | 415 expirationFrame.size.width += kButtonGap; |
324 [expirationView setFrame:expirationFrame]; | 416 [expirationView setFrame:expirationFrame]; |
325 [inputRow_ addSubview:expirationView]; | 417 [inputRowView_ addSubview:expirationView]; |
326 } | 418 } |
327 | 419 |
328 // CVC text input. | 420 // Add CVC text input. |
329 cvcInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | 421 cvcInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
330 [[cvcInput_ cell] | 422 [[cvcInput_ cell] |
331 setPlaceholderString:l10n_util::GetNSString( | 423 setPlaceholderString:l10n_util::GetNSString( |
332 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)]; | 424 IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)]; |
333 [[cvcInput_ cell] setScrollable:YES]; | 425 [[cvcInput_ cell] setScrollable:YES]; |
334 [cvcInput_ setDelegate:self]; | 426 [cvcInput_ setDelegate:self]; |
335 [cvcInput_ sizeToFit]; | 427 [cvcInput_ sizeToFit]; |
336 [cvcInput_ setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0, | 428 [cvcInput_ setFrame:NSMakeRect(NSMaxX([expirationView frame]), 0, |
337 kCvcInputWidth, NSHeight([cvcInput_ frame]))]; | 429 kCvcInputWidth, NSHeight([cvcInput_ frame]))]; |
338 [inputRow_ addSubview:cvcInput_]; | 430 [inputRowView_ addSubview:cvcInput_]; |
339 | 431 |
340 // CVC image. | 432 // Add CVC image. |
341 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 433 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
342 NSImage* cvcImage = | 434 NSImage* cvcImage = |
343 rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage(); | 435 rb.GetNativeImageNamed(controller->GetCvcImageRid()).ToNSImage(); |
344 base::scoped_nsobject<NSImageView> cvcImageView( | 436 base::scoped_nsobject<NSImageView> cvcImageView( |
345 [[NSImageView alloc] initWithFrame:NSZeroRect]); | 437 [[NSImageView alloc] initWithFrame:NSZeroRect]); |
346 [cvcImageView setImage:cvcImage]; | 438 [cvcImageView setImage:cvcImage]; |
347 [cvcImageView setFrameSize:[cvcImage size]]; | 439 [cvcImageView setFrameSize:[cvcImage size]]; |
348 [cvcImageView | 440 [cvcImageView |
349 setFrameOrigin:NSMakePoint(NSMaxX([cvcInput_ frame]) + kButtonGap, 0)]; | 441 setFrameOrigin:NSMakePoint(NSMaxX([cvcInput_ frame]) + kButtonGap, 0)]; |
350 [inputRow_ addSubview:cvcImageView]; | 442 [inputRowView_ addSubview:cvcImageView]; |
351 | 443 |
352 // Cancel button. | 444 // Add error message label. |
353 base::scoped_nsobject<NSButton> cancelButton( | 445 errorLabel_.reset([constrained_window::CreateLabel() retain]); |
| 446 [errorLabel_ |
| 447 setTextColor:gfx::SkColorToCalibratedNSColor(autofill::kWarningColor)]; |
| 448 [mainView addSubview:errorLabel_]; |
| 449 |
| 450 // Add cancel button. |
| 451 cancelButton_.reset( |
354 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 452 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
355 [cancelButton setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; | 453 [cancelButton_ setTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; |
356 [cancelButton setKeyEquivalent:kKeyEquivalentEscape]; | 454 [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape]; |
357 [cancelButton setTarget:self]; | 455 [cancelButton_ setTarget:self]; |
358 [cancelButton setAction:@selector(onCancel:)]; | 456 [cancelButton_ setAction:@selector(onCancel:)]; |
359 [cancelButton sizeToFit]; | 457 [cancelButton_ sizeToFit]; |
360 [mainView addSubview:cancelButton]; | 458 [mainView addSubview:cancelButton_]; |
361 | 459 |
362 // Verify button. | 460 // Add verify button. |
363 verifyButton_.reset( | 461 verifyButton_.reset( |
364 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); | 462 [[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect]); |
365 // TODO(bondd): use l10n string. | 463 // TODO(bondd): use l10n string. |
366 [verifyButton_ setTitle:@"Verify"]; | 464 [verifyButton_ setTitle:@"Verify"]; |
367 [verifyButton_ setKeyEquivalent:kKeyEquivalentReturn]; | 465 [verifyButton_ setKeyEquivalent:kKeyEquivalentReturn]; |
368 [verifyButton_ setTarget:self]; | 466 [verifyButton_ setTarget:self]; |
369 [verifyButton_ setAction:@selector(onVerify:)]; | 467 [verifyButton_ setAction:@selector(onVerify:)]; |
370 [verifyButton_ sizeToFit]; | 468 [verifyButton_ sizeToFit]; |
371 [self updateVerifyButtonEnabled]; | 469 [self updateVerifyButtonEnabled]; |
372 [mainView addSubview:verifyButton_]; | 470 [mainView addSubview:verifyButton_]; |
373 | 471 |
374 // Layout inputRow_. | 472 // Layout inputRowView_. |
375 [CardUnmaskPromptViewCocoa sizeToFitView:inputRow_]; | 473 [CardUnmaskPromptViewCocoa sizeToFitView:inputRowView_]; |
376 [CardUnmaskPromptViewCocoa verticallyCenterSubviewsInView:inputRow_]; | 474 [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 | 475 |
433 [self setView:mainView]; | 476 [self setView:mainView]; |
| 477 [self performLayoutAndDisplay:NO]; |
434 } | 478 } |
435 | 479 |
436 @end | 480 @end |
OLD | NEW |