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, | |
454 // so flagging them as invalid prematurely is not helpful. However, | |
455 // correcting a minor mistake (i.e. a wrong CC digit) should immediately | |
456 // result in validation - positive user feedback. | |
457 if ([textfield invalid] && edited) { | |
458 base::string16 message = delegate_->InputValidityMessage(section_, | |
459 type, | |
460 fieldValue); | |
461 [textfield setValidityMessage:base::SysUTF16ToNSString(message)]; | |
462 [validationDelegate_ updateMessageForField:textfield]; | |
463 | 427 |
464 // If the field transitioned from invalid to valid, re-validate the group, | 428 // This only applies to textfields. |
465 // since inter-field checks become meaningful with valid fields. | 429 if (textfield) { |
groby-ooo-7-16
2014/01/14 19:37:07
You can skip this if - [textfield invalid] will ev
Dan Beam
2014/01/15 03:10:48
we talked about this offline and will change after
| |
466 if (![textfield invalid]) | 430 // If the field is marked as invalid, check if the text is now valid. |
467 [self validateFor:autofill::VALIDATE_EDIT]; | 431 // Many fields (i.e. CC#) are invalid for most of the duration of editing, |
432 // so flagging them as invalid prematurely is not helpful. However, | |
433 // correcting a minor mistake (i.e. a wrong CC digit) should immediately | |
434 // result in validation - positive user feedback. | |
435 if ([textfield invalid] && edited) { | |
436 base::string16 message = delegate_->InputValidityMessage(section_, | |
437 type, | |
438 fieldValue); | |
439 [textfield setValidityMessage:base::SysUTF16ToNSString(message)]; | |
440 [validationDelegate_ updateMessageForField:textfield]; | |
441 | |
442 // If the field transitioned from invalid to valid, re-validate the group, | |
443 // since inter-field checks become meaningful with valid fields. | |
444 if (![textfield invalid]) | |
445 [self validateFor:autofill::VALIDATE_EDIT]; | |
446 } | |
468 } | 447 } |
469 | 448 |
470 // Update the icon if necessary. | 449 // Update the icon if necessary. |
471 if (delegate_->FieldControlsIcons(type)) | 450 if (delegate_->FieldControlsIcons(type)) |
472 [self updateFieldIcons]; | 451 [self updateFieldIcons]; |
473 [self updateEditability]; | 452 [self updateEditability]; |
474 } | 453 } |
475 | 454 |
476 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control { | 455 - (autofill::ServerFieldType)fieldTypeForControl:(NSControl*)control { |
477 DCHECK([control tag]); | 456 DCHECK([control tag]); |
478 return static_cast<autofill::ServerFieldType>([control tag]); | 457 return static_cast<autofill::ServerFieldType>([control tag]); |
479 } | 458 } |
480 | 459 |
481 - (const autofill::DetailInput*)detailInputForType: | 460 - (const autofill::DetailInput*)detailInputForType: |
482 (autofill::ServerFieldType)type { | 461 (autofill::ServerFieldType)type { |
483 for (size_t i = 0; i < detailInputs_.size(); ++i) { | 462 for (size_t i = 0; i < detailInputs_.size(); ++i) { |
484 if (detailInputs_[i]->type == type) | 463 if (detailInputs_[i]->type == type) |
485 return detailInputs_[i]; | 464 return detailInputs_[i]; |
486 } | 465 } |
487 // TODO(groby): Needs to be NOTREACHED. Can't, due to the fact that tests | 466 // TODO(groby): Needs to be NOTREACHED. Can't, due to the fact that tests |
488 // blindly call setFieldValue:forInput:, even for non-existing inputs. | 467 // blindly call setFieldValue:forType:, even for non-existing inputs. |
489 return NULL; | 468 return NULL; |
490 } | 469 } |
491 | 470 |
492 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs | 471 - (void)fillDetailOutputs:(autofill::FieldValueMap*)outputs |
493 fromControls:(NSArray*)controls { | 472 fromControls:(NSArray*)controls { |
494 for (NSControl<AutofillInputField>* input in controls) { | 473 for (NSControl<AutofillInputField>* input in controls) { |
495 DCHECK([input isKindOfClass:[NSControl class]]); | 474 DCHECK([input isKindOfClass:[NSControl class]]); |
496 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); | 475 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); |
497 outputs->insert(std::make_pair( | 476 outputs->insert(std::make_pair( |
498 [self fieldTypeForControl:input], | 477 [self fieldTypeForControl:input], |
499 base::SysNSStringToUTF16([input fieldValue]))); | 478 base::SysNSStringToUTF16([input fieldValue]))); |
500 } | 479 } |
501 } | 480 } |
502 | 481 |
503 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText { | 482 - (NSTextField*)makeDetailSectionLabel:(NSString*)labelText { |
504 base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]); | 483 base::scoped_nsobject<NSTextField> label([[NSTextField alloc] init]); |
505 [label setFont: | 484 [label setFont: |
506 [[NSFontManager sharedFontManager] convertFont:[label font] | 485 [[NSFontManager sharedFontManager] convertFont:[label font] |
507 toHaveTrait:NSBoldFontMask]]; | 486 toHaveTrait:NSBoldFontMask]]; |
508 [label setStringValue:labelText]; | 487 [label setStringValue:labelText]; |
509 [label setEditable:NO]; | 488 [label setEditable:NO]; |
510 [label setBordered:NO]; | 489 [label setBordered:NO]; |
511 [label setDrawsBackground:NO]; | 490 [label setDrawsBackground:NO]; |
512 [label sizeToFit]; | 491 [label sizeToFit]; |
513 return label.autorelease(); | 492 return label.autorelease(); |
514 } | 493 } |
515 | 494 |
516 - (void)updateAndClobber:(BOOL)shouldClobber { | 495 - (void)updateAndClobber:(BOOL)shouldClobber { |
517 const autofill::DetailInputs& updatedInputs = | 496 if (shouldClobber) { |
518 delegate_->RequestedFieldsForSection(section_); | 497 [self makeInputControls]; |
519 | 498 |
520 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); | 499 id delegate = [[view_ window] windowController]; |
521 iter != updatedInputs.end(); | 500 if ([delegate respondsToSelector:@selector(requestRelayout)]) { |
522 ++iter) { | 501 [delegate performSelector:@selector(requestRelayout)]; |
523 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; | 502 } |
524 DCHECK(field); | 503 } else { |
504 const autofill::DetailInputs& updatedInputs = | |
505 delegate_->RequestedFieldsForSection(section_); | |
525 | 506 |
526 if (shouldClobber || [field isDefault]) { | 507 for (autofill::DetailInputs::const_iterator iter = updatedInputs.begin(); |
527 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)]; | 508 iter != updatedInputs.end(); |
509 ++iter) { | |
510 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:iter->type]; | |
511 DCHECK(field); | |
512 if ([field isDefault]) | |
513 [field setFieldValue:base::SysUTF16ToNSString(iter->initial_value)]; | |
528 } | 514 } |
529 if (shouldClobber) | 515 [self updateFieldIcons]; |
530 [field setValidityMessage:@""]; | |
531 } | 516 } |
517 | |
532 [self updateEditability]; | 518 [self updateEditability]; |
533 [self updateFieldIcons]; | |
534 [self modelChanged]; | 519 [self modelChanged]; |
535 } | 520 } |
536 | 521 |
537 - (BOOL)isCreditCardSection { | 522 - (BOOL)isCreditCardSection { |
538 return section_ == autofill::SECTION_CC || | 523 return section_ == autofill::SECTION_CC || |
539 section_ == autofill::SECTION_CC_BILLING; | 524 section_ == autofill::SECTION_CC_BILLING; |
540 } | 525 } |
541 | 526 |
542 - (MenuButton*)makeSuggestionButton { | 527 - (MenuButton*)makeSuggestionButton { |
543 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]); | 528 base::scoped_nsobject<MenuButton> button([[MenuButton alloc] init]); |
(...skipping 20 matching lines...) Expand all Loading... | |
564 [[button cell] setImage:image | 549 [[button cell] setImage:image |
565 forButtonState:image_button_cell::kDisabledState]; | 550 forButtonState:image_button_cell::kDisabledState]; |
566 | 551 |
567 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) | 552 // ImageButtonCell's cellSize is not working. (http://crbug.com/298501) |
568 [button setFrameSize:[image size]]; | 553 [button setFrameSize:[image size]]; |
569 return button.autorelease(); | 554 return button.autorelease(); |
570 } | 555 } |
571 | 556 |
572 // TODO(estade): we should be using Chrome-style constrained window padding | 557 // TODO(estade): we should be using Chrome-style constrained window padding |
573 // values. | 558 // values. |
574 - (LayoutView*)makeInputControls { | 559 - (void)makeInputControls { |
560 detailInputs_.clear(); | |
561 | |
562 // Keep a list of weak pointers to DetailInputs. | |
563 const autofill::DetailInputs& inputs = | |
564 delegate_->RequestedFieldsForSection(section_); | |
565 | |
566 // Reverse the order of all the inputs. | |
567 for (int i = inputs.size() - 1; i >= 0; --i) { | |
568 detailInputs_.push_back(&(inputs[i])); | |
569 } | |
570 | |
571 // Then right the reversal in each row. | |
572 std::vector<const autofill::DetailInput*>::iterator it; | |
573 for (it = detailInputs_.begin(); it < detailInputs_.end(); ++it) { | |
574 std::vector<const autofill::DetailInput*>::iterator start = it; | |
575 while (it != detailInputs_.end() && | |
576 (*it)->length != autofill::DetailInput::LONG) { | |
577 ++it; | |
578 } | |
579 std::reverse(start, it); | |
580 } | |
581 | |
575 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); | 582 base::scoped_nsobject<LayoutView> view([[LayoutView alloc] init]); |
576 [view setLayoutManager: | 583 [view setLayoutManager: |
577 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; | 584 scoped_ptr<SimpleGridLayout>(new SimpleGridLayout(view))]; |
578 SimpleGridLayout* layout = [view layoutManager]; | 585 SimpleGridLayout* layout = [view layoutManager]; |
579 | 586 |
580 int column_set_id = 0; | 587 int column_set_id = 0; |
581 for (size_t i = 0; i < detailInputs_.size(); ++i) { | 588 for (size_t i = 0; i < detailInputs_.size(); ++i) { |
582 const autofill::DetailInput& input = *detailInputs_[i]; | 589 const autofill::DetailInput& input = *detailInputs_[i]; |
583 | 590 |
584 if (input.length == autofill::DetailInput::LONG) | 591 if (input.length == autofill::DetailInput::LONG) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; | 625 inputModel->GetItemAt(inputModel->GetDefaultIndex()))]; |
619 control.reset(popup.release()); | 626 control.reset(popup.release()); |
620 } else { | 627 } else { |
621 base::scoped_nsobject<AutofillTextField> field( | 628 base::scoped_nsobject<AutofillTextField> field( |
622 [[AutofillTextField alloc] init]); | 629 [[AutofillTextField alloc] init]); |
623 [[field cell] setPlaceholderString: | 630 [[field cell] setPlaceholderString: |
624 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)]; | 631 l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)]; |
625 NSString* tooltipText = | 632 NSString* tooltipText = |
626 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type)); | 633 base::SysUTF16ToNSString(delegate_->TooltipForField(input.type)); |
627 if ([tooltipText length] > 0) { | 634 if ([tooltipText length] > 0) { |
628 DCHECK(!tooltipController_); | 635 if (!tooltipController_) { |
629 DCHECK(!tooltipField_); | 636 tooltipController_.reset( |
630 tooltipController_.reset( | 637 [[AutofillTooltipController alloc] |
631 [[AutofillTooltipController alloc] | 638 initWithArrowLocation:info_bubble::kTopRight]); |
632 initWithArrowLocation:info_bubble::kTopRight]); | 639 } |
633 tooltipField_ = field.get(); | 640 tooltipField_ = field.get(); |
634 NSImage* icon = | 641 NSImage* icon = |
635 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 642 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
636 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage(); | 643 IDR_AUTOFILL_TOOLTIP_ICON).ToNSImage(); |
637 [tooltipController_ setImage:icon]; | 644 [tooltipController_ setImage:icon]; |
638 [tooltipController_ setMessage:tooltipText]; | 645 [tooltipController_ setMessage:tooltipText]; |
639 [[field cell] setDecorationSize:[icon size]]; | 646 [[field cell] setDecorationSize:[icon size]]; |
640 } | 647 } |
641 [field setDefaultValue:@""]; | 648 [field setDefaultValue:@""]; |
642 control.reset(field.release()); | 649 control.reset(field.release()); |
643 } | 650 } |
644 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; | 651 [control setFieldValue:base::SysUTF16ToNSString(input.initial_value)]; |
645 [control sizeToFit]; | 652 [control sizeToFit]; |
646 [control setTag:input.type]; | 653 [control setTag:input.type]; |
647 [control setInputDelegate:self]; | 654 [control setInputDelegate:self]; |
648 // Hide away fields that cannot be edited. | 655 // Hide away fields that cannot be edited. |
649 if (kColumnSetId == -1) { | 656 if (kColumnSetId == -1) { |
650 [control setFrame:NSZeroRect]; | 657 [control setFrame:NSZeroRect]; |
651 [control setHidden:YES]; | 658 [control setHidden:YES]; |
652 } | 659 } |
653 layout->AddView(control); | 660 layout->AddView(control); |
654 | 661 |
655 if (input.length == autofill::DetailInput::LONG || | 662 if (input.length == autofill::DetailInput::LONG || |
656 input.length == autofill::DetailInput::SHORT_EOL) { | 663 input.length == autofill::DetailInput::SHORT_EOL) { |
657 ++column_set_id; | 664 ++column_set_id; |
658 } | 665 } |
659 } | 666 } |
660 | 667 |
661 [self updateFieldIcons]; | 668 [self updateFieldIcons]; |
662 return view.autorelease(); | 669 |
670 if (inputs_) | |
671 [[self view] replaceSubview:inputs_ with:view]; | |
groby-ooo-7-16
2014/01/14 19:37:07
I'd post requestRelayout from here.
Dan Beam
2014/01/15 03:10:48
Done.
| |
672 | |
673 inputs_ = view; | |
663 } | 674 } |
664 | 675 |
665 - (void)updateFieldIcons { | 676 - (void)updateFieldIcons { |
666 autofill::FieldValueMap fieldValues; | 677 autofill::FieldValueMap fieldValues; |
667 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { | 678 for (NSControl<AutofillInputField>* input in [inputs_ subviews]) { |
668 DCHECK([input isKindOfClass:[NSControl class]]); | 679 DCHECK([input isKindOfClass:[NSControl class]]); |
669 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); | 680 DCHECK([input conformsToProtocol:@protocol(AutofillInputField)]); |
670 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; | 681 autofill::ServerFieldType fieldType = [self fieldTypeForControl:input]; |
671 NSString* value = [input fieldValue]; | 682 NSString* value = [input fieldValue]; |
672 fieldValues[fieldType] = base::SysNSStringToUTF16(value); | 683 fieldValues[fieldType] = base::SysNSStringToUTF16(value); |
673 } | 684 } |
674 | 685 |
675 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); | 686 autofill::FieldIconMap fieldIcons = delegate_->IconsForFields(fieldValues); |
676 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); | 687 for (autofill::FieldIconMap::const_iterator iter = fieldIcons.begin(); |
677 iter!= fieldIcons.end(); ++iter) { | 688 iter!= fieldIcons.end(); ++iter) { |
678 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( | 689 AutofillTextField* textfield = base::mac::ObjCCastStrict<AutofillTextField>( |
679 [inputs_ viewWithTag:iter->first]); | 690 [inputs_ viewWithTag:iter->first]); |
680 [[textfield cell] setIcon:iter->second.ToNSImage()]; | 691 [[textfield cell] setIcon:iter->second.ToNSImage()]; |
681 } | 692 } |
682 } | 693 } |
683 | 694 |
684 - (void)updateEditability { | 695 - (void)updateEditability { |
685 | |
686 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); | 696 base::scoped_nsobject<NSMutableArray> controls([[NSMutableArray alloc] init]); |
687 [self addInputsToArray:controls]; | 697 [self addInputsToArray:controls]; |
688 for (NSControl<AutofillInputField>* control in controls.get()) { | 698 for (NSControl<AutofillInputField>* control in controls.get()) { |
689 autofill::ServerFieldType type = [self fieldTypeForControl:control]; | 699 autofill::ServerFieldType type = [self fieldTypeForControl:control]; |
690 const autofill::DetailInput* input = [self detailInputForType:type]; | 700 const autofill::DetailInput* input = [self detailInputForType:type]; |
691 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; | 701 if (input) |
702 [control setEnabled:delegate_->InputIsEditable(*input, section_)]; | |
692 } | 703 } |
693 } | 704 } |
694 | 705 |
695 @end | 706 @end |
696 | 707 |
697 | 708 |
698 @implementation AutofillSectionContainer (ForTesting) | 709 @implementation AutofillSectionContainer (ForTesting) |
699 | 710 |
700 - (NSControl*)getField:(autofill::ServerFieldType)type { | 711 - (NSControl*)getField:(autofill::ServerFieldType)type { |
701 return [inputs_ viewWithTag:type]; | 712 return [inputs_ viewWithTag:type]; |
702 } | 713 } |
703 | 714 |
704 - (void)setFieldValue:(NSString*)text | 715 - (void)setFieldValue:(NSString*)text |
705 forType:(autofill::ServerFieldType)type { | 716 forType:(autofill::ServerFieldType)type { |
706 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; | 717 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; |
707 if (field) | 718 if (field) |
708 [field setFieldValue:text]; | 719 [field setFieldValue:text]; |
709 } | 720 } |
710 | 721 |
711 - (void)setSuggestionFieldValue:(NSString*)text { | 722 - (void)setSuggestionFieldValue:(NSString*)text { |
712 [[suggestContainer_ inputField] setFieldValue:text]; | 723 [[suggestContainer_ inputField] setFieldValue:text]; |
713 } | 724 } |
714 | 725 |
715 - (void)activateFieldForType:(autofill::ServerFieldType)type { | 726 - (void)activateFieldForType:(autofill::ServerFieldType)type { |
716 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; | 727 NSControl<AutofillInputField>* field = [inputs_ viewWithTag:type]; |
717 if (field) { | 728 if (field) { |
718 [[field window] makeFirstResponder:field]; | 729 [[field window] makeFirstResponder:field]; |
719 [self textfieldEditedOrActivated:field edited:NO]; | 730 [self fieldEditedOrActivated:field edited:NO]; |
720 } | 731 } |
721 } | 732 } |
722 | 733 |
723 @end | 734 @end |
OLD | NEW |