| Index: chrome/browser/autofill/autofill_dialog_controller_mac.mm
|
| diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm
|
| index c867497bcb28ee677aef41f808bed76d1965097e..c39e3e8c086bd912eaaf429a6d11cda0201f03e8 100644
|
| --- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm
|
| +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm
|
| @@ -4,29 +4,100 @@
|
|
|
| #import "chrome/browser/autofill/autofill_dialog_controller_mac.h"
|
| #include "app/l10n_util.h"
|
| +#include "app/resource_bundle.h"
|
| #include "base/mac_util.h"
|
| #include "base/sys_string_conversions.h"
|
| #import "chrome/browser/autofill/autofill_address_model_mac.h"
|
| -#import "chrome/browser/autofill/autofill_address_view_controller_mac.h"
|
| +#import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h"
|
| #import "chrome/browser/autofill/autofill_credit_card_model_mac.h"
|
| -#import "chrome/browser/autofill/autofill_credit_card_view_controller_mac.h"
|
| +#import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h"
|
| #import "chrome/browser/autofill/personal_data_manager.h"
|
| #include "chrome/browser/browser_process.h"
|
| -#import "chrome/browser/cocoa/disclosure_view_controller.h"
|
| -#import "chrome/browser/cocoa/section_separator_view.h"
|
| #import "chrome/browser/cocoa/window_size_autosaver.h"
|
| #include "chrome/browser/pref_service.h"
|
| #include "chrome/browser/profile.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "grit/generated_resources.h"
|
| +#include "grit/theme_resources.h"
|
| +
|
| +// Delegate protocol that needs to be in place for the AutoFillTableView's
|
| +// handling of delete and backspace keys.
|
| +@protocol DeleteKeyDelegate
|
| +- (IBAction)deleteSelection:(id)sender;
|
| +@end
|
| +
|
| +// A subclass of NSTableView that allows for deleting selected elements using
|
| +// the delete or backspace keys.
|
| +@interface AutoFillTableView : NSTableView {
|
| +}
|
| +@end
|
| +
|
| +@implementation AutoFillTableView
|
| +
|
| +// We override the keyDown method to dispatch the |deleteSelection:| action
|
| +// when the user presses the delete or backspace keys. Note a delegate must
|
| +// be present that conforms to the DeleteKeyDelegate protocol.
|
| +- (void)keyDown:(NSEvent *)event {
|
| + id object = [self delegate];
|
| + unichar c = [[event characters] characterAtIndex: 0];
|
| +
|
| + // If the user pressed delete and the delegate supports deleteSelection:
|
| + if ((c == NSDeleteFunctionKey ||
|
| + c == NSDeleteCharFunctionKey ||
|
| + c == NSDeleteCharacter) &&
|
| + [object respondsToSelector:@selector(deleteSelection:)]) {
|
| + id <DeleteKeyDelegate> delegate = (id <DeleteKeyDelegate>) object;
|
| +
|
| + [delegate deleteSelection:self];
|
| + } else {
|
| + [super keyDown:event];
|
| + }
|
| +}
|
| +
|
| +@end
|
|
|
| // Private interface.
|
| -@interface AutoFillDialogController (PrivateAPI)
|
| +@interface AutoFillDialogController (PrivateMethods)
|
| // Asyncronous handler for when PersonalDataManager data loads. The
|
| // personal data manager notifies the dialog with this method when the
|
| // data loading is complete and ready to be used.
|
| - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
|
| creditCards:(const std::vector<CreditCard*>&)creditCards;
|
| +
|
| +// Returns true if |row| is an index to a valid profile in |tableView_|, and
|
| +// false otherwise.
|
| +- (BOOL)isProfileRow:(NSInteger)row;
|
| +
|
| +// Returns true if |row| is an index to the profile group row in |tableView_|,
|
| +// and false otherwise.
|
| +- (BOOL)isProfileGroupRow:(NSInteger)row;
|
| +
|
| +// Returns true if |row| is an index to a valid credit card in |tableView_|, and
|
| +// false otherwise.
|
| +- (BOOL)isCreditCardRow:(NSInteger)row;
|
| +
|
| +// Returns true if |row| is the index to the credit card group row in
|
| +// |tableView_|, and false otherwise.
|
| +- (BOOL)isCreditCardGroupRow:(NSInteger)row;
|
| +
|
| +// Returns the index to |profiles_| of the corresponding |row| in |tableView_|.
|
| +- (size_t)profileIndexFromRow:(NSInteger)row;
|
| +
|
| +// Returns the index to |creditCards_| of the corresponding |row| in
|
| +// |tableView_|.
|
| +- (size_t)creditCardIndexFromRow:(NSInteger)row;
|
| +
|
| +// Returns the |row| in |tableView_| that corresponds to the index |i| into
|
| +// |profiles_|.
|
| +- (NSInteger)rowFromProfileIndex:(size_t)i;
|
| +
|
| +// Returns the |row| in |tableView_| that corresponds to the index |i| into
|
| +// |creditCards_|.
|
| +- (NSInteger)rowFromCreditCardIndex:(size_t)row;
|
| +
|
| +// Invokes the modal dialog.
|
| +- (void)runModalDialog;
|
| +
|
| @end
|
|
|
| namespace AutoFillDialogControllerInternal {
|
| @@ -94,14 +165,10 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
|
|
| } // namespace AutoFillDialogControllerInternal
|
|
|
| -@interface AutoFillDialogController (PrivateMethods)
|
| -- (void)runModalDialog;
|
| -- (void)installChildViews;
|
| -@end
|
| -
|
| @implementation AutoFillDialogController
|
|
|
| @synthesize auxiliaryEnabled = auxiliaryEnabled_;
|
| +@synthesize itemIsSelected = itemIsSelected_;
|
|
|
| + (void)showAutoFillDialogWithObserver:(AutoFillDialogObserver*)observer
|
| profile:(Profile*)profile
|
| @@ -120,8 +187,6 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| }
|
|
|
| - (void)awakeFromNib {
|
| - [addressSectionBox_ setShowTopLine:FALSE];
|
| -
|
| PersonalDataManager* personal_data_manager =
|
| profile_->GetPersonalDataManager();
|
| DCHECK(personal_data_manager);
|
| @@ -138,46 +203,27 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| self, personal_data_manager, profile_));
|
| personal_data_manager->SetObserver(personalDataManagerObserver_.get());
|
| }
|
| +
|
| + // Explicitly load the data in the table before window displays to avoid
|
| + // nasty flicker as tables update.
|
| + [tableView_ reloadData];
|
| +
|
| + // Set up edit when double-clicking on a table row.
|
| + [tableView_ setDoubleAction:@selector(editSelection:)];
|
| }
|
|
|
| // NSWindow Delegate callback. When the window closes the controller can
|
| // be released.
|
| - (void)windowWillClose:(NSNotification *)notification {
|
| - // Force views to go away so they properly remove their observations.
|
| - addressFormViewControllers_.reset();
|
| - creditCardFormViewControllers_.reset();
|
| + [tableView_ setDataSource:nil];
|
| + [tableView_ setDelegate:nil];
|
| [self autorelease];
|
| }
|
|
|
| // Called when the user clicks the save button.
|
| - (IBAction)save:(id)sender {
|
| - // Call |makeFirstResponder:| to commit pending text field edits.
|
| - [[self window] makeFirstResponder:[self window]];
|
| -
|
| // If we have an |observer_| then communicate the changes back.
|
| if (observer_) {
|
| - profiles_.clear();
|
| - profiles_.resize([addressFormViewControllers_ count]);
|
| - int i = 0;
|
| - for (AutoFillAddressViewController* addressFormViewController in
|
| - addressFormViewControllers_.get()) {
|
| - // Initialize the profile here. The default initializer does not fully
|
| - // initialize.
|
| - profiles_[i] = AutoFillProfile(ASCIIToUTF16(""), 0);
|
| - [addressFormViewController copyModelToProfile:&profiles_[i]];
|
| - i++;
|
| - }
|
| - creditCards_.clear();
|
| - creditCards_.resize([creditCardFormViewControllers_ count]);
|
| - int j = 0;
|
| - for (AutoFillCreditCardViewController* creditCardFormViewController in
|
| - creditCardFormViewControllers_.get()) {
|
| - // Initialize the credit card here. The default initializer does not
|
| - // fully initialize.
|
| - creditCards_[j] = CreditCard(ASCIIToUTF16(""), 0);
|
| - [creditCardFormViewController copyModelToCreditCard:&creditCards_[j]];
|
| - j++;
|
| - }
|
| profile_->GetPrefs()->SetBoolean(prefs::kAutoFillAuxiliaryProfilesEnabled,
|
| auxiliaryEnabled_);
|
| observer_->OnAutoFillDialogApply(&profiles_, &creditCards_);
|
| @@ -191,144 +237,306 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| [self closeDialog];
|
| }
|
|
|
| -// Adds new address to bottom of list. A new address controller is created
|
| -// and its view is inserted into the view hierarchy.
|
| +// Invokes the "Add" sheet for address information. If user saves then the new
|
| +// information is added to |profiles_| in |addressAddDidEnd:| method.
|
| - (IBAction)addNewAddress:(id)sender {
|
| - // Insert relative to top of section, or below last address.
|
| - NSView* insertionPoint;
|
| - NSUInteger count = [addressFormViewControllers_.get() count];
|
| - if (count == 0) {
|
| - insertionPoint = addressSection_;
|
| - } else {
|
| - insertionPoint = [[addressFormViewControllers_.get()
|
| - objectAtIndex:[addressFormViewControllers_.get() count] - 1] view];
|
| + DCHECK(!addressSheetController.get());
|
| +
|
| + // Create a new default address.
|
| + string16 newName = l10n_util::GetStringUTF16(IDS_AUTOFILL_NEW_ADDRESS);
|
| + AutoFillProfile newAddress(newName, 0);
|
| +
|
| + // Create a new address sheet controller in "Add" mode.
|
| + addressSheetController.reset(
|
| + [[AutoFillAddressSheetController alloc]
|
| + initWithProfile:newAddress
|
| + mode:kAutoFillAddressAddMode]);
|
| +
|
| + // Show the sheet.
|
| + [NSApp beginSheet:[addressSheetController window]
|
| + modalForWindow:[self window]
|
| + modalDelegate:self
|
| + didEndSelector:@selector(addressAddDidEnd:returnCode:contextInfo:)
|
| + contextInfo:NULL];
|
| +}
|
| +
|
| +// Invokes the "Add" sheet for credit card information. If user saves then the
|
| +// new information is added to |creditCards_| in |creditCardAddDidEnd:| method.
|
| +- (IBAction)addNewCreditCard:(id)sender {
|
| + DCHECK(!creditCardSheetController.get());
|
| +
|
| + // Create a new default credit card.
|
| + string16 newName = l10n_util::GetStringUTF16(IDS_AUTOFILL_NEW_CREDITCARD);
|
| + CreditCard newCreditCard(newName, 0);
|
| +
|
| + // Create a new address sheet controller in "Add" mode.
|
| + creditCardSheetController.reset(
|
| + [[AutoFillCreditCardSheetController alloc]
|
| + initWithCreditCard:newCreditCard
|
| + mode:kAutoFillCreditCardAddMode
|
| + controller:self]);
|
| +
|
| + // Show the sheet.
|
| + [NSApp beginSheet:[creditCardSheetController window]
|
| + modalForWindow:[self window]
|
| + modalDelegate:self
|
| + didEndSelector:@selector(creditCardAddDidEnd:returnCode:contextInfo:)
|
| + contextInfo:NULL];
|
| +}
|
| +
|
| +// Add address sheet was dismissed. Non-zero |returnCode| indicates a save.
|
| +- (void)addressAddDidEnd:(NSWindow*)sheet
|
| + returnCode:(int)returnCode
|
| + contextInfo:(void*)contextInfo {
|
| + DCHECK(contextInfo == NULL);
|
| +
|
| + if (returnCode) {
|
| + // Create a new address and save it to the |profiles_| list.
|
| + AutoFillProfile newAddress(string16(), 0);
|
| + [addressSheetController copyModelToProfile:&newAddress];
|
| + profiles_.push_back(newAddress);
|
| +
|
| + // Refresh the view based on new data.
|
| + [tableView_ reloadData];
|
| +
|
| + // Update the selection to the newly added item.
|
| + NSInteger row = [self rowFromProfileIndex:profiles_.size() - 1];
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
|
| + byExtendingSelection:NO];
|
| }
|
| + [sheet orderOut:self];
|
| + addressSheetController.reset(nil);
|
| +}
|
|
|
| - // Create a new default address, and add it to our array of controllers.
|
| - string16 new_address_name = l10n_util::GetStringUTF16(
|
| - IDS_AUTOFILL_NEW_ADDRESS);
|
| - AutoFillProfile newProfile(new_address_name, 0);
|
| - scoped_nsobject<AutoFillAddressViewController> addressViewController(
|
| - [[AutoFillAddressViewController alloc]
|
| - initWithProfile:newProfile
|
| - disclosure:NSOnState
|
| - controller:self]);
|
| - [self willChangeValueForKey:@"addressLabels"];
|
| - [addressFormViewControllers_.get() addObject:addressViewController];
|
| - [self didChangeValueForKey:@"addressLabels"];
|
| +// Add credit card sheet was dismissed. Non-zero |returnCode| indicates a save.
|
| +- (void)creditCardAddDidEnd:(NSWindow *)sheet
|
| + returnCode:(int)returnCode
|
| + contextInfo:(void *)contextInfo {
|
| + DCHECK(contextInfo == NULL);
|
| +
|
| + if (returnCode) {
|
| + // Create a new credit card and save it to the |creditCards_| list.
|
| + CreditCard newCreditCard(string16(), 0);
|
| + [creditCardSheetController copyModelToCreditCard:&newCreditCard];
|
| + creditCards_.push_back(newCreditCard);
|
| +
|
| + // Refresh the view based on new data.
|
| + [tableView_ reloadData];
|
| +
|
| + // Update the selection to the newly added item.
|
| + NSInteger row = [self rowFromCreditCardIndex:creditCards_.size() - 1];
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
|
| + byExtendingSelection:NO];
|
| + }
|
| + [sheet orderOut:self];
|
| + creditCardSheetController.reset(nil);
|
| +}
|
|
|
| - // Embed the new address into our target view.
|
| - [childView_ addSubview:[addressViewController view]
|
| - positioned:NSWindowBelow relativeTo:insertionPoint];
|
| - [[addressViewController view] setFrameOrigin:NSMakePoint(0, 0)];
|
| +// Deletes selected item, either address or credit card depending on the item
|
| +// selected.
|
| +- (IBAction)deleteSelection:(id)sender {
|
| + NSInteger selectedRow = [tableView_ selectedRow];
|
| + if ([self isProfileRow:selectedRow]) {
|
| + profiles_.erase(profiles_.begin() + [self profileIndexFromRow:selectedRow]);
|
| +
|
| + // Select the previous row if possible, else current row, else deselect all.
|
| + if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1]
|
| + byExtendingSelection:NO];
|
| + } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
|
| + byExtendingSelection:NO];
|
| + } else {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSet]
|
| + byExtendingSelection:NO];
|
| + }
|
| + [tableView_ reloadData];
|
| + } else if ([self isCreditCardRow:selectedRow]) {
|
| + creditCards_.erase(
|
| + creditCards_.begin() + [self creditCardIndexFromRow:selectedRow]);
|
| +
|
| + // Select the previous row if possible, else current row, else deselect all.
|
| + if ([self tableView:tableView_ shouldSelectRow:selectedRow-1]) {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow-1]
|
| + byExtendingSelection:NO];
|
| + } else if ([self tableView:tableView_ shouldSelectRow:selectedRow]) {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
|
| + byExtendingSelection:NO];
|
| + } else {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSet]
|
| + byExtendingSelection:NO];
|
| + }
|
| + [tableView_ reloadData];
|
| + }
|
| +}
|
|
|
| - [self notifyAddressChange:self];
|
| +// Edits the selected item, either address or credit card depending on the item
|
| +// selected.
|
| +- (IBAction)editSelection:(id)sender {
|
| + NSInteger selectedRow = [tableView_ selectedRow];
|
| + if ([self isProfileRow:selectedRow]) {
|
| + if (!addressSheetController.get()) {
|
| + int i = [self profileIndexFromRow:selectedRow];
|
| +
|
| + // Create a new address sheet controller in "Edit" mode.
|
| + addressSheetController.reset(
|
| + [[AutoFillAddressSheetController alloc]
|
| + initWithProfile:profiles_[i]
|
| + mode:kAutoFillAddressEditMode]);
|
| +
|
| + // Show the sheet.
|
| + [NSApp beginSheet:[addressSheetController window]
|
| + modalForWindow:[self window]
|
| + modalDelegate:self
|
| + didEndSelector:@selector(addressEditDidEnd:returnCode:contextInfo:)
|
| + contextInfo:&profiles_[i]];
|
| + }
|
| + } else if ([self isCreditCardRow:selectedRow]) {
|
| + if (!creditCardSheetController.get()) {
|
| + int i = [self creditCardIndexFromRow:selectedRow];
|
| +
|
| + // Create a new credit card sheet controller in "Edit" mode.
|
| + creditCardSheetController.reset(
|
| + [[AutoFillCreditCardSheetController alloc]
|
| + initWithCreditCard:creditCards_[i]
|
| + mode:kAutoFillCreditCardEditMode
|
| + controller:self]);
|
| +
|
| + // Show the sheet.
|
| + [NSApp beginSheet:[creditCardSheetController window]
|
| + modalForWindow:[self window]
|
| + modalDelegate:self
|
| + didEndSelector:@selector(creditCardEditDidEnd:returnCode:contextInfo:)
|
| + contextInfo:&creditCards_[i]];
|
| + }
|
| + }
|
| +}
|
|
|
| - // Recalculate key view loop to account for change in view tree.
|
| - [[self window] recalculateKeyViewLoop];
|
| +// Edit address sheet was dismissed. Non-zero |returnCode| indicates a save.
|
| +- (void)addressEditDidEnd:(NSWindow *)sheet
|
| + returnCode:(int)returnCode
|
| + contextInfo:(void *)contextInfo {
|
| + DCHECK(contextInfo != NULL);
|
| + if (returnCode) {
|
| + AutoFillProfile* profile = static_cast<AutoFillProfile*>(contextInfo);
|
| + [addressSheetController copyModelToProfile:profile];
|
| + [tableView_ reloadData];
|
| + }
|
| + [sheet orderOut:self];
|
| + addressSheetController.reset(nil);
|
| }
|
|
|
| -// Adds new credit card to bottom of list. A new credit card controller is
|
| -// created and its view is inserted into the view hierarchy.
|
| -- (IBAction)addNewCreditCard:(id)sender {
|
| - // Insert relative to top of section, or below last address.
|
| - NSView* insertionPoint;
|
| - NSUInteger count = [creditCardFormViewControllers_.get() count];
|
| - if (count == 0) {
|
| - insertionPoint = creditCardSection_;
|
| - } else {
|
| - insertionPoint = [[creditCardFormViewControllers_.get()
|
| - objectAtIndex:[creditCardFormViewControllers_.get() count] - 1] view];
|
| +// Edit credit card sheet was dismissed. Non-zero |returnCode| indicates a
|
| +// save.
|
| +- (void)creditCardEditDidEnd:(NSWindow *)sheet
|
| + returnCode:(int)returnCode
|
| + contextInfo:(void *)contextInfo {
|
| + DCHECK(contextInfo != NULL);
|
| + if (returnCode) {
|
| + CreditCard* creditCard = static_cast<CreditCard*>(contextInfo);
|
| + [creditCardSheetController copyModelToCreditCard:creditCard];
|
| + [tableView_ reloadData];
|
| }
|
| + [sheet orderOut:self];
|
| + creditCardSheetController.reset(nil);
|
| +}
|
|
|
| - // Create a new default credit card, and add it to our array of controllers.
|
| - string16 new_credit_card_name = l10n_util::GetStringUTF16(
|
| - IDS_AUTOFILL_NEW_CREDITCARD);
|
| - CreditCard newCreditCard(new_credit_card_name, 0);
|
| - scoped_nsobject<AutoFillCreditCardViewController> creditCardViewController(
|
| - [[AutoFillCreditCardViewController alloc]
|
| - initWithCreditCard:newCreditCard
|
| - disclosure:NSOnState
|
| - controller:self]);
|
| - [self willChangeValueForKey:@"creditCardLabels"];
|
| - [creditCardFormViewControllers_.get() addObject:creditCardViewController];
|
| - [self didChangeValueForKey:@"creditCardLabels"];
|
| -
|
| - // Embed the new address into our target view.
|
| - [childView_ addSubview:[creditCardViewController view]
|
| - positioned:NSWindowBelow relativeTo:insertionPoint];
|
| - [[creditCardViewController view] setFrameOrigin:NSMakePoint(0, 0)];
|
| -
|
| - // Recalculate key view loop to account for change in view tree.
|
| - [[self window] recalculateKeyViewLoop];
|
| -}
|
| -
|
| -- (IBAction)deleteAddress:(id)sender {
|
| - NSUInteger i = [addressFormViewControllers_.get() indexOfObject:sender];
|
| - DCHECK(i != NSNotFound);
|
| -
|
| - // Remove controller's view from superview and remove from list of
|
| - // controllers. Note on lifetime: removing view from super view decrements
|
| - // refcount of view, removing controller from array decrements refcount of
|
| - // controller which in-turn decrement refcount of view. Both should dealloc
|
| - // at this point.
|
| - [[sender view] removeFromSuperview];
|
| - [self willChangeValueForKey:@"addressLabels"];
|
| - [addressFormViewControllers_.get() removeObjectAtIndex:i];
|
| - [self didChangeValueForKey:@"addressLabels"];
|
| -
|
| - [self notifyAddressChange:self];
|
| -
|
| - // Recalculate key view loop to account for change in view tree.
|
| - [[self window] recalculateKeyViewLoop];
|
| -}
|
| -
|
| -- (IBAction)deleteCreditCard:(id)sender {
|
| - NSUInteger i = [creditCardFormViewControllers_.get() indexOfObject:sender];
|
| - DCHECK(i != NSNotFound);
|
| -
|
| - // Remove controller's view from superview and remove from list of
|
| - // controllers. Note on lifetime: removing view from super view decrements
|
| - // refcount of view, removing controller from array decrements refcount of
|
| - // controller which in-turn decrement refcount of view. Both should dealloc
|
| - // at this point.
|
| - [[sender view] removeFromSuperview];
|
| - [self willChangeValueForKey:@"creditCardLabels"];
|
| - [creditCardFormViewControllers_.get() removeObjectAtIndex:i];
|
| - [self didChangeValueForKey:@"creditCardLabels"];
|
| -
|
| - // Recalculate key view loop to account for change in view tree.
|
| - [[self window] recalculateKeyViewLoop];
|
| -}
|
| -
|
| -// Credit card controllers are dependent upon the address labels. So we notify
|
| -// them here that something has changed.
|
| -- (IBAction)notifyAddressChange:(id)sender {
|
| - for (AutoFillCreditCardViewController* creditCardFormViewController in
|
| - creditCardFormViewControllers_.get()) {
|
| - [creditCardFormViewController onAddressesChanged:self];
|
| +// NSTableView Delegate method.
|
| +- (BOOL)tableView:(NSTableView *)tableView isGroupRow:(NSInteger)row {
|
| + if ([self isProfileGroupRow:row] || [self isCreditCardGroupRow:row])
|
| + return YES;
|
| + return NO;
|
| +}
|
| +
|
| +// NSTableView Delegate method.
|
| +- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row {
|
| + return ![self tableView:tableView isGroupRow:row];
|
| +}
|
| +
|
| +// NSTableView Delegate method.
|
| +- (id)tableView:(NSTableView *)tableView
|
| + objectValueForTableColumn:(NSTableColumn *)tableColumn
|
| + row:(NSInteger)row {
|
| + if ([[tableColumn identifier] isEqualToString:@"Spacer"])
|
| + return @"";
|
| +
|
| + // Check that we're initialized before supplying data.
|
| + if (tableView == tableView_) {
|
| +
|
| + // Section label.
|
| + if ([self isProfileGroupRow:row])
|
| + if ([[tableColumn identifier] isEqualToString:@"Label"])
|
| + return @"Addresses";
|
| + else
|
| + return @"";
|
| +
|
| + if (row < 0)
|
| + return @"";
|
| +
|
| + // Data row.
|
| + if ([self isProfileRow:row]) {
|
| + if ([[tableColumn identifier] isEqualToString:@"Label"])
|
| + return SysUTF16ToNSString(
|
| + profiles_[[self profileIndexFromRow:row]].Label());
|
| +
|
| + if ([[tableColumn identifier] isEqualToString:@"Summary"])
|
| + return SysUTF16ToNSString(
|
| + profiles_[[self profileIndexFromRow:row]].PreviewSummary());
|
| +
|
| + return @"";
|
| + }
|
| +
|
| + // Section label.
|
| + if ([self isCreditCardGroupRow:row])
|
| + if ([[tableColumn identifier] isEqualToString:@"Label"])
|
| + return @"Credit Cards";
|
| + else
|
| + return @"";
|
| +
|
| + // Data row.
|
| + if ([self isCreditCardRow:row]) {
|
| + if ([[tableColumn identifier] isEqualToString:@"Label"])
|
| + return SysUTF16ToNSString(
|
| + creditCards_[[self creditCardIndexFromRow:row]].Label());
|
| +
|
| + if ([[tableColumn identifier] isEqualToString:@"Summary"])
|
| + return SysUTF16ToNSString(
|
| + creditCards_[
|
| + [self creditCardIndexFromRow:row]].PreviewSummary());
|
| +
|
| + return @"";
|
| + }
|
| }
|
| +
|
| + return @"";
|
| }
|
|
|
| -- (NSArray*)addressLabels {
|
| - NSUInteger capacity = [addressFormViewControllers_ count];
|
| - NSMutableArray* array = [NSMutableArray arrayWithCapacity:capacity];
|
| +// We implement this delegate method to update our |itemIsSelected| property.
|
| +// The "Edit..." and "Remove" buttons' enabled state depends on having a
|
| +// valid selection in the table.
|
| +- (void)tableViewSelectionDidChange:(NSNotification *)aNotification {
|
| + if ([tableView_ selectedRow] >= 0)
|
| + [self setItemIsSelected:YES];
|
| + else
|
| + [self setItemIsSelected:NO];
|
| +}
|
|
|
| - for (AutoFillAddressViewController* addressFormViewController in
|
| - addressFormViewControllers_.get()) {
|
| - [array addObject:[[addressFormViewController addressModel] label]];
|
| +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
|
| + if (tableView == tableView_) {
|
| + // 1 section header, the profiles, 1 section header, the credit cards.
|
| + return 1 + profiles_.size() + 1 + creditCards_.size();
|
| }
|
|
|
| - return array;
|
| + return 0;
|
| }
|
|
|
| -- (NSArray*)creditCardLabels {
|
| - NSUInteger capacity = [creditCardFormViewControllers_ count];
|
| +- (NSArray*)addressLabels {
|
| + NSUInteger capacity = profiles_.size();
|
| NSMutableArray* array = [NSMutableArray arrayWithCapacity:capacity];
|
|
|
| - for (AutoFillCreditCardViewController* creditCardFormViewController in
|
| - creditCardFormViewControllers_.get()) {
|
| - [array addObject:[[creditCardFormViewController creditCardModel] label]];
|
| + std::vector<AutoFillProfile>::iterator i;
|
| + for (i = profiles_.begin(); i != profiles_.end(); ++i) {
|
| + [array addObject:SysUTF16ToNSString(i->Label())];
|
| }
|
|
|
| return array;
|
| @@ -361,13 +569,14 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| profile:(Profile*)profile
|
| importedProfile:(AutoFillProfile*)importedProfile
|
| importedCreditCard:(CreditCard*)importedCreditCard {
|
| - CHECK(profile);
|
| + DCHECK(profile);
|
| // Use initWithWindowNibPath: instead of initWithWindowNibName: so we
|
| // can override it in a unit test.
|
| NSString* nibpath = [mac_util::MainAppBundle()
|
| pathForResource:@"AutoFillDialog"
|
| ofType:@"nib"];
|
| if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
|
| + // Initialize member variables based on input.
|
| observer_ = observer;
|
| profile_ = profile;
|
| importedProfile_ = importedProfile;
|
| @@ -380,14 +589,6 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| // Do not use [NSMutableArray array] here; we need predictable destruction
|
| // which will be prevented by having a reference held by an autorelease
|
| // pool.
|
| -
|
| - // Initialize array of sub-controllers.
|
| - addressFormViewControllers_.reset(
|
| - [[NSMutableArray alloc] initWithCapacity:0]);
|
| -
|
| - // Initialize array of sub-controllers.
|
| - creditCardFormViewControllers_.reset(
|
| - [[NSMutableArray alloc] initWithCapacity:0]);
|
| }
|
| return self;
|
| }
|
| @@ -398,12 +599,24 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| [NSApp stopModal];
|
| }
|
|
|
| -- (NSMutableArray*)addressFormViewControllers {
|
| - return addressFormViewControllers_.get();
|
| +- (AutoFillAddressSheetController*)addressSheetController {
|
| + return addressSheetController.get();
|
| +}
|
| +
|
| +- (AutoFillCreditCardSheetController*)creditCardSheetController {
|
| + return creditCardSheetController.get();
|
| +}
|
| +
|
| +- (void)selectAddressAtIndex:(size_t)i {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
|
| + [self rowFromProfileIndex:i]]
|
| + byExtendingSelection:NO];
|
| }
|
|
|
| -- (NSMutableArray*)creditCardFormViewControllers {
|
| - return creditCardFormViewControllers_.get();
|
| +- (void)selectCreditCardAtIndex:(size_t)i {
|
| + [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:
|
| + [self rowFromCreditCardIndex:i]]
|
| + byExtendingSelection:NO];
|
| }
|
|
|
| @end
|
| @@ -424,52 +637,6 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| [NSApp runModalForWindow:[self window]];
|
| }
|
|
|
| -// Install controller and views for the address form and the credit card form.
|
| -// They are installed into the appropriate sibling order so that they can be
|
| -// arranged vertically by the VerticalLayoutView class. We insert the views
|
| -// into the |childView_| but we hold onto the controllers and release them in
|
| -// our dealloc once the dialog closes.
|
| -- (void)installChildViews {
|
| - NSView* insertionPoint;
|
| - insertionPoint = addressSection_;
|
| - for (size_t i = 0; i < profiles_.size(); i++) {
|
| - // Special case for first address, we want to show full contents.
|
| - NSCellStateValue disclosureState = (i == 0) ? NSOnState : NSOffState;
|
| - scoped_nsobject<AutoFillAddressViewController> addressViewController(
|
| - [[AutoFillAddressViewController alloc]
|
| - initWithProfile:profiles_[i]
|
| - disclosure:disclosureState
|
| - controller:self]);
|
| - [self willChangeValueForKey:@"addressLabels"];
|
| - [addressFormViewControllers_.get() addObject:addressViewController];
|
| - [self didChangeValueForKey:@"addressLabels"];
|
| -
|
| - // Embed the child view into our (owned by us) target view.
|
| - [childView_ addSubview:[addressViewController view]
|
| - positioned:NSWindowBelow relativeTo:insertionPoint];
|
| - insertionPoint = [addressViewController view];
|
| - [[addressViewController view] setFrameOrigin:NSMakePoint(0, 0)];
|
| - }
|
| -
|
| - insertionPoint = creditCardSection_;
|
| - for (size_t i = 0; i < creditCards_.size(); i++) {
|
| - scoped_nsobject<AutoFillCreditCardViewController> creditCardViewController(
|
| - [[AutoFillCreditCardViewController alloc]
|
| - initWithCreditCard:creditCards_[i]
|
| - disclosure:NSOffState
|
| - controller:self]);
|
| - [self willChangeValueForKey:@"creditCardLabels"];
|
| - [creditCardFormViewControllers_.get() addObject:creditCardViewController];
|
| - [self didChangeValueForKey:@"creditCardLabels"];
|
| -
|
| - // Embed the child view into our (owned by us) target view.
|
| - [childView_ addSubview:[creditCardViewController view]
|
| - positioned:NSWindowBelow relativeTo:insertionPoint];
|
| - insertionPoint = [creditCardViewController view];
|
| - [[creditCardViewController view] setFrameOrigin:NSMakePoint(0, 0)];
|
| - }
|
| -}
|
| -
|
| - (void)onPersonalDataLoaded:(const std::vector<AutoFillProfile*>&)profiles
|
| creditCards:(const std::vector<CreditCard*>&)creditCards {
|
| if (importedProfile_) {
|
| @@ -492,8 +659,116 @@ void PersonalDataManagerObserver::OnPersonalDataLoaded() {
|
| iter != creditCards.end(); ++iter)
|
| creditCards_.push_back(**iter);
|
| }
|
| +}
|
| +
|
| +- (BOOL)isProfileRow:(NSInteger)row {
|
| + if (row > 0 && static_cast<size_t>(row) <= profiles_.size())
|
| + return YES;
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)isProfileGroupRow:(NSInteger)row {
|
| + if (row == 0)
|
| + return YES;
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)isCreditCardRow:(NSInteger)row {
|
| + if (row > 0 &&
|
| + static_cast<size_t>(row) >= profiles_.size() + 2 &&
|
| + static_cast<size_t>(row) <= profiles_.size() + creditCards_.size() + 1)
|
| + return YES;
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)isCreditCardGroupRow:(NSInteger)row {
|
| + if (row > 0 && static_cast<size_t>(row) == profiles_.size() + 1)
|
| + return YES;
|
| + return NO;
|
| +}
|
| +
|
| +- (size_t)profileIndexFromRow:(NSInteger)row {
|
| + DCHECK([self isProfileRow:row]);
|
| + return static_cast<size_t>(row) - 1;
|
| +}
|
| +
|
| +- (size_t)creditCardIndexFromRow:(NSInteger)row {
|
| + DCHECK([self isCreditCardRow:row]);
|
| + return static_cast<size_t>(row) - (profiles_.size() + 2);
|
| +}
|
| +
|
| +- (NSInteger)rowFromProfileIndex:(size_t)i {
|
| + return 1 + i;
|
| +}
|
| +
|
| +- (NSInteger)rowFromCreditCardIndex:(size_t)i {
|
| + return 1 + profiles_.size() + 1 + i;
|
| +}
|
| +
|
| +@end
|
| +
|
| +// An NSValueTransformer subclass for use in validation of empty data entry
|
| +// fields. Transforms a nil or empty string into a warning image. This data
|
| +// transformer is used in the address and credit card sheets for empty label
|
| +// strings.
|
| +@interface MissingAlertTransformer : NSValueTransformer {
|
| +}
|
| +@end
|
| +
|
| +@implementation MissingAlertTransformer
|
| ++ (Class)transformedValueClass {
|
| + return [NSImage class];
|
| +}
|
| +
|
| ++ (BOOL)allowsReverseTransformation {
|
| + return NO;
|
| +}
|
| +
|
| +- (id)transformedValue:(id)string {
|
| + if (string == nil || [string length] == 0) {
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + NSImage* image = rb.GetNSImageNamed(IDR_WARNING);
|
| + DCHECK(image);
|
| + return image;
|
| + }
|
| + return nil;
|
| +}
|
| +
|
| +@end
|
| +
|
| +// An NSValueTransformer subclass for use in validation of phone number
|
| +// fields. Transforms an invalid phone number string into a warning image.
|
| +// This data transformer is used in the credit card sheet for invalid phone and
|
| +// fax numbers.
|
| +@interface InvalidPhoneTransformer : NSValueTransformer {
|
| +}
|
| +@end
|
| +
|
| +@implementation InvalidPhoneTransformer
|
| ++ (Class)transformedValueClass {
|
| + return [NSImage class];
|
| +}
|
|
|
| - [self installChildViews];
|
| ++ (BOOL)allowsReverseTransformation {
|
| + return NO;
|
| +}
|
| +
|
| +- (id)transformedValue:(id)string {
|
| + if (string != nil && [string length] != 0) {
|
| + // TODO(dhollowa): Using SetInfo() call to validate phone number. Should
|
| + // have explicit validation method. More robust validation is needed as
|
| + // well eventually.
|
| + AutoFillProfile profile(string16(), 0);
|
| + profile.SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER),
|
| + base::SysNSStringToUTF16(string));
|
| + if (profile.GetFieldText(AutoFillType(PHONE_HOME_WHOLE_NUMBER)).empty()) {
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + NSImage* image = rb.GetNSImageNamed(IDR_WARNING);
|
| + DCHECK(image);
|
| + return image;
|
| + }
|
| + }
|
| + return nil;
|
| }
|
|
|
| @end
|
|
|