LabeledEditorView.java revision 67713b3e6e3af70020350e2650738389f19c073e
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.EditType;
22405671a7b42d97ebf7ae7c0eeb4721f881139673Daisuke Miyakawaimport com.android.contacts.model.DataKind;
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;
27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.DialogManager.DialogShowingView;
28392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.AlertDialog;
30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.Dialog;
31392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context;
32392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.DialogInterface;
33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Entity;
34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Bundle;
3579c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport android.os.Handler;
3611bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikovimport android.text.TextUtils;
37a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuanimport android.text.TextUtils.TruncateAt;
38392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet;
39a66642330b5c4a62c8b7ce438ccff57c3b017eb1Katherine Kuanimport android.view.Gravity;
402fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.view.LayoutInflater;
41392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View;
42392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.ViewGroup;
43392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.inputmethod.EditorInfo;
442fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.AdapterView;
452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.AdapterView.OnItemSelectedListener;
462fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.ArrayAdapter;
47392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText;
4812a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanimport android.widget.ImageView;
4963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.widget.LinearLayout;
502fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.Spinner;
512fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.TextView;
52392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
5314918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikovimport java.util.List;
5414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov
55392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/**
5663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * Base class for editors that handles labels and values. Uses
5763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * {@link ValuesDelta} to read any existing {@link Entity} values, and to
5863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * correctly write any changes values.
59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */
6063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanpublic abstract class LabeledEditorView extends LinearLayout implements Editor, DialogShowingView {
61392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected static final String DIALOG_ID_KEY = "dialog_id";
62392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static final int DIALOG_ID_CUSTOM = 1;
63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT
65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
672fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    private Spinner mLabel;
682fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    private EditTypeAdapter mEditTypeAdapter;
6963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    private View mDeleteContainer;
7012a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan    private ImageView mDelete;
71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DataKind mKind;
73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ValuesDelta mEntry;
74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EntityDelta mState;
75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private boolean mReadOnly;
762591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan    private boolean mWasEmpty = true;
775e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan    private boolean mIsDeletable = true;
782293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    private boolean mIsAttachedToWindow;
79392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
80392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditType mType;
81392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
82392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private ViewIdGenerator mViewIdGenerator;
83392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DialogManager mDialogManager = null;
84392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private EditorListener mListener;
8591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    protected int mMinLineItemHeight;
86392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
872fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    /**
882fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov     * A marker in the spinner adapter of the currently selected custom type.
892fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov     */
902fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    public static final EditType CUSTOM_SELECTION = new EditType(0, 0);
912fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
922fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    private OnItemSelectedListener mSpinnerListener = new OnItemSelectedListener() {
932fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
942fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        @Override
952fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public void onItemSelected(
962fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                AdapterView<?> parent, View view, int position, long id) {
972fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            onTypeSelectionChange(position);
982fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
992fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
1002fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        @Override
1012fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public void onNothingSelected(AdapterView<?> parent) {
1022fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
1032fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    };
1042fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
105392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context) {
106392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context);
10791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        init(context);
108392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
109392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
110392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context, AttributeSet attrs) {
111392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs);
11291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        init(context);
113392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
114392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
115392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public LabeledEditorView(Context context, AttributeSet attrs, int defStyle) {
116392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        super(context, attrs, defStyle);
11791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        init(context);
11891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    }
11991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
12091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    private void init(Context context) {
12191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        mMinLineItemHeight = context.getResources().getDimensionPixelSize(
12291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov                R.dimen.editor_min_line_item_height);
123392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
124392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
12563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    /** {@inheritDoc} */
12663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    @Override
12763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    protected void onFinishInflate() {
12802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
12963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mLabel = (Spinner) findViewById(R.id.spinner);
13067713b3e6e3af70020350e2650738389f19c073eDaniel Lehmann        // Turn off the Spinner's own state management. We do this ourselves on rotation
13167713b3e6e3af70020350e2650738389f19c073eDaniel Lehmann        mLabel.setId(View.NO_ID);
13263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mLabel.setOnItemSelectedListener(mSpinnerListener);
13391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
13412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mDelete = (ImageView) findViewById(R.id.delete_button);
13563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mDeleteContainer = findViewById(R.id.delete_button_container);
13612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan        mDeleteContainer.setOnClickListener(new OnClickListener() {
13763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            @Override
13863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            public void onClick(View v) {
13963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                // defer removal of this button so that the pressed state is visible shortly
14063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                new Handler().post(new Runnable() {
14163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                    @Override
14263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                    public void run() {
1432293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // Don't do anything if the view is no longer attached to the window
1442293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // (This check is needed because when this {@link Runnable} is executed,
1452293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // we can't guarantee the view is still valid.
1462293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        if (!mIsAttachedToWindow) {
1472293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                            return;
1482293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        }
1492293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // Send the delete request to the listener (which will in turn call
1502293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // deleteEditor() on this view if the deletion is valid - i.e. this is not
1512293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                        // the last {@link Editor} in the section).
15263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                        if (mListener != null) {
1532293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                            mListener.onDeleteRequested(LabeledEditorView.this);
15463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                        }
15563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                    }
15663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan                });
15791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov            }
15863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        });
15991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    }
16091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
1612293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    @Override
1622293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    protected void onAttachedToWindow() {
1632293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        super.onAttachedToWindow();
1642293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        // Keep track of when the view is attached or detached from the window, so we know it's
1652293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        // safe to remove views (in case the user requests to delete this editor).
1662293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        mIsAttachedToWindow = true;
1672293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    }
1682293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan
1692293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    @Override
1702293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    protected void onDetachedFromWindow() {
1712293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        super.onDetachedFromWindow();
1722293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        mIsAttachedToWindow = false;
1732293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    }
1742293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan
1752293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    @Override
1762293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    public void deleteEditor() {
1772293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        // Keep around in model, but mark as deleted
1782293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        mEntry.markDeleted();
1792293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan
1802293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        // Remove the view
1812293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan        ((ViewGroup) getParent()).removeView(LabeledEditorView.this);
1822293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan    }
1832293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan
18463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    public boolean isReadOnly() {
18563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        return mReadOnly;
18691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    }
18791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
18863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan    public int getBaseline(int row) {
18963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        if (row == 0 && mLabel != null) {
19063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            return mLabel.getBaseline();
191392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
19263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        return -1;
193392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
194392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
195392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
196a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan     * Configures the visibility of the type label button and enables or disables it properly.
197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
198392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void setupLabelButton(boolean shouldExist) {
19963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        if (shouldExist) {
20002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mLabel.setEnabled(!mReadOnly && isEnabled());
20163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            mLabel.setVisibility(View.VISIBLE);
20263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        } else {
20363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            mLabel.setVisibility(View.GONE);
204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
205392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
206392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
207392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
208a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan     * Configures the visibility of the "delete" button and enables or disables it properly.
209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
2105e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan    private void setupDeleteButton() {
2115e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan        if (mIsDeletable) {
21263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            mDeleteContainer.setVisibility(View.VISIBLE);
21302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mDelete.setEnabled(!mReadOnly && isEnabled());
21463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        } else {
21563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan            mDeleteContainer.setVisibility(View.GONE);
216392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
2195e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan    public void setDeleteButtonVisible(boolean visible) {
2205e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan        if (mIsDeletable) {
221a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan            mDeleteContainer.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
2225e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan        }
2235e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan    }
2245e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan
225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onOptionalFieldVisibilityChange() {
226392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mListener != null) {
227392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mListener.onRequest(EditorListener.EDITOR_FORM_CHANGED);
228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
230392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
231392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
232392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEditorListener(EditorListener listener) {
233392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mListener = listener;
234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setDeletable(boolean deletable) {
2385e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan        mIsDeletable = deletable;
2395e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan        setupDeleteButton();
240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
241392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
242392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setEnabled(boolean enabled) {
24402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        super.setEnabled(enabled);
24563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mLabel.setEnabled(!mReadOnly && enabled);
24663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mDelete.setEnabled(!mReadOnly && enabled);
247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
248392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
2492fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    public Spinner getLabel() {
250392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mLabel;
251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
25312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan    public ImageView getDelete() {
254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mDelete;
255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
257392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected DataKind getKind() {
258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mKind;
259392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
260392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected ValuesDelta getEntry() {
262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mEntry;
263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
264392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected EditType getType() {
266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mType;
267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Build the current label state based on selected {@link EditType} and
271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * possible custom label string.
272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private void rebuildLabel() {
2742fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        mEditTypeAdapter = new EditTypeAdapter(mContext);
2752fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        mLabel.setAdapter(mEditTypeAdapter);
2762fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        if (mEditTypeAdapter.hasCustomSelection()) {
2772fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            mLabel.setSelection(mEditTypeAdapter.getPosition(CUSTOM_SELECTION));
2782fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        } else {
2792fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            mLabel.setSelection(mEditTypeAdapter.getPosition(mType));
280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
282392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
283392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void onFieldChanged(String column, String value) {
28511bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov        if (!isFieldChanged(column, value)) {
2867d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov            return;
2877d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov        }
2887d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov
289392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Field changes are saved directly
290e55faef88185628c842e0aa778d883f209323630Katherine Kuan        saveValue(column, value);
291e55faef88185628c842e0aa778d883f209323630Katherine Kuan
292e55faef88185628c842e0aa778d883f209323630Katherine Kuan        // Notify listener if applicable
293e55faef88185628c842e0aa778d883f209323630Katherine Kuan        notifyEditorListener();
294e55faef88185628c842e0aa778d883f209323630Katherine Kuan    }
295e55faef88185628c842e0aa778d883f209323630Katherine Kuan
296e55faef88185628c842e0aa778d883f209323630Katherine Kuan    protected void saveValue(String column, String value) {
297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mEntry.put(column, value);
298e55faef88185628c842e0aa778d883f209323630Katherine Kuan    }
299e55faef88185628c842e0aa778d883f209323630Katherine Kuan
300e55faef88185628c842e0aa778d883f209323630Katherine Kuan    protected void notifyEditorListener() {
301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mListener != null) {
302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mListener.onRequest(EditorListener.FIELD_CHANGED);
303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
3042591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan
3052591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan        boolean isEmpty = isEmpty();
3062591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan        if (mWasEmpty != isEmpty) {
3072591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan            if (isEmpty) {
30837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                if (mListener != null) {
30937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                    mListener.onRequest(EditorListener.FIELD_TURNED_EMPTY);
31037bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                }
311a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan                if (mIsDeletable) mDeleteContainer.setVisibility(View.INVISIBLE);
3122591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan            } else {
31337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                if (mListener != null) {
31437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                    mListener.onRequest(EditorListener.FIELD_TURNED_NON_EMPTY);
31537bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan                }
3165e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan                if (mIsDeletable) mDeleteContainer.setVisibility(View.VISIBLE);
3172591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan            }
3182591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan            mWasEmpty = isEmpty;
3192591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan        }
320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
32211bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov    protected boolean isFieldChanged(String column, String value) {
32360b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        final String dbValue = mEntry.getAsString(column);
32460b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        // nullable fields (e.g. Middle Name) are usually represented as empty columns,
32560b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        // so lets treat null and empty space equivalently here
32660b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        final String dbValueNoNull = dbValue == null ? "" : dbValue;
32760b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        final String valueNoNull = value == null ? "" : value;
32860b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann        return !TextUtils.equals(dbValueNoNull, valueNoNull);
32911bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov    }
33011bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov
331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void rebuildValues() {
332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setValues(mKind, mEntry, mState, mReadOnly, mViewIdGenerator);
333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
334392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Prepare this editor using the given {@link DataKind} for defining
337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * structure and {@link ValuesDelta} describing the content to edit.
338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            ViewIdGenerator vig) {
342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mKind = kind;
343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mEntry = entry;
344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mState = state;
345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mReadOnly = readOnly;
346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        mViewIdGenerator = vig;
347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setId(vig.getId(state, kind, entry, ViewIdGenerator.NO_VIEW_INDEX));
348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (!entry.isVisible()) {
350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            // Hide ourselves entirely if deleted
351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            setVisibility(View.GONE);
352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            return;
353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setVisibility(View.VISIBLE);
355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        // Display label selector if multiple types available
357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        final boolean hasTypes = EntityModifier.hasEditTypes(kind);
358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        setupLabelButton(hasTypes);
35963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan        mLabel.setEnabled(!readOnly && isEnabled());
360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (hasTypes) {
361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mType = EntityModifier.getCurrentType(entry, kind);
362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            rebuildLabel();
363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public ValuesDelta getValues() {
367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mEntry;
368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Prepare dialog for entering a custom label. The input value is trimmed: white spaces before
372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * and after the input text is removed.
373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * <p>
374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * If the final value is empty, this change request is ignored;
375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * no empty text is allowed in any custom label.
376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private Dialog createCustomDialog() {
378eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
379eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell        builder.setTitle(R.string.customLabelPickerTitle);
380eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell
381eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell        final EditText customType = new EditText(builder.getContext());
382cb08f1b2a3f2e6e21aa5d993cf44d04658316cccDmitri Plotnikov        customType.setId(R.id.custom_dialog_content);
383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        customType.setInputType(INPUT_TYPE_CUSTOM);
38414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov        customType.setSaveEnabled(true);
385392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        customType.requestFocus();
386392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
387392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setView(customType);
388392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
389392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            @Override
391392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            public void onClick(DialogInterface dialog, int which) {
392392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                final String customText = customType.getText().toString().trim();
393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                if (ContactsUtils.isGraphic(customText)) {
39414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                    final List<EditType> allTypes =
39514918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                            EntityModifier.getValidTypes(mState, mKind, null);
39614918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                    mType = null;
39714918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                    for (EditType editType : allTypes) {
39814918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                        if (editType.customColumn != null) {
39914918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                            mType = editType;
40014918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                            break;
40114918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                        }
40214918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                    }
40314918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov                    if (mType == null) return;
40414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov
405392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mEntry.put(mKind.typeColumn, mType.rawValue);
406392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    mEntry.put(mType.customColumn, customText);
407392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    rebuildLabel();
408392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    requestFocusForFirstEditField();
409392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                    onLabelRebuilt();
410392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                }
411392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
412392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        });
413392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
414392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        builder.setNegativeButton(android.R.string.cancel, null);
415392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
416392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return builder.create();
417392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
418392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
419392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /**
420392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     * Called after the label has changed (either chosen from the list or entered in the Dialog)
421392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann     */
422392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected void onLabelRebuilt() {
423392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
424392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
4252fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    protected void onTypeSelectionChange(int position) {
4262fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        EditType selected = mEditTypeAdapter.getItem(position);
4272fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        // See if the selection has in fact changed
4282fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        if (mEditTypeAdapter.hasCustomSelection() && selected == CUSTOM_SELECTION) {
4292fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            return;
430392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
431392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
4322fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        if (mType == selected && mType.customColumn == null) {
4332fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            return;
4342fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
435392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
4362fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        if (selected.customColumn != null) {
4372fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            showDialog(DIALOG_ID_CUSTOM);
4382fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        } else {
4392fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            // User picked type, and we're sure it's ok to actually write the entry.
4402fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            mType = selected;
4412fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            mEntry.put(mKind.typeColumn, mType.rawValue);
4422fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            rebuildLabel();
4432fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            requestFocusForFirstEditField();
4442fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            onLabelRebuilt();
4452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
446392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
447392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
448392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    /* package */
449392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    void showDialog(int bundleDialogId) {
450392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        Bundle bundle = new Bundle();
451392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        bundle.putInt(DIALOG_ID_KEY, bundleDialogId);
452392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        getDialogManager().showDialogInView(this, bundle);
453392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
454392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
455392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    private DialogManager getDialogManager() {
456392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (mDialogManager == null) {
457392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            Context context = getContext();
458392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            if (!(context instanceof DialogManager.DialogShowingViewActivity)) {
459392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                throw new IllegalStateException(
460392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        "View must be hosted in an Activity that implements " +
461392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                        "DialogManager.DialogShowingViewActivity");
462392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            }
463392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            mDialogManager = ((DialogManager.DialogShowingViewActivity)context).getDialogManager();
464392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
465392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        return mDialogManager;
466392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
467392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
468392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    @Override
469392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public Dialog createDialog(Bundle bundle) {
470392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
471392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        int dialogId = bundle.getInt(DIALOG_ID_KEY);
472392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        switch (dialogId) {
473392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            case DIALOG_ID_CUSTOM:
474392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                return createCustomDialog();
475392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            default:
476392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann                throw new IllegalArgumentException("Invalid dialogId: " + dialogId);
477392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        }
478392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    }
479392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann
480392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    protected abstract void requestFocusForFirstEditField();
4812fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
4822fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    private class EditTypeAdapter extends ArrayAdapter<EditType> {
4832fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        private final LayoutInflater mInflater;
4842fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        private boolean mHasCustomSelection;
485fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan        private int mTextColor;
4862fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
4872fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public EditTypeAdapter(Context context) {
4882fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            super(context, 0);
4892fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
490fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan            mTextColor = context.getResources().getColor(R.color.secondary_text_color);
4912fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
4924fa9cd0088de76d83803210b39f373cd980fd846Dmitri Plotnikov            if (mType != null && mType.customColumn != null) {
4932fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
4942fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                // Use custom label string when present
4952fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                final String customText = mEntry.getAsString(mType.customColumn);
4962fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                if (customText != null) {
4972fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                    add(CUSTOM_SELECTION);
4982fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                    mHasCustomSelection = true;
4992fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                }
5002fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            }
5012fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5022fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            addAll(EntityModifier.getValidTypes(mState, mKind, mType));
5032fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
5042fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5052fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public boolean hasCustomSelection() {
5062fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            return mHasCustomSelection;
5072fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
5082fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5092fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        @Override
5102fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public View getView(int position, View convertView, ViewGroup parent) {
5112fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            return createViewFromResource(
5122fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                    position, convertView, parent, android.R.layout.simple_spinner_item);
5132fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
5142fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5152fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        @Override
5162fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        public View getDropDownView(int position, View convertView, ViewGroup parent) {
5172fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            return createViewFromResource(
5182fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                    position, convertView, parent, android.R.layout.simple_spinner_dropdown_item);
5192fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
5202fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5212fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        private View createViewFromResource(int position, View convertView, ViewGroup parent,
5222fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                int resource) {
5232fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            TextView textView;
5242fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5252fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            if (convertView == null) {
526fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                textView = (TextView) mInflater.inflate(resource, parent, false);
527fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                textView.setAllCaps(true);
5281ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan                textView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
529fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                textView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
530fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                textView.setTextColor(mTextColor);
531a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan                textView.setEllipsize(TruncateAt.MIDDLE);
5322fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            } else {
533fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                textView = (TextView) convertView;
5342fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            }
5352fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov
5362fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            EditType type = getItem(position);
5372fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            String text;
5382fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            if (type == CUSTOM_SELECTION) {
5392fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                text = mEntry.getAsString(mType.customColumn);
5402fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            } else {
5412fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov                text = getContext().getString(type.labelRes);
5422fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov            }
543fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan            textView.setText(text);
544fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan            return textView;
5452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov        }
5462fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov    }
547392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann}
548