1aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey/* 2aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Copyright (C) 2009 The Android Open Source Project 3aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * 4aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * you may not use this file except in compliance with the License. 6aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * You may obtain a copy of the License at 7aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * 8aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * 10aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * See the License for the specific language governing permissions and 14aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * limitations under the License. 15aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey */ 16aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 19aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport com.android.contacts.R; 2018ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.Editor.EditorListener; 21405671a7b42d97ebf7ae7c0eeb4721f881139673Daisuke Miyakawaimport com.android.contacts.model.DataKind; 22d25f958595b190586bd838d50718b1a2a3f0d417Dmitri Plotnikovimport com.android.contacts.model.EntityDelta; 23aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport com.android.contacts.model.EntityDelta.ValuesDelta; 24d25f958595b190586bd838d50718b1a2a3f0d417Dmitri Plotnikovimport com.android.contacts.model.EntityModifier; 25aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 26aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.content.Context; 273e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmannimport android.text.TextUtils; 28aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.util.AttributeSet; 2963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.view.LayoutInflater; 30aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.view.View; 31aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.view.ViewGroup; 32aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.widget.LinearLayout; 331b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuanimport android.widget.TextView; 34aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 3562bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikovimport java.util.ArrayList; 361b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuanimport java.util.List; 3762bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov 38aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey/** 39aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Custom view for an entire section of data as segmented by 40aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * {@link DataKind} around a {@link Data#MIMETYPE}. This view shows a 41aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * section header and a trigger for adding new {@link Data} rows. 42aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey */ 43bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmannpublic class KindSectionView extends LinearLayout implements EditorListener { 44aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey private static final String TAG = "KindSectionView"; 45aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 46a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan private TextView mTitle; 47aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey private ViewGroup mEditors; 481b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan private View mAddFieldFooter; 49f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann private String mTitleString; 50aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 51aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey private DataKind mKind; 52aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey private EntityDelta mState; 5392525ff51e2cb06531447a7dcde5e22334669c8eMegha Joshi private boolean mReadOnly; 546f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey 554b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki private ViewIdGenerator mViewIdGenerator; 564b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki 5763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan private LayoutInflater mInflater; 5891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 59aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey public KindSectionView(Context context) { 6091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov this(context, null); 61aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 62aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 63aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey public KindSectionView(Context context, AttributeSet attrs) { 64aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey super(context, attrs); 65aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 66aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 6702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov @Override 6802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public void setEnabled(boolean enabled) { 6902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov super.setEnabled(enabled); 7002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov if (mEditors != null) { 7102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov int childCount = mEditors.getChildCount(); 7202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov for (int i = 0; i < childCount; i++) { 7302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mEditors.getChildAt(i).setEnabled(enabled); 7402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 7502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 7602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 771b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan if (enabled && !mReadOnly) { 781b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.VISIBLE); 791b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } else { 801b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.GONE); 8191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 8291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov } 8391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov 8402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov public boolean isReadOnly() { 8502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov return mReadOnly; 8602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov } 8702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 88aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey /** {@inheritDoc} */ 89aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey @Override 90aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey protected void onFinishInflate() { 91aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey setDrawingCacheEnabled(true); 92aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey setAlwaysDrawnWithCacheEnabled(true); 93aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 9463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 9563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 96a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan mTitle = (TextView) findViewById(R.id.kind_title); 97a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan mEditors = (ViewGroup) findViewById(R.id.kind_editors); 981b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter = findViewById(R.id.add_field_footer); 991b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setOnClickListener(new OnClickListener() { 10079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann @Override 101bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann public void onClick(View v) { 1021b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // Setup click listener to add an empty field when the footer is clicked. 1031b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.GONE); 1041b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan addItem(); 105bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann } 106bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann }); 107aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 108aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 10979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann @Override 1102293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void onDeleteRequested(Editor editor) { 1112293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // If there is only 1 editor in the section, then don't allow the user to delete it. 1122293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Just clear the fields in the editor. 1132293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan if (getEditorCount() == 1) { 1142293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan editor.clearAllFields(); 1152293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } else { 1162293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Otherwise it's okay to delete this {@link Editor} 1172293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan editor.deleteEditor(); 1182293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 1191b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateAddFooterVisible(); 120aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 121aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 12279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann @Override 1236f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey public void onRequest(int request) { 1242591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan // If a field has become empty or non-empty, then check if another row 1252591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan // can be added dynamically. 1262591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (request == FIELD_TURNED_EMPTY || request == FIELD_TURNED_NON_EMPTY) { 1271b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateAddFooterVisible(); 1281b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 1296f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey } 1306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey 1314b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki public void setState(DataKind kind, EntityDelta state, boolean readOnly, ViewIdGenerator vig) { 132aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey mKind = kind; 133aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey mState = state; 13492525ff51e2cb06531447a7dcde5e22334669c8eMegha Joshi mReadOnly = readOnly; 1354b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki mViewIdGenerator = vig; 1364b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki 1374b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki setId(mViewIdGenerator.getId(state, kind, null, ViewIdGenerator.NO_VIEW_INDEX)); 138aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 139aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey // TODO: handle resources from remote packages 140f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann mTitleString = (kind.titleRes == -1 || kind.titleRes == 0) 141f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann ? "" 142cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann : getResources().getString(kind.titleRes); 143fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan mTitle.setText(mTitleString); 144aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 145bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann rebuildFromState(); 1461b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateAddFooterVisible(); 1471b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateSectionVisible(); 148bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann } 149bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann 150f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann public String getTitle() { 151f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann return mTitleString; 152aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 153aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 1543fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan public void setTitleVisible(boolean visible) { 1553fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan findViewById(R.id.kind_title_layout).setVisibility(visible ? View.VISIBLE : View.GONE); 1563fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan } 1573fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan 158aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey /** 159aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Build editors for all current {@link #mState} rows. 160aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey */ 161aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey public void rebuildFromState() { 162aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey // Remove any existing editors 163aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey mEditors.removeAllViews(); 164aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 165da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann // Check if we are displaying anything here 166da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann boolean hasEntries = mState.hasMimeEntries(mKind.mimeType); 167da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann 168da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann if (hasEntries) { 169da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann for (ValuesDelta entry : mState.getMimeEntries(mKind.mimeType)) { 170da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann // Skip entries that aren't visible 171da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann if (!entry.isVisible()) continue; 1723e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann if (isEmptyNoop(entry)) continue; 173da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann 174634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann createEditorView(entry); 175da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann } 176aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 177aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 178aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey 179634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann 180634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann /** 181634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann * Creates an EditorView for the given entry. This function must be used while constructing 182634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann * the views corresponding to the the object-model. The resulting EditorView is also added 183634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann * to the end of mEditors 184634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann */ 185634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann private View createEditorView(ValuesDelta entry) { 186634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann final View view; 18763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan try { 18863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, false); 18963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } catch (Exception e) { 19063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan throw new RuntimeException( 19163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan "Cannot allocate editor with layout resource ID " + 1922591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan mKind.editorLayoutResourceId + " for MIME type " + mKind.mimeType + 1932591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan " with error " + e.toString()); 194634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann } 195634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann 19602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov view.setEnabled(isEnabled()); 19702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov 198634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann if (view instanceof Editor) { 199634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann Editor editor = (Editor) view; 2005e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan editor.setDeletable(true); 201634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator); 202634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann editor.setEditorListener(this); 203634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann } 204634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann mEditors.addView(view); 205634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann return view; 206634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann } 207634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann 2089e83c84a7603eb6fca1b42631d894731d61f7a34Daniel Lehmann /** 2093e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann * Tests whether the given item has no changes (so it exists in the database) but is empty 2103e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann */ 2113e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann private boolean isEmptyNoop(ValuesDelta item) { 2123e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann if (!item.isNoop()) return false; 2133e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann final int fieldCount = mKind.fieldList.size(); 2143e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann for (int i = 0; i < fieldCount; i++) { 2153e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann final String column = mKind.fieldList.get(i).column; 2163e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann final String value = item.getAsString(column); 2173e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann if (!TextUtils.isEmpty(value)) return false; 2183e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann } 2193e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann return true; 2203e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann } 2213e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann 2221b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan private void updateSectionVisible() { 223bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann setVisibility(getEditorCount() != 0 ? VISIBLE : GONE); 224bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann } 225bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann 2261b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan protected void updateAddFooterVisible() { 22750a27b70581b0191995969c63edd1f6a3db3d1b7Makoto Onuki if (!mReadOnly && (mKind.typeOverallMax != 1)) { 2281b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // First determine whether there are any existing empty editors. 2291b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateEmptyEditors(); 2301b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // If there are no existing empty editors and it's possible to add 2311b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // another field, then make the "add footer" field visible. 2321b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan if (!hasEmptyEditor() && EntityModifier.canInsert(mState, mKind)) { 2331b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.VISIBLE); 2341b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan return; 2351b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2361b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2371b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.GONE); 2381b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 239bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann 2401b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan /** 2412591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan * Updates the editors being displayed to the user removing extra empty 2422591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan * {@link Editor}s, so there is only max 1 empty {@link Editor} view at a time. 2431b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan */ 2441b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan private void updateEmptyEditors() { 2452591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan List<View> emptyEditors = getEmptyEditors(); 2461b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan 2471b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // If there is more than 1 empty editor, then remove it from the list of editors. 2482591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (emptyEditors.size() > 1) { 2492591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan for (View emptyEditorView : emptyEditors) { 2501b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // If no child {@link View}s are being focused on within 2511b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // this {@link View}, then remove this empty editor. 2521b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan if (emptyEditorView.findFocus() == null) { 2531b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mEditors.removeView(emptyEditorView); 2541b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2551b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2563f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann } 2571b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2581b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan 2591b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan /** 2602591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan * Returns a list of empty editor views in this section. 2612591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan */ 2622591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan private List<View> getEmptyEditors() { 2632591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan List<View> emptyEditorViews = new ArrayList<View>(); 2642591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan for (int i = 0; i < mEditors.getChildCount(); i++) { 2652591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan View view = mEditors.getChildAt(i); 2662591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (((Editor) view).isEmpty()) { 2672591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan emptyEditorViews.add(view); 2682591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } 2692591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } 2702591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan return emptyEditorViews; 2712591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan } 2722591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan 2732591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan /** 2742591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan * Returns true if one of the editors has all of its fields empty, or false 2751b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan * otherwise. 2761b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan */ 2771b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan private boolean hasEmptyEditor() { 2782591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan return getEmptyEditors().size() > 0; 279aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 2806f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey 2813fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan /** 2823fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan * Returns true if all editors are empty. 2833fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan */ 2843fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan public boolean isEmpty() { 2853fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan for (int i = 0; i < mEditors.getChildCount(); i++) { 2863fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan View view = mEditors.getChildAt(i); 2873fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan if (!((Editor) view).isEmpty()) { 2883fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan return false; 2893fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan } 2903fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan } 2913fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan return true; 2923fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan } 2933fa75acf99f5245eae00c77086ff130b3552ceecKatherine Kuan 294bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann public void addItem() { 29562bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov ValuesDelta values = null; 2962591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan // If this is a list, we can freely add. If not, only allow adding the first. 29750a27b70581b0191995969c63edd1f6a3db3d1b7Makoto Onuki if (mKind.typeOverallMax == 1) { 29862bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov if (getEditorCount() == 1) { 29962bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov return; 30062bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov } 30162bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov 30262bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov // If we already have an item, just make it visible 30362bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov ArrayList<ValuesDelta> entries = mState.getMimeEntries(mKind.mimeType); 30462bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov if (entries != null && entries.size() > 0) { 30562bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov values = entries.get(0); 30662bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov } 30762bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov } 308da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann 309634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann // Insert a new child, create its view and set its focus 31062bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov if (values == null) { 31162bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov values = EntityModifier.insertChild(mState, mKind); 31262bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov } 31362bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov 31462bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov final View newField = createEditorView(values); 315eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov post(new Runnable() { 316eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov 317eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov @Override 318eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov public void run() { 319eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov newField.requestFocus(); 320eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov } 321eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov }); 3224b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki 3231b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan // Hide the "add field" footer because there is now a blank field. 3241b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan mAddFieldFooter.setVisibility(View.GONE); 325eeac4dc8dccb20466669525f16dc58fa593a3483Daniel Lehmann 326634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann // Ensure we are visible 3271b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan updateSectionVisible(); 328bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann } 329bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann 330bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann public int getEditorCount() { 331bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann return mEditors.getChildCount(); 332bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann } 333bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann 334bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann public DataKind getKind() { 335bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann return mKind; 336aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey } 337aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey} 338