LabeledEditorView.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.EditType;
23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta;
24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta.ValuesDelta;
25392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityModifier;
26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.DialogManager;
2779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport com.android.contacts.util.ThemeUtils;
28392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.DialogManager.DialogShowingView;
29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.AlertDialog;
31392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.Dialog;
32392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context;
33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.DialogInterface;
34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Entity;
35392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.res.Resources;
36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Bundle;
3779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport android.os.Handler;
38392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet;
39cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmannimport android.view.Gravity;
40392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.Menu;
41392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.MenuItem;
42392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View;
43392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.ViewGroup;
44392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.inputmethod.EditorInfo;
45392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.Button;
46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText;
47392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.ImageButton;
48392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.PopupMenu;
49392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
50392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport java.util.List;
51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
52392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/**
53392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Base class for editors that handles labels and values.
54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Uses {@link ValuesDelta} to read any existing
55392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * {@link Entity} values, and to correctly write any changes values.
56392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */
57392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannpublic abstract class LabeledEditorView extends ViewGroup implements Editor, DialogShowingView {
58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected static final String DIALOG_ID_KEY = "dialog_id";
59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static final int DIALOG_ID_CUSTOM = 1;
60392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
61392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT
62392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private Button mLabel;
65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ImageButton mDelete;
66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DataKind mKind;
68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ValuesDelta mEntry;
69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EntityDelta mState;
70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mReadOnly;
71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditType mType;
73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    // Used only when a user tries to use custom label.
74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditType mPendingType;
75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ViewIdGenerator mViewIdGenerator;
77392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DialogManager mDialogManager = null;
78392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditorListener mListener;
79392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
80392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context) {
81392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context);
82392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
83392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
84392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context, AttributeSet attrs) {
85392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs);
86392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
87392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
88392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context, AttributeSet attrs, int defStyle) {
89392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs, defStyle);
90392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
91392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
9202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    public boolean isReadOnly() {
9302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        return mReadOnly;
9402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    }
9502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
96392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
97392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onLayout(boolean changed, int l, int t, int r, int b) {
98392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Subtract padding from the borders ==> x1 variables
99392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int t1 = getPaddingTop();
100392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int r1 = getMeasuredWidth() - getPaddingRight();
101392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int b1 = getMeasuredHeight() - getPaddingBottom();
102392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
103cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        final int r2;
104cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        if (mDelete != null) {
105cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann            r2 = r1 - mDelete.getMeasuredWidth();
106cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann            mDelete.layout(
107cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r2, b1 - mDelete.getMeasuredHeight(),
108cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r1, b1);
109cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        } else {
110cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann            r2 = r1;
111cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        }
112392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
113cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann        if (mLabel != null) {
114392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mLabel.layout(
115cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r2 - mLabel.getMeasuredWidth(), t1,
116cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                    r2, t1 + mLabel.getMeasuredHeight());
117392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
118392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
120392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
121392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
122392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
123392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        measureChildren(widthMeasureSpec, heightMeasureSpec);
124392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
125392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final int padding = getPaddingTop() + getPaddingBottom();
126392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final int deleteHeight = mDelete != null ? mDelete.getMeasuredHeight() : 0;
127392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final int labelHeight = mLabel != null ? mLabel.getMeasuredHeight() : 0;
128392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
129392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final int height = padding +
130392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                Math.max(Math.max(deleteHeight, labelHeight), getEditorHeight());
131392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
132392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
133392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                resolveSize(height, heightMeasureSpec));
134392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
135392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
136392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected abstract int getEditorHeight();
137392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
138392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
139392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Creates or removes the type/label button. Doesn't do anything if already correctly configured
140392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
141392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void setupLabelButton(boolean shouldExist) {
142392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (shouldExist && mLabel == null) {
143f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann            mLabel = new Button(mContext, null, android.R.attr.dropDownSpinnerStyle);
144392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final int width =
145392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mContext.getResources().getDimensionPixelSize(R.dimen.editor_type_label_width);
146392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mLabel.setLayoutParams(new LayoutParams(width, LayoutParams.WRAP_CONTENT));
147cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann            mLabel.setGravity(Gravity.RIGHT);
148cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann            mLabel.setTextColor(getResources().getColor(R.color.editor_label_text_color));
149b01a75066862566855c6290ca5413ef96a1963beDaniel Lehmann            mLabel.setFocusable(true);
150392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mLabel.setOnClickListener(new OnClickListener() {
151392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                @Override
152392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                public void onClick(View v) {
153392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    showLabelPopupMenu();
154392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
155392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            });
15602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mLabel.setEnabled(!mReadOnly && isEnabled());
157392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            addView(mLabel);
158392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        } else if (!shouldExist && mLabel != null) {
159392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            removeView(mLabel);
160392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mLabel = null;
161392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
162392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
163392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
164392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
165392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Creates or removes the remove button. Doesn't do anything if already correctly configured
166392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
167392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void setupDeleteButton(boolean shouldExist) {
168392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (shouldExist && mDelete == null) {
169392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete = new ImageButton(mContext);
170915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann            mDelete.setImageResource(R.drawable.ic_menu_remove_field_holo_light);
17179c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann            mDelete.setBackgroundResource(
17279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    ThemeUtils.getSelectableItemBackground(mContext.getTheme()));
173392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final Resources resources = mContext.getResources();
174392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete.setPadding(
175392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_left),
176392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_top),
177392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_right),
178392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_bottom));
179392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete.setContentDescription(
180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    getResources().getText(R.string.description_minus_button));
181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete.setLayoutParams(
182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
183392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete.setOnClickListener(new OnClickListener() {
184392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                @Override
185392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                public void onClick(View v) {
18679c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    // defer removal of this button so that the pressed state is visible shortly
18779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    new Handler().post(new Runnable() {
18879c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                        @Override
18979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                        public void run() {
19079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                            // Keep around in model, but mark as deleted
19179c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                            mEntry.markDeleted();
19279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann
19379c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                            ((ViewGroup) getParent()).removeView(LabeledEditorView.this);
19479c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann
19579c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                            if (mListener != null) {
19679c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                                // Notify listener when present
19779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                                mListener.onDeleted(LabeledEditorView.this);
19879c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                            }
19979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                        }
20079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    });
201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            });
20302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mDelete.setEnabled(!mReadOnly && isEnabled());
204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            addView(mDelete);
205392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        } else if (!shouldExist && mDelete != null) {
206392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            removeView(mDelete);
207392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDelete = null;
208392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
210392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
211392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onOptionalFieldVisibilityChange() {
212392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mListener != null) {
213392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mListener.onRequest(EditorListener.EDITOR_FORM_CHANGED);
214392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
215392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
216392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEditorListener(EditorListener listener) {
219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mListener = listener;
220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
223392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setDeletable(boolean deletable) {
224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setupDeleteButton(deletable);
225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
226392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
227392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEnabled(boolean enabled) {
22902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        super.setEnabled(enabled);
23002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mLabel != null) mLabel.setEnabled(!mReadOnly && enabled);
23102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mDelete != null) mDelete.setEnabled(!mReadOnly && enabled);
232392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
233392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public Button getLabel() {
235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mLabel;
236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public ImageButton getDelete() {
239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mDelete;
240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
241392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
242392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected DataKind getKind() {
243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mKind;
244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected ValuesDelta getEntry() {
247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mEntry;
248392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
249392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
250392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected EditType getType() {
251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mType;
252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
253392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Build the current label state based on selected {@link EditType} and
256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * possible custom label string.
257392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void rebuildLabel() {
259392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mLabel == null) return;
260392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Handle undetected types
261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mType == null) {
262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mLabel.setText(R.string.unknown);
263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            return;
264392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mType.customColumn != null) {
267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Use custom label string when present
268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final String customText = mEntry.getAsString(mType.customColumn);
269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (customText != null) {
270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                mLabel.setText(customText);
271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return;
272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
274392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
275392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Otherwise fall back to using default label
276392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mLabel.setText(mType.labelRes);
277392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
278392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /** {@inheritDoc} */
280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void onFieldChanged(String column, String value) {
282392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Field changes are saved directly
283392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mEntry.put(column, value);
284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mListener != null) {
285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mListener.onRequest(EditorListener.FIELD_CHANGED);
286392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
287392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
288392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
289392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void rebuildValues() {
290392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setValues(mKind, mEntry, mState, mReadOnly, mViewIdGenerator);
291392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
292392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
293392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
294392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Prepare this editor using the given {@link DataKind} for defining
295392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * structure and {@link ValuesDelta} describing the content to edit.
296392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ViewIdGenerator vig) {
300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mKind = kind;
301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mEntry = entry;
302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mState = state;
303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mReadOnly = readOnly;
304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mViewIdGenerator = vig;
305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setId(vig.getId(state, kind, entry, ViewIdGenerator.NO_VIEW_INDEX));
306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (!entry.isVisible()) {
308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Hide ourselves entirely if deleted
309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            setVisibility(View.GONE);
310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            return;
311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setVisibility(View.VISIBLE);
313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Display label selector if multiple types available
315392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final boolean hasTypes = EntityModifier.hasEditTypes(kind);
316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setupLabelButton(hasTypes);
31702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mLabel != null) mLabel.setEnabled(!readOnly && isEnabled());
318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (hasTypes) {
319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mType = EntityModifier.getCurrentType(entry, kind);
320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            rebuildLabel();
321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
322392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
323392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public ValuesDelta getValues() {
325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mEntry;
326392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Prepare dialog for entering a custom label. The input value is trimmed: white spaces before
330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * and after the input text is removed.
331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * <p>
332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * If the final value is empty, this change request is ignored;
333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * no empty text is allowed in any custom label.
334392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private Dialog createCustomDialog() {
336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final EditText customType = new EditText(mContext);
337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        customType.setInputType(INPUT_TYPE_CUSTOM);
338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        customType.requestFocus();
339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setTitle(R.string.customLabelPickerTitle);
342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setView(customType);
343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public void onClick(DialogInterface dialog, int which) {
347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                final String customText = customType.getText().toString().trim();
348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (ContactsUtils.isGraphic(customText)) {
349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // Now we're sure it's ok to actually change the type value.
350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mType = mPendingType;
351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mPendingType = null;
352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mEntry.put(mKind.typeColumn, mType.rawValue);
353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mEntry.put(mType.customColumn, customText);
354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    rebuildLabel();
355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    requestFocusForFirstEditField();
356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    onLabelRebuilt();
357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        });
360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setNegativeButton(android.R.string.cancel, null);
362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return builder.create();
364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Called after the label has changed (either chosen from the list or entered in the Dialog)
368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onLabelRebuilt() {
370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Show PopupMenu for picking a new {@link EditType} or entering a
374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * custom label. This dialog is limited to the valid types as determined
375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * by {@link EntityModifier}.
376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void showLabelPopupMenu() {
378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Build list of valid types, including the current value
379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final List<EditType> validTypes = EntityModifier.getValidTypes(mState, mKind, mType);
380392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final PopupMenu popupMenu = new PopupMenu(getContext(), mLabel);
382392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final Menu menu = popupMenu.getMenu();
383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
384392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        for (int i = 0; i < validTypes.size(); i++) {
385392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            final EditType type = validTypes.get(i);
386392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            menu.add(Menu.NONE, i, Menu.NONE, type.labelRes);
387392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
388392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
389392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
391392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public boolean onMenuItemClick(MenuItem item) {
392392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                final EditType selected = validTypes.get(item.getItemId());
393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (selected.customColumn != null) {
394392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // Show custom label dialog if requested by type.
395392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    //
396392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // Only when the custum value input in the next step is correct one.
397392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // this method also set the type value to what the user requested here.
398392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mPendingType = selected;
399392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    showDialog(DIALOG_ID_CUSTOM);
400392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                } else {
401392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    // User picked type, and we're sure it's ok to actually write the entry.
402392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mType = selected;
403392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mEntry.put(mKind.typeColumn, mType.rawValue);
404392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    rebuildLabel();
405392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    requestFocusForFirstEditField();
406392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    onLabelRebuilt();
407392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
408392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return true;
409392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
410392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        });
411392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
412392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        popupMenu.show();
413392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
414392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
415392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /* package */
416392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    void showDialog(int bundleDialogId) {
417392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        Bundle bundle = new Bundle();
418392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        bundle.putInt(DIALOG_ID_KEY, bundleDialogId);
419392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        getDialogManager().showDialogInView(this, bundle);
420392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
421392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
422392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DialogManager getDialogManager() {
423392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mDialogManager == null) {
424392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            Context context = getContext();
425392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (!(context instanceof DialogManager.DialogShowingViewActivity)) {
426392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                throw new IllegalStateException(
427392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        "View must be hosted in an Activity that implements " +
428392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        "DialogManager.DialogShowingViewActivity");
429392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
430392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDialogManager = ((DialogManager.DialogShowingViewActivity)context).getDialogManager();
431392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
432392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mDialogManager;
433392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
434392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
435392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
436392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public Dialog createDialog(Bundle bundle) {
437392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
438392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int dialogId = bundle.getInt(DIALOG_ID_KEY);
439392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        switch (dialogId) {
440392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            case DIALOG_ID_CUSTOM:
441392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return createCustomDialog();
442392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            default:
443392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                throw new IllegalArgumentException("Invalid dialogId: " + dialogId);
444392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
445392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
446392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
447392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected abstract void requestFocusForFirstEditField();
448392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann}
449