1392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/* 2392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Copyright (C) 2010 The Android Open Source Project 3392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 4392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * you may not use this file except in compliance with the License. 6392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * You may obtain a copy of the License at 7392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 8392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 10392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Unless required by applicable law or agreed to in writing, software 11392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * See the License for the specific language governing permissions and 14392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * limitations under the License. 15392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 16392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 19392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.AlertDialog; 20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.Dialog; 21392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context; 22392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.DialogInterface; 23a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmannimport android.content.DialogInterface.OnShowListener; 24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Bundle; 2579c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport android.os.Handler; 26a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmannimport android.text.Editable; 2711bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikovimport android.text.TextUtils; 28a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuanimport android.text.TextUtils.TruncateAt; 29e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.text.TextWatcher; 30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet; 31a66642330b5c4a62c8b7ce438ccff57c3b017eb1Katherine Kuanimport android.view.Gravity; 322fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.view.LayoutInflater; 33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View; 34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.ViewGroup; 35a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmannimport android.view.WindowManager; 36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.inputmethod.EditorInfo; 372fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.AdapterView; 382fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.AdapterView.OnItemSelectedListener; 392fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.ArrayAdapter; 40a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmannimport android.widget.Button; 41392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText; 4212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanimport android.widget.ImageView; 4363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.widget.LinearLayout; 442fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.Spinner; 452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.TextView; 46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 47e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 48cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContactDelta; 49cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.ContactsUtils; 50738ff8623dc77dd91a1b9023861e924ba5e4c27eChiao Chengimport com.android.contacts.common.model.ValuesDelta; 51cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContactModifier; 52428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType.EditType; 53428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 54e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.DialogManager; 55e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.DialogManager.DialogShowingView; 56e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 5714918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikovimport java.util.List; 5814918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov 59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/** 6063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * Base class for editors that handles labels and values. Uses 61851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * {@link ValuesDelta} to read any existing {@link RawContact} values, and to 6263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * correctly write any changes values. 63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 6463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanpublic abstract class LabeledEditorView extends LinearLayout implements Editor, DialogShowingView { 65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected static final String DIALOG_ID_KEY = "dialog_id"; 66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static final int DIALOG_ID_CUSTOM = 1; 67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT 69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS; 70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 712fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private Spinner mLabel; 722fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private EditTypeAdapter mEditTypeAdapter; 7363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan private View mDeleteContainer; 7412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan private ImageView mDelete; 75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DataKind mKind; 77392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ValuesDelta mEntry; 78851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu private RawContactDelta mState; 79392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mReadOnly; 802591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan private boolean mWasEmpty = true; 815e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan private boolean mIsDeletable = true; 822293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan private boolean mIsAttachedToWindow; 83392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 84392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditType mType; 85392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 86392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 87392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DialogManager mDialogManager = null; 88392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditorListener mListener; 8991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected int mMinLineItemHeight; 90392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 912fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov /** 922fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov * A marker in the spinner adapter of the currently selected custom type. 932fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov */ 942fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public static final EditType CUSTOM_SELECTION = new EditType(0, 0); 952fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 962fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private OnItemSelectedListener mSpinnerListener = new OnItemSelectedListener() { 972fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 982fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 992fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public void onItemSelected( 1002fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov AdapterView<?> parent, View view, int position, long id) { 1012fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov onTypeSelectionChange(position); 1022fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 1032fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 1042fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 1052fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public void onNothingSelected(AdapterView<?> parent) { 1062fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 1072fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov }; 1082fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 109392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context) { 110392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context); 11191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 112392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 113392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 114392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context, AttributeSet attrs) { 115392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs); 11691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 117392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 118392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context, AttributeSet attrs, int defStyle) { 120392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs, defStyle); 12191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 12291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 12391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 12491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov private void init(Context context) { 12591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov mMinLineItemHeight = context.getResources().getDimensionPixelSize( 12691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov R.dimen.editor_min_line_item_height); 127392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 128392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 12963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan /** {@inheritDoc} */ 13063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 13163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan protected void onFinishInflate() { 13202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 13363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel = (Spinner) findViewById(R.id.spinner); 13467713b3e6e3af70020350e2650738389f19c073eDaniel Lehmann // Turn off the Spinner's own state management. We do this ourselves on rotation 13567713b3e6e3af70020350e2650738389f19c073eDaniel Lehmann mLabel.setId(View.NO_ID); 13663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel.setOnItemSelectedListener(mSpinnerListener); 13791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 13812a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mDelete = (ImageView) findViewById(R.id.delete_button); 13963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mDeleteContainer = findViewById(R.id.delete_button_container); 14012a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mDeleteContainer.setOnClickListener(new OnClickListener() { 14163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 14263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public void onClick(View v) { 14363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // defer removal of this button so that the pressed state is visible shortly 14463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan new Handler().post(new Runnable() { 14563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 14663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public void run() { 1472293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Don't do anything if the view is no longer attached to the window 1482293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // (This check is needed because when this {@link Runnable} is executed, 1492293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // we can't guarantee the view is still valid. 1502293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan if (!mIsAttachedToWindow) { 1512293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan return; 1522293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 1532293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Send the delete request to the listener (which will in turn call 1542293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // deleteEditor() on this view if the deletion is valid - i.e. this is not 1552293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // the last {@link Editor} in the section). 15663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan if (mListener != null) { 1572293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan mListener.onDeleteRequested(LabeledEditorView.this); 15863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } 15963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } 16063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan }); 16191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 16263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan }); 16391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 16491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 1652293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan @Override 1662293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan protected void onAttachedToWindow() { 1672293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan super.onAttachedToWindow(); 1682293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Keep track of when the view is attached or detached from the window, so we know it's 1692293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // safe to remove views (in case the user requests to delete this editor). 1702293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan mIsAttachedToWindow = true; 1712293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 1722293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan 1732293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan @Override 1742293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan protected void onDetachedFromWindow() { 1752293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan super.onDetachedFromWindow(); 1762293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan mIsAttachedToWindow = false; 1772293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 1782293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan 1792293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan @Override 1802293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void deleteEditor() { 1812293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Keep around in model, but mark as deleted 1822293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan mEntry.markDeleted(); 1832293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan 1842293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Remove the view 185ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann EditorAnimator.getInstance().removeEditorView(this); 1862293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 1872293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan 18863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public boolean isReadOnly() { 18963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan return mReadOnly; 19091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 19191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 19263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public int getBaseline(int row) { 19363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan if (row == 0 && mLabel != null) { 19463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan return mLabel.getBaseline(); 195392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 19663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan return -1; 197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 198392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 199392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 200a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan * Configures the visibility of the type label button and enables or disables it properly. 201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void setupLabelButton(boolean shouldExist) { 20363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan if (shouldExist) { 20402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mLabel.setEnabled(!mReadOnly && isEnabled()); 20563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel.setVisibility(View.VISIBLE); 20663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } else { 20763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel.setVisibility(View.GONE); 208392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 210392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 211392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 212a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan * Configures the visibility of the "delete" button and enables or disables it properly. 213392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 2145e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan private void setupDeleteButton() { 2155e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan if (mIsDeletable) { 21663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mDeleteContainer.setVisibility(View.VISIBLE); 21702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mDelete.setEnabled(!mReadOnly && isEnabled()); 21863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } else { 21963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mDeleteContainer.setVisibility(View.GONE); 220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2235e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan public void setDeleteButtonVisible(boolean visible) { 2245e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan if (mIsDeletable) { 225a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan mDeleteContainer.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); 2265e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan } 2275e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan } 2285e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan 229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onOptionalFieldVisibilityChange() { 230392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mListener != null) { 231392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener.onRequest(EditorListener.EDITOR_FORM_CHANGED); 232392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 233392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setEditorListener(EditorListener listener) { 237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener = listener; 238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 241392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setDeletable(boolean deletable) { 2425e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan mIsDeletable = deletable; 2435e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan setupDeleteButton(); 244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setEnabled(boolean enabled) { 24802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov super.setEnabled(enabled); 24963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel.setEnabled(!mReadOnly && enabled); 25063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mDelete.setEnabled(!mReadOnly && enabled); 251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2532fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public Spinner getLabel() { 254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mLabel; 255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 25712a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan public ImageView getDelete() { 258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mDelete; 259392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 260392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected DataKind getKind() { 262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mKind; 263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 264392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected ValuesDelta getEntry() { 266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mEntry; 267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected EditType getType() { 270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mType; 271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 274392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Build the current label state based on selected {@link EditType} and 275392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * possible custom label string. 276392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 277392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void rebuildLabel() { 2782fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mEditTypeAdapter = new EditTypeAdapter(mContext); 2792fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setAdapter(mEditTypeAdapter); 2802fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mEditTypeAdapter.hasCustomSelection()) { 2812fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setSelection(mEditTypeAdapter.getPosition(CUSTOM_SELECTION)); 2822fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 2832fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setSelection(mEditTypeAdapter.getPosition(mType)); 284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 286392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 287392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 288392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onFieldChanged(String column, String value) { 28911bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov if (!isFieldChanged(column, value)) { 2907d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov return; 2917d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov } 2927d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov 293392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Field changes are saved directly 294e55faef88185628c842e0aa778d883f209323630Katherine Kuan saveValue(column, value); 295e55faef88185628c842e0aa778d883f209323630Katherine Kuan 296e55faef88185628c842e0aa778d883f209323630Katherine Kuan // Notify listener if applicable 297e55faef88185628c842e0aa778d883f209323630Katherine Kuan notifyEditorListener(); 298e55faef88185628c842e0aa778d883f209323630Katherine Kuan } 299e55faef88185628c842e0aa778d883f209323630Katherine Kuan 300e55faef88185628c842e0aa778d883f209323630Katherine Kuan protected void saveValue(String column, String value) { 301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(column, value); 302e55faef88185628c842e0aa778d883f209323630Katherine Kuan } 303e55faef88185628c842e0aa778d883f209323630Katherine Kuan 304e55faef88185628c842e0aa778d883f209323630Katherine Kuan protected void notifyEditorListener() { 305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mListener != null) { 306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener.onRequest(EditorListener.FIELD_CHANGED); 307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 3082591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan 3092591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan boolean isEmpty = isEmpty(); 3102591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (mWasEmpty != isEmpty) { 3112591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (isEmpty) { 31237bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (mListener != null) { 31337bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mListener.onRequest(EditorListener.FIELD_TURNED_EMPTY); 31437bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 315a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan if (mIsDeletable) mDeleteContainer.setVisibility(View.INVISIBLE); 3162591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } else { 31737bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan if (mListener != null) { 31837bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan mListener.onRequest(EditorListener.FIELD_TURNED_NON_EMPTY); 31937bddc2fa266fa0378fcd85ac5047b1fb0af2dc0Katherine Kuan } 3205e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan if (mIsDeletable) mDeleteContainer.setVisibility(View.VISIBLE); 3212591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } 3222591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan mWasEmpty = isEmpty; 3232591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } 324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 32611bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov protected boolean isFieldChanged(String column, String value) { 32760b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String dbValue = mEntry.getAsString(column); 32860b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann // nullable fields (e.g. Middle Name) are usually represented as empty columns, 32960b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann // so lets treat null and empty space equivalently here 33060b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String dbValueNoNull = dbValue == null ? "" : dbValue; 33160b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String valueNoNull = value == null ? "" : value; 33260b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann return !TextUtils.equals(dbValueNoNull, valueNoNull); 33311bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 33411bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov 335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void rebuildValues() { 336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setValues(mKind, mEntry, mState, mReadOnly, mViewIdGenerator); 337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Prepare this editor using the given {@link DataKind} for defining 341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * structure and {@link ValuesDelta} describing the content to edit. 342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 344851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly, 345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ViewIdGenerator vig) { 346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mKind = kind; 347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry = entry; 348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mState = state; 349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mReadOnly = readOnly; 350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mViewIdGenerator = vig; 351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setId(vig.getId(state, kind, entry, ViewIdGenerator.NO_VIEW_INDEX)); 352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!entry.isVisible()) { 354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Hide ourselves entirely if deleted 355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setVisibility(View.GONE); 356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return; 357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setVisibility(View.VISIBLE); 359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Display label selector if multiple types available 361851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final boolean hasTypes = RawContactModifier.hasEditTypes(kind); 362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setupLabelButton(hasTypes); 36363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mLabel.setEnabled(!readOnly && isEnabled()); 364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (hasTypes) { 365851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mType = RawContactModifier.getCurrentType(entry, kind); 366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann rebuildLabel(); 367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public ValuesDelta getValues() { 371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mEntry; 372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Prepare dialog for entering a custom label. The input value is trimmed: white spaces before 376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * and after the input text is removed. 377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * <p> 378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * If the final value is empty, this change request is ignored; 379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * no empty text is allowed in any custom label. 380392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private Dialog createCustomDialog() { 382eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 383a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final LayoutInflater layoutInflater = LayoutInflater.from(builder.getContext()); 384eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell builder.setTitle(R.string.customLabelPickerTitle); 385eb765ac75178eccf5a44a3410e21a7f88419fd84Adam Powell 386a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final View view = layoutInflater.inflate(R.layout.contact_editor_label_name_dialog, null); 387a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final EditText editText = (EditText) view.findViewById(R.id.custom_dialog_content); 388a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann editText.setInputType(INPUT_TYPE_CUSTOM); 389a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann editText.setSaveEnabled(true); 390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 391a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann builder.setView(view); 392a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann editText.requestFocus(); 393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 394392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 395392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 396392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 397a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final String customText = editText.getText().toString().trim(); 398392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (ContactsUtils.isGraphic(customText)) { 39914918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov final List<EditType> allTypes = 400851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu RawContactModifier.getValidTypes(mState, mKind, null); 40114918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov mType = null; 40214918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov for (EditType editType : allTypes) { 40314918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov if (editType.customColumn != null) { 40414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov mType = editType; 40514918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov break; 40614918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov } 40714918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov } 40814918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov if (mType == null) return; 40914918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov 410392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(mKind.typeColumn, mType.rawValue); 411392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(mType.customColumn, customText); 412392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann rebuildLabel(); 413392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann requestFocusForFirstEditField(); 414392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann onLabelRebuilt(); 415392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 416392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 417392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }); 418392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 419392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setNegativeButton(android.R.string.cancel, null); 420392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 421a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final AlertDialog dialog = builder.create(); 422a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann dialog.setOnShowListener(new OnShowListener() { 423a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann @Override 424a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann public void onShow(DialogInterface dialogInterface) { 425a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann updateCustomDialogOkButtonState(dialog, editText); 426a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann } 427a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann }); 428a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann editText.addTextChangedListener(new TextWatcher() { 429a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann @Override 430a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann public void onTextChanged(CharSequence s, int start, int before, int count) { 431a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann } 432a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann 433a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann @Override 434a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann public void beforeTextChanged(CharSequence s, int start, int count, int after) { 435a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann } 436a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann 437a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann @Override 438a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann public void afterTextChanged(Editable s) { 439a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann updateCustomDialogOkButtonState(dialog, editText); 440a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann } 441a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann }); 442a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann dialog.getWindow().setSoftInputMode( 443a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); 444a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann 445a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann return dialog; 446a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann } 447a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann 448a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann /* package */ void updateCustomDialogOkButtonState(AlertDialog dialog, EditText editText) { 449a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann final Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); 450a04dc9c9ed2812af8f4466c2a5225a37d38d250eDaniel Lehmann okButton.setEnabled(!TextUtils.isEmpty(editText.getText().toString().trim())); 451392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 452392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 453392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 454392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Called after the label has changed (either chosen from the list or entered in the Dialog) 455392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 456392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onLabelRebuilt() { 457392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 458392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4592fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov protected void onTypeSelectionChange(int position) { 4602fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov EditType selected = mEditTypeAdapter.getItem(position); 4612fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // See if the selection has in fact changed 4622fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mEditTypeAdapter.hasCustomSelection() && selected == CUSTOM_SELECTION) { 4632fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return; 464392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 465392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4662fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mType == selected && mType.customColumn == null) { 4672fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return; 4682fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 469392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4702fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (selected.customColumn != null) { 4712fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov showDialog(DIALOG_ID_CUSTOM); 4722fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 4732fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // User picked type, and we're sure it's ok to actually write the entry. 4742fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mType = selected; 4752fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mEntry.put(mKind.typeColumn, mType.rawValue); 4762fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov rebuildLabel(); 4772fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov requestFocusForFirstEditField(); 4782fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov onLabelRebuilt(); 4792fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 480392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 481392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 482392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /* package */ 483392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann void showDialog(int bundleDialogId) { 484392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Bundle bundle = new Bundle(); 485392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann bundle.putInt(DIALOG_ID_KEY, bundleDialogId); 486392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann getDialogManager().showDialogInView(this, bundle); 487392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 488392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 489392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DialogManager getDialogManager() { 490392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mDialogManager == null) { 491392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Context context = getContext(); 492392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!(context instanceof DialogManager.DialogShowingViewActivity)) { 493392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann throw new IllegalStateException( 494392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann "View must be hosted in an Activity that implements " + 495392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann "DialogManager.DialogShowingViewActivity"); 496392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 497392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDialogManager = ((DialogManager.DialogShowingViewActivity)context).getDialogManager(); 498392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 499392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mDialogManager; 500392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 501392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 502392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 503392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public Dialog createDialog(Bundle bundle) { 504392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (bundle == null) throw new IllegalArgumentException("bundle must not be null"); 505392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int dialogId = bundle.getInt(DIALOG_ID_KEY); 506392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann switch (dialogId) { 507392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann case DIALOG_ID_CUSTOM: 508392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return createCustomDialog(); 509392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann default: 510392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann throw new IllegalArgumentException("Invalid dialogId: " + dialogId); 511392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 512392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 513392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 514392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected abstract void requestFocusForFirstEditField(); 5152fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5162fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private class EditTypeAdapter extends ArrayAdapter<EditType> { 5172fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private final LayoutInflater mInflater; 5182fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private boolean mHasCustomSelection; 519fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan private int mTextColor; 5202fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5212fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public EditTypeAdapter(Context context) { 5222fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov super(context, 0); 5232fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 524fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mTextColor = context.getResources().getColor(R.color.secondary_text_color); 5252fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5264fa9cd0088de76d83803210b39f373cd980fd846Dmitri Plotnikov if (mType != null && mType.customColumn != null) { 5272fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5282fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // Use custom label string when present 5292fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov final String customText = mEntry.getAsString(mType.customColumn); 5302fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (customText != null) { 5312fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov add(CUSTOM_SELECTION); 5322fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mHasCustomSelection = true; 5332fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5342fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5352fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 536851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu addAll(RawContactModifier.getValidTypes(mState, mKind, mType)); 5372fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5382fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5392fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public boolean hasCustomSelection() { 5402fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return mHasCustomSelection; 5412fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5422fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5432fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 5442fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public View getView(int position, View convertView, ViewGroup parent) { 5452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return createViewFromResource( 5462fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov position, convertView, parent, android.R.layout.simple_spinner_item); 5472fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5482fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5492fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 5502fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public View getDropDownView(int position, View convertView, ViewGroup parent) { 5512fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return createViewFromResource( 5522fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov position, convertView, parent, android.R.layout.simple_spinner_dropdown_item); 5532fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5542fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5552fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private View createViewFromResource(int position, View convertView, ViewGroup parent, 5562fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov int resource) { 5572fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov TextView textView; 5582fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5592fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (convertView == null) { 560fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView = (TextView) mInflater.inflate(resource, parent, false); 561fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView.setAllCaps(true); 5627d3b91577f84a4f5092d28ed0f3cfe7e0df32696Fabrice Di Meglio textView.setGravity(Gravity.END | Gravity.CENTER_VERTICAL); 563fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView.setTextAppearance(mContext, android.R.style.TextAppearance_Small); 564fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView.setTextColor(mTextColor); 565a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan textView.setEllipsize(TruncateAt.MIDDLE); 5662fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 567fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView = (TextView) convertView; 5682fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5692fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5702fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov EditType type = getItem(position); 5712fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov String text; 5722fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (type == CUSTOM_SELECTION) { 5732fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov text = mEntry.getAsString(mType.customColumn); 5742fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 5752fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov text = getContext().getString(type.labelRes); 5762fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 577fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan textView.setText(text); 578fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan return textView; 5792fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5802fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 581392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann} 582