Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: chrome/browser/ui/cocoa/autofill/autofill_section_container.mm

Issue 124533003: Add country combobox to change country and rebuild address inputs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 textfieldEditedOrActivated: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];
287
288 AutofillPopUpButton* popup = base::mac::ObjCCast<AutofillPopUpButton>(sender);
289 if (popup) {
groby-ooo-7-16 2014/01/10 01:56:38 If you must get a separate popup notification, I'd
Dan Beam 2014/01/11 04:16:58 see updated code
290 // Add one to account for the spacer at the top of the list.
291 int index = [popup indexOfSelectedItem] + 1;
292 delegate_->ComboboxItemSelected([self fieldTypeForControl:popup], index);
293 }
294
306 [self validateFor:autofill::VALIDATE_EDIT]; 295 [self validateFor:autofill::VALIDATE_EDIT];
307 [self updateEditability]; 296 [self updateEditability];
308 } 297 }
309 298
310 - (void)updateSuggestionState { 299 - (void)updateSuggestionState {
311 const autofill::SuggestionState& suggestionState = 300 const autofill::SuggestionState& suggestionState =
312 delegate_->SuggestionStateForSection(section_); 301 delegate_->SuggestionStateForSection(section_);
313 showSuggestions_ = suggestionState.visible; 302 showSuggestions_ = suggestionState.visible;
314 303
315 if (!suggestionState.extra_text.empty()) { 304 if (!suggestionState.extra_text.empty()) {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 toHaveTrait:NSBoldFontMask]]; 496 toHaveTrait:NSBoldFontMask]];
508 [label setStringValue:labelText]; 497 [label setStringValue:labelText];
509 [label setEditable:NO]; 498 [label setEditable:NO];
510 [label setBordered:NO]; 499 [label setBordered:NO];
511 [label setDrawsBackground:NO]; 500 [label setDrawsBackground:NO];
512 [label sizeToFit]; 501 [label sizeToFit];
513 return label.autorelease(); 502 return label.autorelease();
514 } 503 }
515 504
516 - (void)updateAndClobber:(BOOL)shouldClobber { 505 - (void)updateAndClobber:(BOOL)shouldClobber {
517 const autofill::DetailInputs& updatedInputs = 506 if (shouldClobber) {
groby-ooo-7-16 2014/01/10 01:56:38 I'd prefer to not rebuild the entire layout whenev
Dan Beam 2014/01/11 04:16:58 we talked about this and will wait until it's noti
518 delegate_->RequestedFieldsForSection(section_); 507 [self makeInputControls];
groby-ooo-7-16 2014/01/10 01:56:38 Also, you presumably want to request a relayout he
Dan Beam 2014/01/11 04:16:58 Done.
508 } else {
509 const autofill::DetailInputs& updatedInputs =
510 delegate_->RequestedFieldsForSection(section_);
519 511
520 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); 512 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin();
521 iter != updatedInputs.end(); 513 iter != updatedInputs.end();
522 ++iter) { 514 ++iter) {
523 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; 515 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type];
524 DCHECK(field); 516 DCHECK(field);
525 517
526 if (shouldClobber || [field isDefault]) { 518 if (shouldClobber || [field isDefault]) {
527 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)]; 519 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)];
520 }
521 if (shouldClobber)
groby-ooo-7-16 2014/01/10 01:56:38 How could shouldClobber ever be true here? You're
Dan Beam 2014/01/11 04:16:58 copy pasta, removed
522 [field setValidityMessage:@""];
528 } 523 }
529 if (shouldClobber) 524 [self updateFieldIcons];
530 [field setValidityMessage:@""];
531 } 525 }
526
532 [self updateEditability]; 527 [self updateEditability];
533 [self updateFieldIcons];
534 [self modelChanged]; 528 [self modelChanged];
535 } 529 }
536 530
537 - (BOOL)isCreditCardSection { 531 - (BOOL)isCreditCardSection {
538 return section_ == autofill::SECTION_CC || 532 return section_ == autofill::SECTION_CC ||
539 section_ == autofill::SECTION_CC_BILLING; 533 section_ == autofill::SECTION_CC_BILLING;
540 } 534 }
541 535
542 - (MenuButton*)makeSuggestionButton { 536 - (MenuButton*)makeSuggestionButton {
543 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]); 537 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]);
(...skipping 20 matching lines...) Expand all
564 [[button cell] setImage:image 558 [[button cell] setImage:image
565 forButtonState:image_button_cell::kDisabledState]; 559 forButtonState:image_button_cell::kDisabledState];
566 560
567 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) 561 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501)
568 [button setFrameSize:[image size]]; 562 [button setFrameSize:[image size]];
569 return button.autorelease(); 563 return button.autorelease();
570 } 564 }
571 565
572 // TODO(estade): we should be using Chrome-style constrained window padding 566 // TODO(estade): we should be using Chrome-style constrained window padding
573 // values. 567 // values.
574 - (LayoutView*)makeInputControls { 568 - (void)makeInputControls {
569 detailInputs_.clear();
570
571 // Keep a list of weak pointers to DetailInputs.
572 const autofill::DetailInputs& inputs =
573 delegate_->RequestedFieldsForSection(section_);
574
575 // Reverse the order of all the inputs.
576 for (int i = inputs.size() - 1; i >= 0; --i) {
577 detailInputs_.push_back(&(inputs[i]));
578 }
579
580 // Then right the reversal in each row.
581 std::vector<const autofill::DetailInput*>::iterator it;
582 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) {
583 std::vector<const autofill::DetailInput*>::iterator start = it;
584 while (it != detailInputs_.end() &&
585 (*it)->length != autofill::DetailInput::LONG) {
586 ++it;
587 }
588 std::reverse(start, it);
589 }
590
575 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); 591 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]);
576 [view setLayoutManager: 592 [view setLayoutManager:
577 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; 593 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))];
578 SimpleGridLayout* layout = [view layoutManager]; 594 SimpleGridLayout* layout = [view layoutManager];
579 595
580 int column_set_id = 0; 596 int column_set_id = 0;
581 for (size_t i = 0; i < detailInputs_.size(); ++i) { 597 for (size_t i = 0; i < detailInputs_.size(); ++i) {
582 const autofill::DetailInput& input = *detailInputs_[i]; 598 const autofill::DetailInput& input = *detailInputs_[i];
583 599
584 if (input.length == autofill::DetailInput::LONG) 600 if (input.length == autofill::DetailInput::LONG)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; 634 inputModel->GetItemAt(inputModel->GetDefaultIndex()))];
619 control.reset(popup.release()); 635 control.reset(popup.release());
620 } else { 636 } else {
621 base::scoped_nsobject<AutofillTextField> field( 637 base::scoped_nsobject<AutofillTextField> field(
622 [[AutofillTextField alloc] init]); 638 [[AutofillTextField alloc] init]);
623 [[field cell] setPlaceholderString: 639 [[field cell] setPlaceholderString:
624 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)]; 640 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)];
625 NSString* tooltipText = 641 NSString* tooltipText =
626 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type)); 642 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type));
627 if ([tooltipText length] > 0) { 643 if ([tooltipText length] > 0) {
628 DCHECK(!tooltipController_); 644 if (!tooltipController_) {
629 DCHECK(!tooltipField_); 645 tooltipController_.reset(
630 tooltipController_.reset( 646 [[AutofillTooltipController alloc]
631 [[AutofillTooltipController alloc] 647 initWithArrowLocation:info_bubble::kTopRight]);
632 initWithArrowLocation:info_bubble::kTopRight]); 648 }
633 tooltipField_ = field.get(); 649 tooltipField_ = field.get();
634 NSImage* icon = 650 NSImage* icon =
635 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( 651 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
636 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage(); 652 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage();
637 [tooltipController_ setImage:icon]; 653 [tooltipController_ setImage:icon];
638 [tooltipController_ setMessage:tooltipText]; 654 [tooltipController_ setMessage:tooltipText];
639 [[field cell] setDecorationSize:[icon size]]; 655 [[field cell] setDecorationSize:[icon size]];
640 } 656 }
641 [field setDefaultValue:@""]; 657 [field setDefaultValue:@""];
642 control.reset(field.release()); 658 control.reset(field.release());
643 } 659 }
644 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; 660 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)];
645 [control sizeToFit]; 661 [control sizeToFit];
646 [control setTag:input.type]; 662 [control setTag:input.type];
647 [control setInputDelegate:self]; 663 [control setInputDelegate:self];
648 // Hide away fields that cannot be edited. 664 // Hide away fields that cannot be edited.
649 if (kColumnSetId == -1) { 665 if (kColumnSetId == -1) {
650 [control setFrame:NSZeroRect]; 666 [control setFrame:NSZeroRect];
651 [control setHidden:YES]; 667 [control setHidden:YES];
652 } 668 }
653 layout->AddView(control); 669 layout->AddView(control);
654 670
655 if (input.length == autofill::DetailInput::LONG || 671 if (input.length == autofill::DetailInput::LONG ||
656 input.length == autofill::DetailInput::SHORT_EOL) { 672 input.length == autofill::DetailInput::SHORT_EOL) {
657 ++column_set_id; 673 ++column_set_id;
658 } 674 }
659 } 675 }
660 676
661 [self updateFieldIcons]; 677 [self updateFieldIcons];
662 return view.autorelease(); 678
679 if (inputs_)
680 [[self view] replaceSubview:inputs_ with:view];
681
682 inputs_ = view;
663 } 683 }
664 684
665 - (void)updateFieldIcons { 685 - (void)updateFieldIcons {
666 autofill::FieldValueMap fieldValues; 686 autofill::FieldValueMap fieldValues;
667 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { 687 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) {
668 DCHECK([input isKindOfClass:[NSControl class]]); 688 DCHECK([input isKindOfClass:[NSControl class]]);
669 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); 689 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]);
670 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; 690 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input];
671 NSString* value = [input fieldValue]; 691 NSString* value = [input fieldValue];
672 fieldValues[fieldType] = base::SysNSStringToUTF16(value); 692 fieldValues[fieldType] = base::SysNSStringToUTF16(value);
673 } 693 }
674 694
675 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); 695 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues);
676 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); 696 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin();
677 iter!= fieldIcons.end(); ++iter) { 697 iter!= fieldIcons.end(); ++iter) {
678 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( 698 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>(
679 [inputs_ viewWithTag:iter->first]); 699 [inputs_ viewWithTag:iter->first]);
680 [[textfield cell] setIcon:iter->second.ToNSImage()]; 700 [[textfield cell] setIcon:iter->second.ToNSImage()];
681 } 701 }
682 } 702 }
683 703
684 - (void)updateEditability { 704 - (void)updateEditability {
685
686 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); 705 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]);
687 [self addInputsToArray:controls]; 706 [self addInputsToArray:controls];
688 for (NSControl<AutofillInputField>* control in controls.get()) { 707 for (NSControl<AutofillInputField>* control in controls.get()) {
689 autofill::ServerFieldType type = [self fieldTypeForControl:control]; 708 autofill::ServerFieldType type = [self fieldTypeForControl:control];
690 const autofill::DetailInput* input = [self detailInputForType:type]; 709 const autofill::DetailInput* input = [self detailInputForType:type];
691 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; 710 [control setEnabled:delegate_->InputIsEditable(*input, section_)];
692 } 711 }
693 } 712 }
694 713
695 @end 714 @end
696 715
697 716
698 @implementation AutofillSectionContainer (ForTesting) 717 @implementation AutofillSectionContainer (ForTesting)
699 718
700 - (NSControl*)getField:(autofill::ServerFieldType)type { 719 - (NSControl*)getField:(autofill::ServerFieldType)type {
701 return [inputs_ viewWithTag:type]; 720 return [inputs_ viewWithTag:type];
702 } 721 }
703 722
704 - (void)setFieldValue:(NSString*)text 723 - (void)setFieldValue:(NSString*)text
705 forType:(autofill::ServerFieldType)type { 724 forType:(autofill::ServerFieldType)type {
706 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; 725 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type];
707 if (field) 726 if (field) {
727 AutofillPopUpButton* popup =
groby-ooo-7-16 2014/01/10 01:56:38 Please do that in AutofillPopUp, not here.
Dan Beam 2014/01/11 04:16:58 Done.
728 base::mac::ObjCCast<AutofillPopUpButton>(field);
729 int index = popup ? [popup indexOfSelectedItem] : -1;
708 [field setFieldValue:text]; 730 [field setFieldValue:text];
731 if (popup && [popup indexOfSelectedItem] != index)
732 [self didEndEditing:field];
733 }
709 } 734 }
710 735
711 - (void)setSuggestionFieldValue:(NSString*)text { 736 - (void)setSuggestionFieldValue:(NSString*)text {
712 [[suggestContainer_ inputField] setFieldValue:text]; 737 [[suggestContainer_ inputField] setFieldValue:text];
713 } 738 }
714 739
715 - (void)activateFieldForType:(autofill::ServerFieldType)type { 740 - (void)activateFieldForType:(autofill::ServerFieldType)type {
716 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; 741 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type];
717 if (field) { 742 if (field) {
718 [[field window] makeFirstResponder:field]; 743 [[field window] makeFirstResponder:field];
719 [self textfieldEditedOrActivated:field edited:NO]; 744 [self textfieldEditedOrActivated:field edited:NO];
720 } 745 }
721 } 746 }
722 747
723 @end 748 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698