1392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/*
2392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Copyright (C) 2010 The Android Open Source Project
3392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann *
4392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License");
5392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * you may not use this file except in compliance with the License.
6392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * You may obtain a copy of the License at
7392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann *
8392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann *      http://www.apache.org/licenses/LICENSE-2.0
9392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann *
10392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Unless required by applicable law or agreed to in writing, software
11392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS,
12392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * See the License for the specific language governing permissions and
14392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * limitations under the License.
15392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */
16392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor;
18392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
19392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context;
20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.graphics.Rect;
21392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcel;
22392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcelable;
23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.Editable;
24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.InputType;
251b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuanimport android.text.TextUtils;
26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.TextWatcher;
27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet;
2826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.util.Log;
29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.Gravity;
30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View;
3163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.view.ViewGroup;
320af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuanimport android.view.inputmethod.EditorInfo;
3326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.view.inputmethod.InputMethodManager;
34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText;
3512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanimport android.widget.ImageView;
36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.LinearLayout;
37da5bf1cf60beef3de5e651a569fa544293683926Dave Santoro
38e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
39cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContactDelta;
40cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.ContactsUtils;
41738ff8623dc77dd91a1b9023861e924ba5e4c27eChiao Chengimport com.android.contacts.common.model.ValuesDelta;
42428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType.EditField;
43428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind;
44720ac2f99fc6cb4b92852a1a54ccd8c7c796c7d2Chiao Chengimport com.android.contacts.common.util.PhoneNumberFormatter;
45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/**
4763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * Simple editor that handles labels and any {@link EditField} defined for the
48851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * entry. Uses {@link ValuesDelta} to read any existing {@link RawContact} values,
4963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * and to correctly write any changes values.
50392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */
51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannpublic class TextFieldsEditorView extends LabeledEditorView {
5226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus    private static final String TAG = TextFieldsEditorView.class.getSimpleName();
5326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus
54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditText[] mFieldEditTexts = null;
5563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    private ViewGroup mFields = null;
5612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan    private View mExpansionViewContainer;
5712a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan    private ImageView mExpansionView;
58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mHideOptional = true;
59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mHasShortAndLongForms;
601ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan    private int mMinFieldHeight;
615cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell    private int mEditTextTopPadding;
625cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell    private int mEditTextBottomPadding;
63ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee    private int mPreviousViewHeight;
64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context) {
66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context);
67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context, AttributeSet attrs) {
70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs);
71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context, AttributeSet attrs, int defStyle) {
74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs, defStyle);
75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
7763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    /** {@inheritDoc} */
7891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    @Override
7963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    protected void onFinishInflate() {
8063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        super.onFinishInflate();
8163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan
8263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        setDrawingCacheEnabled(true);
8363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        setAlwaysDrawnWithCacheEnabled(true);
8463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan
851ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan        mMinFieldHeight = mContext.getResources().getDimensionPixelSize(
861ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan                R.dimen.editor_min_line_item_height);
875cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell        mEditTextBottomPadding = mContext.getResources().getDimensionPixelSize(
885cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell                R.dimen.editor_text_field_bottom_padding);
895cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell        mEditTextTopPadding = mContext.getResources().getDimensionPixelSize(
905cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell                R.dimen.editor_text_field_top_padding);
9163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mFields = (ViewGroup) findViewById(R.id.editors);
9212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mExpansionView = (ImageView) findViewById(R.id.expansion_view);
9312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mExpansionViewContainer = findViewById(R.id.expansion_view_container);
9412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mExpansionViewContainer.setOnClickListener(new OnClickListener() {
9563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            @Override
9663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            public void onClick(View v) {
97ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee                mPreviousViewHeight = mFields.getHeight();
98ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee
9963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                // Save focus
10063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                final View focusedChild = getFocusedChild();
10163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();
10263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan
10363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                // Reconfigure GUI
10463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                mHideOptional = !mHideOptional;
10563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                onOptionalFieldVisibilityChange();
10663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                rebuildValues();
10763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan
10863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                // Restore focus
10963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                View newFocusView = findViewById(focusedViewId);
11063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                if (newFocusView == null || newFocusView.getVisibility() == GONE) {
11163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                    // find first visible child
11263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                    newFocusView = TextFieldsEditorView.this;
113392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
11463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                newFocusView.requestFocus();
115ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee
116ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee                EditorAnimator.getInstance().slideAndFadeIn(mFields, mPreviousViewHeight);
117392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
11863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        });
119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
120392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
121392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
12226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus    public void editNewlyAddedField() {
12326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        // Some editors may have multiple fields (eg: first-name/last-name), but since the user
12426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        // has not selected a particular one, it is reasonable to simply pick the first.
12526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        final View editor = mFields.getChildAt(0);
12626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus
12726918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        // Show the soft-keyboard.
12826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        InputMethodManager imm =
12926918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus                (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
13026918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        if (imm != null) {
13126918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus            if (!imm.showSoftInput(editor, InputMethodManager.SHOW_IMPLICIT)) {
13226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus                Log.w(TAG, "Failed to show soft input method.");
13326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus            }
13426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus        }
13526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus    }
13626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus
13726918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus    @Override
138392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEnabled(boolean enabled) {
139392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.setEnabled(enabled);
140392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
141392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
142392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (int index = 0; index < mFieldEditTexts.length; index++) {
14302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled);
144392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
145392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
14612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mExpansionView.setEnabled(!isReadOnly() && enabled);
147392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
148392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
149392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
150392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Creates or removes the type/label button. Doesn't do anything if already correctly configured
151392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
15212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan    private void setupExpansionView(boolean shouldExist, boolean collapsed) {
153392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (shouldExist) {
15412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan            mExpansionViewContainer.setVisibility(View.VISIBLE);
15512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan            mExpansionView.setImageResource(collapsed
156915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                    ? R.drawable.ic_menu_expander_minimized_holo_light
157915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                    : R.drawable.ic_menu_expander_maximized_holo_light);
15863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        } else {
15912a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan            mExpansionViewContainer.setVisibility(View.GONE);
160392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
161392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
162392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
163392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
164392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void requestFocusForFirstEditField() {
165392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null && mFieldEditTexts.length != 0) {
166392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            EditText firstField = null;
167392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            boolean anyFieldHasFocus = false;
168392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText editText : mFieldEditTexts) {
169392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (firstField == null && editText.getVisibility() == View.VISIBLE) {
170392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    firstField = editText;
171392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
172392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.hasFocus()) {
173392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    anyFieldHasFocus = true;
174392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    break;
175392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
176392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
177392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (!anyFieldHasFocus && firstField != null) {
178392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                firstField.requestFocus();
179392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
18344cfc56d1701629070384364416c1311b780535dChiao Cheng    public void setValue(int field, String value) {
18444cfc56d1701629070384364416c1311b780535dChiao Cheng        mFieldEditTexts[field].setText(value);
18544cfc56d1701629070384364416c1311b780535dChiao Cheng    }
18644cfc56d1701629070384364416c1311b780535dChiao Cheng
187392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
188851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
189392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ViewIdGenerator vig) {
190392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.setValues(kind, entry, state, readOnly, vig);
191392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Remove edit texts that we currently have
192392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
193392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText fieldEditText : mFieldEditTexts) {
19463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                mFields.removeView(fieldEditText);
195392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
196392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        boolean hidePossible = false;
198392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
199392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int fieldCount = kind.fieldList.size();
200392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mFieldEditTexts = new EditText[fieldCount];
201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int index = 0; index < fieldCount; index++) {
202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final EditField field = kind.fieldList.get(index);
203392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final EditText fieldView = new EditText(mContext);
204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
2055cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell                    LayoutParams.WRAP_CONTENT));
2069db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan            // Set either a minimum line requirement or a minimum height (because {@link TextView}
2079db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan            // only takes one or the other at a single time).
2089db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan            if (field.minLines != 0) {
2099db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan                fieldView.setMinLines(field.minLines);
2109db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan            } else {
2119db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan                fieldView.setMinHeight(mMinFieldHeight);
2129db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan            }
21350a27b70581b0191995969c63edd1f6a3db3d1b7Makoto Onuki            fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);
2145cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell            fieldView.setPadding(fieldView.getPaddingLeft(), mEditTextTopPadding,
2155cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell                    fieldView.getPaddingRight(), mEditTextBottomPadding);
2165cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell            fieldView.setHintTextColor(R.color.secondary_text_color);
217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setGravity(Gravity.TOP);
218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mFieldEditTexts[index] = fieldView;
219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setId(vig.getId(state, kind, entry, index));
220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (field.titleRes > 0) {
221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.setHint(field.titleRes);
222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
223392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            int inputType = field.inputType;
224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setInputType(inputType);
225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (inputType == InputType.TYPE_CLASS_PHONE) {
226e598332967106e3db63b73c701f21902d169efefMakoto Onuki                PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView);
227cbfb11288368bca3a6e350ae880d53ffb4907b78Yorke Lee                fieldView.setTextDirection(View.TEXT_DIRECTION_LTR);
228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
2300af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan            // Show the "next" button in IME to navigate between text fields
2310af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan            // TODO: Still need to properly navigate to/from sections without text fields,
2320af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan            // See Bug: 5713510
2330af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan            fieldView.setImeOptions(EditorInfo.IME_ACTION_NEXT);
2340af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan
235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Read current value from state
236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final String column = field.column;
237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final String value = entry.getAsString(column);
238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setText(value);
239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
2405e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan            // Show the delete button if we have a non-null value
2415e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan            setDeleteButtonVisible(value != null);
2425e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan
243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Prepare listener for writing changes
244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.addTextChangedListener(new TextWatcher() {
245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                @Override
246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                public void afterTextChanged(Editable s) {
247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // Trigger event for newly changed value
248392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    onFieldChanged(column, s.toString());
249392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
250392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                @Override
252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
253392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                @Override
256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                public void onTextChanged(CharSequence s, int start, int before, int count) {
257392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            });
259392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
26002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            fieldView.setEnabled(isEnabled() && !readOnly);
261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (field.shortForm) {
263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                hidePossible = true;
264392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                mHasShortAndLongForms = true;
265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE);
266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            } else if (field.longForm) {
267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                hidePossible = true;
268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                mHasShortAndLongForms = true;
269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE);
270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            } else {
271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                // Hide field when empty and optional value
272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional);
273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                final boolean willHide = (mHideOptional && couldHide);
274392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE);
275392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                hidePossible = hidePossible || couldHide;
276392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
277392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
27863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            mFields.addView(fieldView);
279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // When hiding fields, place expandable
28212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        setupExpansionView(hidePossible, mHideOptional);
28312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mExpansionView.setEnabled(!readOnly && isEnabled());
284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
2862591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan    @Override
2872591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan    public boolean isEmpty() {
2881b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan        for (int i = 0; i < mFields.getChildCount(); i++) {
2891b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan            EditText editText = (EditText) mFields.getChildAt(i);
2902591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan            if (!TextUtils.isEmpty(editText.getText())) {
2912591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan                return false;
2921b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan            }
2931b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan        }
2942591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan        return true;
2951b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan    }
2961b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan
297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Returns true if the editor is currently configured to show optional fields.
299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public boolean areOptionalFieldsVisible() {
301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return !mHideOptional;
302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public boolean hasShortAndLongForms() {
305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mHasShortAndLongForms;
306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Populates the bound rectangle with the bounds of the last editor field inside this view.
310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void acquireEditorBounds(Rect bounds) {
312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (int i = mFieldEditTexts.length; --i >= 0;) {
314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                EditText editText = mFieldEditTexts[i];
315392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.getVisibility() == View.VISIBLE) {
316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    bounds.set(editText.getLeft(), editText.getTop(), editText.getRight(),
317392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                            editText.getBottom());
318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    return;
319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
322392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
323392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Saves the visibility of the child EditTexts, and mHideOptional.
326392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected Parcelable onSaveInstanceState() {
329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        Parcelable superState = super.onSaveInstanceState();
330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState ss = new SavedState(superState);
331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        ss.mHideOptional = mHideOptional;
333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
3345ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov        final int numChildren = mFieldEditTexts == null ? 0 : mFieldEditTexts.length;
335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        ss.mVisibilities = new int[numChildren];
336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int i = 0; i < numChildren; i++) {
337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility();
338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return ss;
341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Restores the visibility of the child EditTexts, and mHideOptional.
345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onRestoreInstanceState(Parcelable state) {
348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState ss = (SavedState) state;
349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.onRestoreInstanceState(ss.getSuperState());
350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mHideOptional = ss.mHideOptional;
352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length);
354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int i = 0; i < numChildren; i++) {
355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]);
356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static class SavedState extends BaseSavedState {
360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public boolean mHideOptional;
361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public int[] mVisibilities;
362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState(Parcelable superState) {
364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super(superState);
365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        private SavedState(Parcel in) {
368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super(in);
369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mVisibilities = new int[in.readInt()];
370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            in.readIntArray(mVisibilities);
371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        @Override
374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public void writeToParcel(Parcel out, int flags) {
375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super.writeToParcel(out, flags);
376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            out.writeInt(mVisibilities.length);
377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            out.writeIntArray(mVisibilities);
378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
380cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        @SuppressWarnings({"unused", "hiding" })
381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public static final Parcelable.Creator<SavedState> CREATOR
382392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                = new Parcelable.Creator<SavedState>() {
383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
384392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public SavedState createFromParcel(Parcel in) {
385392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return new SavedState(in);
386392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
387392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
388392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
389392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public SavedState[] newArray(int size) {
390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return new SavedState[size];
391392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
392392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        };
393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
394da5bf1cf60beef3de5e651a569fa544293683926Dave Santoro
3952293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    @Override
3962293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    public void clearAllFields() {
3972293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        if (mFieldEditTexts != null) {
3982293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan            for (EditText fieldEditText : mFieldEditTexts) {
3992293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                // Update UI (which will trigger a state change through the {@link TextWatcher})
4002293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                fieldEditText.setText("");
4012293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan            }
4022293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        }
4032293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    }
404392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann}
405