LabeledEditorView.java revision 60b239c24c05233bbf3f7cb45697252e15ec76cc
1392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/* 2392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Copyright (C) 2010 The Android Open Source Project 3392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 4392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * you may not use this file except in compliance with the License. 6392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * You may obtain a copy of the License at 7392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 8392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 10392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Unless required by applicable law or agreed to in writing, software 11392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * See the License for the specific language governing permissions and 14392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * limitations under the License. 15392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 16392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 19392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.ContactsUtils; 20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.R; 214597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.DataKind; 224597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.EditType; 23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta; 24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta.ValuesDelta; 25392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityModifier; 26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.DialogManager; 27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.DialogManager.DialogShowingView; 282fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport com.android.contacts.util.ThemeUtils; 29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.AlertDialog; 31392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.app.Dialog; 32392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context; 33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.DialogInterface; 34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Entity; 35392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.res.Resources; 36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Bundle; 3779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport android.os.Handler; 3811bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikovimport android.text.TextUtils; 39392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet; 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; 48392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.ImageButton; 492fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.Spinner; 502fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikovimport android.widget.TextView; 51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 5214918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikovimport java.util.List; 5314918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov 54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/** 55392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Base class for editors that handles labels and values. 56392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Uses {@link ValuesDelta} to read any existing 57392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * {@link Entity} values, and to correctly write any changes values. 58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannpublic abstract class LabeledEditorView extends ViewGroup implements Editor, DialogShowingView { 60392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected static final String DIALOG_ID_KEY = "dialog_id"; 61392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static final int DIALOG_ID_CUSTOM = 1; 62392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT 64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS; 65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 662fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private Spinner mLabel; 672fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private EditTypeAdapter mEditTypeAdapter; 68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ImageButton mDelete; 69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DataKind mKind; 71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ValuesDelta mEntry; 72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EntityDelta mState; 73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mReadOnly; 74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditType mType; 76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 77392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ViewIdGenerator mViewIdGenerator; 78392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DialogManager mDialogManager = null; 79392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditorListener mListener; 8091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected int mMinLineItemHeight; 81392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 822fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov /** 832fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov * A marker in the spinner adapter of the currently selected custom type. 842fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov */ 852fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public static final EditType CUSTOM_SELECTION = new EditType(0, 0); 862fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 872fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private OnItemSelectedListener mSpinnerListener = new OnItemSelectedListener() { 882fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 892fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 902fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public void onItemSelected( 912fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov AdapterView<?> parent, View view, int position, long id) { 922fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov onTypeSelectionChange(position); 932fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 942fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 952fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 962fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public void onNothingSelected(AdapterView<?> parent) { 972fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 982fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov }; 992fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 100392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context) { 101392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context); 10291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 103392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 104392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 105392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context, AttributeSet attrs) { 106392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs); 10791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 108392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 109392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 110392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public LabeledEditorView(Context context, AttributeSet attrs, int defStyle) { 111392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs, defStyle); 11291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov init(context); 11391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 11491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 11591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov private void init(Context context) { 11691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov mMinLineItemHeight = context.getResources().getDimensionPixelSize( 11791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov R.dimen.editor_min_line_item_height); 118392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 12002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public boolean isReadOnly() { 12102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov return mReadOnly; 12202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 12302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 12491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov public int getBaseline(int row) { 12591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov if (row == 0 && mLabel != null) { 12691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov return mLabel.getBaseline(); 12791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 12891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov return -1; 12991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 13091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 13191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov /** 13291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov * Returns the number of rows in this editor, including the invisible ones. 13391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov */ 13491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected int getLineItemCount() { 13591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov return 1; 13691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 13791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 13891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected boolean isLineItemVisible(int row) { 13991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov return true; 14091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 14191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 14291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected int getLineItemHeight(int row) { 14391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int fieldHeight = 0; 14491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int buttonHeight = 0; 14591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov if (row == 0) { 14691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov // summarize the EditText heights 14791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov if (mLabel != null) { 14891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov fieldHeight = mLabel.getMeasuredHeight(); 14991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 15091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 15191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov // Ensure there is enough space for the minus button 15291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov View deleteButton = getDelete(); 15391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov final int deleteHeight = (deleteButton != null) ? deleteButton.getMeasuredHeight() : 0; 15491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov buttonHeight += deleteHeight; 15591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 15691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 15791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov return Math.max(Math.max(buttonHeight, fieldHeight), mMinLineItemHeight); 15891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 15991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 16091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov @Override 16191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 16291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov measureChildren(widthMeasureSpec, heightMeasureSpec); 16391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 16491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int height = 0; 16591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov height += getPaddingTop() + getPaddingBottom(); 16691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 16791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int count = getLineItemCount(); 16891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov for (int i = 0; i < count; i++) { 16991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov if (isLineItemVisible(i)) { 17091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov height += getLineItemHeight(i); 17191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 17291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 17391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 17491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 17591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov resolveSize(height, heightMeasureSpec)); 17691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 17791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 178392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 179392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onLayout(boolean changed, int l, int t, int r, int b) { 180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Subtract padding from the borders ==> x1 variables 181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int t1 = getPaddingTop(); 182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int r1 = getMeasuredWidth() - getPaddingRight(); 183392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int b1 = getMeasuredHeight() - getPaddingBottom(); 184392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 185cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann final int r2; 186cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann if (mDelete != null) { 187cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann r2 = r1 - mDelete.getMeasuredWidth(); 18891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov // Vertically center the delete button in the first line item 18991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int height = mDelete.getMeasuredHeight(); 19091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int top = t1 + (mMinLineItemHeight - height) / 2; 191cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann mDelete.layout( 19291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov r2, top, 19391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov r1, top + height); 194cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann } else { 195cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann r2 = r1; 196cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann } 197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 198cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann if (mLabel != null) { 19991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int baseline = getBaseline(0); 20091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov int y = t1 + baseline - mLabel.getBaseline(); 201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mLabel.layout( 20291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov r2 - mLabel.getMeasuredWidth(), y, 20391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov r2, y + mLabel.getMeasuredHeight()); 204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 205392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 206392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 207392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 208392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Creates or removes the type/label button. Doesn't do anything if already correctly configured 209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 210392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void setupLabelButton(boolean shouldExist) { 211392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (shouldExist && mLabel == null) { 2122fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel = new Spinner(mContext); 213392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final int width = 214392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mContext.getResources().getDimensionPixelSize(R.dimen.editor_type_label_width); 215392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mLabel.setLayoutParams(new LayoutParams(width, LayoutParams.WRAP_CONTENT)); 2162fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setOnItemSelectedListener(mSpinnerListener); 21702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mLabel.setEnabled(!mReadOnly && isEnabled()); 218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann addView(mLabel); 219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else if (!shouldExist && mLabel != null) { 220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann removeView(mLabel); 221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mLabel = null; 222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 223392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 226392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Creates or removes the remove button. Doesn't do anything if already correctly configured 227392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void setupDeleteButton(boolean shouldExist) { 229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (shouldExist && mDelete == null) { 230392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete = new ImageButton(mContext); 231915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann mDelete.setImageResource(R.drawable.ic_menu_remove_field_holo_light); 23279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann mDelete.setBackgroundResource( 23379c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann ThemeUtils.getSelectableItemBackground(mContext.getTheme())); 234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final Resources resources = mContext.getResources(); 235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete.setPadding( 236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_left), 237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_top), 238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_right), 239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_bottom)); 240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete.setContentDescription( 241392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann getResources().getText(R.string.description_minus_button)); 242392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete.setLayoutParams( 243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete.setOnClickListener(new OnClickListener() { 245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onClick(View v) { 24779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann // defer removal of this button so that the pressed state is visible shortly 24879c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann new Handler().post(new Runnable() { 24979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann @Override 25079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann public void run() { 25179c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann // Keep around in model, but mark as deleted 25279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann mEntry.markDeleted(); 25379c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann 25479c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann ((ViewGroup) getParent()).removeView(LabeledEditorView.this); 25579c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann 25679c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann if (mListener != null) { 25779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann // Notify listener when present 25879c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann mListener.onDeleted(LabeledEditorView.this); 25979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann } 26079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann } 26179c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann }); 262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }); 26402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mDelete.setEnabled(!mReadOnly && isEnabled()); 265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann addView(mDelete); 266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else if (!shouldExist && mDelete != null) { 267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann removeView(mDelete); 268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDelete = null; 269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onOptionalFieldVisibilityChange() { 273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mListener != null) { 274392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener.onRequest(EditorListener.EDITOR_FORM_CHANGED); 275392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 276392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 277392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 278392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setEditorListener(EditorListener listener) { 280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener = listener; 281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 282392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 283392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setDeletable(boolean deletable) { 285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setupDeleteButton(deletable); 286392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 287392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 288392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 289392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setEnabled(boolean enabled) { 29002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov super.setEnabled(enabled); 29102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mLabel != null) mLabel.setEnabled(!mReadOnly && enabled); 29202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mDelete != null) mDelete.setEnabled(!mReadOnly && enabled); 293392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 294392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2952fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public Spinner getLabel() { 296392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mLabel; 297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public ImageButton getDelete() { 300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mDelete; 301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected DataKind getKind() { 304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mKind; 305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected ValuesDelta getEntry() { 308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mEntry; 309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected EditType getType() { 312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mType; 313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 315392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Build the current label state based on selected {@link EditType} and 317392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * possible custom label string. 318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void rebuildLabel() { 320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mLabel == null) return; 3212fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mEditTypeAdapter = new EditTypeAdapter(mContext); 3222fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setAdapter(mEditTypeAdapter); 3232fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mEditTypeAdapter.hasCustomSelection()) { 3242fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setSelection(mEditTypeAdapter.getPosition(CUSTOM_SELECTION)); 3252fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 3262fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mLabel.setSelection(mEditTypeAdapter.getPosition(mType)); 327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onFieldChanged(String column, String value) { 33211bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov if (!isFieldChanged(column, value)) { 3337d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov return; 3347d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov } 3357d4a8dda946f5c013573e4d6601fc14c03156ba6Dmitri Plotnikov 336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Field changes are saved directly 337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(column, value); 338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mListener != null) { 339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mListener.onRequest(EditorListener.FIELD_CHANGED); 340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 34311bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov protected boolean isFieldChanged(String column, String value) { 34460b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String dbValue = mEntry.getAsString(column); 34560b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann // nullable fields (e.g. Middle Name) are usually represented as empty columns, 34660b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann // so lets treat null and empty space equivalently here 34760b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String dbValueNoNull = dbValue == null ? "" : dbValue; 34860b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann final String valueNoNull = value == null ? "" : value; 34960b239c24c05233bbf3f7cb45697252e15ec76ccDaniel Lehmann return !TextUtils.equals(dbValueNoNull, valueNoNull); 35011bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov } 35111bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov 352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void rebuildValues() { 353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setValues(mKind, mEntry, mState, mReadOnly, mViewIdGenerator); 354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Prepare this editor using the given {@link DataKind} for defining 358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * structure and {@link ValuesDelta} describing the content to edit. 359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, 362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ViewIdGenerator vig) { 363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mKind = kind; 364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry = entry; 365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mState = state; 366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mReadOnly = readOnly; 367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mViewIdGenerator = vig; 368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setId(vig.getId(state, kind, entry, ViewIdGenerator.NO_VIEW_INDEX)); 369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!entry.isVisible()) { 371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Hide ourselves entirely if deleted 372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setVisibility(View.GONE); 373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return; 374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setVisibility(View.VISIBLE); 376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Display label selector if multiple types available 378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final boolean hasTypes = EntityModifier.hasEditTypes(kind); 379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setupLabelButton(hasTypes); 38002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mLabel != null) mLabel.setEnabled(!readOnly && isEnabled()); 381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (hasTypes) { 382392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mType = EntityModifier.getCurrentType(entry, kind); 383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann rebuildLabel(); 384392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 385392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 386392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 387392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public ValuesDelta getValues() { 388392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mEntry; 389392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 391392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 392392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Prepare dialog for entering a custom label. The input value is trimmed: white spaces before 393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * and after the input text is removed. 394392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * <p> 395392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * If the final value is empty, this change request is ignored; 396392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * no empty text is allowed in any custom label. 397392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 398392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private Dialog createCustomDialog() { 399392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final EditText customType = new EditText(mContext); 400cb08f1b2a3f2e6e21aa5d993cf44d04658316cccDmitri Plotnikov customType.setId(R.id.custom_dialog_content); 401392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann customType.setInputType(INPUT_TYPE_CUSTOM); 40214918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov customType.setSaveEnabled(true); 403392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann customType.requestFocus(); 404392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 405392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 406392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setTitle(R.string.customLabelPickerTitle); 407392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setView(customType); 408392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 409392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 410392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 411392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onClick(DialogInterface dialog, int which) { 412392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final String customText = customType.getText().toString().trim(); 413392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (ContactsUtils.isGraphic(customText)) { 41414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov final List<EditType> allTypes = 41514918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov EntityModifier.getValidTypes(mState, mKind, null); 41614918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov mType = null; 41714918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov for (EditType editType : allTypes) { 41814918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov if (editType.customColumn != null) { 41914918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov mType = editType; 42014918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov break; 42114918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov } 42214918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov } 42314918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov if (mType == null) return; 42414918c07e1cb3b5b190bec4cc9106db7adbba29fDmitri Plotnikov 425392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(mKind.typeColumn, mType.rawValue); 426392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mEntry.put(mType.customColumn, customText); 427392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann rebuildLabel(); 428392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann requestFocusForFirstEditField(); 429392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann onLabelRebuilt(); 430392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 431392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 432392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }); 433392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 434392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann builder.setNegativeButton(android.R.string.cancel, null); 435392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 436392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return builder.create(); 437392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 438392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 439392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 440392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Called after the label has changed (either chosen from the list or entered in the Dialog) 441392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 442392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onLabelRebuilt() { 443392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 444392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov protected void onTypeSelectionChange(int position) { 4462fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov EditType selected = mEditTypeAdapter.getItem(position); 4472fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // See if the selection has in fact changed 4482fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mEditTypeAdapter.hasCustomSelection() && selected == CUSTOM_SELECTION) { 4492fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return; 450392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 451392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4522fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (mType == selected && mType.customColumn == null) { 4532fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return; 4542fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 455392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 4562fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (selected.customColumn != null) { 4572fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov showDialog(DIALOG_ID_CUSTOM); 4582fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 4592fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // User picked type, and we're sure it's ok to actually write the entry. 4602fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mType = selected; 4612fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mEntry.put(mKind.typeColumn, mType.rawValue); 4622fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov rebuildLabel(); 4632fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov requestFocusForFirstEditField(); 4642fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov onLabelRebuilt(); 4652fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 466392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 467392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 468392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /* package */ 469392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann void showDialog(int bundleDialogId) { 470392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Bundle bundle = new Bundle(); 471392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann bundle.putInt(DIALOG_ID_KEY, bundleDialogId); 472392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann getDialogManager().showDialogInView(this, bundle); 473392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 474392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 475392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private DialogManager getDialogManager() { 476392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mDialogManager == null) { 477392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Context context = getContext(); 478392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!(context instanceof DialogManager.DialogShowingViewActivity)) { 479392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann throw new IllegalStateException( 480392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann "View must be hosted in an Activity that implements " + 481392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann "DialogManager.DialogShowingViewActivity"); 482392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 483392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mDialogManager = ((DialogManager.DialogShowingViewActivity)context).getDialogManager(); 484392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 485392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mDialogManager; 486392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 487392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 488392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 489392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public Dialog createDialog(Bundle bundle) { 490392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (bundle == null) throw new IllegalArgumentException("bundle must not be null"); 491392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int dialogId = bundle.getInt(DIALOG_ID_KEY); 492392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann switch (dialogId) { 493392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann case DIALOG_ID_CUSTOM: 494392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return createCustomDialog(); 495392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann default: 496392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann throw new IllegalArgumentException("Invalid dialogId: " + dialogId); 497392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 498392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 499392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 500392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected abstract void requestFocusForFirstEditField(); 5012fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5022fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private class EditTypeAdapter extends ArrayAdapter<EditType> { 5032fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private final LayoutInflater mInflater; 5042fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private boolean mHasCustomSelection; 5052fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5062fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public EditTypeAdapter(Context context) { 5072fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov super(context, 0); 5082fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 5092fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5104fa9cd0088de76d83803210b39f373cd980fd846Dmitri Plotnikov if (mType != null && mType.customColumn != null) { 5112fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5122fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov // Use custom label string when present 5132fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov final String customText = mEntry.getAsString(mType.customColumn); 5142fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (customText != null) { 5152fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov add(CUSTOM_SELECTION); 5162fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov mHasCustomSelection = true; 5172fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5182fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5192fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5202fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov addAll(EntityModifier.getValidTypes(mState, mKind, mType)); 5212fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5222fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5232fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public boolean hasCustomSelection() { 5242fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return mHasCustomSelection; 5252fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5262fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5272fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 5282fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public View getView(int position, View convertView, ViewGroup parent) { 5292fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return createViewFromResource( 5302fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov position, convertView, parent, android.R.layout.simple_spinner_item); 5312fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5322fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5332fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov @Override 5342fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov public View getDropDownView(int position, View convertView, ViewGroup parent) { 5352fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return createViewFromResource( 5362fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov position, convertView, parent, android.R.layout.simple_spinner_dropdown_item); 5372fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5382fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5392fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov private View createViewFromResource(int position, View convertView, ViewGroup parent, 5402fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov int resource) { 5412fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov View view; 5422fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov TextView textView; 5432fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5442fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (convertView == null) { 5452fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov view = mInflater.inflate(resource, parent, false); 5462fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 5472fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov view = convertView; 5482fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5492fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5502fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov textView = (TextView) view; 5512fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov 5522fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov EditType type = getItem(position); 5532fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov String text; 5542fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov if (type == CUSTOM_SELECTION) { 5552fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov text = mEntry.getAsString(mType.customColumn); 5562fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } else { 5572fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov text = getContext().getString(type.labelRes); 5582fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5592fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov textView.setText(text); 5602fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov return view; 5612fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 5622fcfa499dd44f62dc63636e363522354e13aa20dDmitri Plotnikov } 563392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann} 564