OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" | 5 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #import "base/mac/foundation_util.h" | 8 #import "base/mac/foundation_util.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #include "components/strings/grit/components_strings.h" | 10 #include "components/strings/grit/components_strings.h" |
11 #import "ios/chrome/browser/ui/autofill/autofill_edit_accessory_view.h" | 11 #import "ios/chrome/browser/ui/autofill/autofill_edit_accessory_view.h" |
12 #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" | 12 #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" |
13 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom e.h" | 13 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom e.h" |
14 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item .h" | 14 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item .h" |
15 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item+collec tion_view_controller.h" | 15 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item+collec tion_view_controller.h" |
16 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item .h" | |
16 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | 17 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
17 #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h" | 18 #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h" |
18 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" | 19 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" |
19 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller+int ernal.h" | 20 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_act ions.h" |
20 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" | 21 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" |
21 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 22 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
22 #include "ios/chrome/grit/ios_theme_resources.h" | 23 #include "ios/chrome/grit/ios_theme_resources.h" |
23 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" | 24 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" |
24 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
25 | 26 |
26 #if !defined(__has_feature) || !__has_feature(objc_arc) | 27 #if !defined(__has_feature) || !__has_feature(objc_arc) |
27 #error "This file requires ARC support." | 28 #error "This file requires ARC support." |
28 #endif | 29 #endif |
29 | 30 |
(...skipping 15 matching lines...) Expand all Loading... | |
45 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); | 46 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); |
46 if (cell) | 47 if (cell) |
47 return cell; | 48 return cell; |
48 } | 49 } |
49 | 50 |
50 // There has to be a cell associated with this text field. | 51 // There has to be a cell associated with this text field. |
51 NOTREACHED(); | 52 NOTREACHED(); |
52 return nil; | 53 return nil; |
53 } | 54 } |
54 | 55 |
56 CollectionViewSwitchCell* CollectionViewSwitchCellForSwitchField( | |
57 UISwitch* switchField) { | |
58 for (UIView* view = switchField; view; view = [view superview]) { | |
59 CollectionViewSwitchCell* cell = | |
60 base::mac::ObjCCast<CollectionViewSwitchCell>(view); | |
61 if (cell) | |
62 return cell; | |
63 } | |
64 | |
65 // There should be a cell associated with this switch field. | |
66 NOTREACHED(); | |
67 return nil; | |
68 } | |
69 | |
55 typedef NS_ENUM(NSInteger, SectionIdentifier) { | 70 typedef NS_ENUM(NSInteger, SectionIdentifier) { |
56 SectionIdentifierHeader = kSectionIdentifierEnumZero, | 71 SectionIdentifierHeader = kSectionIdentifierEnumZero, |
57 SectionIdentifierFooter, | 72 SectionIdentifierFooter, |
58 SectionIdentifierFirstField, // Must be the last section identifier. | 73 SectionIdentifierFirstField, // Must be the last section identifier. |
59 }; | 74 }; |
60 | 75 |
61 typedef NS_ENUM(NSInteger, ItemType) { | 76 typedef NS_ENUM(NSInteger, ItemType) { |
62 ItemTypeHeader = kItemTypeEnumZero, | 77 ItemTypeHeader = kItemTypeEnumZero, |
63 ItemTypeFooter, | 78 ItemTypeFooter, |
64 ItemTypeTextField, // This is a repeated item type. | 79 ItemTypeTextField, // This is a repeated item type. |
65 ItemTypeSelectorField, // This is a repeated item type. | 80 ItemTypeSelectorField, // This is a repeated item type. |
81 ItemTypeSwitchField, // This is a repeated item type. | |
66 ItemTypeErrorMessage, // This is a repeated item type. | 82 ItemTypeErrorMessage, // This is a repeated item type. |
67 }; | 83 }; |
68 | 84 |
69 } // namespace | 85 } // namespace |
70 | 86 |
71 @interface PaymentRequestEditViewController ()<AutofillEditAccessoryDelegate, | 87 @interface PaymentRequestEditViewController ()< |
72 UITextFieldDelegate, | 88 PaymentRequestEditViewControllerActions, |
lpromero
2017/05/30 12:35:45
Sort alphabetically.
Moe
2017/05/31 03:21:11
Done.
| |
73 UIPickerViewDataSource, | 89 AutofillEditAccessoryDelegate, |
74 UIPickerViewDelegate> { | 90 UITextFieldDelegate, |
91 UIPickerViewDataSource, | |
92 UIPickerViewDelegate> { | |
75 // The currently focused cell. May be nil. | 93 // The currently focused cell. May be nil. |
76 __weak AutofillEditCell* _currentEditingCell; | 94 __weak AutofillEditCell* _currentEditingCell; |
77 | 95 |
78 AutofillEditAccessoryView* _accessoryView; | 96 AutofillEditAccessoryView* _accessoryView; |
79 } | 97 } |
80 | 98 |
81 // The map of autofill types to the fields definitions for the editor. | 99 // The map of section identifiers to the fields definitions for the editor. |
82 @property(nonatomic, strong) | 100 @property(nonatomic, strong) |
83 NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap; | 101 NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap; |
84 | 102 |
85 // The list of field definitions for the editor. | 103 // The list of field definitions for the editor. |
86 @property(nonatomic, strong) NSArray<EditorField*>* fields; | 104 @property(nonatomic, strong) NSArray<EditorField*>* fields; |
87 | 105 |
88 // The map of autofill types to lists of UIPickerView options. | 106 // The map of autofill types to lists of UIPickerView options. |
89 @property(nonatomic, strong) | 107 @property(nonatomic, strong) |
90 NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options; | 108 NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options; |
91 | 109 |
(...skipping 13 matching lines...) Expand all Loading... | |
105 // Enables or disables the accessory view's previous and next buttons depending | 123 // Enables or disables the accessory view's previous and next buttons depending |
106 // on whether there is a text field before and after the currently focused text | 124 // on whether there is a text field before and after the currently focused text |
107 // field. | 125 // field. |
108 - (void)updateAccessoryViewButtonsStates; | 126 - (void)updateAccessoryViewButtonsStates; |
109 | 127 |
110 // Adds an error message item in the section |sectionIdentifier| if | 128 // Adds an error message item in the section |sectionIdentifier| if |
111 // |errorMessage| is non-empty. Otherwise removes such an item if one exists. | 129 // |errorMessage| is non-empty. Otherwise removes such an item if one exists. |
112 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage | 130 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage |
113 inSectionWithIdentifier:(NSInteger)sectionIdentifier; | 131 inSectionWithIdentifier:(NSInteger)sectionIdentifier; |
114 | 132 |
133 // Validates each field. If there is a validation error, displays an error | |
134 // message item in the same section as the field and returns NO. Otherwise | |
135 // removes the error message item in that section if one exists and sets the | |
136 // value on the field. Returns YES if all the fields are validated successfully. | |
137 - (BOOL)validateForm; | |
138 | |
139 // Returns the index path for the cell associated with the currently focused | |
140 // text field. | |
141 - (NSIndexPath*)indexPathForCurrentTextField; | |
142 | |
115 @end | 143 @end |
116 | 144 |
117 @implementation PaymentRequestEditViewController | 145 @implementation PaymentRequestEditViewController |
118 | 146 |
119 @synthesize dataSource = _dataSource; | 147 @synthesize dataSource = _dataSource; |
120 @synthesize delegate = _delegate; | 148 @synthesize delegate = _delegate; |
121 @synthesize validatorDelegate = _validatorDelegate; | 149 @synthesize validatorDelegate = _validatorDelegate; |
122 @synthesize fieldsMap = _fieldsMap; | 150 @synthesize fieldsMap = _fieldsMap; |
123 @synthesize fields = _fields; | 151 @synthesize fields = _fields; |
124 @synthesize options = _options; | 152 @synthesize options = _options; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 | 221 |
194 [self.pickerViews removeAllObjects]; | 222 [self.pickerViews removeAllObjects]; |
195 | 223 |
196 CollectionViewItem* headerItem = [_dataSource headerItem]; | 224 CollectionViewItem* headerItem = [_dataSource headerItem]; |
197 if (headerItem) { | 225 if (headerItem) { |
198 [headerItem setType:ItemTypeHeader]; | 226 [headerItem setType:ItemTypeHeader]; |
199 [model addSectionWithIdentifier:SectionIdentifierHeader]; | 227 [model addSectionWithIdentifier:SectionIdentifierHeader]; |
200 [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader]; | 228 [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader]; |
201 } | 229 } |
202 | 230 |
231 self.fieldsMap = | |
232 [[NSMutableDictionary alloc] initWithCapacity:self.fields.count]; | |
233 | |
203 // Iterate over the fields and add the respective sections and items. | 234 // Iterate over the fields and add the respective sections and items. |
204 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, | 235 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, |
205 NSUInteger index, BOOL* stop) { | 236 NSUInteger index, BOOL* stop) { |
206 NSInteger sectionIdentifier = SectionIdentifierFirstField + index; | 237 NSInteger sectionIdentifier = SectionIdentifierFirstField + index; |
207 [model addSectionWithIdentifier:sectionIdentifier]; | 238 [model addSectionWithIdentifier:sectionIdentifier]; |
208 switch (field.fieldType) { | 239 switch (field.fieldType) { |
209 case EditorFieldTypeTextField: { | 240 case EditorFieldTypeTextField: { |
210 AutofillEditItem* item = | 241 AutofillEditItem* item = |
211 [[AutofillEditItem alloc] initWithType:ItemTypeTextField]; | 242 [[AutofillEditItem alloc] initWithType:ItemTypeTextField]; |
212 item.textFieldName = field.label; | 243 item.textFieldName = field.label; |
213 item.textFieldEnabled = field.enabled; | 244 item.textFieldEnabled = field.enabled; |
214 item.textFieldValue = field.value; | 245 item.textFieldValue = field.value; |
215 item.required = field.isRequired; | 246 item.required = field.isRequired; |
216 item.autofillUIType = field.autofillUIType; | 247 item.autofillUIType = field.autofillUIType; |
248 item.identifyingIcon = [_dataSource iconIdentifyingEditorFied:field]; | |
217 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | 249 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
218 field.item = item; | 250 field.item = item; |
219 | 251 |
220 break; | 252 break; |
221 } | 253 } |
222 case EditorFieldTypeSelector: { | 254 case EditorFieldTypeSelector: { |
223 PaymentsSelectorEditItem* item = [[PaymentsSelectorEditItem alloc] | 255 PaymentsSelectorEditItem* item = [[PaymentsSelectorEditItem alloc] |
224 initWithType:ItemTypeSelectorField]; | 256 initWithType:ItemTypeSelectorField]; |
225 item.name = field.label; | 257 item.name = field.label; |
226 item.value = field.displayValue; | 258 item.value = field.displayValue; |
227 item.required = field.isRequired; | 259 item.required = field.isRequired; |
228 item.autofillUIType = field.autofillUIType; | 260 item.autofillUIType = field.autofillUIType; |
229 item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; | 261 item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; |
230 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | 262 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
231 field.item = item; | 263 field.item = item; |
232 break; | 264 break; |
233 } | 265 } |
266 case EditorFieldTypeSwitch: { | |
267 CollectionViewSwitchItem* item = | |
268 [[CollectionViewSwitchItem alloc] initWithType:ItemTypeSwitchField]; | |
269 item.text = field.label; | |
270 item.on = [field.value boolValue]; | |
271 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | |
272 field.item = item; | |
273 break; | |
274 } | |
234 default: | 275 default: |
235 NOTREACHED(); | 276 NOTREACHED(); |
236 } | 277 } |
237 | 278 |
238 field.sectionIdentifier = sectionIdentifier; | 279 field.sectionIdentifier = sectionIdentifier; |
280 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; | |
281 [self.fieldsMap setObject:field forKey:key]; | |
239 }]; | 282 }]; |
240 | 283 |
241 [self loadFooterItems]; | 284 [model addSectionWithIdentifier:SectionIdentifierFooter]; |
285 CollectionViewFooterItem* footerItem = | |
286 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; | |
287 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE); | |
288 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter]; | |
242 } | 289 } |
243 | 290 |
244 - (void)viewDidLoad { | 291 - (void)viewDidLoad { |
245 [super viewDidLoad]; | 292 [super viewDidLoad]; |
246 | 293 |
247 self.collectionView.accessibilityIdentifier = | 294 self.collectionView.accessibilityIdentifier = |
248 kPaymentRequestEditCollectionViewAccessibilityID; | 295 kPaymentRequestEditCollectionViewAccessibilityID; |
249 | 296 |
250 // Customize collection view settings. | 297 // Customize collection view settings. |
251 self.styler.cellStyle = MDCCollectionViewCellStyleCard; | 298 self.styler.cellStyle = MDCCollectionViewCellStyleCard; |
252 self.styler.separatorInset = | 299 self.styler.separatorInset = |
253 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset); | 300 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset); |
254 } | 301 } |
255 | 302 |
256 #pragma mark - PaymentRequestEditConsumer | 303 #pragma mark - PaymentRequestEditConsumer |
257 | 304 |
258 - (void)setEditorFields:(NSArray<EditorField*>*)fields { | 305 - (void)setEditorFields:(NSArray<EditorField*>*)fields { |
259 self.fields = fields; | 306 self.fields = fields; |
260 self.fieldsMap = [[NSMutableDictionary alloc] initWithCapacity:fields.count]; | |
261 // Iterate over the fields and populate the map. | |
262 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, | |
263 NSUInteger index, BOOL* stop) { | |
264 NSNumber* key = [NSNumber numberWithInt:field.autofillUIType]; | |
265 [self.fieldsMap setObject:field forKey:key]; | |
266 }]; | |
267 } | 307 } |
268 | 308 |
269 - (void)setOptions:(NSArray<NSString*>*)options | 309 - (void)setOptions:(NSArray<NSString*>*)options |
270 forEditorField:(EditorField*)field { | 310 forEditorField:(EditorField*)field { |
271 DCHECK(field.fieldType == EditorFieldTypeTextField); | 311 DCHECK(field.fieldType == EditorFieldTypeTextField); |
272 AutofillEditItem* item = | 312 AutofillEditItem* item = |
273 base::mac::ObjCCastStrict<AutofillEditItem>(field.item); | 313 base::mac::ObjCCastStrict<AutofillEditItem>(field.item); |
274 item.textFieldEnabled = field.enabled; | 314 item.textFieldEnabled = field.enabled; |
275 item.textFieldValue = field.value; | 315 item.textFieldValue = field.value; |
276 | 316 |
(...skipping 20 matching lines...) Expand all Loading... | |
297 | 337 |
298 - (void)textFieldDidBeginEditing:(UITextField*)textField { | 338 - (void)textFieldDidBeginEditing:(UITextField*)textField { |
299 _currentEditingCell = AutofillEditCellForTextField(textField); | 339 _currentEditingCell = AutofillEditCellForTextField(textField); |
300 [textField setInputAccessoryView:_accessoryView]; | 340 [textField setInputAccessoryView:_accessoryView]; |
301 [self updateAccessoryViewButtonsStates]; | 341 [self updateAccessoryViewButtonsStates]; |
302 } | 342 } |
303 | 343 |
304 - (void)textFieldDidEndEditing:(UITextField*)textField { | 344 - (void)textFieldDidEndEditing:(UITextField*)textField { |
305 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); | 345 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); |
306 | 346 |
307 CollectionViewModel* model = self.collectionViewModel; | 347 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; |
348 NSInteger sectionIdentifier = [self.collectionViewModel | |
349 sectionIdentifierForSection:[indexPath section]]; | |
308 | 350 |
309 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; | 351 // Find the respective editor field, update its value, and validate it. |
310 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( | 352 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; |
311 [model itemAtIndexPath:indexPath]); | |
312 | |
313 // Find and validate the respective editor field. | |
314 NSNumber* key = [NSNumber numberWithInt:item.autofillUIType]; | |
315 EditorField* field = self.fieldsMap[key]; | 353 EditorField* field = self.fieldsMap[key]; |
316 DCHECK(field); | 354 DCHECK(field); |
317 field.value = textField.text; | 355 field.value = textField.text; |
318 NSString* errorMessage = | 356 NSString* errorMessage = |
319 [_validatorDelegate paymentRequestEditViewController:self | 357 [_validatorDelegate paymentRequestEditViewController:self |
320 validateField:field]; | 358 validateField:field]; |
321 NSInteger sectionIdentifier = | |
322 [model sectionIdentifierForSection:[indexPath section]]; | |
323 [self addOrRemoveErrorMessage:errorMessage | 359 [self addOrRemoveErrorMessage:errorMessage |
324 inSectionWithIdentifier:sectionIdentifier]; | 360 inSectionWithIdentifier:sectionIdentifier]; |
325 | 361 |
326 [textField setInputAccessoryView:nil]; | 362 [textField setInputAccessoryView:nil]; |
327 _currentEditingCell = nil; | 363 _currentEditingCell = nil; |
328 } | 364 } |
329 | 365 |
330 - (BOOL)textFieldShouldReturn:(UITextField*)textField { | 366 - (BOOL)textFieldShouldReturn:(UITextField*)textField { |
331 DCHECK([_currentEditingCell textField] == textField); | 367 DCHECK([_currentEditingCell textField] == textField); |
332 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; | 368 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; |
333 if (nextCell) | 369 if (nextCell) |
334 [self nextPressed]; | 370 [self nextPressed]; |
335 else | 371 else |
336 [self closePressed]; | 372 [self closePressed]; |
337 | 373 |
338 return NO; | 374 return NO; |
339 } | 375 } |
340 | 376 |
377 // This method is called as the text is being typed in, pasted, or deleted. Asks | |
378 // the delegate if the text should be changed. Should always return YES. During | |
379 // typing/pasting text, |newText| contains one or more new characters. When user | |
380 // deletes text, |newText| is empty. |range| is the range of characters to be | |
381 // replaced. | |
382 - (BOOL)textField:(UITextField*)textField | |
383 shouldChangeCharactersInRange:(NSRange)range | |
384 replacementString:(NSString*)newText { | |
385 CollectionViewModel* model = self.collectionViewModel; | |
386 | |
387 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); | |
388 | |
389 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; | |
390 NSInteger sectionIdentifier = | |
391 [model sectionIdentifierForSection:[indexPath section]]; | |
392 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( | |
393 [model itemAtIndexPath:indexPath]); | |
394 | |
395 // Find the respective editor field and update its value. | |
396 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; | |
397 EditorField* field = self.fieldsMap[key]; | |
398 DCHECK(field); | |
399 // Obtain the text being typed. | |
400 NSString* updatedText = | |
401 [textField.text stringByReplacingCharactersInRange:range | |
402 withString:newText]; | |
403 field.value = updatedText; | |
404 | |
405 // Get the icon that identifies the field value and reload the cell if the | |
406 // icon changes. | |
407 UIImage* oldIcon = item.identifyingIcon; | |
408 item.identifyingIcon = [_dataSource iconIdentifyingEditorFied:field]; | |
409 if (item.identifyingIcon != oldIcon) | |
410 [self reconfigureCellsForItems:@[ item ]]; | |
411 | |
412 return YES; | |
413 } | |
414 | |
341 #pragma mark - AutofillEditAccessoryDelegate | 415 #pragma mark - AutofillEditAccessoryDelegate |
342 | 416 |
343 - (void)nextPressed { | 417 - (void)nextPressed { |
344 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; | 418 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; |
345 if (nextCell) | 419 if (nextCell) |
346 [nextCell.textField becomeFirstResponder]; | 420 [nextCell.textField becomeFirstResponder]; |
347 } | 421 } |
348 | 422 |
349 - (void)previousPressed { | 423 - (void)previousPressed { |
350 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1]; | 424 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1]; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 base::mac::ObjCCast<AutofillEditCell>(cell); | 481 base::mac::ObjCCast<AutofillEditCell>(cell); |
408 autofillEditCell.textField.delegate = self; | 482 autofillEditCell.textField.delegate = self; |
409 autofillEditCell.textField.clearButtonMode = UITextFieldViewModeNever; | 483 autofillEditCell.textField.clearButtonMode = UITextFieldViewModeNever; |
410 autofillEditCell.textLabel.font = [MDCTypography body2Font]; | 484 autofillEditCell.textLabel.font = [MDCTypography body2Font]; |
411 autofillEditCell.textLabel.textColor = [[MDCPalette greyPalette] tint900]; | 485 autofillEditCell.textLabel.textColor = [[MDCPalette greyPalette] tint900]; |
412 autofillEditCell.textField.font = [MDCTypography body1Font]; | 486 autofillEditCell.textField.font = [MDCTypography body1Font]; |
413 autofillEditCell.textField.textColor = | 487 autofillEditCell.textField.textColor = |
414 [[MDCPalette cr_bluePalette] tint600]; | 488 [[MDCPalette cr_bluePalette] tint600]; |
415 break; | 489 break; |
416 } | 490 } |
491 case ItemTypeSwitchField: { | |
492 CollectionViewSwitchCell* switchCell = | |
493 base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell); | |
494 [switchCell.switchView addTarget:self | |
495 action:@selector(switchToggled:) | |
496 forControlEvents:UIControlEventValueChanged]; | |
497 break; | |
498 } | |
417 case ItemTypeErrorMessage: { | 499 case ItemTypeErrorMessage: { |
418 PaymentsTextCell* errorMessageCell = | 500 PaymentsTextCell* errorMessageCell = |
419 base::mac::ObjCCastStrict<PaymentsTextCell>(cell); | 501 base::mac::ObjCCastStrict<PaymentsTextCell>(cell); |
420 errorMessageCell.textLabel.font = [MDCTypography body1Font]; | 502 errorMessageCell.textLabel.font = [MDCTypography body1Font]; |
421 errorMessageCell.textLabel.textColor = | 503 errorMessageCell.textLabel.textColor = |
422 [[MDCPalette cr_redPalette] tint600]; | 504 [[MDCPalette cr_redPalette] tint600]; |
423 break; | 505 break; |
424 } | 506 } |
425 case ItemTypeFooter: { | 507 case ItemTypeFooter: { |
426 CollectionViewFooterCell* footerCell = | 508 CollectionViewFooterCell* footerCell = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 #pragma mark MDCCollectionViewStylingDelegate | 546 #pragma mark MDCCollectionViewStylingDelegate |
465 | 547 |
466 - (CGFloat)collectionView:(UICollectionView*)collectionView | 548 - (CGFloat)collectionView:(UICollectionView*)collectionView |
467 cellHeightAtIndexPath:(NSIndexPath*)indexPath { | 549 cellHeightAtIndexPath:(NSIndexPath*)indexPath { |
468 CollectionViewItem* item = | 550 CollectionViewItem* item = |
469 [self.collectionViewModel itemAtIndexPath:indexPath]; | 551 [self.collectionViewModel itemAtIndexPath:indexPath]; |
470 switch (item.type) { | 552 switch (item.type) { |
471 case ItemTypeHeader: | 553 case ItemTypeHeader: |
472 case ItemTypeFooter: | 554 case ItemTypeFooter: |
473 case ItemTypeTextField: | 555 case ItemTypeTextField: |
556 case ItemTypeSwitchField: | |
474 case ItemTypeErrorMessage: | 557 case ItemTypeErrorMessage: |
475 return [MDCCollectionViewCell | 558 return [MDCCollectionViewCell |
476 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) | 559 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) |
477 forItem:item]; | 560 forItem:item]; |
478 case ItemTypeSelectorField: | 561 case ItemTypeSelectorField: |
479 return MDCCellDefaultOneLineHeight; | 562 return MDCCellDefaultOneLineHeight; |
480 default: | 563 default: |
481 NOTREACHED(); | 564 NOTREACHED(); |
482 return MDCCellDefaultOneLineHeight; | 565 return MDCCellDefaultOneLineHeight; |
483 } | 566 } |
484 } | 567 } |
485 | 568 |
486 - (BOOL)collectionView:(UICollectionView*)collectionView | 569 - (BOOL)collectionView:(UICollectionView*)collectionView |
487 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { | 570 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { |
488 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; | 571 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; |
489 switch (type) { | 572 switch (type) { |
490 case ItemTypeHeader: | 573 case ItemTypeHeader: |
491 case ItemTypeFooter: | 574 case ItemTypeFooter: |
492 case ItemTypeErrorMessage: | 575 case ItemTypeErrorMessage: |
576 case ItemTypeTextField: | |
577 case ItemTypeSwitchField: | |
493 return YES; | 578 return YES; |
494 default: | 579 default: |
495 return NO; | 580 return NO; |
496 } | 581 } |
497 } | 582 } |
498 | 583 |
499 - (BOOL)collectionView:(UICollectionView*)collectionView | 584 - (BOOL)collectionView:(UICollectionView*)collectionView |
500 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { | 585 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { |
501 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; | 586 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; |
502 switch (type) { | 587 switch (type) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 errorMessageItem.text = errorMessage; | 660 errorMessageItem.text = errorMessage; |
576 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING); | 661 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING); |
577 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID; | 662 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID; |
578 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier]; | 663 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier]; |
579 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage | 664 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage |
580 sectionIdentifier:sectionIdentifier]; | 665 sectionIdentifier:sectionIdentifier]; |
581 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; | 666 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; |
582 } | 667 } |
583 } | 668 } |
584 | 669 |
585 #pragma mark - Keyboard handling | |
586 | |
587 - (void)keyboardDidShow { | |
588 [self.collectionView | |
589 scrollToItemAtIndexPath:[self.collectionView | |
590 indexPathForCell:_currentEditingCell] | |
591 atScrollPosition:UICollectionViewScrollPositionCenteredVertically | |
592 animated:YES]; | |
593 } | |
594 | |
595 @end | |
596 | |
597 @implementation PaymentRequestEditViewController (Internal) | |
598 | |
599 - (BOOL)validateForm { | 670 - (BOOL)validateForm { |
600 for (EditorField* field in self.fields) { | 671 for (EditorField* field in self.fields) { |
601 NSString* errorMessage = | 672 NSString* errorMessage = |
602 [_validatorDelegate paymentRequestEditViewController:self | 673 [_validatorDelegate paymentRequestEditViewController:self |
603 validateField:field]; | 674 validateField:field]; |
604 [self addOrRemoveErrorMessage:errorMessage | 675 [self addOrRemoveErrorMessage:errorMessage |
605 inSectionWithIdentifier:field.sectionIdentifier]; | 676 inSectionWithIdentifier:field.sectionIdentifier]; |
606 if (errorMessage.length) | 677 if (errorMessage.length) |
607 return NO; | 678 return NO; |
608 } | 679 } |
609 return YES; | 680 return YES; |
610 } | 681 } |
611 | 682 |
612 - (void)loadFooterItems { | |
613 CollectionViewModel* model = self.collectionViewModel; | |
614 | |
615 [model addSectionWithIdentifier:SectionIdentifierFooter]; | |
616 CollectionViewFooterItem* footerItem = | |
617 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; | |
618 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE); | |
619 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter]; | |
620 } | |
621 | |
622 - (NSIndexPath*)indexPathForCurrentTextField { | 683 - (NSIndexPath*)indexPathForCurrentTextField { |
623 DCHECK(_currentEditingCell); | 684 DCHECK(_currentEditingCell); |
624 NSIndexPath* indexPath = | 685 NSIndexPath* indexPath = |
625 [[self collectionView] indexPathForCell:_currentEditingCell]; | 686 [[self collectionView] indexPathForCell:_currentEditingCell]; |
626 DCHECK(indexPath); | 687 DCHECK(indexPath); |
627 return indexPath; | 688 return indexPath; |
628 } | 689 } |
629 | 690 |
691 #pragma mark - Keyboard handling | |
692 | |
693 - (void)keyboardDidShow { | |
694 [self.collectionView | |
695 scrollToItemAtIndexPath:[self.collectionView | |
696 indexPathForCell:_currentEditingCell] | |
697 atScrollPosition:UICollectionViewScrollPositionCenteredVertically | |
698 animated:YES]; | |
699 } | |
700 | |
701 #pragma mark Switch Actions | |
702 | |
703 - (void)switchToggled:(UISwitch*)sender { | |
704 CollectionViewSwitchCell* switchCell = | |
705 CollectionViewSwitchCellForSwitchField(sender); | |
706 NSIndexPath* indexPath = [[self collectionView] indexPathForCell:switchCell]; | |
707 DCHECK(indexPath); | |
708 | |
709 NSInteger sectionIdentifier = [self.collectionViewModel | |
710 sectionIdentifierForSection:[indexPath section]]; | |
711 | |
712 // Update editor field's value. | |
713 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; | |
714 EditorField* field = self.fieldsMap[key]; | |
715 DCHECK(field); | |
716 field.value = [sender isOn] ? @"YES" : @"NO"; | |
717 } | |
718 | |
630 #pragma mark - PaymentRequestEditViewControllerActions methods | 719 #pragma mark - PaymentRequestEditViewControllerActions methods |
631 | 720 |
632 - (void)onCancel { | 721 - (void)onCancel { |
722 [self.delegate paymentRequestEditViewControllerDidCancel:self]; | |
633 } | 723 } |
634 | 724 |
635 - (void)onDone { | 725 - (void)onDone { |
636 [_currentEditingCell.textField resignFirstResponder]; | 726 [_currentEditingCell.textField resignFirstResponder]; |
727 | |
728 if (![self validateForm]) | |
729 return; | |
730 | |
731 [self.delegate paymentRequestEditViewController:self | |
732 didFinishEditingFields:self.fields]; | |
637 } | 733 } |
638 | 734 |
639 @end | 735 @end |
OLD | NEW |