OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #import "chrome/browser/ui/cocoa/autofill/autofill_section_container.h" | 5 #import "chrome/browser/ui/cocoa/autofill/autofill_section_container.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 return true; | 65 return true; |
66 } | 66 } |
67 | 67 |
68 return section == autofill::SECTION_CC_BILLING; | 68 return section == autofill::SECTION_CC_BILLING; |
69 } | 69 } |
70 | 70 |
71 } // namespace | 71 } // namespace |
72 | 72 |
73 @interface AutofillSectionContainer () | 73 @interface AutofillSectionContainer () |
74 | 74 |
75 // A text field has been edited or activated - inform the delegate that it's | 75 // An input field has been edited or activated - inform the delegate and |
76 // time to show a suggestion popup & possibly reset the validity of the input. | 76 // possibly reset the validity of the input (if it's a textfield). |
77 - (void)textfieldEditedOrActivated:(NSControl<AutofillInputField>*)field | 77 - (void)fieldEditedOrActivated:(NSControl<AutofillInputField>*)field |
78 edited:(BOOL)edited; | 78 edited:(BOOL)edited; |
79 | 79 |
80 // Convenience method to retrieve a field type via the control's tag. | 80 // Convenience method to retrieve a field type via the control's tag. |
81 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control; | 81 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control; |
82 | 82 |
83 // Find the DetailInput* associated with a field type. | 83 // Find the DetailInput* associated with a field type. |
84 - (const autofill::DetailInput*)detailInputForType: | 84 - (const autofill::DetailInput*)detailInputForType: |
85 (autofill::ServerFieldType)type; | 85 (autofill::ServerFieldType)type; |
86 | 86 |
87 // Takes an NSArray of controls and builds a FieldValueMap from them. | 87 // Takes an NSArray of controls and builds a FieldValueMap from them. |
88 // Translates between Cocoa code and delegate, essentially. | 88 // Translates between Cocoa code and delegate, essentially. |
89 // All controls must inherit from NSControl and conform to AutofillInputView. | 89 // All controls must inherit from NSControl and conform to AutofillInputView. |
90 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs | 90 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs |
91 fromControls:(NSArray*)controls; | 91 fromControls:(NSArray*)controls; |
92 | 92 |
93 // Updates input fields based on delegate status. If |shouldClobber| is YES, | 93 // Updates input fields based on delegate status. If |shouldClobber| is YES, |
94 // will clobber existing data and reset fields to the initial values. | 94 // will clobber existing data and reset fields to the initial values. |
95 - (void)updateAndClobber:(BOOL)shouldClobber; | 95 - (void)updateAndClobber:(BOOL)shouldClobber; |
96 | 96 |
97 // Return YES if this is a section that contains CC info. (And, more | 97 // Return YES if this is a section that contains CC info. (And, more |
98 // importantly, a potential CVV field) | 98 // importantly, a potential CVV field) |
99 - (BOOL)isCreditCardSection; | 99 - (BOOL)isCreditCardSection; |
100 | 100 |
101 // Create properly styled label for section. Autoreleased. | 101 // Create properly styled label for section. Autoreleased. |
102 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText; | 102 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText; |
103 | 103 |
104 // Create a button offering input suggestions. | 104 // Create a button offering input suggestions. |
105 - (MenuButton*)makeSuggestionButton; | 105 - (MenuButton*)makeSuggestionButton; |
106 | 106 |
107 // Create a view with all inputs requested by |delegate_|. Autoreleased. | 107 // Create a view with all inputs requested by |delegate_| and resets |input_|. |
108 - (LayoutView*)makeInputControls; | 108 - (void)makeInputControls; |
109 | 109 |
110 // Refresh all field icons based on |delegate_| status. | 110 // Refresh all field icons based on |delegate_| status. |
111 - (void)updateFieldIcons; | 111 - (void)updateFieldIcons; |
112 | 112 |
113 // Refresh the enabled/disabled state of all input fields. | 113 // Refresh the enabled/disabled state of all input fields. |
114 - (void)updateEditability; | 114 - (void)updateEditability; |
115 | 115 |
116 @end | 116 @end |
117 | 117 |
118 @implementation AutofillSectionContainer | 118 @implementation AutofillSectionContainer |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 if (![[self view] isHidden]) | 152 if (![[self view] isHidden]) |
153 [self validateFor:autofill::VALIDATE_EDIT]; | 153 [self validateFor:autofill::VALIDATE_EDIT]; |
154 | 154 |
155 // Always request re-layout on state change. | 155 // Always request re-layout on state change. |
156 id delegate = [[view_ window] windowController]; | 156 id delegate = [[view_ window] windowController]; |
157 if ([delegate respondsToSelector:@selector(requestRelayout)]) | 157 if ([delegate respondsToSelector:@selector(requestRelayout)]) |
158 [delegate performSelector:@selector(requestRelayout)]; | 158 [delegate performSelector:@selector(requestRelayout)]; |
159 } | 159 } |
160 | 160 |
161 - (void)loadView { | 161 - (void)loadView { |
162 // Keep a list of weak pointers to DetailInputs. | 162 [self makeInputControls]; |
163 const autofill::DetailInputs& inputs = | |
164 delegate_->RequestedFieldsForSection(section_); | |
165 | 163 |
166 // Reverse the order of all the inputs. | |
167 for (int i = inputs.size() - 1; i >= 0; --i) { | |
168 detailInputs_.push_back(&(inputs[i])); | |
169 } | |
170 | |
171 // Then right the reversal in each row. | |
172 std::vector<const autofill::DetailInput*>::iterator it; | |
173 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) { | |
174 std::vector<const autofill::DetailInput*>::iterator start = it; | |
175 while (it != detailInputs_.end() && | |
176 (*it)->length != autofill::DetailInput::LONG) { | |
177 ++it; | |
178 } | |
179 std::reverse(start, it); | |
180 } | |
181 | |
182 inputs_.reset([[self makeInputControls] retain]); | |
183 base::string16 labelText = delegate_->LabelForSection(section_); | 164 base::string16 labelText = delegate_->LabelForSection(section_); |
184 label_.reset( | 165 label_.reset( |
185 [[self makeDetailSectionLabel:base::SysUTF16ToNSString(labelText)] | 166 [[self makeDetailSectionLabel:base::SysUTF16ToNSString(labelText)] |
186 retain]); | 167 retain]); |
187 | 168 |
188 suggestButton_.reset([[self makeSuggestionButton] retain]); | 169 suggestButton_.reset([[self makeSuggestionButton] retain]); |
189 suggestContainer_.reset([[AutofillSuggestionContainer alloc] init]); | 170 suggestContainer_.reset([[AutofillSuggestionContainer alloc] init]); |
190 | 171 |
191 view_.reset([[AutofillSectionView alloc] initWithFrame:NSZeroRect]); | 172 view_.reset([[AutofillSectionView alloc] initWithFrame:NSZeroRect]); |
192 [self setView:view_]; | 173 [self setView:view_]; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 if (webEvent.type != content::NativeWebKeyboardEvent::RawKeyDown) | 262 if (webEvent.type != content::NativeWebKeyboardEvent::RawKeyDown) |
282 return kKeyEventNotHandled; | 263 return kKeyEventNotHandled; |
283 | 264 |
284 // Allow the delegate to intercept key messages. | 265 // Allow the delegate to intercept key messages. |
285 if (delegate_->HandleKeyPressEventInInput(webEvent)) | 266 if (delegate_->HandleKeyPressEventInInput(webEvent)) |
286 return kKeyEventHandled; | 267 return kKeyEventHandled; |
287 return kKeyEventNotHandled; | 268 return kKeyEventNotHandled; |
288 } | 269 } |
289 | 270 |
290 - (void)onMouseDown:(NSControl<AutofillInputField>*)field { | 271 - (void)onMouseDown:(NSControl<AutofillInputField>*)field { |
291 [self textfieldEditedOrActivated:field edited:NO]; | 272 [self fieldEditedOrActivated:field edited:NO]; |
292 [validationDelegate_ updateMessageForField:field]; | 273 [validationDelegate_ updateMessageForField:field]; |
293 } | 274 } |
294 | 275 |
295 - (void)fieldBecameFirstResponder:(NSControl<AutofillInputField>*)field { | 276 - (void)fieldBecameFirstResponder:(NSControl<AutofillInputField>*)field { |
296 [validationDelegate_ updateMessageForField:field]; | 277 [validationDelegate_ updateMessageForField:field]; |
297 } | 278 } |
298 | 279 |
299 - (void)didChange:(id)sender { | 280 - (void)didChange:(id)sender { |
300 [self textfieldEditedOrActivated:sender edited:YES]; | 281 [self fieldEditedOrActivated:sender edited:YES]; |
301 } | 282 } |
302 | 283 |
303 - (void)didEndEditing:(id)sender { | 284 - (void)didEndEditing:(id)sender { |
304 delegate_->FocusMoved(); | 285 delegate_->FocusMoved(); |
305 [validationDelegate_ hideErrorBubble]; | 286 [validationDelegate_ hideErrorBubble]; |
306 [self validateFor:autofill::VALIDATE_EDIT]; | 287 [self validateFor:autofill::VALIDATE_EDIT]; |
307 [self updateEditability]; | 288 [self updateEditability]; |
308 } | 289 } |
309 | 290 |
310 - (void)updateSuggestionState { | 291 - (void)updateSuggestionState { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 - (void)addInputsToArray:(NSMutableArray*)array { | 393 - (void)addInputsToArray:(NSMutableArray*)array { |
413 [array addObjectsFromArray:[inputs_ subviews]]; | 394 [array addObjectsFromArray:[inputs_ subviews]]; |
414 | 395 |
415 // Only credit card sections can have a suggestion input. | 396 // Only credit card sections can have a suggestion input. |
416 if ([self isCreditCardSection]) | 397 if ([self isCreditCardSection]) |
417 [array addObject:[suggestContainer_ inputField]]; | 398 [array addObject:[suggestContainer_ inputField]]; |
418 } | 399 } |
419 | 400 |
420 #pragma mark Internal API for AutofillSectionContainer. | 401 #pragma mark Internal API for AutofillSectionContainer. |
421 | 402 |
422 - (void)textfieldEditedOrActivated:(NSControl<AutofillInputField>*)field | 403 - (void)fieldEditedOrActivated:(NSControl<AutofillInputField>*)field |
423 edited:(BOOL)edited { | 404 edited:(BOOL)edited { |
424 AutofillTextField* textfield = | |
425 base::mac::ObjCCastStrict<AutofillTextField>(field); | |
426 | |
427 // This only applies to textfields. | |
428 if (!textfield) | |
429 return; | |
430 | |
431 autofill::ServerFieldType type = [self fieldTypeForControl:field]; | 405 autofill::ServerFieldType type = [self fieldTypeForControl:field]; |
432 base::string16 fieldValue = base::SysNSStringToUTF16([textfield fieldValue]); | 406 base::string16 fieldValue = base::SysNSStringToUTF16([field fieldValue]); |
433 | 407 |
434 // Get the frame rectangle for the designated field, in screen coordinates. | 408 // Get the frame rectangle for the designated field, in screen coordinates. |
435 NSRect textFrameInScreen = [field convertRect:[field bounds] toView:nil]; | 409 NSRect textFrameInScreen = [field convertRect:[field bounds] toView:nil]; |
436 textFrameInScreen.origin = | 410 textFrameInScreen.origin = |
437 [[field window] convertBaseToScreen:textFrameInScreen.origin]; | 411 [[field window] convertBaseToScreen:textFrameInScreen.origin]; |
438 | 412 |
439 // And adjust for gfx::Rect being flipped compared to OSX coordinates. | 413 // And adjust for gfx::Rect being flipped compared to OSX coordinates. |
440 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; | 414 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; |
441 textFrameInScreen.origin.y = | 415 textFrameInScreen.origin.y = |
442 NSMaxY([screen frame]) - NSMaxY(textFrameInScreen); | 416 NSMaxY([screen frame]) - NSMaxY(textFrameInScreen); |
443 gfx::Rect textFrameRect(NSRectToCGRect(textFrameInScreen)); | 417 gfx::Rect textFrameRect(NSRectToCGRect(textFrameInScreen)); |
444 | 418 |
445 delegate_->UserEditedOrActivatedInput(section_, | 419 delegate_->UserEditedOrActivatedInput(section_, |
446 type, | 420 type, |
447 [self view], | 421 [self view], |
448 textFrameRect, | 422 textFrameRect, |
449 fieldValue, | 423 fieldValue, |
450 edited); | 424 edited); |
451 | 425 |
452 // If the field is marked as invalid, check if the text is now valid. | 426 AutofillTextField* textfield = base::mac::ObjCCast<AutofillTextField>(field); |
453 // Many fields (i.e. CC#) are invalid for most of the duration of editing, | 427 if (!textfield) |
454 // so flagging them as invalid prematurely is not helpful. However, | 428 return; |
455 // correcting a minor mistake (i.e. a wrong CC digit) should immediately | 429 |
456 // result in validation - positive user feedback. | 430 // If the field is marked as invalid, check if the text is now valid. Many |
| 431 // fields (i.e. CC#) are invalid for most of the duration of editing, so |
| 432 // flagging them as invalid prematurely is not helpful. However, correcting a |
| 433 // minor mistake (i.e. a wrong CC digit) should immediately result in |
| 434 // validation - positive user feedback. |
457 if ([textfield invalid] && edited) { | 435 if ([textfield invalid] && edited) { |
458 base::string16 message = delegate_->InputValidityMessage(section_, | 436 base::string16 message = delegate_->InputValidityMessage(section_, |
459 type, | 437 type, |
460 fieldValue); | 438 fieldValue); |
461 [textfield setValidityMessage:base::SysUTF16ToNSString(message)]; | 439 [textfield setValidityMessage:base::SysUTF16ToNSString(message)]; |
462 [validationDelegate_ updateMessageForField:textfield]; | 440 [validationDelegate_ updateMessageForField:textfield]; |
463 | 441 |
464 // If the field transitioned from invalid to valid, re-validate the group, | 442 // If the field transitioned from invalid to valid, re-validate the group, |
465 // since inter-field checks become meaningful with valid fields. | 443 // since inter-field checks become meaningful with valid fields. |
466 if (![textfield invalid]) | 444 if (![textfield invalid]) |
467 [self validateFor:autofill::VALIDATE_EDIT]; | 445 [self validateFor:autofill::VALIDATE_EDIT]; |
468 } | 446 } |
469 | 447 |
470 // Update the icon if necessary. | 448 // Update the icon if necessary. |
471 if (delegate_->FieldControlsIcons(type)) | 449 if (delegate_->FieldControlsIcons(type)) |
472 [self updateFieldIcons]; | 450 [self updateFieldIcons]; |
473 [self updateEditability]; | 451 [self updateEditability]; |
474 } | 452 } |
475 | 453 |
476 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control { | 454 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control { |
477 DCHECK([control tag]); | 455 DCHECK([control tag]); |
478 return static_cast<autofill::ServerFieldType>([control tag]); | 456 return static_cast<autofill::ServerFieldType>([control tag]); |
479 } | 457 } |
480 | 458 |
481 - (const autofill::DetailInput*)detailInputForType: | 459 - (const autofill::DetailInput*)detailInputForType: |
482 (autofill::ServerFieldType)type { | 460 (autofill::ServerFieldType)type { |
483 for (size_t i = 0; i < detailInputs_.size(); ++i) { | 461 for (size_t i = 0; i < detailInputs_.size(); ++i) { |
484 if (detailInputs_[i]->type == type) | 462 if (detailInputs_[i]->type == type) |
485 return detailInputs_[i]; | 463 return detailInputs_[i]; |
486 } | 464 } |
487 // TODO(groby): Needs to be NOTREACHED. Can't, due to the fact that tests | 465 // TODO(groby): Needs to be NOTREACHED. Can't, due to the fact that tests |
488 // blindly call setFieldValue:forInput:, even for non-existing inputs. | 466 // blindly call setFieldValue:forType:, even for non-existing inputs. |
489 return NULL; | 467 return NULL; |
490 } | 468 } |
491 | 469 |
492 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs | 470 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs |
493 fromControls:(NSArray*)controls { | 471 fromControls:(NSArray*)controls { |
494 for (NSControl<AutofillInputField>* input in controls) { | 472 for (NSControl<AutofillInputField>* input in controls) { |
495 DCHECK([input isKindOfClass:[NSControl class]]); | 473 DCHECK([input isKindOfClass:[NSControl class]]); |
496 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); | 474 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); |
497 outputs->insert(std::make_pair( | 475 outputs->insert(std::make_pair( |
498 [self fieldTypeForControl:input], | 476 [self fieldTypeForControl:input], |
499 base::SysNSStringToUTF16([input fieldValue]))); | 477 base::SysNSStringToUTF16([input fieldValue]))); |
500 } | 478 } |
501 } | 479 } |
502 | 480 |
503 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText { | 481 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText { |
504 base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]); | 482 base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]); |
505 [label setFont: | 483 [label setFont: |
506 [[NSFontManager sharedFontManager] convertFont:[label font] | 484 [[NSFontManager sharedFontManager] convertFont:[label font] |
507 toHaveTrait:NSBoldFontMask]]; | 485 toHaveTrait:NSBoldFontMask]]; |
508 [label setStringValue:labelText]; | 486 [label setStringValue:labelText]; |
509 [label setEditable:NO]; | 487 [label setEditable:NO]; |
510 [label setBordered:NO]; | 488 [label setBordered:NO]; |
511 [label setDrawsBackground:NO]; | 489 [label setDrawsBackground:NO]; |
512 [label sizeToFit]; | 490 [label sizeToFit]; |
513 return label.autorelease(); | 491 return label.autorelease(); |
514 } | 492 } |
515 | 493 |
516 - (void)updateAndClobber:(BOOL)shouldClobber { | 494 - (void)updateAndClobber:(BOOL)shouldClobber { |
517 const autofill::DetailInputs& updatedInputs = | 495 if (shouldClobber) { |
518 delegate_->RequestedFieldsForSection(section_); | 496 [self makeInputControls]; |
| 497 } else { |
| 498 const autofill::DetailInputs& updatedInputs = |
| 499 delegate_->RequestedFieldsForSection(section_); |
519 | 500 |
520 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); | 501 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); |
521 iter != updatedInputs.end(); | 502 iter != updatedInputs.end(); |
522 ++iter) { | 503 ++iter) { |
523 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; | 504 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; |
524 DCHECK(field); | 505 DCHECK(field); |
| 506 if ([field isDefault]) |
| 507 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)]; |
| 508 } |
| 509 [self updateFieldIcons]; |
| 510 } |
525 | 511 |
526 if (shouldClobber || [field isDefault]) { | |
527 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)]; | |
528 } | |
529 if (shouldClobber) | |
530 [field setValidityMessage:@""]; | |
531 } | |
532 [self updateEditability]; | 512 [self updateEditability]; |
533 [self updateFieldIcons]; | |
534 [self modelChanged]; | 513 [self modelChanged]; |
535 } | 514 } |
536 | 515 |
537 - (BOOL)isCreditCardSection { | 516 - (BOOL)isCreditCardSection { |
538 return section_ == autofill::SECTION_CC || | 517 return section_ == autofill::SECTION_CC || |
539 section_ == autofill::SECTION_CC_BILLING; | 518 section_ == autofill::SECTION_CC_BILLING; |
540 } | 519 } |
541 | 520 |
542 - (MenuButton*)makeSuggestionButton { | 521 - (MenuButton*)makeSuggestionButton { |
543 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]); | 522 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]); |
(...skipping 20 matching lines...) Expand all Loading... |
564 [[button cell] setImage:image | 543 [[button cell] setImage:image |
565 forButtonState:image_button_cell::kDisabledState]; | 544 forButtonState:image_button_cell::kDisabledState]; |
566 | 545 |
567 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) | 546 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) |
568 [button setFrameSize:[image size]]; | 547 [button setFrameSize:[image size]]; |
569 return button.autorelease(); | 548 return button.autorelease(); |
570 } | 549 } |
571 | 550 |
572 // TODO(estade): we should be using Chrome-style constrained window padding | 551 // TODO(estade): we should be using Chrome-style constrained window padding |
573 // values. | 552 // values. |
574 - (LayoutView*)makeInputControls { | 553 - (void)makeInputControls { |
| 554 if (inputs_) { |
| 555 // When |inputs_| is replaced in response to a country change, there's a |
| 556 // didEndEditing dispatched that segfaults or DCHECKS() as it's operating on |
| 557 // stale input fields. Nil out the input delegate so this doesn't happen. |
| 558 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { |
| 559 [input setInputDelegate:nil]; |
| 560 } |
| 561 } |
| 562 |
| 563 detailInputs_.clear(); |
| 564 |
| 565 // Keep a list of weak pointers to DetailInputs. |
| 566 const autofill::DetailInputs& inputs = |
| 567 delegate_->RequestedFieldsForSection(section_); |
| 568 |
| 569 // Reverse the order of all the inputs. |
| 570 for (int i = inputs.size() - 1; i >= 0; --i) { |
| 571 detailInputs_.push_back(&(inputs[i])); |
| 572 } |
| 573 |
| 574 // Then right the reversal in each row. |
| 575 std::vector<const autofill::DetailInput*>::iterator it; |
| 576 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) { |
| 577 std::vector<const autofill::DetailInput*>::iterator start = it; |
| 578 while (it != detailInputs_.end() && |
| 579 (*it)->length != autofill::DetailInput::LONG) { |
| 580 ++it; |
| 581 } |
| 582 std::reverse(start, it); |
| 583 } |
| 584 |
575 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); | 585 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); |
576 [view setLayoutManager: | 586 [view setLayoutManager: |
577 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; | 587 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; |
578 SimpleGridLayout* layout = [view layoutManager]; | 588 SimpleGridLayout* layout = [view layoutManager]; |
579 | 589 |
580 int column_set_id = 0; | 590 int column_set_id = 0; |
581 for (size_t i = 0; i < detailInputs_.size(); ++i) { | 591 for (size_t i = 0; i < detailInputs_.size(); ++i) { |
582 const autofill::DetailInput& input = *detailInputs_[i]; | 592 const autofill::DetailInput& input = *detailInputs_[i]; |
583 | 593 |
584 if (input.length == autofill::DetailInput::LONG) | 594 if (input.length == autofill::DetailInput::LONG) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; | 628 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; |
619 control.reset(popup.release()); | 629 control.reset(popup.release()); |
620 } else { | 630 } else { |
621 base::scoped_nsobject<AutofillTextField> field( | 631 base::scoped_nsobject<AutofillTextField> field( |
622 [[AutofillTextField alloc] init]); | 632 [[AutofillTextField alloc] init]); |
623 [[field cell] setPlaceholderString: | 633 [[field cell] setPlaceholderString: |
624 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)]; | 634 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)]; |
625 NSString* tooltipText = | 635 NSString* tooltipText = |
626 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type)); | 636 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type)); |
627 if ([tooltipText length] > 0) { | 637 if ([tooltipText length] > 0) { |
628 DCHECK(!tooltipController_); | 638 if (!tooltipController_) { |
629 DCHECK(!tooltipField_); | 639 tooltipController_.reset( |
630 tooltipController_.reset( | 640 [[AutofillTooltipController alloc] |
631 [[AutofillTooltipController alloc] | 641 initWithArrowLocation:info_bubble::kTopRight]); |
632 initWithArrowLocation:info_bubble::kTopRight]); | 642 } |
633 tooltipField_ = field.get(); | 643 tooltipField_ = field.get(); |
634 NSImage* icon = | 644 NSImage* icon = |
635 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 645 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
636 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage(); | 646 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage(); |
637 [tooltipController_ setImage:icon]; | 647 [tooltipController_ setImage:icon]; |
638 [tooltipController_ setMessage:tooltipText]; | 648 [tooltipController_ setMessage:tooltipText]; |
639 [[field cell] setDecorationSize:[icon size]]; | 649 [[field cell] setDecorationSize:[icon size]]; |
640 } | 650 } |
641 [field setDefaultValue:@""]; | 651 [field setDefaultValue:@""]; |
642 control.reset(field.release()); | 652 control.reset(field.release()); |
643 } | 653 } |
644 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; | 654 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; |
645 [control sizeToFit]; | 655 [control sizeToFit]; |
646 [control setTag:input.type]; | 656 [control setTag:input.type]; |
647 [control setInputDelegate:self]; | 657 [control setInputDelegate:self]; |
648 // Hide away fields that cannot be edited. | 658 // Hide away fields that cannot be edited. |
649 if (kColumnSetId == -1) { | 659 if (kColumnSetId == -1) { |
650 [control setFrame:NSZeroRect]; | 660 [control setFrame:NSZeroRect]; |
651 [control setHidden:YES]; | 661 [control setHidden:YES]; |
652 } | 662 } |
653 layout->AddView(control); | 663 layout->AddView(control); |
654 | 664 |
655 if (input.length == autofill::DetailInput::LONG || | 665 if (input.length == autofill::DetailInput::LONG || |
656 input.length == autofill::DetailInput::SHORT_EOL) { | 666 input.length == autofill::DetailInput::SHORT_EOL) { |
657 ++column_set_id; | 667 ++column_set_id; |
658 } | 668 } |
659 } | 669 } |
660 | 670 |
| 671 if (inputs_) { |
| 672 [[self view] replaceSubview:inputs_ with:view]; |
| 673 id delegate = [[view_ window] windowController]; |
| 674 if ([delegate respondsToSelector:@selector(requestRelayout)]) |
| 675 [delegate performSelector:@selector(requestRelayout)]; |
| 676 } |
| 677 |
| 678 inputs_ = view; |
661 [self updateFieldIcons]; | 679 [self updateFieldIcons]; |
662 return view.autorelease(); | |
663 } | 680 } |
664 | 681 |
665 - (void)updateFieldIcons { | 682 - (void)updateFieldIcons { |
666 autofill::FieldValueMap fieldValues; | 683 autofill::FieldValueMap fieldValues; |
667 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { | 684 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { |
668 DCHECK([input isKindOfClass:[NSControl class]]); | 685 DCHECK([input isKindOfClass:[NSControl class]]); |
669 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); | 686 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); |
670 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; | 687 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; |
671 NSString* value = [input fieldValue]; | 688 NSString* value = [input fieldValue]; |
672 fieldValues[fieldType] = base::SysNSStringToUTF16(value); | 689 fieldValues[fieldType] = base::SysNSStringToUTF16(value); |
673 } | 690 } |
674 | 691 |
675 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); | 692 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); |
676 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); | 693 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); |
677 iter!= fieldIcons.end(); ++iter) { | 694 iter!= fieldIcons.end(); ++iter) { |
678 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( | 695 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( |
679 [inputs_ viewWithTag:iter->first]); | 696 [inputs_ viewWithTag:iter->first]); |
680 [[textfield cell] setIcon:iter->second.ToNSImage()]; | 697 [[textfield cell] setIcon:iter->second.ToNSImage()]; |
681 } | 698 } |
682 } | 699 } |
683 | 700 |
684 - (void)updateEditability { | 701 - (void)updateEditability { |
685 | |
686 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); | 702 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); |
687 [self addInputsToArray:controls]; | 703 [self addInputsToArray:controls]; |
688 for (NSControl<AutofillInputField>* control in controls.get()) { | 704 for (NSControl<AutofillInputField>* control in controls.get()) { |
689 autofill::ServerFieldType type = [self fieldTypeForControl:control]; | 705 autofill::ServerFieldType type = [self fieldTypeForControl:control]; |
690 const autofill::DetailInput* input = [self detailInputForType:type]; | 706 const autofill::DetailInput* input = [self detailInputForType:type]; |
691 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; | 707 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; |
692 } | 708 } |
693 } | 709 } |
694 | 710 |
695 @end | 711 @end |
(...skipping 13 matching lines...) Expand all Loading... |
709 } | 725 } |
710 | 726 |
711 - (void)setSuggestionFieldValue:(NSString*)text { | 727 - (void)setSuggestionFieldValue:(NSString*)text { |
712 [[suggestContainer_ inputField] setFieldValue:text]; | 728 [[suggestContainer_ inputField] setFieldValue:text]; |
713 } | 729 } |
714 | 730 |
715 - (void)activateFieldForType:(autofill::ServerFieldType)type { | 731 - (void)activateFieldForType:(autofill::ServerFieldType)type { |
716 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; | 732 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; |
717 if (field) { | 733 if (field) { |
718 [[field window] makeFirstResponder:field]; | 734 [[field window] makeFirstResponder:field]; |
719 [self textfieldEditedOrActivated:field edited:NO]; | 735 [self fieldEditedOrActivated:field edited:NO]; |
720 } | 736 } |
721 } | 737 } |
722 | 738 |
723 @end | 739 @end |
OLD | NEW |