// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.preferences.autofill;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
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.AddressUiComponent;
import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.DropdownKeyValue;
import org.chromium.chrome.browser.widget.CompatibilityTextInputLayout;
import java.util.ArrayList;
import java.util.List;
/**
* Provides the Java-ui for editing a Profile autofill entry.
*/
public class AutofillProfileEditor extends AutofillEditorBase {
private boolean mNoCountryItemIsSelected;
private LayoutInflater mInflater;
private EditText mPhoneText;
private CompatibilityTextInputLayout mPhoneLabel;
private EditText mEmailText;
private CompatibilityTextInputLayout mEmailLabel;
private String mLanguageCodeString;
private List<String> mCountryCodes;
private int mCurrentCountryPos;
private Spinner mCountriesDropdown;
private ViewGroup mWidgetRoot;
private CompatibilityTextInputLayout[] mAddressFields;
private AutofillProfileBridge mAutofillProfileBridge;
private boolean mUseSavedProfileLanguage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
mInflater = inflater;
mAddressFields = new CompatibilityTextInputLayout[AddressField.NUM_FIELDS];
mPhoneText = (EditText) v.findViewById(R.id.phone_number_edit);
mPhoneLabel = (CompatibilityTextInputLayout) v.findViewById(R.id.phone_number_label);
mEmailText = (EditText) v.findViewById(R.id.email_address_edit);
mEmailLabel = (CompatibilityTextInputLayout) v.findViewById(R.id.email_address_label);
mWidgetRoot = (ViewGroup) v.findViewById(R.id.autofill_profile_widget_root);
mCountriesDropdown = (Spinner) v.findViewById(R.id.spinner);
TextView countriesLabel = (TextView) v.findViewById(R.id.spinner_label);
countriesLabel.setText(v.getContext().getString(R.string.autofill_profile_editor_country));
mAutofillProfileBridge = new AutofillProfileBridge();
populateCountriesDropdown();
createAndPopulateEditFields();
initializeButtons(v);
return v;
}
@Override
protected int getLayoutId() {
return R.layout.autofill_profile_editor;
}
@Override
protected int getTitleResourceId(boolean isNewEntry) {
return isNewEntry ? R.string.autofill_create_profile : R.string.autofill_edit_profile;
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean empty = mNoCountryItemIsSelected && TextUtils.isEmpty(s) && allFieldsEmpty();
setSaveButtonEnabled(!empty);
}
private boolean allFieldsEmpty() {
if (!TextUtils.isEmpty(mPhoneText.getText())
|| !TextUtils.isEmpty(mEmailText.getText())) {
return false;
}
for (CompatibilityTextInputLayout 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) {
if (position != mCurrentCountryPos) {
mCurrentCountryPos = position;
mUseSavedProfileLanguage = false;
// 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;
setSaveButtonEnabled(true);
}
}
private void populateCountriesDropdown() {
List<DropdownKeyValue> countries = AutofillProfileBridge.getSupportedCountries();
mCountryCodes = new ArrayList<String>();
for (DropdownKeyValue country : countries) {
mCountryCodes.add(country.getKey());
}
ArrayAdapter<DropdownKeyValue> countriesAdapter = new ArrayAdapter<DropdownKeyValue>(
getActivity(), android.R.layout.simple_spinner_item, countries);
countriesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mCountriesDropdown.setAdapter(countriesAdapter);
}
private void createAndPopulateEditFields() {
AutofillProfile profile = PersonalDataManager.getInstance().getProfile(mGUID);
if (profile != null) {
if (!TextUtils.isEmpty(profile.getPhoneNumber())) {
mPhoneLabel.getEditText().setText(profile.getPhoneNumber());
}
if (!TextUtils.isEmpty(profile.getEmailAddress())) {
mEmailLabel.getEditText().setText(profile.getEmailAddress());
}
mLanguageCodeString = profile.getLanguageCode();
mUseSavedProfileLanguage = true;
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);
}
mCountriesDropdown.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;
}
}
// Remove all address form fields.
mWidgetRoot.removeAllViews();
// Get address fields for the selected country.
List<AddressUiComponent> fields = mAutofillProfileBridge.getAddressUiComponents(
mCountryCodes.get(countryCodeIndex),
mLanguageCodeString);
if (!mUseSavedProfileLanguage) {
mLanguageCodeString = mAutofillProfileBridge.getCurrentBestLanguageCode();
}
// Create form fields and focus the first field if autoFocusFirstField is true.
boolean firstField = true;
for (AddressUiComponent field : fields) {
CompatibilityTextInputLayout fieldFloatLabel =
(CompatibilityTextInputLayout) mInflater.inflate(
R.layout.preference_address_float_label_layout, mWidgetRoot, false);
fieldFloatLabel.setHint(field.label);
EditText fieldEditText = fieldFloatLabel.getEditText();
fieldEditText.addTextChangedListener(this);
if (field.id == AddressField.STREET_ADDRESS) {
fieldEditText.setSingleLine(false);
}
mAddressFields[field.id] = fieldFloatLabel;
mWidgetRoot.addView(fieldFloatLabel);
if (firstField && autoFocusFirstField) {
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].getEditText().setText(fieldText[i]);
}
}
}
// Read edited data; save in the associated Chrome profile.
// Ignore empty fields.
@Override
protected void saveEntry() {
AutofillProfile profile = new PersonalDataManager.AutofillProfile(mGUID,
AutofillPreferences.SETTINGS_ORIGIN, true /* isLocal */,
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].getEditText().setText(text);
}
}
@Override
protected void deleteEntry() {
if (mGUID != null) {
PersonalDataManager.getInstance().deleteProfile(mGUID);
}
}
@Override
protected void initializeButtons(View v) {
super.initializeButtons(v);
// Listen for changes to inputs. Enable the save button after something has changed.
mPhoneText.addTextChangedListener(this);
mEmailText.addTextChangedListener(this);
mCountriesDropdown.setOnItemSelectedListener(this);
mNoCountryItemIsSelected = true;
}
private void setSaveButtonEnabled(boolean enabled) {
if (getView() != null) {
Button button = (Button) getView().findViewById(R.id.button_primary);
button.setEnabled(enabled);
}
}
}