diff options
author | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-03 18:12:54 +0000 |
---|---|---|
committer | georgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-03 18:12:54 +0000 |
commit | f8e7b62dd159148eccfc779d599300e27fdf8a0d (patch) | |
tree | bb5621051845f8be667b3b6b6690737dad4b87d2 /chrome | |
parent | a471e9c8828edff914937df14c1998d4bc3dff72 (diff) | |
download | chromium_src-f8e7b62dd159148eccfc779d599300e27fdf8a0d.zip chromium_src-f8e7b62dd159148eccfc779d599300e27fdf8a0d.tar.gz chromium_src-f8e7b62dd159148eccfc779d599300e27fdf8a0d.tar.bz2 |
New autofill UI. Still not done:
1. Countries ComboBox - need countries list.
2. Correct icons size.
TEST=in the mocks.
BUG=37816,39238,41232,41793,36601
Review URL: http://codereview.chromium.org/2500002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48849 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/generated_resources.grd | 32 | ||||
-rw-r--r-- | chrome/app/resources/locale_settings.grd | 20 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number.cc | 9 | ||||
-rw-r--r-- | chrome/browser/autofill/phone_number.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/autofill_profiles_view_win.cc | 1307 | ||||
-rw-r--r-- | chrome/browser/views/autofill_profiles_view_win.h | 309 |
6 files changed, 826 insertions, 854 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cca5768..acebc64 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -5617,13 +5617,38 @@ Keep your key file in a safe place. You will need it to create new versions of y Credit Cards </message> <message name="IDS_AUTOFILL_ADD_ADDRESS_BUTTON" desc="The label of the button that adds a new AutoFill address."> - Add an address + Add address... </message> <message name="IDS_AUTOFILL_ADD_CREDITCARD_BUTTON" desc="The label of the button that adds a new AutoFill credit card."> + Add credit card... + </message> + <message name="IDS_AUTOFILL_EDIT_BUTTON" + desc="Text of the edit button in the autofill editor"> + Edit... + </message> + <message name="IDS_AUTOFILL_EDIT_ADDRESS_CAPTION" desc="The caption on the edit AutoFill address dialog."> + Edit address + </message> + <message name="IDS_AUTOFILL_ADD_ADDRESS_CAPTION" desc="The caption on the edit AutoFill address dialog for the new entry."> + Add an address + </message> + <message name="IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION" desc="The caption on the edit AutoFill credit card dialog."> + Edit credit card + </message> + <message name="IDS_AUTOFILL_ADD_CREDITCARD_CAPTION" desc="The caption on the edit AutoFill credit card dialog the new entry."> Add a credit card </message> + <message name="IDS_AUTOFILL_LIST_HEADER_LABEL" desc="The text on the list view header over the label."> + Profile + </message> + <message name="IDS_AUTOFILL_LIST_HEADER_SUMMARY" desc="The text on the list view header over the summary."> + Summary + </message> <message name="IDS_AUTOFILL_DELETE_BUTTON" desc="The label of the button that deletes an AutoFill profile."> - Delete + Remove + </message> + <message name="IDS_AUTOFILL_BAD_LABEL_TOOLTIP" desc="Tooltip that appears over the wrong label."> + Label must contain at least one character. </message> <message name="IDS_AUTOFILL_NEW_ADDRESS" desc="The profile label of a new address."> New address @@ -5658,6 +5683,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_AUTOFILL_DIALOG_LABEL" desc="The label of the Label entry."> Label </message> + <message name="IDS_AUTOFILL_DIALOG_FULL_NAME" desc="The label of the Full name entry."> + Full name + </message> <message name="IDS_AUTOFILL_DIALOG_FIRST_NAME" desc="The label of the First name entry."> First name </message> diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index fbb9da12..c693bba 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd @@ -640,6 +640,26 @@ 32 </message> + <!-- The width of the AutoFill edit Address dialog in characters. --> + <message name="IDS_AUTOFILL_DIALOG_EDIT_ADDRESS_WIDTH_CHARS" use_name_for_id="true"> + 80 + </message> + + <!-- The height of the AutoFill edit Address dialog in lines. --> + <message name="IDS_AUTOFILL_DIALOG_EDIT_ADDRESS_HEIGHT_LINES" use_name_for_id="true"> + 27 + </message> + + <!-- The width of the AutoFill edit Credit Card dialog in characters. --> + <message name="IDS_AUTOFILL_DIALOG_EDIT_CCARD_WIDTH_CHARS" use_name_for_id="true"> + 60 + </message> + + <!-- The height of the AutoFill edit Credit Card dialog in lines. --> + <message name="IDS_AUTOFILL_DIALOG_EDIT_CCARD_HEIGHT_LINES" use_name_for_id="true"> + 18 + </message> + <!-- The URL for About Google Translate. --> <message name="IDS_ABOUT_GOOGLE_TRANSLATE_URL" translateable="false"> http://www.google.com/support/chrome/bin/answer.py?answer=173424&hl=[GRITLANGCODE] diff --git a/chrome/browser/autofill/phone_number.cc b/chrome/browser/autofill/phone_number.cc index a32bb57..2c541b4 100644 --- a/chrome/browser/autofill/phone_number.cc +++ b/chrome/browser/autofill/phone_number.cc @@ -123,7 +123,7 @@ void PhoneNumber::SetInfo(const AutoFillType& type, const string16& value) { } // Static. -void PhoneNumber::ParsePhoneNumber(const string16& value, +bool PhoneNumber::ParsePhoneNumber(const string16& value, string16* number, string16* city_code, string16* country_code) { @@ -142,24 +142,25 @@ void PhoneNumber::ParsePhoneNumber(const string16& value, StripPunctuation(&working); if (working.size() < kPhoneNumberLength) - return; + return false; // Treat the last 7 digits as the number. *number = working.substr(working.size() - kPhoneNumberLength, kPhoneNumberLength); working.resize(working.size() - kPhoneNumberLength); if (working.size() < kPhoneCityCodeLength) - return; + return true; // Treat the next three digits as the city code. *city_code = working.substr(working.size() - kPhoneCityCodeLength, kPhoneCityCodeLength); working.resize(working.size() - kPhoneCityCodeLength); if (working.empty()) - return; + return true; // Treat any remaining digits as the country code. *country_code = working; + return true; } string16 PhoneNumber::WholeNumber() const { diff --git a/chrome/browser/autofill/phone_number.h b/chrome/browser/autofill/phone_number.h index da6f051..9da3b98 100644 --- a/chrome/browser/autofill/phone_number.h +++ b/chrome/browser/autofill/phone_number.h @@ -30,7 +30,8 @@ class PhoneNumber : public FormGroup { // returns the trailing 7 digits, |city_code| returns the next 3 digits, and // |country_code| returns any remaining digits. // Separator characters are stripped before parsing the digits. - static void ParsePhoneNumber(const string16& value, + // Returns true if parsing was successfull, false otherwise. + static bool ParsePhoneNumber(const string16& value, string16* number, string16* city_code, string16* country_code); diff --git a/chrome/browser/views/autofill_profiles_view_win.cc b/chrome/browser/views/autofill_profiles_view_win.cc index dc2af81..c7421c7 100644 --- a/chrome/browser/views/autofill_profiles_view_win.cc +++ b/chrome/browser/views/autofill_profiles_view_win.cc @@ -9,7 +9,10 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/message_loop.h" +#include "base/string_util.h" +#include "base/time.h" #include "chrome/browser/autofill/autofill_manager.h" +#include "chrome/browser/autofill/phone_number.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" @@ -32,6 +35,7 @@ #include "views/controls/label.h" #include "views/controls/scroll_view.h" #include "views/controls/separator.h" +#include "views/controls/table/table_view.h" #include "views/grid_layout.h" #include "views/standard_layout.h" #include "views/window/window.h" @@ -51,10 +55,6 @@ const int kSubViewInsets = 5; AutoFillProfilesView* AutoFillProfilesView::instance_ = NULL; ///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, static data: -int AutoFillProfilesView::ScrollViewContents::line_height_ = 0; - -///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView, public: AutoFillProfilesView::AutoFillProfilesView( AutoFillDialogObserver* observer, @@ -65,23 +65,21 @@ AutoFillProfilesView::AutoFillProfilesView( : observer_(observer), personal_data_manager_(personal_data_manager), preferences_(preferences), - save_changes_(NULL), + add_address_button_(NULL), + add_credit_card_button_(NULL), + edit_button_(NULL), + remove_button_(NULL), scroll_view_(NULL), - focus_manager_(NULL) { + focus_manager_(NULL), + billing_model_(true), + child_dialog_opened_(false) { DCHECK(preferences_); - default_profile_ = preferences_->GetString(prefs::kAutoFillDefaultProfile); - default_credit_card_ = - preferences_->GetString(prefs::kAutoFillDefaultCreditCard); - default_profile_iterator_ = profiles_set_.end(); - default_credit_card_iterator_ = credit_card_set_.end(); if (imported_profile) { - profiles_set_.push_back(EditableSetInfo(imported_profile, true, true)); - default_profile_iterator_ = profiles_set_.begin(); + profiles_set_.push_back(EditableSetInfo(imported_profile)); } if (imported_credit_card) { credit_card_set_.push_back( - EditableSetInfo(imported_credit_card, true, true)); - default_credit_card_iterator_ = credit_card_set_.begin(); + EditableSetInfo(imported_credit_card)); } } @@ -113,113 +111,100 @@ int AutoFillProfilesView::Show(gfx::NativeWindow parent, ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView, protected: -void AutoFillProfilesView::AddClicked(EditableSetType item_type) { - int group_id = 0; - if (item_type == EDITABLE_SET_ADDRESS) { +void AutoFillProfilesView::AddClicked(int group_type) { + std::vector<EditableSetInfo>::iterator it = profiles_set_.end(); + int added_item_index = -1; + if (group_type == ContentListTableModel::kAddressGroup) { AutoFillProfile address(std::wstring(), 0); - // If it is the first item, set it to default. Otherwise default is already - // set. - bool default_item = (profiles_set_.size() == 0); - profiles_set_.push_back(EditableSetInfo(&address, true, default_item)); - group_id = profiles_set_.size() - 1; - SetDefaultProfileIterator(); - } else if (item_type == EDITABLE_SET_CREDIT_CARD) { + profiles_set_.push_back(EditableSetInfo(&address)); + added_item_index = profiles_set_.size() - 1; + it = profiles_set_.begin() + added_item_index; + } else if (group_type == ContentListTableModel::kCreditCardGroup) { CreditCard credit_card(std::wstring(), 0); - // If it is the first item, set it to default. Otherwise default is already - // set. - bool default_item = (credit_card_set_.size() == 0); - credit_card_set_.push_back(EditableSetInfo(&credit_card, true, - default_item)); - group_id = profiles_set_.size() + credit_card_set_.size() - 1; - SetDefaultCreditCardIterator(); + credit_card_set_.push_back(EditableSetInfo(&credit_card)); + added_item_index = profiles_set_.size() + credit_card_set_.size() - 1; + it = credit_card_set_.begin() + (credit_card_set_.size() - 1); } else { NOTREACHED(); } - scroll_view_->RebuildView(FocusedItem(group_id, - EditableSetViewContents::kLabelText)); - scroll_view_->EnsureGroupOnScreen(group_id); -} - -void AutoFillProfilesView::DeleteEditableSet( - std::vector<EditableSetInfo>::iterator field_set_iterator) { - FocusedItem focused_item_index; - if (field_set_iterator->is_address) { - string16 label = field_set_iterator->address.Label(); - bool set_new_default = false; - if (field_set_iterator->is_default && profiles_set_.size() > 1) - set_new_default = true; - profiles_set_.erase(field_set_iterator); - // Set first profile as a new default. - if (set_new_default) { - profiles_set_[0].is_default = true; - default_profile_iterator_ = profiles_set_.begin(); - } - for (std::vector<EditableSetInfo>::iterator it = credit_card_set_.begin(); - it != credit_card_set_.end(); - ++it) { - if (it->credit_card.shipping_address() == label) - it->credit_card.set_shipping_address(string16()); - if (it->credit_card.billing_address() == label) - it->credit_card.set_billing_address(string16()); - } - focused_item_index = FocusedItem(ScrollViewContents::kAddAddressButton, 0); - } else { - bool set_new_default = false; - if (field_set_iterator->is_default && credit_card_set_.size() > 1) - set_new_default = true; - credit_card_set_.erase(field_set_iterator); - // Set first credit card as a new default. - if (set_new_default) { - credit_card_set_[0].is_default = true; - default_credit_card_iterator_ = credit_card_set_.begin(); - } - focused_item_index = FocusedItem(ScrollViewContents::kAddCcButton, 0); - } - scroll_view_->RebuildView(focused_item_index); + EditableSetViewContents *edit_view = new + EditableSetViewContents(this, &billing_model_, true, it); + views::Window::CreateChromeWindow(window()->GetNativeWindow(), gfx::Rect(), + edit_view); + edit_view->window()->Show(); } -void AutoFillProfilesView::CollapseStateChanged( - std::vector<EditableSetInfo>::iterator field_set_iterator) { - scroll_view_->RebuildView(FocusedItem()); +void AutoFillProfilesView::EditClicked() { + DCHECK(scroll_view_); + int index = scroll_view_->FirstSelectedRow(); + DCHECK(index >= 0); + DCHECK(index < static_cast<int>(profiles_set_.size() + + credit_card_set_.size())); + std::vector<EditableSetInfo>::iterator it; + if (index < static_cast<int>(profiles_set_.size())) + it = profiles_set_.begin() + index; + else + it = credit_card_set_.begin() + (index - profiles_set_.size()); + + EditableSetViewContents *edit_view = new + EditableSetViewContents(this, &billing_model_, false, it); + views::Window::CreateChromeWindow(window()->GetNativeWindow(), gfx::Rect(), + edit_view); + edit_view->window()->Show(); } -void AutoFillProfilesView::NewDefaultSet( - std::vector<EditableSetInfo>::iterator field_set_iterator) { - if (field_set_iterator->is_address) { - if (default_profile_iterator_ != profiles_set_.end()) - default_profile_iterator_->is_default = false; - default_profile_iterator_ = field_set_iterator; - } else { - if (default_credit_card_iterator_ != credit_card_set_.end()) - default_credit_card_iterator_->is_default = false; - default_credit_card_iterator_ = field_set_iterator; - } +void AutoFillProfilesView::DeleteClicked() { + DCHECK(scroll_view_); + DCHECK(table_model_.get()); + int selected_item_index = scroll_view_->FirstSelectedRow(); + DCHECK(selected_item_index >= 0); + table_model_->RemoveItem(selected_item_index); + UpdateButtonState(); } +void AutoFillProfilesView::UpdateButtonState() { + DCHECK(personal_data_manager_); + DCHECK(scroll_view_); + DCHECK(add_address_button_); + DCHECK(add_credit_card_button_); + DCHECK(edit_button_); + DCHECK(remove_button_); + add_address_button_->SetEnabled(personal_data_manager_->IsDataLoaded() && + !child_dialog_opened_); + add_credit_card_button_->SetEnabled(personal_data_manager_->IsDataLoaded() && + !child_dialog_opened_); -void AutoFillProfilesView::ValidateAndFixLabel() { - std::wstring unset_label(l10n_util::GetString(IDS_AUTOFILL_UNTITLED_LABEL)); - for (std::vector<EditableSetInfo>::iterator it = profiles_set_.begin(); - it != profiles_set_.end(); - ++it) { - if (it->address.Label().empty()) - it->address.set_label(unset_label); - } - for (std::vector<EditableSetInfo>::iterator it = credit_card_set_.begin(); - it != credit_card_set_.end(); - ++it) { - if (it->credit_card.Label().empty()) - it->credit_card.set_label(unset_label); + int selected_item_index = scroll_view_->FirstSelectedRow(); + edit_button_->SetEnabled(selected_item_index >= 0 && !child_dialog_opened_); + remove_button_->SetEnabled(selected_item_index >= 0 && !child_dialog_opened_); +} + +void AutoFillProfilesView::ChildWindowOpened() { + child_dialog_opened_ = true; + UpdateButtonState(); +} + +void AutoFillProfilesView::ChildWindowClosed() { + child_dialog_opened_ = false; + UpdateButtonState(); +} + +SkBitmap* AutoFillProfilesView::GetWarningBimap(bool good) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + // TODO(georgey) : change to correct icons when available. + if (good) { + return rb.GetBitmapNamed(ThemeResourcesUtil::GetId("update_uptodate")); + } else { + return rb.GetBitmapNamed(ThemeResourcesUtil::GetId("update_available")); } } + ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView, views::View implementations void AutoFillProfilesView::Layout() { - scroll_view_->SetBounds(kDialogPadding, kDialogPadding, - width() - (2 * kDialogPadding), - height() - (2 * kDialogPadding)); + View::Layout(); } gfx::Size AutoFillProfilesView::GetPreferredSize() { @@ -305,36 +290,25 @@ views::View* AutoFillProfilesView::GetContentsView() { return this; } +bool AutoFillProfilesView::Cancel() { + // No way to cancel - we save back all the info always. + return Accept(); +} + bool AutoFillProfilesView::Accept() { DCHECK(observer_); - ValidateAndFixLabel(); std::vector<AutoFillProfile> profiles; profiles.reserve(profiles_set_.size()); std::vector<EditableSetInfo>::iterator it; - string16 new_default_profile; for (it = profiles_set_.begin(); it != profiles_set_.end(); ++it) { profiles.push_back(it->address); - if (it->is_default) - new_default_profile = it->address.Label(); } std::vector<CreditCard> credit_cards; credit_cards.reserve(credit_card_set_.size()); - string16 new_default_cc; for (it = credit_card_set_.begin(); it != credit_card_set_.end(); ++it) { credit_cards.push_back(it->credit_card); - if (it->is_default) - new_default_cc = it->credit_card.Label(); } DCHECK(preferences_); - if (default_profile_ != new_default_profile) { - default_profile_ = new_default_profile; - preferences_->SetString(prefs::kAutoFillDefaultProfile, default_profile_); - } - if (default_credit_card_ != new_default_cc) { - default_credit_card_ = new_default_cc; - preferences_->SetString(prefs::kAutoFillDefaultCreditCard, - default_credit_card_); - } observer_->OnAutoFillDialogApply(&profiles, &credit_cards); return true; } @@ -343,7 +317,15 @@ bool AutoFillProfilesView::Accept() { // AutoFillProfilesView, views::ButtonListener implementations: void AutoFillProfilesView::ButtonPressed(views::Button* sender, const views::Event& event) { - NOTIMPLEMENTED(); + if (sender == add_address_button_) { + AddClicked(ContentListTableModel::kAddressGroup); + } else if (sender == add_credit_card_button_) { + AddClicked(ContentListTableModel::kCreditCardGroup); + } else if (sender == edit_button_) { + EditClicked(); + } else if (sender == remove_button_) { + DeleteClicked(); + } } ///////////////////////////////////////////////////////////////////////////// @@ -365,42 +347,96 @@ void AutoFillProfilesView::FocusWillChange(views::View* focused_before, } } +///////////////////////////////////////////////////////////////////////////// +// AutoFillProfilesView, views::TableViewObserver implementations: +void AutoFillProfilesView::OnSelectionChanged() { + UpdateButtonState(); +} + +void AutoFillProfilesView::OnDoubleClick() { + if (!child_dialog_opened_) + EditClicked(); +} + ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView, PersonalDataManager::Observer implementation. void AutoFillProfilesView::OnPersonalDataLoaded() { personal_data_manager_->RemoveObserver(this); GetData(); - FocusedItem focused_item_index(ScrollViewContents::kAddAddressButton, 0); - if (profiles_set_.size() + credit_card_set_.size() > 0) { - focused_item_index = FocusedItem(0, EditableSetViewContents::kLabelText); - } - - scroll_view_->RebuildView(focused_item_index); } ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView, private: void AutoFillProfilesView::Init() { GetData(); - scroll_view_ = new AutoFillScrollView(this, - &profiles_set_, - &credit_card_set_); + + billing_model_.set_address_labels(&profiles_set_); + + table_model_.reset(new ContentListTableModel(&profiles_set_, + &credit_card_set_)); + std::vector<TableColumn> columns; + columns.resize(2); + columns[0] = TableColumn(IDS_AUTOFILL_LIST_HEADER_LABEL, + TableColumn::LEFT, -1, .33f); + columns.back().sortable = false; + columns[1] = TableColumn(IDS_AUTOFILL_LIST_HEADER_SUMMARY, + TableColumn::LEFT, -1, .67f); + columns.back().sortable = false; + + scroll_view_ = new views::TableView(table_model_.get(), columns, + views::TEXT_ONLY, true, true, true); + scroll_view_->SetObserver(this); + + add_address_button_ = new views::NativeButton(this, + l10n_util::GetString(IDS_AUTOFILL_ADD_ADDRESS_BUTTON)); + add_credit_card_button_ = new views::NativeButton(this, + l10n_util::GetString(IDS_AUTOFILL_ADD_CREDITCARD_BUTTON)); + edit_button_ = new views::NativeButton(this, + l10n_util::GetString(IDS_AUTOFILL_EDIT_BUTTON)); + remove_button_ = new views::NativeButton(this, + l10n_util::GetString(IDS_AUTOFILL_DELETE_BUTTON)); views::GridLayout* layout = CreatePanelGridLayout(this); SetLayoutManager(layout); - const int single_column_view_set_id = 0; + const int table_with_buttons_column_view_set_id = 0; views::ColumnSet* column_set = - layout->AddColumnSet(single_column_view_set_id); + layout->AddColumnSet(table_with_buttons_column_view_set_id); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, - views::GridLayout::USE_PREF, 0, 0); - layout->StartRow(1, single_column_view_set_id); - layout->AddView(scroll_view_); - ValidateAndFixLabel(); + views::GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0, + views::GridLayout::USE_PREF, 0, 0); + + layout->StartRow(0, table_with_buttons_column_view_set_id); + layout->AddView(scroll_view_, 1, 8, views::GridLayout::FILL, + views::GridLayout::FILL); + layout->AddView(add_address_button_); + + layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0, + kRelatedControlVerticalSpacing); + layout->SkipColumns(2); + layout->AddView(add_credit_card_button_); + + layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0, + kRelatedControlVerticalSpacing); + layout->SkipColumns(2); + layout->AddView(edit_button_); + + layout->StartRowWithPadding(0, table_with_buttons_column_view_set_id, 0, + kRelatedControlVerticalSpacing); + layout->SkipColumns(2); + layout->AddView(remove_button_); + + layout->AddPaddingRow(1, table_with_buttons_column_view_set_id); + + focus_manager_ = GetFocusManager(); DCHECK(focus_manager_); focus_manager_->AddFocusChangeListener(this); + + UpdateButtonState(); } void AutoFillProfilesView::GetData() { @@ -410,83 +446,85 @@ void AutoFillProfilesView::GetData() { } bool imported_data_present = !profiles_set_.empty() || !credit_card_set_.empty(); - bool default_set = !profiles_set_.empty(); if (!imported_data_present) { profiles_set_.reserve(personal_data_manager_->profiles().size()); for (std::vector<AutoFillProfile*>::const_iterator address_it = personal_data_manager_->profiles().begin(); address_it != personal_data_manager_->profiles().end(); ++address_it) { - bool default_profile = ((*address_it)->Label() == default_profile_); - default_set = (default_set || default_profile); - profiles_set_.push_back(EditableSetInfo(*address_it, false, - default_profile)); + profiles_set_.push_back(EditableSetInfo(*address_it)); } } - // If nothing is default, set first to be default. - if (!default_set && profiles_set_.size() > 0) - profiles_set_[0].is_default = true; - default_set = !credit_card_set_.empty(); if (!imported_data_present) { credit_card_set_.reserve(personal_data_manager_->credit_cards().size()); for (std::vector<CreditCard*>::const_iterator cc_it = personal_data_manager_->credit_cards().begin(); cc_it != personal_data_manager_->credit_cards().end(); ++cc_it) { - bool default_cc = ((*cc_it)->Label() == default_credit_card_); - default_set = (default_set || default_cc); - credit_card_set_.push_back(EditableSetInfo(*cc_it, false, default_cc)); + credit_card_set_.push_back(EditableSetInfo(*cc_it)); } } - // If nothing is default, set first to be default. - if (!default_set && credit_card_set_.size() > 0) - credit_card_set_[0].is_default = true; + if (table_model_.get()) + table_model_->Refresh(); - // Remember default iterators. - SetDefaultProfileIterator(); - SetDefaultCreditCardIterator(); + // Update state only if buttons already created. + if (add_address_button_) { + UpdateButtonState(); + } } bool AutoFillProfilesView::IsDataReady() const { return personal_data_manager_->IsDataLoaded(); } -void AutoFillProfilesView::SetDefaultProfileIterator() { - for (default_profile_iterator_ = profiles_set_.begin(); - default_profile_iterator_ != profiles_set_.end(); - ++default_profile_iterator_) { - if (default_profile_iterator_->is_default) - break; - } -} - -void AutoFillProfilesView::SetDefaultCreditCardIterator() { - for (default_credit_card_iterator_ = credit_card_set_.begin(); - default_credit_card_iterator_ != credit_card_set_.end(); - ++default_credit_card_iterator_) { - if (default_credit_card_iterator_->is_default) - break; - } -} - ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::PhoneSubView, public: AutoFillProfilesView::PhoneSubView::PhoneSubView( + AutoFillProfilesView* autofill_view, views::Label* label, - views::Textfield* text_country, - views::Textfield* text_area, views::Textfield* text_phone) - : label_(label), - text_country_(text_country), - text_area_(text_area), - text_phone_(text_phone) { + : autofill_view_(autofill_view), + label_(label), + text_phone_(text_phone), + phone_warning_button_(NULL), + last_state_(false) { DCHECK(label_); - DCHECK(text_country_); - DCHECK(text_area_); DCHECK(text_phone_); } +void AutoFillProfilesView::PhoneSubView::ContentsChanged( + views::Textfield* sender, const string16& new_contents) { + if (sender == text_phone_) { + UpdateButtons(); + } +} + +bool AutoFillProfilesView::PhoneSubView::IsValid() const { + if (text_phone_) { + string16 phone = text_phone_->text(); + if (phone.empty()) + return true; + + // Try to parse it. + string16 country, city, stripped_phone; + return PhoneNumber::ParsePhoneNumber(phone, &country, &city, + &stripped_phone); + } + return false; +} + +void AutoFillProfilesView::PhoneSubView::UpdateButtons() { + if (phone_warning_button_) { + SkBitmap* image = autofill_view_->GetWarningBimap(IsValid()); + phone_warning_button_->SetImage(views::CustomButton::BS_NORMAL, image); + if (last_state_ != IsValid()) { + last_state_ = IsValid(); + SchedulePaint(); + } + } +} + ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::PhoneSubView, protected: ///////////////////////////////////////////////////////////////////////////// @@ -496,26 +534,25 @@ void AutoFillProfilesView::PhoneSubView::ViewHierarchyChanged( if (is_add && this == child) { views::GridLayout* layout = new views::GridLayout(this); SetLayoutManager(layout); - const int triple_column_fill_view_set_id = 0; + const int two_column_fill_view_set_id = 0; views::ColumnSet* column_set = - layout->AddColumnSet(triple_column_fill_view_set_id); + layout->AddColumnSet(two_column_fill_view_set_id); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1, + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0); - column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 2, - views::GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, triple_column_fill_view_set_id); - layout->AddView(label_, 5, 1); - layout->StartRow(0, triple_column_fill_view_set_id); - text_country_->set_default_width_in_chars(5); - text_area_->set_default_width_in_chars(5); - text_phone_->set_default_width_in_chars(10); - layout->AddView(text_country_); - layout->AddView(text_area_); + layout->StartRow(0, two_column_fill_view_set_id); + layout->AddView(label_, 3, 1); + layout->StartRow(0, two_column_fill_view_set_id); + text_phone_->set_default_width_in_chars(15); layout->AddView(text_phone_); + phone_warning_button_ = new views::ImageButton(this); + phone_warning_button_->SetEnabled(false); + phone_warning_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, + views::ImageButton::ALIGN_MIDDLE); + layout->AddView(phone_warning_button_); + UpdateButtons(); } } @@ -524,15 +561,9 @@ void AutoFillProfilesView::PhoneSubView::ViewHierarchyChanged( AutoFillProfilesView::EditableSetViewContents::TextFieldToAutoFill AutoFillProfilesView::EditableSetViewContents::address_fields_[] = { { AutoFillProfilesView::EditableSetViewContents::TEXT_LABEL, NO_SERVER_DATA }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_FIRST_NAME, - NAME_FIRST }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_MIDDLE_NAME, - NAME_MIDDLE }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_LAST_NAME, - NAME_LAST }, + { AutoFillProfilesView::EditableSetViewContents::TEXT_FULL_NAME, + NAME_FULL }, { AutoFillProfilesView::EditableSetViewContents::TEXT_EMAIL, EMAIL_ADDRESS }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_COMPANY_NAME, - COMPANY_NAME }, { AutoFillProfilesView::EditableSetViewContents::TEXT_ADDRESS_LINE_1, ADDRESS_HOME_LINE1 }, { AutoFillProfilesView::EditableSetViewContents::TEXT_ADDRESS_LINE_2, @@ -545,16 +576,8 @@ AutoFillProfilesView::EditableSetViewContents::TextFieldToAutoFill ADDRESS_HOME_ZIP }, { AutoFillProfilesView::EditableSetViewContents::TEXT_ADDRESS_COUNTRY, ADDRESS_HOME_COUNTRY }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_COUNTRY, - PHONE_HOME_COUNTRY_CODE }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_AREA, - PHONE_HOME_CITY_CODE }, { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_PHONE, PHONE_HOME_NUMBER }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_FAX_COUNTRY, - PHONE_FAX_COUNTRY_CODE }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_FAX_AREA, - PHONE_FAX_CITY_CODE }, { AutoFillProfilesView::EditableSetViewContents::TEXT_FAX_PHONE, PHONE_FAX_NUMBER }, }; @@ -566,20 +589,8 @@ AutoFillProfilesView::EditableSetViewContents::TextFieldToAutoFill CREDIT_CARD_NAME }, { AutoFillProfilesView::EditableSetViewContents::TEXT_CC_NUMBER, CREDIT_CARD_NUMBER }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_CC_EXPIRATION_MONTH, - CREDIT_CARD_EXP_MONTH }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_CC_EXPIRATION_YEAR, - CREDIT_CARD_EXP_4_DIGIT_YEAR }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_CC_EXPIRATION_CVC, + { AutoFillProfilesView::EditableSetViewContents::TEXT_CC_CVC, CREDIT_CARD_VERIFICATION_CODE }, - /* Phone is disabled for now. - { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_COUNTRY, - PHONE_HOME_COUNTRY_CODE }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_AREA, - PHONE_HOME_CITY_CODE }, - { AutoFillProfilesView::EditableSetViewContents::TEXT_PHONE_PHONE, - PHONE_HOME_NUMBER }, - */ }; ///////////////////////////////////////////////////////////////////////////// @@ -587,59 +598,19 @@ AutoFillProfilesView::EditableSetViewContents::TextFieldToAutoFill AutoFillProfilesView::EditableSetViewContents::EditableSetViewContents( AutoFillProfilesView* observer, AddressComboBoxModel* billing_model, - AddressComboBoxModel* shipping_model, + bool new_item, std::vector<EditableSetInfo>::iterator field_set) : editable_fields_set_(field_set), - delete_button_(NULL), - expand_item_button_(NULL), + temporary_info_(*editable_fields_set_), title_label_(NULL), - title_label_preview_(NULL), + label_warning_button_(NULL), observer_(observer), billing_model_(billing_model), - shipping_model_(shipping_model), combo_box_billing_(NULL), - combo_box_shipping_(NULL) { + new_item_(new_item) { ZeroMemory(text_fields_, sizeof(text_fields_)); } -// Two helpers to set focus correctly during rebuild of list view. -int AutoFillProfilesView::EditableSetViewContents::GetFocusedControlIndex( - const views::View* focus) const { - DCHECK(focus); - if (static_cast<const views::View*>(expand_item_button_) == focus) - return 0; - if (static_cast<const views::View*>(combo_box_billing_) == focus) - return 1; - if (static_cast<const views::View*>(combo_box_shipping_) == focus) - return 2; - if (static_cast<const views::View*>(delete_button_) == focus) - return 3; - for (int i = 0; i < MAX_TEXT_FIELD; ++i) { - if (static_cast<const views::View*>(text_fields_[i]) == focus) - return i + 4; - } - return AutoFillProfilesView::kNoItemFocused; -} - -views::View* AutoFillProfilesView::EditableSetViewContents::GetFocusedControl( - int index) { - if (index == 0 || index == AutoFillProfilesView::kNoItemFocused || - !editable_fields_set_->is_opened) { - return expand_item_button_; - } - switch (index) { - case 1: - return combo_box_billing_; - case 2: - return combo_box_shipping_; - case 3: - return delete_button_; - default: - DCHECK(index - 4 < MAX_TEXT_FIELD); - return text_fields_[index - 4]; - } -} - ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::EditableSetViewContents, protected: ///////////////////////////////////////////////////////////////////////////// @@ -649,62 +620,157 @@ void AutoFillProfilesView::EditableSetViewContents::Layout() { } gfx::Size AutoFillProfilesView::EditableSetViewContents::GetPreferredSize() { - gfx::Size prefsize; - views::View* parent = GetParent(); - if (parent && parent->width()) { - const int width = parent->width(); - prefsize = gfx::Size(width, GetHeightForWidth(width)); + if (temporary_info_.is_address) { + return views::Window::GetLocalizedContentsSize( + IDS_AUTOFILL_DIALOG_EDIT_ADDRESS_WIDTH_CHARS, + IDS_AUTOFILL_DIALOG_EDIT_ADDRESS_HEIGHT_LINES); + } else { + return views::Window::GetLocalizedContentsSize( + IDS_AUTOFILL_DIALOG_EDIT_CCARD_WIDTH_CHARS, + IDS_AUTOFILL_DIALOG_EDIT_CCARD_HEIGHT_LINES); } - return prefsize; } void AutoFillProfilesView::EditableSetViewContents::ViewHierarchyChanged( bool is_add, views::View* parent, views::View* child) { if (is_add && this == child) { + observer_->ChildWindowOpened(); views::GridLayout* layout = new views::GridLayout(this); layout->SetInsets(kSubViewInsets, kSubViewInsets, kSubViewInsets, kSubViewInsets); SetLayoutManager(layout); InitLayoutGrid(layout); - delete_button_ = new views::NativeButton(this, - l10n_util::GetString(IDS_AUTOFILL_DELETE_BUTTON)); - InitTitle(layout); - if (editable_fields_set_->is_opened) { - if (editable_fields_set_->is_address) - InitAddressFields(layout); - else - InitCreditCardFields(layout); - // Create border, but only if it is opened. - // The border is a standard group box. - SkColor border_color = - gfx::NativeTheme::instance()->GetThemeColorWithDefault( - gfx::NativeTheme::BUTTON, BP_GROUPBOX, GBS_NORMAL, - TMT_EDGESHADOWCOLOR, COLOR_GRAYTEXT); - set_border(views::Border::CreateSolidBorder(1, border_color)); + if (temporary_info_.is_address) + InitAddressFields(layout); + else + InitCreditCardFields(layout); + } +} + +///////////////////////////////////////////////////////////////////////////// +// AutoFillProfilesView::EditableSetViewContents, +// views::DialogDelegate implementations +int AutoFillProfilesView::EditableSetViewContents::GetDialogButtons() const { + return MessageBoxFlags::DIALOGBUTTON_CANCEL | + MessageBoxFlags::DIALOGBUTTON_OK; +} + +std::wstring +AutoFillProfilesView::EditableSetViewContents::GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const { + switch (button) { + case MessageBoxFlags::DIALOGBUTTON_OK: + return l10n_util::GetString(IDS_AUTOFILL_DIALOG_SAVE); + case MessageBoxFlags::DIALOGBUTTON_CANCEL: + return std::wstring(); + default: + break; + } + NOTREACHED(); + return std::wstring(); +} + +bool AutoFillProfilesView::EditableSetViewContents::IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const { + switch (button) { + case MessageBoxFlags::DIALOGBUTTON_OK: { + bool phones_are_valid = true; + for (std::vector<PhoneSubView*>::const_iterator it = + phone_sub_views_.begin(); + it != phone_sub_views_.end() && phones_are_valid; ++it) + phones_are_valid = (phones_are_valid && (*it)->IsValid()); + + return phones_are_valid && LabelValid(); + } + case MessageBoxFlags::DIALOGBUTTON_CANCEL: + return true; + default: + break; + } + NOTREACHED(); + return false; +} + +std::wstring +AutoFillProfilesView::EditableSetViewContents::GetWindowTitle() const { + int string_id = 0; + if (temporary_info_.is_address) { + string_id = new_item_ ? IDS_AUTOFILL_ADD_ADDRESS_CAPTION : + IDS_AUTOFILL_EDIT_ADDRESS_CAPTION; + } else { + string_id = new_item_ ? IDS_AUTOFILL_ADD_CREDITCARD_CAPTION : + IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION; + } + return l10n_util::GetString(string_id); +} + +void AutoFillProfilesView::EditableSetViewContents::WindowClosing() { + observer_->ChildWindowClosed(); +} + +views::View* AutoFillProfilesView::EditableSetViewContents::GetContentsView() { + return this; +} + +bool AutoFillProfilesView::EditableSetViewContents::Cancel() { + if (new_item_) { + // Remove added item - it is last in the list. + if (temporary_info_.is_address) { + observer_->profiles_set_.pop_back(); + } else { + observer_->credit_card_set_.pop_back(); } } + return true; +} + +bool AutoFillProfilesView::EditableSetViewContents::Accept() { + *editable_fields_set_ = temporary_info_; + int index = -1; + if (temporary_info_.is_address) { + index = editable_fields_set_ - observer_->profiles_set_.begin(); + } else { + index = editable_fields_set_ - observer_->credit_card_set_.begin(); + index += observer_->profiles_set_.size(); + } + if (new_item_) + observer_->table_model_->AddItem(index); + else + observer_->table_model_->UpdateItem(index); + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// AutoFillProfilesView::EditableSetViewContents, +// views::ButtonListener implementations +void AutoFillProfilesView::EditableSetViewContents::ButtonPressed( + views::Button* sender, const views::Event& event) { + NOTREACHED(); } + ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::EditableSetViewContents, // views::Textfield::Controller implementations void AutoFillProfilesView::EditableSetViewContents::ContentsChanged( views::Textfield* sender, const string16& new_contents) { - if (editable_fields_set_->is_address) { + if (temporary_info_.is_address) { for (int field = 0; field < arraysize(address_fields_); ++field) { DCHECK(text_fields_[address_fields_[field].text_field]); if (text_fields_[address_fields_[field].text_field] == sender) { if (address_fields_[field].text_field == TEXT_LABEL) { - editable_fields_set_->address.set_label(new_contents); + temporary_info_.address.set_label(new_contents); title_label_->SetText(new_contents); // One of the address labels changed - update combo boxes billing_model_->LabelChanged(); - shipping_model_->LabelChanged(); } else { - editable_fields_set_->address.SetInfo( + UpdateContentsPhoneViews(address_fields_[field].text_field, + sender, new_contents); + temporary_info_.address.SetInfo( AutoFillType(address_fields_[field].type), new_contents); } + UpdateButtons(); return; } } @@ -713,12 +779,15 @@ void AutoFillProfilesView::EditableSetViewContents::ContentsChanged( DCHECK(text_fields_[credit_card_fields_[field].text_field]); if (text_fields_[credit_card_fields_[field].text_field] == sender) { if (credit_card_fields_[field].text_field == TEXT_LABEL) { - editable_fields_set_->credit_card.set_label(new_contents); + temporary_info_.credit_card.set_label(new_contents); title_label_->SetText(new_contents); } else { - editable_fields_set_->credit_card.SetInfo( + UpdateContentsPhoneViews(address_fields_[field].text_field, + sender, new_contents); + temporary_info_.credit_card.SetInfo( AutoFillType(credit_card_fields_[field].type), new_contents); } + UpdateButtons(); return; } } @@ -728,55 +797,45 @@ void AutoFillProfilesView::EditableSetViewContents::ContentsChanged( bool AutoFillProfilesView::EditableSetViewContents::HandleKeystroke( views::Textfield* sender, const views::Textfield::Keystroke& keystroke) { if (sender == text_fields_[TEXT_CC_NUMBER] && - !editable_fields_set_->has_credit_card_number_been_edited) { + !temporary_info_.has_credit_card_number_been_edited) { // You cannot edit obfuscated number, you must retype it anew. sender->SetText(string16()); - editable_fields_set_->has_credit_card_number_been_edited = true; + temporary_info_.has_credit_card_number_been_edited = true; } return false; } ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::EditableSetViewContents, -// views::ButtonListener implementations: -void AutoFillProfilesView::EditableSetViewContents::ButtonPressed( - views::Button* sender, const views::Event& event) { - if (sender == delete_button_) { - observer_->DeleteEditableSet(editable_fields_set_); - } else if (sender == expand_item_button_ || - sender == title_label_ || sender == title_label_preview_) { - editable_fields_set_->is_opened = !editable_fields_set_->is_opened; - observer_->CollapseStateChanged(editable_fields_set_); - } else if (sender == default_) { - editable_fields_set_->is_default = true; - observer_->NewDefaultSet(editable_fields_set_); - } -} - -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::EditableSetViewContents, // views::Combobox::Listener implementations: void AutoFillProfilesView::EditableSetViewContents::ItemChanged( views::Combobox* combo_box, int prev_index, int new_index) { DCHECK(billing_model_); - DCHECK(shipping_model_); if (combo_box == combo_box_billing_) { if (new_index == -1) { NOTREACHED(); } else { - editable_fields_set_->credit_card.set_billing_address( + temporary_info_.credit_card.set_billing_address( billing_model_->GetItemAt(new_index)); } - } else if (combo_box == combo_box_shipping_) { + } else if (combo_box == combo_box_month_) { + if (new_index == -1) { + NOTREACHED(); + } else { + temporary_info_.credit_card.SetInfo( + AutoFillType(CREDIT_CARD_EXP_MONTH), + combo_box_model_month_->GetItemAt(new_index)); + } + } else if (combo_box == combo_box_year_) { if (new_index == -1) { NOTREACHED(); - } else if (new_index == 0) { - editable_fields_set_->credit_card.set_shipping_address( - editable_fields_set_->credit_card.billing_address()); } else { - editable_fields_set_->credit_card.set_shipping_address( - shipping_model_->GetItemAt(new_index)); + temporary_info_.credit_card.SetInfo( + AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), + combo_box_model_year_->GetItemAt(new_index)); } + } else { + NOTREACHED(); } } @@ -785,70 +844,33 @@ void AutoFillProfilesView::EditableSetViewContents::ItemChanged( void AutoFillProfilesView::EditableSetViewContents::InitTitle( views::GridLayout* layout) { std::wstring title; - std::wstring title_preview; - if (editable_fields_set_->is_address) { - title = editable_fields_set_->address.Label(); + if (temporary_info_.is_address) { + title = temporary_info_.address.Label(); if (title.empty()) title = l10n_util::GetString(IDS_AUTOFILL_NEW_ADDRESS); - title_preview = editable_fields_set_->address.PreviewSummary(); } else { - title = editable_fields_set_->credit_card.Label(); + title = temporary_info_.credit_card.Label(); if (title.empty()) title = l10n_util::GetString(IDS_AUTOFILL_NEW_CREDITCARD); - title_preview = editable_fields_set_->credit_card.PreviewSummary(); } - expand_item_button_ = new views::ImageButton(this); + label_warning_button_ = new views::ImageButton(this); + label_warning_button_->SetEnabled(false); + label_warning_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, + views::ImageButton::ALIGN_MIDDLE); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap* image = NULL; - if (editable_fields_set_->is_opened) { - image = - rb.GetBitmapNamed(ThemeResourcesUtil::GetId("expand_arrow_down_icon")); - } else { - image = - rb.GetBitmapNamed(ThemeResourcesUtil::GetId("expand_arrow_right_icon")); - title_label_preview_ = new views::TextButton(this, title_preview); - } - expand_item_button_->SetImage(views::CustomButton::BS_NORMAL, image); - expand_item_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, - views::ImageButton::ALIGN_MIDDLE); - expand_item_button_->SetFocusable(true); - title_label_ = new views::TextButton(this, title); gfx::Font title_font = rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD); - title_label_->SetFont(title_font); - // Text *must* be re-set after font to update dimensions. - title_label_->SetText(title); - - SkColor title_color = - gfx::NativeTheme::instance()->GetThemeColorWithDefault( - gfx::NativeTheme::BUTTON, BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, - COLOR_WINDOWTEXT); - title_label_->SetEnabledColor(title_color); - SkColor bk_color = - gfx::NativeTheme::instance()->GetThemeColorWithDefault( - gfx::NativeTheme::BUTTON, BP_PUSHBUTTON, PBS_NORMAL, TMT_BTNFACE, - COLOR_BTNFACE); - if (editable_fields_set_->is_opened) { - expand_item_button_->set_background( - views::Background::CreateSolidBackground(bk_color)); - title_label_->set_background( - views::Background::CreateSolidBackground(bk_color)); - } - title_label_->set_alignment(views::TextButton::ALIGN_LEFT); + title_label_ = new views::Label(title, title_font); + title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - layout->StartRow(0, three_column_header_); - layout->AddView(expand_item_button_, 2, 1); - if (editable_fields_set_->is_opened) { - layout->AddView(title_label_, 3, 1); - } else { - layout->AddView(title_label_); - layout->AddView(title_label_preview_); - } + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, triple_column_leading_view_set_id_); + layout->AddView(title_label_); } void AutoFillProfilesView::EditableSetViewContents::InitAddressFields( views::GridLayout* layout) { - DCHECK(editable_fields_set_->is_address); + DCHECK(temporary_info_.is_address); for (int field = 0; field < arraysize(address_fields_); ++field) { DCHECK(!text_fields_[address_fields_[field].text_field]); @@ -857,100 +879,119 @@ void AutoFillProfilesView::EditableSetViewContents::InitAddressFields( text_fields_[address_fields_[field].text_field]->SetController(this); if (address_fields_[field].text_field == TEXT_LABEL) { text_fields_[TEXT_LABEL]->SetText( - editable_fields_set_->address.Label()); + temporary_info_.address.Label()); } else { text_fields_[address_fields_[field].text_field]->SetText( - editable_fields_set_->address.GetFieldText( + temporary_info_.address.GetFieldText( AutoFillType(address_fields_[field].type))); } } - default_ = new views::RadioButton( - l10n_util::GetString(IDS_AUTOFILL_DIALOG_MAKE_DEFAULT), - kDefaultAddressesGroup); - default_->SetChecked(editable_fields_set_->is_default); - default_->set_listener(this); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, triple_column_leading_view_set_id_); layout->AddView(new views::Label( l10n_util::GetString(IDS_AUTOFILL_DIALOG_LABEL))); - layout->AddView(default_, 3, 1); + layout->StartRow(0, triple_column_fill_view_set_id_); layout->AddView(text_fields_[TEXT_LABEL]); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_FIRST_NAME)); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_MIDDLE_NAME)); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_LAST_NAME)); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(text_fields_[TEXT_FIRST_NAME]); - layout->AddView(text_fields_[TEXT_MIDDLE_NAME]); - layout->AddView(text_fields_[TEXT_LAST_NAME]); + layout->AddView(label_warning_button_); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EMAIL)); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_COMPANY_NAME), - 3, 1); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_FULL_NAME)); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(text_fields_[TEXT_EMAIL]); - layout->AddView(text_fields_[TEXT_COMPANY_NAME]); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(text_fields_[TEXT_FULL_NAME]); - layout->StartRow(0, triple_column_leading_view_set_id_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_leading_view_set_id_); layout->AddView(new views::Label(l10n_util::GetString( - IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1)), 3, 1); + IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1))); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(text_fields_[TEXT_ADDRESS_LINE_1], 3, 1); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(text_fields_[TEXT_ADDRESS_LINE_1]); - layout->StartRow(0, triple_column_leading_view_set_id_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_leading_view_set_id_); layout->AddView(new views::Label(l10n_util::GetString( - IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2)), 3, 1); + IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2))); - layout->StartRow(0, triple_column_fill_view_set_id_); - layout->AddView(text_fields_[TEXT_ADDRESS_LINE_2], 3, 1); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(text_fields_[TEXT_ADDRESS_LINE_2]); - layout->StartRow(0, four_column_city_state_zip_set_id_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, triple_column_fill_view_set_id_); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_CITY)); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_STATE)); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_ZIP_CODE)); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_COUNTRY)); - // City (33% - 16/48), state(33%), zip (12.7% - 5/42), country (21% - 11/48) + text_fields_[TEXT_ADDRESS_CITY]->set_default_width_in_chars(16); text_fields_[TEXT_ADDRESS_STATE]->set_default_width_in_chars(16); text_fields_[TEXT_ADDRESS_ZIP]->set_default_width_in_chars(5); - text_fields_[TEXT_ADDRESS_COUNTRY]->set_default_width_in_chars(11); - layout->StartRow(0, four_column_city_state_zip_set_id_); + layout->StartRow(0, triple_column_fill_view_set_id_); layout->AddView(text_fields_[TEXT_ADDRESS_CITY]); layout->AddView(text_fields_[TEXT_ADDRESS_STATE]); layout->AddView(text_fields_[TEXT_ADDRESS_ZIP]); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_COUNTRY)); + + text_fields_[TEXT_ADDRESS_COUNTRY]->set_default_width_in_chars(11); + + layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(text_fields_[TEXT_ADDRESS_COUNTRY]); PhoneSubView* phone = new PhoneSubView( + observer_, CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_PHONE), - text_fields_[TEXT_PHONE_COUNTRY], - text_fields_[TEXT_PHONE_AREA], text_fields_[TEXT_PHONE_PHONE]); + phone_sub_views_.push_back(phone); + PhoneSubView* fax = new PhoneSubView( + observer_, CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_FAX), - text_fields_[TEXT_FAX_COUNTRY], - text_fields_[TEXT_FAX_AREA], text_fields_[TEXT_FAX_PHONE]); + phone_sub_views_.push_back(fax); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(phone); layout->AddView(fax); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EMAIL)); - layout->StartRow(0, triple_column_leading_view_set_id_); - layout->AddView(delete_button_); + layout->StartRow(0, double_column_fill_view_set_id_); + layout->AddView(text_fields_[TEXT_EMAIL]); + + UpdateButtons(); } void AutoFillProfilesView::EditableSetViewContents::InitCreditCardFields( views::GridLayout* layout) { - DCHECK(!editable_fields_set_->is_address); + DCHECK(!temporary_info_.is_address); DCHECK(billing_model_); - DCHECK(shipping_model_); + + // Create combo box models. + combo_box_model_month_.reset(new StringVectorComboboxModel); + std::vector<std::wstring> model_strings; + model_strings.reserve(12); + for (int month = 1; month <= 12; ++month) + model_strings.push_back(StringPrintf(L"%02i", month)); + combo_box_model_month_->set_cb_strings(&model_strings); + model_strings.clear(); + model_strings.reserve(20); + base::Time::Exploded exploded_time; + base::Time::Now().LocalExplode(&exploded_time); + for (int year = 0; year < 20; ++year) + model_strings.push_back(StringPrintf(L"%04i", year + exploded_time.year)); + combo_box_model_year_.reset(new StringVectorComboboxModel); + combo_box_model_year_->set_cb_strings(&model_strings); for (int field = 0; field < arraysize(credit_card_fields_); ++field) { DCHECK(!text_fields_[credit_card_fields_[field].text_field]); @@ -960,89 +1001,86 @@ void AutoFillProfilesView::EditableSetViewContents::InitCreditCardFields( string16 field_text; switch (credit_card_fields_[field].text_field) { case TEXT_LABEL: - field_text = editable_fields_set_->credit_card.Label(); + field_text = temporary_info_.credit_card.Label(); break; case TEXT_CC_NUMBER: - field_text = editable_fields_set_->credit_card.GetFieldText( + field_text = temporary_info_.credit_card.GetFieldText( AutoFillType(credit_card_fields_[field].type)); if (!field_text.empty()) - field_text = editable_fields_set_->credit_card.ObfuscatedNumber(); + field_text = temporary_info_.credit_card.ObfuscatedNumber(); break; default: - field_text = editable_fields_set_->credit_card.GetFieldText( + field_text = temporary_info_.credit_card.GetFieldText( AutoFillType(credit_card_fields_[field].type)); break; } text_fields_[credit_card_fields_[field].text_field]->SetText(field_text); } - default_ = new views::RadioButton( - l10n_util::GetString(IDS_AUTOFILL_DIALOG_MAKE_DEFAULT), - kDefaultCreditCardsGroup); - default_->SetChecked(editable_fields_set_->is_default); - default_->set_listener(this); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, triple_column_leading_view_set_id_); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_LABEL)); - layout->AddView(default_, 3, 1); layout->StartRow(0, triple_column_fill_view_set_id_); layout->AddView(text_fields_[TEXT_LABEL]); + layout->AddView(label_warning_button_); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_NAME_ON_CARD)); layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(text_fields_[TEXT_CC_NAME]); + // Address combo boxes. combo_box_billing_ = new views::Combobox(billing_model_); combo_box_billing_->set_listener(this); combo_box_billing_->SetSelectedItem( billing_model_->GetIndex( - editable_fields_set_->credit_card.billing_address())); + temporary_info_.credit_card.billing_address())); billing_model_->UsedWithComboBox(combo_box_billing_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_BILLING_ADDRESS)); layout->StartRow(0, double_column_fill_view_set_id_); layout->AddView(combo_box_billing_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - combo_box_shipping_ = new views::Combobox(shipping_model_); - combo_box_shipping_->set_listener(this); - if (editable_fields_set_->credit_card.shipping_address() == - editable_fields_set_->credit_card.billing_address()) { - // The addresses are the same, so use "the same address" label. - combo_box_shipping_->SetSelectedItem(0); - } else { - combo_box_shipping_->SetSelectedItem( - shipping_model_->GetIndex( - editable_fields_set_->credit_card.shipping_address())); - } - shipping_model_->UsedWithComboBox(combo_box_shipping_); - - layout->StartRow(0, double_column_fill_view_set_id_); - layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_SHIPPING_ADDRESS)); - layout->StartRow(0, double_column_fill_view_set_id_); - layout->AddView(combo_box_shipping_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - // Layout credit card info - layout->StartRow(0, four_column_ccnumber_expiration_cvc_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + layout->StartRow(0, double_column_ccnumber_cvc_); layout->AddView( CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER)); - layout->AddView( - CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE), 3, 1); layout->AddView(CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_CVC)); - layout->StartRow(0, four_column_ccnumber_expiration_cvc_); + layout->StartRow(0, double_column_ccnumber_cvc_); // Number (20 chars), month(2 chars), year (4 chars), cvc (4 chars) text_fields_[TEXT_CC_NUMBER]->set_default_width_in_chars(20); - text_fields_[TEXT_CC_EXPIRATION_MONTH]->set_default_width_in_chars(2); - text_fields_[TEXT_CC_EXPIRATION_YEAR]->set_default_width_in_chars(4); - text_fields_[TEXT_CC_EXPIRATION_CVC]->set_default_width_in_chars(4); + text_fields_[TEXT_CC_CVC]->set_default_width_in_chars(4); layout->AddView(text_fields_[TEXT_CC_NUMBER]); - layout->AddView(text_fields_[TEXT_CC_EXPIRATION_MONTH]); - layout->AddView(text_fields_[TEXT_CC_EXPIRATION_YEAR]); - layout->AddView(text_fields_[TEXT_CC_EXPIRATION_CVC]); + layout->AddView(text_fields_[TEXT_CC_CVC]); - layout->StartRow(0, triple_column_leading_view_set_id_); - layout->AddView(delete_button_); + layout->StartRow(0, double_column_ccexpiration_); + layout->AddView( + CreateLeftAlignedLabel(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE), 3, 1); + + combo_box_month_ = new views::Combobox(combo_box_model_month_.get()); + combo_box_month_->set_listener(this); + string16 field_text; + field_text = temporary_info_.credit_card.GetFieldText( + AutoFillType(CREDIT_CARD_EXP_MONTH)); + combo_box_month_->SetSelectedItem( + combo_box_model_month_->GetIndex(field_text)); + + combo_box_year_ = new views::Combobox(combo_box_model_year_.get()); + combo_box_year_->set_listener(this); + field_text = temporary_info_.credit_card.GetFieldText( + AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)); + combo_box_year_->SetSelectedItem(combo_box_model_year_->GetIndex(field_text)); + + layout->StartRow(0, double_column_ccexpiration_); + layout->AddView(combo_box_month_); + layout->AddView(combo_box_year_); + + UpdateButtons(); } void AutoFillProfilesView::EditableSetViewContents::InitLayoutGrid( @@ -1096,20 +1134,23 @@ void AutoFillProfilesView::EditableSetViewContents::InitLayoutGrid( column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 11, views::GridLayout::USE_PREF, 0, 0); - column_set = layout->AddColumnSet(four_column_ccnumber_expiration_cvc_); + column_set = layout->AddColumnSet(double_column_ccnumber_cvc_); column_set->AddPaddingColumn(0, kPanelHorizIndentation); - // Number, expiration (month/year), and CVC are in ratio 20:2:4:4 + // Number and CVC are in ratio 20:4 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 20, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 2, views::GridLayout::USE_PREF, 0, 0); - column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 4, views::GridLayout::USE_PREF, 0, 0); + + column_set = layout->AddColumnSet(double_column_ccexpiration_); + column_set->AddPaddingColumn(0, kPanelHorizIndentation); + // Month and year are in proportion 1:2 + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, + 2, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, - 4, views::GridLayout::USE_PREF, 0, 0); + 4, views::GridLayout::USE_PREF, 0, 0); column_set = layout->AddColumnSet(three_column_header_); column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, @@ -1130,6 +1171,37 @@ AutoFillProfilesView::EditableSetViewContents::CreateLeftAlignedLabel( return label; } +bool AutoFillProfilesView::EditableSetViewContents::LabelValid() const { + if (temporary_info_.is_address) + return !temporary_info_.address.Label().empty(); + else + return !temporary_info_.credit_card.Label().empty(); +} + +void AutoFillProfilesView::EditableSetViewContents::UpdateButtons() { + SkBitmap* image = observer_->GetWarningBimap(LabelValid()); + if (LabelValid()) { + label_warning_button_->SetTooltipText(std::wstring()); + } else { + label_warning_button_->SetTooltipText(l10n_util::GetString( + IDS_AUTOFILL_BAD_LABEL_TOOLTIP)); + } + label_warning_button_->SetImage(views::CustomButton::BS_NORMAL, image); + GetDialogClientView()->UpdateDialogButtons(); +} + +void AutoFillProfilesView::EditableSetViewContents::UpdateContentsPhoneViews( + TextFields field, views::Textfield* sender, const string16& new_contents) { + switch (field) { + case TEXT_PHONE_PHONE: + case TEXT_FAX_PHONE: { + for (std::vector<PhoneSubView*>::iterator it = phone_sub_views_.begin(); + it != phone_sub_views_.end(); ++it) + (*it)->ContentsChanged(sender, new_contents); + } break; + } +} + ///////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView::AddressComboBoxModel, public: AutoFillProfilesView::AddressComboBoxModel::AddressComboBoxModel( @@ -1190,265 +1262,112 @@ std::wstring AutoFillProfilesView::AddressComboBoxModel::GetItemAt(int index) { return label; } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, public: -AutoFillProfilesView::ScrollViewContents::ScrollViewContents( - AutoFillProfilesView* observer, - std::vector<EditableSetInfo>* profiles, - std::vector<EditableSetInfo>* credit_cards) - : profiles_(profiles), - credit_cards_(credit_cards), - add_address_(NULL), - add_credit_card_(NULL), - observer_(observer), - billing_model_(true), - shipping_model_(false) { -} - -AutoFillProfilesView::FocusedItem -AutoFillProfilesView::ScrollViewContents::GetFocusedControlIndex( - const views::View* focus) const { - if (static_cast<const views::View*>(add_address_) == focus) - return FocusedItem(kAddAddressButton, 0); - if (static_cast<const views::View*>(add_credit_card_) == focus) - return FocusedItem(kAddCcButton, 0); - for (size_t i = 0; i < editable_contents_.size(); ++i) { - int index = editable_contents_[i]->GetFocusedControlIndex(focus); - if (index != AutoFillProfilesView::kNoItemFocused) - return FocusedItem(i, index); - } - return FocusedItem(); -} - -views::View* AutoFillProfilesView::ScrollViewContents::GetFocusedControl( - const AutoFillProfilesView::FocusedItem& index) { - if (index.group == AutoFillProfilesView::kNoItemFocused) - return add_address_; - switch (index.group) { - case kAddAddressButton: - return add_address_; - case kAddCcButton: - return add_credit_card_; - default: - DCHECK(index.group < static_cast<int>(editable_contents_.size())); - DCHECK(index.group >= 0); - return editable_contents_[index.group]->GetFocusedControl( - index.item); - } +void AutoFillProfilesView::StringVectorComboboxModel::set_cb_strings( + std::vector<std::wstring> *source) { + cb_strings_.swap(*source); } -views::View* AutoFillProfilesView::ScrollViewContents::GetGroup( - int group_index) { - DCHECK(static_cast<size_t>(group_index) < editable_contents_.size()); - return static_cast<views::View*>(editable_contents_[group_index]); +int AutoFillProfilesView::StringVectorComboboxModel::GetItemCount() { + return cb_strings_.size(); } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, protected: -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, views::View implementations -int AutoFillProfilesView::ScrollViewContents::GetLineScrollIncrement( - views::ScrollView* scroll_view, bool is_horizontal, bool is_positive) { - if (!is_horizontal) - return line_height_; - return View::GetPageScrollIncrement(scroll_view, is_horizontal, is_positive); -} - -void AutoFillProfilesView::ScrollViewContents::Layout() { - views::View* parent = GetParent(); - if (parent && parent->width()) { - const int width = parent->width(); - const int height = GetHeightForWidth(width); - SetBounds(x(), y(), width, height); - } else { - gfx::Size prefsize = GetPreferredSize(); - SetBounds(0, 0, prefsize.width(), prefsize.height()); +std::wstring AutoFillProfilesView::StringVectorComboboxModel::GetItemAt( + int index) { + DCHECK_GT(static_cast<int>(cb_strings_.size()), index); + return cb_strings_[index]; +} + +int AutoFillProfilesView::StringVectorComboboxModel::GetIndex( + const std::wstring& value) { + for (size_t index = 0; index < cb_strings_.size(); ++index) { + if (cb_strings_[index] == value) + return index; } - View::Layout(); + return -1; } -gfx::Size AutoFillProfilesView::ScrollViewContents::GetPreferredSize() { - return gfx::Size(); +AutoFillProfilesView::ContentListTableModel::ContentListTableModel( + std::vector<EditableSetInfo>* profiles, + std::vector<EditableSetInfo>* credit_cards) + : profiles_(profiles), + credit_cards_(credit_cards) { } -void AutoFillProfilesView::ScrollViewContents::ViewHierarchyChanged( - bool is_add, views::View* parent, views::View* child) { - if (is_add && this == child) { - if (!line_height_) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - line_height_ = rb.GetFont(ResourceBundle::BaseFont).height(); - } - Init(); - } +void AutoFillProfilesView::ContentListTableModel::Refresh() { + if (observer_) + observer_->OnModelChanged(); } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, -// views::ButtonListener implementations -void AutoFillProfilesView::ScrollViewContents::ButtonPressed( - views::Button* sender, const views::Event& event) { - if (sender == add_address_) - observer_->AddClicked(EDITABLE_SET_ADDRESS); - else if (sender == add_credit_card_) - observer_->AddClicked(EDITABLE_SET_CREDIT_CARD); +void AutoFillProfilesView::ContentListTableModel::AddItem(int index) { + if (observer_) + observer_->OnItemsAdded(index, 1); } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::ScrollViewContents, private -void AutoFillProfilesView::ScrollViewContents::Init() { - gfx::Rect lb = GetLocalBounds(false); - SetBounds(lb); +void AutoFillProfilesView::ContentListTableModel::RemoveItem(int index) { + DCHECK(index < static_cast<int>(profiles_->size() + credit_cards_->size())); + if (index < static_cast<int>(profiles_->size())) + profiles_->erase(profiles_->begin() + index); + else + credit_cards_->erase(credit_cards_->begin() + (index - profiles_->size())); + if (observer_) + observer_->OnItemsRemoved(index, 1); +} - views::GridLayout* layout = new views::GridLayout(this); - SetLayoutManager(layout); +void AutoFillProfilesView::ContentListTableModel::UpdateItem(int index) { + if (observer_) + observer_->OnItemsChanged(index, 1); +} - const int single_column_filled_view_set_id = 0; - views::ColumnSet* column_set = - layout->AddColumnSet(single_column_filled_view_set_id); - column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, - views::GridLayout::USE_PREF, 0, 0); - if (!observer_->IsDataReady()) { - layout->StartRow(0, single_column_filled_view_set_id); - layout->AddView(new views::Label( - l10n_util::GetString(IDS_AUTOFILL_LOADING))); - return; - } - const int single_column_left_view_set_id = 1; - column_set = layout->AddColumnSet(single_column_left_view_set_id); - column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); - column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, - 1, views::GridLayout::USE_PREF, 0, 0); - const int single_column_filled_view_set_id_full_width = 2; - column_set = - layout->AddColumnSet(single_column_filled_view_set_id_full_width); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, - views::GridLayout::USE_PREF, 0, 0); - views::Label* title_label = new views::Label( - l10n_util::GetString(IDS_AUTOFILL_ADDRESSES_GROUP_NAME)); - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - gfx::Font title_font = - rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD); - title_label->SetFont(title_font); - layout->StartRow(0, single_column_left_view_set_id); - layout->AddView(title_label); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - layout->StartRow(0, single_column_filled_view_set_id_full_width); - layout->AddView(new views::Separator); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); +int AutoFillProfilesView::ContentListTableModel::RowCount() { + return profiles_->size() + credit_cards_->size(); +} - editable_contents_.reserve(profiles_->size() + credit_cards_->size()); - std::vector<EditableSetInfo>::iterator it; - for (it = profiles_->begin(); it != profiles_->end(); ++it) { - EditableSetViewContents* address_view = - new EditableSetViewContents(observer_, &billing_model_, - &shipping_model_, it); - layout->StartRow(0, single_column_filled_view_set_id); - layout->AddView(address_view); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - editable_contents_.push_back(address_view); +std::wstring AutoFillProfilesView::ContentListTableModel::GetText( + int row, int column_id) { + DCHECK(row < static_cast<int>(profiles_->size() + credit_cards_->size())); + if (row < static_cast<int>(profiles_->size())) { + if (column_id == IDS_AUTOFILL_LIST_HEADER_LABEL) { + return profiles_->at(row).address.Label(); + } else { + return profiles_->at(row).address.PreviewSummary(); + } + } else { + row -= profiles_->size(); + if (column_id == IDS_AUTOFILL_LIST_HEADER_LABEL) { + return credit_cards_->at(row).credit_card.Label(); + } else { + return credit_cards_->at(row).credit_card.PreviewSummary(); + } } +} - billing_model_.set_address_labels(profiles_); - shipping_model_.set_address_labels(profiles_); - - add_address_ = new views::NativeButton(this, - l10n_util::GetString(IDS_AUTOFILL_ADD_ADDRESS_BUTTON)); - layout->StartRow(0, single_column_left_view_set_id); - layout->AddView(add_address_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - - title_label = new views::Label( - l10n_util::GetString(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME)); - title_label->SetFont(title_font); - layout->StartRow(0, single_column_left_view_set_id); - layout->AddView(title_label); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - layout->StartRow(0, single_column_filled_view_set_id_full_width); - layout->AddView(new views::Separator); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); +TableModel::Groups AutoFillProfilesView::ContentListTableModel::GetGroups() { + TableModel::Groups groups; - for (it = credit_cards_->begin(); it != credit_cards_->end(); ++it) { - EditableSetViewContents* cc_view = - new EditableSetViewContents(observer_, &billing_model_, - &shipping_model_, it); - layout->StartRow(0, single_column_filled_view_set_id); - layout->AddView(cc_view); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - editable_contents_.push_back(cc_view); - } + TableModel::Group profile_group; + profile_group.title = l10n_util::GetString(IDS_AUTOFILL_ADDRESSES_GROUP_NAME); + profile_group.id = kAddressGroup; + groups.push_back(profile_group); - add_credit_card_ = new views::NativeButton(this, - l10n_util::GetString(IDS_AUTOFILL_ADD_CREDITCARD_BUTTON)); + Group cc_group; + cc_group.title = l10n_util::GetString(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME); + cc_group.id = kCreditCardGroup; + groups.push_back(cc_group); - layout->StartRow(0, single_column_left_view_set_id); - layout->AddView(add_credit_card_); + return groups; } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::AutoFillScrollView, public: -AutoFillProfilesView::AutoFillScrollView::AutoFillScrollView( - AutoFillProfilesView* observer, - std::vector<EditableSetInfo>* profiles, - std::vector<EditableSetInfo>* credit_cards) - : scroll_view_(new views::ScrollView), - scroll_contents_view_( - new ScrollViewContents(observer, profiles, credit_cards)), - profiles_(profiles), - credit_cards_(credit_cards), - observer_(observer) { - AddChildView(scroll_view_); - // After the following call, |scroll_view_| owns |scroll_contents_view_| - // and deletes it when it gets deleted or reset. - scroll_view_->SetContents(scroll_contents_view_); - set_background(new ListBackground()); -} - -void AutoFillProfilesView::AutoFillScrollView::RebuildView( - const AutoFillProfilesView::FocusedItem& new_focus_index) { - AutoFillProfilesView::FocusedItem focus_index(new_focus_index); - gfx::Rect visible_rectangle = scroll_view_->GetVisibleRect(); - if (focus_index.group == AutoFillProfilesView::kNoItemFocused && - GetFocusManager()) { - // Save focus and restore it later. - focus_index = scroll_contents_view_->GetFocusedControlIndex( - GetFocusManager()->GetFocusedView()); - } - - scroll_contents_view_ = new ScrollViewContents(observer_, - profiles_, - credit_cards_); - // Deletes the old contents view and takes ownership of - // |scroll_contents_view_|. - scroll_view_->SetContents(scroll_contents_view_); - if (focus_index.group != AutoFillProfilesView::kNoItemFocused) { - views::View* view = scroll_contents_view_->GetFocusedControl(focus_index); - if (view && GetFocusManager()) { - GetFocusManager()->SetFocusedView(view); - } - } - scroll_contents_view_->ScrollRectToVisible(visible_rectangle); +int AutoFillProfilesView::ContentListTableModel::GetGroupID(int row) { + DCHECK(row < static_cast<int>(profiles_->size() + credit_cards_->size())); + return (row < static_cast<int>(profiles_->size())) ? kAddressGroup : + kCreditCardGroup; } -void AutoFillProfilesView::AutoFillScrollView::EnsureGroupOnScreen( - int group_index) { - views::View* group = scroll_contents_view_->GetGroup(group_index); - - group->ScrollRectToVisible(gfx::Rect(group->width(), group->height())); +void AutoFillProfilesView::ContentListTableModel::SetObserver( + TableModelObserver* observer) { + observer_ = observer; } -///////////////////////////////////////////////////////////////////////////// -// AutoFillProfilesView::AutoFillScrollView, views::View implementations -void AutoFillProfilesView::AutoFillScrollView::Layout() { - gfx::Rect lb = GetLocalBounds(false); - - gfx::Size border = gfx::NativeTheme::instance()->GetThemeBorderSize( - gfx::NativeTheme::LIST); - border.set_width(border.width() + kPanelHorizMargin); - lb.Inset(border.width(), border.height()); - scroll_view_->SetBounds(lb); - scroll_view_->Layout(); -} // Declared in "chrome/browser/autofill/autofill_dialog.h" void ShowAutoFillDialog(gfx::NativeView parent, diff --git a/chrome/browser/views/autofill_profiles_view_win.h b/chrome/browser/views/autofill_profiles_view_win.h index 8b32e631..02770a6 100644 --- a/chrome/browser/views/autofill_profiles_view_win.h +++ b/chrome/browser/views/autofill_profiles_view_win.h @@ -9,11 +9,13 @@ #include <vector> #include "app/combobox_model.h" +#include "app/table_model.h" #include "chrome/browser/autofill/autofill_dialog.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/personal_data_manager.h" #include "views/controls/combobox/combobox.h" #include "views/controls/link.h" +#include "views/controls/table/table_view_observer.h" #include "views/controls/textfield/textfield.h" #include "views/focus/focus_manager.h" #include "views/view.h" @@ -24,11 +26,12 @@ class GridLayout; class ImageButton; class Label; class RadioButton; -class ScrollView; +class TableView; class TextButton; } class PrefService; +class SkBitmap; /////////////////////////////////////////////////////////////////////////////// // AutoFillProfilesView @@ -36,11 +39,6 @@ class PrefService; // The contents of the "AutoFill profiles" dialog window. // // Overview: has following sub-views: -// AutoFillScrollView - scroll view that has all of the addresses and credit -// cards. Implemented by connecting views::ScrollView to ScrollViewContents. -// ScrollViewContents - contents of the scroll view. Has multiple -// EditableSetViewContents views for credit cards and addresses and -// 'Add address' and 'Add Credit Card' buttons. // EditableSetViewContents - set of displayed fields for address or credit card, // has iterator to std::vector<EditableSetInfo> vector so data could be // updated or notifications passes to the dialog view. @@ -54,6 +52,7 @@ class AutoFillProfilesView : public views::View, public views::ButtonListener, public views::LinkController, public views::FocusChangeListener, + public views::TableViewObserver, public PersonalDataManager::Observer { public: virtual ~AutoFillProfilesView(); @@ -66,31 +65,29 @@ class AutoFillProfilesView : public views::View, CreditCard* imported_credit_card); protected: - enum EditableSetType { - EDITABLE_SET_ADDRESS, - EDITABLE_SET_CREDIT_CARD, - }; // forward declaration. This struct defined further down. struct EditableSetInfo; - // Callbacks, called from EditableSetViewContents and ScrollViewContents. - // Called from ScrollViewContents when 'Add Address' (|item_type| is - // EDITABLE_SET_ADDRESS) or 'Add Credit Card' (|item_type| is - // EDITABLE_SET_CREDIT_CARD) is clicked. - void AddClicked(EditableSetType item_type); - // Called from EditableSetViewContents when 'Delete' is clicked. - // |field_set_iterator| is iterator to item being deleted - void DeleteEditableSet( - std::vector<EditableSetInfo>::iterator field_set_iterator); - // Called from EditableSetViewContents when header of the item is clicked - // either to collapse or expand. |field_set_iterator| is iterator to item - // being changed. - void CollapseStateChanged( - std::vector<EditableSetInfo>::iterator field_set_iterator); - // Called from EditableSetViewContents when default profile or credit card - // changes. - void NewDefaultSet(std::vector<EditableSetInfo>::iterator field_set_iterator); - // Validates data and fixes invalid data. - void ValidateAndFixLabel(); + // Called when 'Add Address' (|group_type| is + // ContentListTableModel::kAddressGroup) or 'Add Credit Card' (|group_type| is + // ContentListTableModel::kCreditCardGroup) is clicked. + void AddClicked(int group_type); + // Called when 'Edit...' is clicked. + void EditClicked(); + // Called when 'Remove' is clicked. + void DeleteClicked(); + + // Updates state of the buttons. + void UpdateButtonState(); + + // Following two functions are called from opened child dialog to + // disable/enable buttons. + void ChildWindowOpened(); + void ChildWindowClosed(); + + // Returns warning bitmap to set on warning indicator. If |good| is true it + // returns the bitmap idicating validity, if false - indicating error. + // Caller owns the bitmap after the call. + SkBitmap* GetWarningBimap(bool good); // views::View methods: virtual void Layout(); @@ -112,6 +109,7 @@ class AutoFillProfilesView : public views::View, virtual std::wstring GetWindowTitle() const; virtual void WindowClosing(); virtual views::View* GetContentsView(); + virtual bool Cancel(); virtual bool Accept(); // views::ButtonListener methods: @@ -125,6 +123,10 @@ class AutoFillProfilesView : public views::View, virtual void FocusWillChange(views::View* focused_before, views::View* focused_now); + // views::TableViewObserver methods: + virtual void OnSelectionChanged(); + virtual void OnDoubleClick(); + // PersonalDataManager::Observer methods: void OnPersonalDataLoaded(); @@ -134,29 +136,20 @@ class AutoFillProfilesView : public views::View, // and then rebuild EditableSetViewContents. struct EditableSetInfo { bool is_address; - bool is_opened; - // There is one default item in the addresses list, and one in credit cards. - bool is_default; bool has_credit_card_number_been_edited; // If |is_address| is true |address| has some data and |credit_card| // is empty, and vice versa AutoFillProfile address; CreditCard credit_card; - EditableSetInfo(const AutoFillProfile* input_address, bool opened, - bool default_profile) + explicit EditableSetInfo(const AutoFillProfile* input_address) : address(*input_address), is_address(true), - is_opened(opened), - is_default(default_profile), has_credit_card_number_been_edited(false) { } - EditableSetInfo(const CreditCard* input_credit_card, bool opened, - bool default_cc) + explicit EditableSetInfo(const CreditCard* input_credit_card) : credit_card(*input_credit_card), is_address(false), - is_opened(opened), - is_default(default_cc), has_credit_card_number_been_edited(false) { } }; @@ -183,57 +176,62 @@ class AutoFillProfilesView : public views::View, void GetData(); bool IsDataReady() const; - // Sets default iterators. - void SetDefaultProfileIterator(); - void SetDefaultCreditCardIterator(); + // Rebuilds the view by deleting and re-creating sub-views + void RebuildView(const FocusedItem& new_focus_index); // PhoneSubView encapsulates three phone fields (country, area, and phone) // and label above them, so they could be used together in one grid cell. - class PhoneSubView : public views::View { + class PhoneSubView : public views::View, + public views::ButtonListener { public: - PhoneSubView(views::Label* label, - views::Textfield* text_country, - views::Textfield* text_area, + PhoneSubView(AutoFillProfilesView* autofill_view, + views::Label* label, views::Textfield* text_phone); virtual ~PhoneSubView() {} + virtual void ContentsChanged(views::Textfield* sender, + const string16& new_contents); + + bool IsValid() const; protected: // views::View methods: virtual void ViewHierarchyChanged(bool is_add, views::View* parent, views::View* child); + + // public views::ButtonListener method: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event) { + // Only stub is needed, it is never called. + NOTREACHED(); + } private: + void UpdateButtons(); + AutoFillProfilesView* autofill_view_; views::Label* label_; - views::Textfield* text_country_; - views::Textfield* text_area_; views::Textfield* text_phone_; + views::ImageButton* phone_warning_button_; + bool last_state_; DISALLOW_COPY_AND_ASSIGN(PhoneSubView); }; // forward declaration class AddressComboBoxModel; + class StringVectorComboboxModel; // Sub-view dealing with addresses. class EditableSetViewContents : public views::View, - public views::Textfield::Controller, + public views::DialogDelegate, public views::ButtonListener, + public views::Textfield::Controller, public views::Combobox::Listener { public: EditableSetViewContents(AutoFillProfilesView* observer, AddressComboBoxModel* billing_model, - AddressComboBoxModel* shipping_model, + bool new_item, std::vector<EditableSetInfo>::iterator field_set); virtual ~EditableSetViewContents() {} - // Two constants defined for indexes of sub-group. The first one is index - // of expand button, the second one is the index of the label in expanded - // EditableSet. - static const int kExpandButton = 0; - static const int kLabelText = 4; - - // Two helpers to set focus correctly during rebuild of list view. - int GetFocusedControlIndex(const views::View* focus) const; - views::View* GetFocusedControl(int index); protected: // views::View methods: virtual void Layout(); @@ -241,65 +239,83 @@ class AutoFillProfilesView : public views::View, virtual void ViewHierarchyChanged(bool is_add, views::View* parent, views::View* child); + // views::DialogDelegate methods: + virtual int GetDialogButtons() const; + virtual std::wstring GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const; + virtual bool IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const; + virtual bool CanResize() const { return true; } + virtual bool CanMaximize() const { return true; } + virtual bool IsAlwaysOnTop() const { return false; } + virtual bool HasAlwaysOnTopMenu() const { return false; } + virtual std::wstring GetWindowTitle() const; + virtual void WindowClosing(); + virtual views::View* GetContentsView(); + virtual bool Cancel(); + virtual bool Accept(); + + // views::ButtonListener methods: + virtual void ButtonPressed(views::Button* sender, + const views::Event& event); + // views::Textfield::Controller methods: virtual void ContentsChanged(views::Textfield* sender, const string16& new_contents); virtual bool HandleKeystroke(views::Textfield* sender, const views::Textfield::Keystroke& keystroke); - // views::ButtonListener methods: - virtual void ButtonPressed(views::Button* sender, - const views::Event& event); // views::Combobox::Listener methods: virtual void ItemChanged(views::Combobox* combo_box, int prev_index, int new_index); private: - void InitTitle(views::GridLayout* layout); - void InitAddressFields(views::GridLayout* layout); - void InitCreditCardFields(views::GridLayout* layout); - void InitLayoutGrid(views::GridLayout* layout); - views::Label* CreateLeftAlignedLabel(int label_id); - enum TextFields { TEXT_LABEL, - TEXT_FIRST_NAME, - TEXT_MIDDLE_NAME, - TEXT_LAST_NAME, + TEXT_FULL_NAME, TEXT_EMAIL, - TEXT_COMPANY_NAME, TEXT_ADDRESS_LINE_1, TEXT_ADDRESS_LINE_2, TEXT_ADDRESS_CITY, TEXT_ADDRESS_STATE, TEXT_ADDRESS_ZIP, TEXT_ADDRESS_COUNTRY, - TEXT_PHONE_COUNTRY, - TEXT_PHONE_AREA, TEXT_PHONE_PHONE, - TEXT_FAX_COUNTRY, - TEXT_FAX_AREA, TEXT_FAX_PHONE, TEXT_CC_NAME, TEXT_CC_NUMBER, - TEXT_CC_EXPIRATION_MONTH, - TEXT_CC_EXPIRATION_YEAR, - TEXT_CC_EXPIRATION_CVC, + TEXT_CC_CVC, // must be last MAX_TEXT_FIELD }; + + void InitTitle(views::GridLayout* layout); + void InitAddressFields(views::GridLayout* layout); + void InitCreditCardFields(views::GridLayout* layout); + void InitLayoutGrid(views::GridLayout* layout); + views::Label* CreateLeftAlignedLabel(int label_id); + + bool LabelValid() const; + void UpdateButtons(); + + void UpdateContentsPhoneViews(TextFields field, + views::Textfield* sender, + const string16& new_contents); + views::Textfield* text_fields_[MAX_TEXT_FIELD]; std::vector<EditableSetInfo>::iterator editable_fields_set_; - views::ImageButton* expand_item_button_; - views::TextButton* title_label_; - views::TextButton* title_label_preview_; - views::RadioButton* default_; - views::Button* delete_button_; + EditableSetInfo temporary_info_; + views::Label* title_label_; + views::ImageButton* label_warning_button_; AutoFillProfilesView* observer_; AddressComboBoxModel* billing_model_; - AddressComboBoxModel* shipping_model_; views::Combobox* combo_box_billing_; - views::Combobox* combo_box_shipping_; + scoped_ptr<StringVectorComboboxModel> combo_box_model_month_; + views::Combobox* combo_box_month_; + scoped_ptr<StringVectorComboboxModel> combo_box_model_year_; + views::Combobox* combo_box_year_; + bool new_item_; + std::vector<PhoneSubView*> phone_sub_views_; struct TextFieldToAutoFill { TextFields text_field; @@ -314,8 +330,9 @@ class AutoFillProfilesView : public views::View, static const int triple_column_fill_view_set_id_ = 2; static const int triple_column_leading_view_set_id_ = 3; static const int four_column_city_state_zip_set_id_ = 4; - static const int four_column_ccnumber_expiration_cvc_ = 5; + static const int double_column_ccnumber_cvc_ = 5; static const int three_column_header_ = 6; + static const int double_column_ccexpiration_ = 7; static const int kDefaultAddressesGroup = 0; static const int kDefaultCreditCardsGroup = 1; @@ -358,83 +375,66 @@ class AutoFillProfilesView : public views::View, DISALLOW_COPY_AND_ASSIGN(AddressComboBoxModel); }; - // Sub-view for scrolling credit cards and addresses - class ScrollViewContents : public views::View, - public views::ButtonListener { + class StringVectorComboboxModel : public ComboboxModel { public: - ScrollViewContents(AutoFillProfilesView* observer, - std::vector<EditableSetInfo>* profiles, - std::vector<EditableSetInfo>* credit_cards); - virtual ~ScrollViewContents() {} - - // Two constants defined for indexes of groups. The first one is index - // of Add Address button, the second one is the index of Add Credit Card - // button. - static const int kAddAddressButton = -10; - static const int kAddCcButton = -11; - // Two helpers to set focus correctly during rebuild of list view. - // The returned index is a group shifted by 8 bits to the left + index of - // control in that group. - FocusedItem GetFocusedControlIndex(const views::View* focus) const; - views::View* GetFocusedControl(const FocusedItem& index); - views::View* GetGroup(int group_index); + StringVectorComboboxModel() {} + virtual ~StringVectorComboboxModel() {} - protected: - // views::View methods: - virtual int GetLineScrollIncrement(views::ScrollView* scroll_view, - bool is_horizontal, bool is_positive); - virtual void Layout(); - virtual gfx::Size GetPreferredSize(); - virtual void ViewHierarchyChanged(bool is_add, views::View* parent, - views::View* child); + // Sets the vector of the strings for the combobox. Swaps content with + // |source|. + void set_cb_strings(std::vector<std::wstring> *source); - // views::ButtonListener methods: - virtual void ButtonPressed(views::Button* sender, - const views::Event& event); - private: - void Init(); + // Return the number of items in the combo box. + virtual int GetItemCount(); - std::vector<EditableSetInfo>* profiles_; - std::vector<EditableSetInfo>* credit_cards_; - std::vector<EditableSetViewContents *> editable_contents_; - views::Button* add_address_; - views::Button* add_credit_card_; - AutoFillProfilesView* observer_; + // Return the string that should be used to represent a given item. + virtual std::wstring GetItemAt(int index); - AddressComboBoxModel billing_model_; - AddressComboBoxModel shipping_model_; + // Find an index of the item in the model, -1 if not present. + int GetIndex(const std::wstring& value); - static int line_height_; + protected: + private: + std::vector<std::wstring> cb_strings_; - DISALLOW_COPY_AND_ASSIGN(ScrollViewContents); + DISALLOW_COPY_AND_ASSIGN(StringVectorComboboxModel); }; - class AutoFillScrollView : public views::View { + + // Model for scrolling credit cards and addresses + class ContentListTableModel : public TableModel { public: - AutoFillScrollView(AutoFillProfilesView* observer, - std::vector<EditableSetInfo>* profiles, - std::vector<EditableSetInfo>* credit_cards); - virtual ~AutoFillScrollView() {} + ContentListTableModel(std::vector<EditableSetInfo>* profiles, + std::vector<EditableSetInfo>* credit_cards); + virtual ~ContentListTableModel() {} + + // Two constants defined for indexes of groups. The first one is index + // of Add Address button, the second one is the index of Add Credit Card + // button. + static const int kAddressGroup = 1; + static const int kCreditCardGroup = 2; - // Rebuilds the view by deleting and re-creating sub-views - void RebuildView(const FocusedItem& new_focus_index); - // Ensures that group is shown on the page, scrolls if necessary. - void EnsureGroupOnScreen(int group_index); + void Refresh(); + void AddItem(int index); + void RemoveItem(int index); + void UpdateItem(int index); protected: - // views::View overrides: - virtual void Layout(); - private: - // The scroll view that contains list of the profiles. - views::ScrollView* scroll_view_; - ScrollViewContents* scroll_contents_view_; + // TableModel members: + virtual int RowCount(); + virtual std::wstring GetText(int row, int column_id); + virtual bool HasGroups() { return true; } + virtual TableModel::Groups GetGroups(); + virtual int GetGroupID(int row); + virtual void SetObserver(TableModelObserver* observer); + private: std::vector<EditableSetInfo>* profiles_; std::vector<EditableSetInfo>* credit_cards_; - AutoFillProfilesView* observer_; + TableModelObserver* observer_; - DISALLOW_COPY_AND_ASSIGN(AutoFillScrollView); + DISALLOW_COPY_AND_ASSIGN(ContentListTableModel); }; AutoFillDialogObserver* observer_; @@ -442,14 +442,17 @@ class AutoFillProfilesView : public views::View, PrefService* preferences_; std::vector<EditableSetInfo> profiles_set_; std::vector<EditableSetInfo> credit_card_set_; - std::vector<EditableSetInfo>::iterator default_profile_iterator_; - std::vector<EditableSetInfo>::iterator default_credit_card_iterator_; - string16 default_profile_; - string16 default_credit_card_; - views::Button* save_changes_; - AutoFillScrollView* scroll_view_; + AddressComboBoxModel billing_model_; + + views::Button* add_address_button_; + views::Button* add_credit_card_button_; + views::Button* edit_button_; + views::Button* remove_button_; + views::TableView* scroll_view_; + scoped_ptr<ContentListTableModel> table_model_; views::FocusManager* focus_manager_; + bool child_dialog_opened_; static AutoFillProfilesView* instance_; |