TextFieldsEditorView.java revision 02bb1252aa990813fa9e86ad75c458acc15e6801
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 com.android.contacts.ContactsUtils;
20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.R;
214597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.DataKind;
224597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.EditField;
23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta;
24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta.ValuesDelta;
2579c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport com.android.contacts.util.ThemeUtils;
26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context;
28392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Entity;
29915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmannimport android.content.res.Resources;
30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.graphics.Rect;
31392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcel;
32392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcelable;
33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.telephony.PhoneNumberFormattingTextWatcher;
34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.Editable;
35392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.InputType;
36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.TextWatcher;
37392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet;
38392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.Gravity;
39392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View;
40392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText;
41392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.ImageButton;
42392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.LinearLayout;
43392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
44392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/**
45392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Simple editor that handles labels and any {@link EditField} defined for
46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * the entry. Uses {@link ValuesDelta} to read any existing
47392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * {@link Entity} values, and to correctly write any changes values.
48392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */
49392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannpublic class TextFieldsEditorView extends LabeledEditorView {
50392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditText[] mFieldEditTexts = null;
51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ImageButton mMoreOrLess;
52392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mHideOptional = true;
53392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mHasShortAndLongForms;
54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
55392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context) {
56392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context);
57392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context, AttributeSet attrs) {
60392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs);
61392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
62392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public TextFieldsEditorView(Context context, AttributeSet attrs, int defStyle) {
64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs, defStyle);
65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onLayout(boolean changed, int l, int t, int r, int b) {
69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.onLayout(changed, l, t, r, b);
70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int l1 = getPaddingLeft();
72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int t1 = getPaddingTop();
73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int r1 = getMeasuredWidth() - getPaddingRight();
74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
75cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        if ((mMoreOrLess != null)) {
76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mMoreOrLess.layout(
77cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r1 - mMoreOrLess.getMeasuredWidth(), t1,
78cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r1, t1 + mMoreOrLess.getMeasuredHeight());
79392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
80392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
81cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        // Subtract buttons if necessary
82cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int labelWidth = (getLabel() != null) ? getLabel().getMeasuredWidth() : 0;
83cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int deleteWidth = (getDelete() != null) ? getDelete().getMeasuredWidth() : 0;
84cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int moreOrLessWidth = mMoreOrLess != null ? mMoreOrLess.getMeasuredWidth() : 0;
85cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int r2 = r1 - Math.max(deleteWidth, moreOrLessWidth) - labelWidth;
86cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann
87cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        // Layout text fields
88392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int y = t1;
89392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
90392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText editText : mFieldEditTexts) {
91392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.getVisibility() != View.GONE) {
92392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    int height = editText.getMeasuredHeight();
93392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    editText.layout(
94cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                            l1, t1 + y,
95392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                            r2, t1 + y + height);
96392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    y += height;
97392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
98392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
99392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
100392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
101392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
102392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
103392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected int getEditorHeight() {
104392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int result = 0;
105392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // summarize the EditText heights
106392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
107392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText editText : mFieldEditTexts) {
108392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.getVisibility() != View.GONE) {
109392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    result += editText.getMeasuredHeight();
110392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
111392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
112392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
113cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        // Ensure there is enough space for the minus and more/less button
114cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int deleteHeight = (getDelete() != null) ? getDelete().getMeasuredHeight() : 0;
115cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int moreOrLessHeight = mMoreOrLess != null ? mMoreOrLess.getMeasuredHeight() : 0;
116cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        result = Math.max(deleteHeight + moreOrLessHeight, result);
117392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return result;
118392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
120392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
121392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEnabled(boolean enabled) {
122392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.setEnabled(enabled);
123392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
124392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
125392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (int index = 0; index < mFieldEditTexts.length; index++) {
12602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled);
127392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
128392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
12902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mMoreOrLess != null) mMoreOrLess.setEnabled(!isReadOnly() && enabled);
130392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
131392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
132392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
133392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Creates or removes the type/label button. Doesn't do anything if already correctly configured
134392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
135392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void setupMoreOrLessButton(boolean shouldExist, boolean collapsed) {
136392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (shouldExist) {
137392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (mMoreOrLess == null) {
138915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                mMoreOrLess = new ImageButton(mContext);
13979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                mMoreOrLess.setBackgroundResource(
14079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                        ThemeUtils.getSelectableItemBackground(mContext.getTheme()));
141915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                final Resources resources = mContext.getResources();
142915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                mMoreOrLess.setPadding(
143915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                        resources.getDimensionPixelOffset(
144915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                                R.dimen.editor_round_button_padding_left),
145915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                        resources.getDimensionPixelOffset(
146915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                                R.dimen.editor_round_button_padding_top),
147915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                        resources.getDimensionPixelOffset(
148915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                                R.dimen.editor_round_button_padding_right),
149915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                        resources.getDimensionPixelOffset(
150915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                                R.dimen.editor_round_button_padding_bottom));
151392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                mMoreOrLess.setLayoutParams(
152392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
153392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                mMoreOrLess.setOnClickListener(new OnClickListener() {
154392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    @Override
155392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    public void onClick(View v) {
156392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        // Save focus
157392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        final View focusedChild = getFocusedChild();
158392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();
159392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
160392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        // Reconfigure GUI
161392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        mHideOptional = !mHideOptional;
162392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        onOptionalFieldVisibilityChange();
163392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        rebuildValues();
164392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
165392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        // Restore focus
166392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        View newFocusView = findViewById(focusedViewId);
167392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        if (newFocusView == null || newFocusView.getVisibility() == GONE) {
168392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                            // find first visible child
169392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                            newFocusView = TextFieldsEditorView.this;
170392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        }
171cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                        newFocusView.requestFocus();
172392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    }
173392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                });
174392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                addView(mMoreOrLess);
175392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
176915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann            mMoreOrLess.setImageResource(collapsed
177915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                    ? R.drawable.ic_menu_expander_minimized_holo_light
178915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann                    : R.drawable.ic_menu_expander_maximized_holo_light);
179392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        } else if (mMoreOrLess != null) {
180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            removeView(mMoreOrLess);
181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mMoreOrLess = null;
182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
183392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
184392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
185392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
186392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void requestFocusForFirstEditField() {
187392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null && mFieldEditTexts.length != 0) {
188392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            EditText firstField = null;
189392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            boolean anyFieldHasFocus = false;
190392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText editText : mFieldEditTexts) {
191392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (firstField == null && editText.getVisibility() == View.VISIBLE) {
192392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    firstField = editText;
193392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
194392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.hasFocus()) {
195392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    anyFieldHasFocus = true;
196392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    break;
197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
198392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
199392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (!anyFieldHasFocus && firstField != null) {
200392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                firstField.requestFocus();
201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
203392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
205392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
206392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
207392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ViewIdGenerator vig) {
208392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.setValues(kind, entry, state, readOnly, vig);
209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Remove edit texts that we currently have
210392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
211392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (EditText fieldEditText : mFieldEditTexts) {
212392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                removeView(fieldEditText);
213392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
214392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
215392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        boolean hidePossible = false;
216392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int fieldCount = kind.fieldList.size();
218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mFieldEditTexts = new EditText[fieldCount];
219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int index = 0; index < fieldCount; index++) {
220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final EditField field = kind.fieldList.get(index);
221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final EditText fieldView = new EditText(mContext);
222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
223392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    LayoutParams.WRAP_CONTENT));
224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setGravity(Gravity.TOP);
225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mFieldEditTexts[index] = fieldView;
226392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setId(vig.getId(state, kind, entry, index));
227392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (field.titleRes > 0) {
228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.setHint(field.titleRes);
229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
230392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            int inputType = field.inputType;
231392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setInputType(inputType);
232392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (inputType == InputType.TYPE_CLASS_PHONE) {
233392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                fieldView.addTextChangedListener(new PhoneNumberFormattingTextWatcher(
234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        ContactsUtils.getCurrentCountryIso(mContext)));
235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setMinLines(field.minLines);
237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Read current value from state
239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final String column = field.column;
240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final String value = entry.getAsString(column);
241392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            fieldView.setText(value);
242392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
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
278392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            addView(fieldView);
279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // When hiding fields, place expandable
282392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setupMoreOrLessButton(hidePossible, mHideOptional);
28302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mMoreOrLess != null) mMoreOrLess.setEnabled(!readOnly && isEnabled());
284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
286392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
287392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Returns true if the editor is currently configured to show optional fields.
288392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
289392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public boolean areOptionalFieldsVisible() {
290392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return !mHideOptional;
291392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
292392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
293392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public boolean hasShortAndLongForms() {
294392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mHasShortAndLongForms;
295392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
296392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Populates the bound rectangle with the bounds of the last editor field inside this view.
299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void acquireEditorBounds(Rect bounds) {
301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mFieldEditTexts != null) {
302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            for (int i = mFieldEditTexts.length; --i >= 0;) {
303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                EditText editText = mFieldEditTexts[i];
304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (editText.getVisibility() == View.VISIBLE) {
305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    bounds.set(editText.getLeft(), editText.getTop(), editText.getRight(),
306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                            editText.getBottom());
307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    return;
308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Saves the visibility of the child EditTexts, and mHideOptional.
315392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
317392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected Parcelable onSaveInstanceState() {
318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        Parcelable superState = super.onSaveInstanceState();
319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState ss = new SavedState(superState);
320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        ss.mHideOptional = mHideOptional;
322392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
323392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final int numChildren = mFieldEditTexts.length;
324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        ss.mVisibilities = new int[numChildren];
325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int i = 0; i < numChildren; i++) {
326392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility();
327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return ss;
330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Restores the visibility of the child EditTexts, and mHideOptional.
334392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onRestoreInstanceState(Parcelable state) {
337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState ss = (SavedState) state;
338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super.onRestoreInstanceState(ss.getSuperState());
339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mHideOptional = ss.mHideOptional;
341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length);
343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int i = 0; i < numChildren; i++) {
344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]);
345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static class SavedState extends BaseSavedState {
349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public boolean mHideOptional;
350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public int[] mVisibilities;
351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        SavedState(Parcelable superState) {
353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super(superState);
354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        private SavedState(Parcel in) {
357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super(in);
358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mVisibilities = new int[in.readInt()];
359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            in.readIntArray(mVisibilities);
360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        @Override
363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public void writeToParcel(Parcel out, int flags) {
364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            super.writeToParcel(out, flags);
365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            out.writeInt(mVisibilities.length);
366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            out.writeIntArray(mVisibilities);
367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
369cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        @SuppressWarnings({"unused", "hiding" })
370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        public static final Parcelable.Creator<SavedState> CREATOR
371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                = new Parcelable.Creator<SavedState>() {
372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public SavedState createFromParcel(Parcel in) {
374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return new SavedState(in);
375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public SavedState[] newArray(int size) {
379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return new SavedState[size];
380392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        };
382392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann}
384