Chromium Code Reviews| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 // Return YES if this is a section that contains CC info. (And, more | 96 // Return YES if this is a section that contains CC info. (And, more |
| 97 // importantly, a potential CVV field) | 97 // importantly, a potential CVV field) |
| 98 - (BOOL)isCreditCardSection; | 98 - (BOOL)isCreditCardSection; |
| 99 | 99 |
| 100 // Create properly styled label for section. Autoreleased. | 100 // Create properly styled label for section. Autoreleased. |
| 101 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText; | 101 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText; |
| 102 | 102 |
| 103 // Create a button offering input suggestions. | 103 // Create a button offering input suggestions. |
| 104 - (MenuButton*)makeSuggestionButton; | 104 - (MenuButton*)makeSuggestionButton; |
| 105 | 105 |
| 106 // Create a view with all inputs requested by |delegate_|. Autoreleased. | 106 // Create a view with all inputs requested by |delegate_| and resets |input_|. |
|
groby-ooo-7-16
2013/12/05 02:56:10
Should probably mention that it replaces the old i
| |
| 107 - (LayoutView*)makeInputControls; | 107 - (void)makeInputControls; |
| 108 | 108 |
| 109 // Refresh all field icons based on |delegate_| status. | 109 // Refresh all field icons based on |delegate_| status. |
| 110 - (void)updateFieldIcons; | 110 - (void)updateFieldIcons; |
| 111 | 111 |
| 112 // Refresh the enabled/disabled state of all input fields. | 112 // Refresh the enabled/disabled state of all input fields. |
| 113 - (void)updateEditability; | 113 - (void)updateEditability; |
| 114 | 114 |
| 115 @end | 115 @end |
| 116 | 116 |
| 117 @implementation AutofillSectionContainer | 117 @implementation AutofillSectionContainer |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 if (![[self view] isHidden]) | 151 if (![[self view] isHidden]) |
| 152 [self validateFor:autofill::VALIDATE_EDIT]; | 152 [self validateFor:autofill::VALIDATE_EDIT]; |
| 153 | 153 |
| 154 // Always request re-layout on state change. | 154 // Always request re-layout on state change. |
| 155 id delegate = [[view_ window] windowController]; | 155 id delegate = [[view_ window] windowController]; |
| 156 if ([delegate respondsToSelector:@selector(requestRelayout)]) | 156 if ([delegate respondsToSelector:@selector(requestRelayout)]) |
| 157 [delegate performSelector:@selector(requestRelayout)]; | 157 [delegate performSelector:@selector(requestRelayout)]; |
| 158 } | 158 } |
| 159 | 159 |
| 160 - (void)loadView { | 160 - (void)loadView { |
| 161 // Keep a list of weak pointers to DetailInputs. | 161 [self makeInputControls]; |
| 162 const autofill::DetailInputs& inputs = | |
| 163 delegate_->RequestedFieldsForSection(section_); | |
| 164 | |
| 165 // Reverse the order of all the inputs. | |
| 166 for (int i = inputs.size() - 1; i >= 0; --i) { | |
| 167 detailInputs_.push_back(&(inputs[i])); | |
| 168 } | |
| 169 | |
| 170 // Then right the reversal in each row. | |
| 171 std::vector<const autofill::DetailInput*>::iterator it; | |
| 172 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) { | |
| 173 std::vector<const autofill::DetailInput*>::iterator start = it; | |
| 174 while (it != detailInputs_.end() && | |
| 175 (*it)->length != autofill::DetailInput::LONG) { | |
| 176 ++it; | |
| 177 } | |
| 178 std::reverse(start, it); | |
| 179 } | |
| 180 | |
| 181 inputs_.reset([[self makeInputControls] retain]); | |
| 182 string16 labelText = delegate_->LabelForSection(section_); | 162 string16 labelText = delegate_->LabelForSection(section_); |
| 183 label_.reset( | 163 label_.reset( |
| 184 [[self makeDetailSectionLabel:base::SysUTF16ToNSString(labelText)] | 164 [[self makeDetailSectionLabel:base::SysUTF16ToNSString(labelText)] |
| 185 retain]); | 165 retain]); |
| 186 | 166 |
| 187 suggestButton_.reset([[self makeSuggestionButton] retain]); | 167 suggestButton_.reset([[self makeSuggestionButton] retain]); |
| 188 suggestContainer_.reset([[AutofillSuggestionContainer alloc] init]); | 168 suggestContainer_.reset([[AutofillSuggestionContainer alloc] init]); |
| 189 | 169 |
| 190 view_.reset([[AutofillSectionView alloc] initWithFrame:NSZeroRect]); | 170 view_.reset([[AutofillSectionView alloc] initWithFrame:NSZeroRect]); |
| 191 [self setView:view_]; | 171 [self setView:view_]; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 [validationDelegate_ updateMessageForField:field]; | 262 [validationDelegate_ updateMessageForField:field]; |
| 283 } | 263 } |
| 284 | 264 |
| 285 - (void)didChange:(id)sender { | 265 - (void)didChange:(id)sender { |
| 286 [self textfieldEditedOrActivated:sender edited:YES]; | 266 [self textfieldEditedOrActivated:sender edited:YES]; |
| 287 } | 267 } |
| 288 | 268 |
| 289 - (void)didEndEditing:(id)sender { | 269 - (void)didEndEditing:(id)sender { |
| 290 delegate_->FocusMoved(); | 270 delegate_->FocusMoved(); |
| 291 [validationDelegate_ hideErrorBubble]; | 271 [validationDelegate_ hideErrorBubble]; |
| 272 | |
| 273 AutofillPopUpButton* popup = base::mac::ObjCCast<AutofillPopUpButton>(sender); | |
| 274 if (popup) { | |
| 275 // Add one to account for the spacer at the top of the list. | |
| 276 int index = [popup indexOfSelectedItem] + 1; | |
| 277 delegate_->ComboboxItemSelected([self fieldTypeForControl:popup], index); | |
| 278 } | |
| 279 | |
| 292 [self validateFor:autofill::VALIDATE_EDIT]; | 280 [self validateFor:autofill::VALIDATE_EDIT]; |
| 293 [self updateEditability]; | 281 [self updateEditability]; |
| 294 } | 282 } |
| 295 | 283 |
| 296 - (void)updateSuggestionState { | 284 - (void)updateSuggestionState { |
| 297 const autofill::SuggestionState& suggestionState = | 285 const autofill::SuggestionState& suggestionState = |
| 298 delegate_->SuggestionStateForSection(section_); | 286 delegate_->SuggestionStateForSection(section_); |
| 299 // TODO(estade): use |vertically_compact_text| when it fits. | 287 // TODO(estade): use |vertically_compact_text| when it fits. |
| 300 const base::string16& text = suggestionState.horizontally_compact_text; | 288 const base::string16& text = suggestionState.horizontally_compact_text; |
| 301 showSuggestions_ = suggestionState.visible; | 289 showSuggestions_ = suggestionState.visible; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 toHaveTrait:NSBoldFontMask]]; | 471 toHaveTrait:NSBoldFontMask]]; |
| 484 [label setStringValue:labelText]; | 472 [label setStringValue:labelText]; |
| 485 [label setEditable:NO]; | 473 [label setEditable:NO]; |
| 486 [label setBordered:NO]; | 474 [label setBordered:NO]; |
| 487 [label setDrawsBackground:NO]; | 475 [label setDrawsBackground:NO]; |
| 488 [label sizeToFit]; | 476 [label sizeToFit]; |
| 489 return label.autorelease(); | 477 return label.autorelease(); |
| 490 } | 478 } |
| 491 | 479 |
| 492 - (void)updateAndClobber:(BOOL)shouldClobber { | 480 - (void)updateAndClobber:(BOOL)shouldClobber { |
| 481 if (shouldClobber) | |
| 482 [self makeInputControls]; | |
| 483 | |
| 493 const autofill::DetailInputs& updatedInputs = | 484 const autofill::DetailInputs& updatedInputs = |
| 494 delegate_->RequestedFieldsForSection(section_); | 485 delegate_->RequestedFieldsForSection(section_); |
| 495 | 486 |
| 496 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); | 487 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); |
| 497 iter != updatedInputs.end(); | 488 iter != updatedInputs.end(); |
| 498 ++iter) { | 489 ++iter) { |
| 499 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; | 490 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; |
| 500 DCHECK(field); | 491 DCHECK(field); |
| 501 | 492 |
| 502 if (shouldClobber || [field isDefault]) { | 493 if (shouldClobber || [field isDefault]) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 [[button cell] setImage:image | 531 [[button cell] setImage:image |
| 541 forButtonState:image_button_cell::kDisabledState]; | 532 forButtonState:image_button_cell::kDisabledState]; |
| 542 | 533 |
| 543 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) | 534 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) |
| 544 [button setFrameSize:[image size]]; | 535 [button setFrameSize:[image size]]; |
| 545 return button.autorelease(); | 536 return button.autorelease(); |
| 546 } | 537 } |
| 547 | 538 |
| 548 // TODO(estade): we should be using Chrome-style constrained window padding | 539 // TODO(estade): we should be using Chrome-style constrained window padding |
| 549 // values. | 540 // values. |
| 550 - (LayoutView*)makeInputControls { | 541 - (void)makeInputControls { |
| 542 detailInputs_.clear(); | |
| 543 | |
| 544 // Keep a list of weak pointers to DetailInputs. | |
| 545 const autofill::DetailInputs& inputs = | |
| 546 delegate_->RequestedFieldsForSection(section_); | |
| 547 | |
| 548 // Reverse the order of all the inputs. | |
| 549 for (int i = inputs.size() - 1; i >= 0; --i) { | |
| 550 detailInputs_.push_back(&(inputs[i])); | |
| 551 } | |
| 552 | |
| 553 // Then right the reversal in each row. | |
| 554 std::vector<const autofill::DetailInput*>::iterator it; | |
| 555 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) { | |
| 556 std::vector<const autofill::DetailInput*>::iterator start = it; | |
| 557 while (it != detailInputs_.end() && | |
| 558 (*it)->length != autofill::DetailInput::LONG) { | |
| 559 ++it; | |
| 560 } | |
| 561 std::reverse(start, it); | |
| 562 } | |
| 563 | |
| 551 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); | 564 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); |
| 552 [view setLayoutManager: | 565 [view setLayoutManager: |
| 553 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; | 566 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; |
| 554 SimpleGridLayout* layout = [view layoutManager]; | 567 SimpleGridLayout* layout = [view layoutManager]; |
| 555 | 568 |
| 556 int column_set_id = 0; | 569 int column_set_id = 0; |
| 557 for (size_t i = 0; i < detailInputs_.size(); ++i) { | 570 for (size_t i = 0; i < detailInputs_.size(); ++i) { |
| 558 const autofill::DetailInput& input = *detailInputs_[i]; | 571 const autofill::DetailInput& input = *detailInputs_[i]; |
| 559 | 572 |
| 560 if (input.length == autofill::DetailInput::LONG) | 573 if (input.length == autofill::DetailInput::LONG) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 590 [popup addItemWithTitle: | 603 [popup addItemWithTitle: |
| 591 base::SysUTF16ToNSString(inputModel->GetItemAt(i))]; | 604 base::SysUTF16ToNSString(inputModel->GetItemAt(i))]; |
| 592 } | 605 } |
| 593 [popup setDefaultValue:base::SysUTF16ToNSString( | 606 [popup setDefaultValue:base::SysUTF16ToNSString( |
| 594 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; | 607 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; |
| 595 control.reset(popup.release()); | 608 control.reset(popup.release()); |
| 596 } else { | 609 } else { |
| 597 base::scoped_nsobject<AutofillTextField> field( | 610 base::scoped_nsobject<AutofillTextField> field( |
| 598 [[AutofillTextField alloc] init]); | 611 [[AutofillTextField alloc] init]); |
| 599 [[field cell] setPlaceholderString: | 612 [[field cell] setPlaceholderString: |
| 600 l10n_util::GetNSStringWithFixup(input.placeholder_text_rid)]; | 613 base::SysUTF16ToNSString(input.placeholder_text)]; |
| 601 [field setDefaultValue:@""]; | 614 [field setDefaultValue:@""]; |
| 602 control.reset(field.release()); | 615 control.reset(field.release()); |
| 603 } | 616 } |
| 604 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; | 617 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; |
| 605 [control sizeToFit]; | 618 [control sizeToFit]; |
| 606 [control setTag:input.type]; | 619 [control setTag:input.type]; |
| 607 [control setInputDelegate:self]; | 620 [control setInputDelegate:self]; |
| 608 // Hide away fields that cannot be edited. | 621 // Hide away fields that cannot be edited. |
| 609 if (kColumnSetId == -1) { | 622 if (kColumnSetId == -1) { |
| 610 [control setFrame:NSZeroRect]; | 623 [control setFrame:NSZeroRect]; |
| 611 [control setHidden:YES]; | 624 [control setHidden:YES]; |
| 612 } | 625 } |
| 613 layout->AddView(control); | 626 layout->AddView(control); |
| 614 | 627 |
| 615 if (input.length == autofill::DetailInput::LONG) | 628 if (input.length == autofill::DetailInput::LONG || |
| 629 input.length == autofill::DetailInput::SHORT_EOL) { | |
| 616 ++column_set_id; | 630 ++column_set_id; |
| 631 } | |
| 617 } | 632 } |
| 618 | 633 |
| 619 [self updateFieldIcons]; | 634 [self updateFieldIcons]; |
|
groby-ooo-7-16
2013/12/05 02:56:10
This must be called _after_ updating inputs_ - upd
| |
| 620 return view.autorelease(); | 635 |
| 636 if (inputs_) | |
| 637 [[self view] replaceSubview:inputs_ with:view]; | |
| 638 | |
| 639 inputs_ = view; | |
| 621 } | 640 } |
| 622 | 641 |
| 623 - (void)updateFieldIcons { | 642 - (void)updateFieldIcons { |
| 624 autofill::FieldValueMap fieldValues; | 643 autofill::FieldValueMap fieldValues; |
| 625 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { | 644 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { |
| 626 DCHECK([input isKindOfClass:[NSControl class]]); | 645 DCHECK([input isKindOfClass:[NSControl class]]); |
| 627 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); | 646 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); |
| 628 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; | 647 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; |
| 629 NSString* value = [input fieldValue]; | 648 NSString* value = [input fieldValue]; |
| 630 fieldValues[fieldType] = base::SysNSStringToUTF16(value); | 649 fieldValues[fieldType] = base::SysNSStringToUTF16(value); |
| 631 } | 650 } |
| 632 | 651 |
| 633 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); | 652 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); |
| 634 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); | 653 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); |
| 635 iter!= fieldIcons.end(); ++iter) { | 654 iter!= fieldIcons.end(); ++iter) { |
| 636 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( | 655 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( |
| 637 [inputs_ viewWithTag:iter->first]); | 656 [inputs_ viewWithTag:iter->first]); |
| 638 [[textfield cell] setIcon:iter->second.ToNSImage()]; | 657 [[textfield cell] setIcon:iter->second.ToNSImage()]; |
| 639 } | 658 } |
| 640 } | 659 } |
| 641 | 660 |
| 642 - (void)updateEditability { | 661 - (void)updateEditability { |
| 643 | 662 |
| 644 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); | 663 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); |
| 645 [self addInputsToArray:controls]; | 664 [self addInputsToArray:controls]; |
| 646 for (NSControl<AutofillInputField>* control in controls.get()) { | 665 for (NSControl<AutofillInputField>* control in controls.get()) { |
| 647 autofill::ServerFieldType type = [self fieldTypeForControl:control]; | 666 autofill::ServerFieldType type = [self fieldTypeForControl:control]; |
| 648 const autofill::DetailInput* input = [self detailInputForType:type]; | 667 const autofill::DetailInput* input = [self detailInputForType:type]; |
|
groby-ooo-7-16
2013/12/05 02:56:10
Why can this now be zero?
| |
| 649 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; | 668 if (input) |
| 669 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; | |
| 650 } | 670 } |
| 651 } | 671 } |
| 652 | 672 |
| 653 @end | 673 @end |
| 654 | 674 |
| 655 | 675 |
| 656 @implementation AutofillSectionContainer (ForTesting) | 676 @implementation AutofillSectionContainer (ForTesting) |
| 657 | 677 |
| 658 - (NSControl*)getField:(autofill::ServerFieldType)type { | 678 - (NSControl*)getField:(autofill::ServerFieldType)type { |
| 659 return [inputs_ viewWithTag:type]; | 679 return [inputs_ viewWithTag:type]; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 675 - (void)activateFieldForInput:(const autofill::DetailInput&)input { | 695 - (void)activateFieldForInput:(const autofill::DetailInput&)input { |
| 676 if ([self detailInputForType:input.type] != &input) | 696 if ([self detailInputForType:input.type] != &input) |
| 677 return; | 697 return; |
| 678 | 698 |
| 679 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:input.type]; | 699 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:input.type]; |
| 680 [[field window] makeFirstResponder:field]; | 700 [[field window] makeFirstResponder:field]; |
| 681 [self textfieldEditedOrActivated:field edited:NO]; | 701 [self textfieldEditedOrActivated:field edited:NO]; |
| 682 } | 702 } |
| 683 | 703 |
| 684 @end | 704 @end |
| OLD | NEW |