Index: chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileEditor.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileEditor.java |
index ce69ae098bcdd9bfb081506686314d6ed4f8658c..1e3e931647ff43c1e2be3723aa03524a405bde00 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileEditor.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileEditor.java |
@@ -9,24 +9,26 @@ import android.os.Bundle; |
import android.text.Editable; |
import android.text.TextUtils; |
import android.text.TextWatcher; |
+import android.util.Pair; |
import android.view.LayoutInflater; |
import android.view.View; |
import android.view.ViewGroup; |
import android.widget.AdapterView; |
import android.widget.AdapterView.OnItemSelectedListener; |
+import android.widget.ArrayAdapter; |
import android.widget.Button; |
import android.widget.EditText; |
import android.widget.Spinner; |
-import com.android.i18n.addressinput.AddressData; |
-import com.android.i18n.addressinput.AddressField; |
-import com.android.i18n.addressinput.AddressWidget; |
-import com.android.i18n.addressinput.FormOptions; |
-import com.android.i18n.addressinput.SimpleClientCacheManager; |
- |
import org.chromium.chrome.R; |
import org.chromium.chrome.browser.autofill.PersonalDataManager; |
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; |
+import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.AddressField; |
+import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Country; |
+import org.chromium.chrome.browser.widget.FloatLabelLayout; |
+ |
+import java.util.ArrayList; |
+import java.util.List; |
/** |
* Provides the Java-ui for editing a Profile autofill entry. |
@@ -37,11 +39,18 @@ public class AutofillProfileEditor extends Fragment implements TextWatcher, |
// May be the empty string if creating a new profile. |
private String mGUID; |
- private AddressWidget mAddressWidget; |
private boolean mNoCountryItemIsSelected; |
+ private LayoutInflater mInflater; |
private EditText mPhoneText; |
+ private FloatLabelLayout mPhoneLabel; |
private EditText mEmailText; |
+ private FloatLabelLayout mEmailLabel; |
private String mLanguageCodeString; |
+ private List<String> mCountryCodes; |
+ private int mCurrentCountryPos; |
+ private Spinner mCountriesSpinner; |
+ private ViewGroup mWidgetRoot; |
+ private FloatLabelLayout[] mAddressFields; |
@Override |
public void onCreate(Bundle savedState) { |
@@ -53,11 +62,6 @@ public class AutofillProfileEditor extends Fragment implements TextWatcher, |
Bundle savedInstanceState) { |
super.onCreate(savedInstanceState); |
- View v = inflater.inflate(R.layout.autofill_profile_editor, container, false); |
- |
- mPhoneText = (EditText) v.findViewById(R.id.autofill_profile_editor_phone_number_edit); |
- mEmailText = (EditText) v.findViewById(R.id.autofill_profile_editor_email_address_edit); |
- |
// We know which profile to edit based on the GUID stuffed in |
// our extras by AutofillPreferences. |
Bundle extras = getArguments(); |
@@ -71,8 +75,21 @@ public class AutofillProfileEditor extends Fragment implements TextWatcher, |
getActivity().setTitle(R.string.autofill_edit_profile); |
} |
- addProfileDataToEditFields(v); |
+ mInflater = inflater; |
+ mAddressFields = new FloatLabelLayout[AddressField.NUM_FIELDS]; |
+ View v = mInflater.inflate(R.layout.autofill_profile_editor, container, false); |
+ |
+ mPhoneText = (EditText) v.findViewById(R.id.phone_number_edit); |
+ mPhoneLabel = (FloatLabelLayout) v.findViewById(R.id.phone_number_label); |
+ mEmailText = (EditText) v.findViewById(R.id.email_address_edit); |
+ mEmailLabel = (FloatLabelLayout) v.findViewById(R.id.email_address_label); |
+ mWidgetRoot = (ViewGroup) v.findViewById(R.id.autofill_profile_widget_root); |
+ mCountriesSpinner = (Spinner) v.findViewById(R.id.countries); |
+ |
+ populateCountriesSpinner(); |
+ createAndPopulateEditFields(); |
hookupSaveCancelDeleteButtons(v); |
+ |
return v; |
} |
@@ -84,78 +101,196 @@ public class AutofillProfileEditor extends Fragment implements TextWatcher, |
@Override |
public void onTextChanged(CharSequence s, int start, int before, int count) { |
- enableSaveButton(); |
+ boolean empty = mNoCountryItemIsSelected && TextUtils.isEmpty(s) && allFieldsEmpty(); |
+ setSaveButtonEnabled(!empty); |
+ } |
+ |
+ private boolean allFieldsEmpty() { |
+ if (!TextUtils.isEmpty(mPhoneText.getText()) |
+ || !TextUtils.isEmpty(mEmailText.getText())) { |
+ return false; |
+ } |
+ for (FloatLabelLayout field : mAddressFields) { |
+ if (field != null && !TextUtils.isEmpty(field.getEditText().getText())) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
} |
@Override |
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { |
- mAddressWidget.onItemSelected(parent, view, position, id); |
- |
- if (mNoCountryItemIsSelected) { |
+ if (position != mCurrentCountryPos) { |
+ mCurrentCountryPos = position; |
+ // If all fields are empty (e.g. the user just entered the form and the first thing |
+ // they did was select a country), focus on the first form element. Otherwise, don't. |
+ resetFormFields(position, allFieldsEmpty()); |
mNoCountryItemIsSelected = false; |
- return; |
+ setSaveButtonEnabled(true); |
} |
- |
- enableSaveButton(); |
} |
@Override |
public void onNothingSelected(AdapterView<?> parent) {} |
- private void addProfileDataToEditFields(View v) { |
- AddressData.Builder address = new AddressData.Builder(); |
+ private void populateCountriesSpinner() { |
+ List<Country> countries = AutofillProfileBridge.getSupportedCountries(); |
+ mCountryCodes = new ArrayList<String>(); |
+ |
+ for (Country country : countries) { |
+ mCountryCodes.add(country.mCode); |
+ } |
+ |
+ ArrayAdapter<Country> countriesAdapter = new ArrayAdapter<Country>(getActivity(), |
+ android.R.layout.simple_spinner_item, countries); |
+ countriesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
+ mCountriesSpinner.setAdapter(countriesAdapter); |
+ } |
+ |
+ private void createAndPopulateEditFields() { |
AutofillProfile profile = PersonalDataManager.getInstance().getProfile(mGUID); |
if (profile != null) { |
- mPhoneText.setText(profile.getPhoneNumber()); |
- mEmailText.setText(profile.getEmailAddress()); |
+ if (!TextUtils.isEmpty(profile.getPhoneNumber())) { |
+ mPhoneLabel.setText(profile.getPhoneNumber()); |
+ } |
+ |
+ if (!TextUtils.isEmpty(profile.getEmailAddress())) { |
+ mEmailLabel.setText(profile.getEmailAddress()); |
+ } |
+ |
mLanguageCodeString = profile.getLanguageCode(); |
- address.setAdminArea(profile.getRegion()); |
- address.setLocality(profile.getLocality()); |
- address.setRecipient(profile.getFullName()); |
- address.setOrganization(profile.getCompanyName()); |
- address.setDependentLocality(profile.getDependentLocality()); |
- address.setPostalCode(profile.getPostalCode()); |
- address.setSortingCode(profile.getSortingCode()); |
- address.setAddress(profile.getStreetAddress()); |
- address.setCountry(profile.getCountryCode()); |
+ mCurrentCountryPos = mCountryCodes.indexOf(profile.getCountryCode()); |
+ if (mCurrentCountryPos == -1) { |
+ // Use the default country code if profile code is invalid. |
+ mCurrentCountryPos = mCountryCodes.indexOf( |
+ AutofillProfileBridge.getDefaultCountryCode()); |
+ if (mCurrentCountryPos == -1) { |
+ // Use the first item in country spinner if the default country code is |
+ // invalid. |
+ mCurrentCountryPos = 0; |
+ } |
+ } |
+ |
+ resetFormFields(mCurrentCountryPos, false); |
+ |
+ setFieldText(AddressField.ADMIN_AREA, profile.getRegion()); |
+ setFieldText(AddressField.LOCALITY, profile.getLocality()); |
+ setFieldText(AddressField.DEPENDENT_LOCALITY, profile.getDependentLocality()); |
+ setFieldText(AddressField.SORTING_CODE, profile.getSortingCode()); |
+ setFieldText(AddressField.POSTAL_CODE, profile.getPostalCode()); |
+ setFieldText(AddressField.STREET_ADDRESS, profile.getStreetAddress()); |
+ setFieldText(AddressField.ORGANIZATION, profile.getCompanyName()); |
+ setFieldText(AddressField.RECIPIENT, profile.getFullName()); |
+ } else { |
+ mCurrentCountryPos = mCountryCodes.indexOf( |
+ AutofillProfileBridge.getDefaultCountryCode()); |
+ if (mCurrentCountryPos == -1) { |
+ // Use the first item in country spinner if the default country code is |
+ // invalid. |
+ mCurrentCountryPos = 0; |
+ } |
+ resetFormFields(mCurrentCountryPos, true); |
+ } |
+ |
+ mCountriesSpinner.setSelection(mCurrentCountryPos); |
+ } |
+ |
+ private void resetFormFields(int countryCodeIndex, boolean autoFocusFirstField) { |
+ // Save field text so we can restore it after updating the fields for the current country, |
+ // and reset mAddressFields. |
+ String[] fieldText = new String[mAddressFields.length]; |
+ for (int i = 0; i < mAddressFields.length; i++) { |
+ if (mAddressFields[i] != null) { |
+ fieldText[i] = mAddressFields[i].getEditText().getText().toString(); |
+ mAddressFields[i] = null; |
+ } |
} |
- ViewGroup widgetRoot = (ViewGroup) v.findViewById(R.id.autofill_profile_widget_root); |
- mAddressWidget = new AddressWidget(getActivity(), widgetRoot, |
- (new FormOptions.Builder()).build(), |
- new SimpleClientCacheManager(), |
- address.build(), |
- new ChromeAddressWidgetUiComponentProvider(getActivity())); |
+ // Remove all address form fields. |
+ mWidgetRoot.removeAllViews(); |
+ |
+ // Get address fields for the selected country. |
+ List<Pair<Integer, String>> fields = AutofillProfileBridge.getAddressUiComponents( |
+ mCountryCodes.get(countryCodeIndex)); |
- if (profile == null) { |
- widgetRoot.requestFocus(); |
+ // Create form fields and focus the first field if autoFocusFirstField is true. |
+ boolean firstField = true; |
+ for (Pair<Integer, String> field : fields) { |
+ int fieldId = field.first; |
+ String fieldLabel = field.second; |
+ FloatLabelLayout fieldFloatLabel = (FloatLabelLayout) mInflater.inflate( |
+ R.layout.preference_address_float_label_layout, mWidgetRoot, false); |
+ fieldFloatLabel.setHint(fieldLabel); |
+ |
+ EditText fieldEditText = |
+ (EditText) fieldFloatLabel.findViewById(R.id.address_edit_text); |
+ fieldEditText.setHint(fieldLabel); |
+ fieldEditText.setContentDescription(fieldLabel); |
+ fieldEditText.addTextChangedListener(this); |
+ if (fieldId == AddressField.STREET_ADDRESS) { |
+ fieldEditText.setSingleLine(false); |
+ } |
+ |
+ mAddressFields[fieldId] = fieldFloatLabel; |
+ mWidgetRoot.addView(fieldFloatLabel); |
+ |
+ if (firstField && autoFocusFirstField) { |
+ // FloatLabelLayout animates showing the field label when the EditText is focused; |
+ // to avoid this animation, manually set the label to be visible and the EditText |
+ // hint to null and request focus on the EditText field. |
+ fieldFloatLabel.getLabel().setVisibility(View.VISIBLE); |
+ fieldEditText.setHint(null); |
+ fieldEditText.requestFocus(); |
+ firstField = false; |
+ } |
+ } |
+ |
+ // Add back saved field text. |
+ for (int i = 0; i < mAddressFields.length; i++) { |
+ if (mAddressFields[i] != null && fieldText[i] != null |
+ && !TextUtils.isEmpty(fieldText[i])) { |
+ mAddressFields[i].setText(fieldText[i]); |
+ } |
} |
} |
// Read edited data; save in the associated Chrome profile. |
// Ignore empty fields. |
private void saveProfile() { |
- AddressData input = mAddressWidget.getAddressData(); |
AutofillProfile profile = new PersonalDataManager.AutofillProfile( |
mGUID, |
AutofillPreferences.SETTINGS_ORIGIN, |
- input.getRecipient(), |
- input.getOrganization(), |
- TextUtils.join("\n", input.getAddressLines()), |
- input.getAdministrativeArea(), |
- input.getLocality(), |
- input.getDependentLocality(), |
- input.getPostalCode(), |
- input.getSortingCode(), |
- input.getPostalCountry(), |
+ getFieldText(AddressField.RECIPIENT), |
+ getFieldText(AddressField.ORGANIZATION), |
+ getFieldText(AddressField.STREET_ADDRESS), |
+ getFieldText(AddressField.ADMIN_AREA), |
+ getFieldText(AddressField.LOCALITY), |
+ getFieldText(AddressField.DEPENDENT_LOCALITY), |
+ getFieldText(AddressField.POSTAL_CODE), |
+ getFieldText(AddressField.SORTING_CODE), |
+ mCountryCodes.get(mCurrentCountryPos), |
mPhoneText.getText().toString(), |
mEmailText.getText().toString(), |
mLanguageCodeString); |
PersonalDataManager.getInstance().setProfile(profile); |
} |
+ private String getFieldText(int fieldId) { |
+ if (mAddressFields[fieldId] != null) { |
+ return mAddressFields[fieldId].getEditText().getText().toString(); |
+ } |
+ return null; |
+ } |
+ |
+ private void setFieldText(int fieldId, String text) { |
+ if (mAddressFields[fieldId] != null && !TextUtils.isEmpty(text)) { |
+ mAddressFields[fieldId].setText(text); |
+ } |
+ } |
+ |
private void deleteProfile() { |
if (AutofillProfileEditor.this.mGUID != null) { |
PersonalDataManager.getInstance().deleteProfile(mGUID); |
@@ -196,20 +331,14 @@ public class AutofillProfileEditor extends Fragment implements TextWatcher, |
// Listen for changes to inputs. Enable the save button after something has changed. |
mPhoneText.addTextChangedListener(this); |
mEmailText.addTextChangedListener(this); |
+ mCountriesSpinner.setOnItemSelectedListener(this); |
mNoCountryItemIsSelected = true; |
- |
- for (AddressField field : AddressField.values()) { |
- View input = mAddressWidget.getViewForField(field); |
- if (input instanceof EditText) { |
- ((EditText) input).addTextChangedListener(this); |
- } else if (input instanceof Spinner) { |
- ((Spinner) input).setOnItemSelectedListener(this); |
- } |
- } |
} |
- private void enableSaveButton() { |
- Button button = (Button) getView().findViewById(R.id.autofill_profile_save); |
- button.setEnabled(true); |
+ private void setSaveButtonEnabled(boolean enabled) { |
+ if (getView() != null) { |
+ Button button = (Button) getView().findViewById(R.id.autofill_profile_save); |
+ button.setEnabled(enabled); |
+ } |
} |
} |