KindSectionView.java revision 62bab31374dd66462643cbc04ebb2acece4b9b39
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;
214597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.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;
2779c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmannimport android.os.Handler;
28aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.provider.ContactsContract.Data;
293e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmannimport android.text.TextUtils;
30aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.util.AttributeSet;
31aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.view.View;
32aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.view.ViewGroup;
338d8e2e838babfcaca2eaff99862652ce3aceac29Daniel Lehmannimport android.widget.ImageButton;
34aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.widget.LinearLayout;
35aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport android.widget.TextView;
36aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
3762bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikovimport java.util.ArrayList;
3862bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov
39aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey/**
40aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * Custom view for an entire section of data as segmented by
41aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * {@link DataKind} around a {@link Data#MIMETYPE}. This view shows a
42aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey * section header and a trigger for adding new {@link Data} rows.
43aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey */
44bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmannpublic class KindSectionView extends LinearLayout implements EditorListener {
45aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    private static final String TAG = "KindSectionView";
46aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
47aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    private ViewGroup mEditors;
4891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    private View mAddPlusButtonContainer;
498d8e2e838babfcaca2eaff99862652ce3aceac29Daniel Lehmann    private ImageButton mAddPlusButton;
50aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    private TextView mTitle;
51f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann    private String mTitleString;
52aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
53aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    private DataKind mKind;
54aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    private EntityDelta mState;
5592525ff51e2cb06531447a7dcde5e22334669c8eMegha Joshi    private boolean mReadOnly;
566f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
574b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private ViewIdGenerator mViewIdGenerator;
584b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
5991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    private int mMinLineItemHeight;
6091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
61aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    public KindSectionView(Context context) {
6291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        this(context, null);
63aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
64aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
65aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    public KindSectionView(Context context, AttributeSet attrs) {
66aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        super(context, attrs);
6791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        mMinLineItemHeight = context.getResources().getDimensionPixelSize(
6891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov                R.dimen.editor_min_line_item_height);
69aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
70aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
7102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    @Override
7202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    public void setEnabled(boolean enabled) {
7302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        super.setEnabled(enabled);
7402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mEditors != null) {
7502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            int childCount = mEditors.getChildCount();
7602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            for (int i = 0; i < childCount; i++) {
7702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                mEditors.getChildAt(i).setEnabled(enabled);
7802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            }
7902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        }
8002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
8102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mAddPlusButton != null) {
8202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mAddPlusButton.setEnabled(enabled && !mReadOnly);
8302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        }
8402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    }
8502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
8691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    @Override
8791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    protected void onLayout(boolean changed, int l, int t, int r, int b) {
8891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        super.onLayout(changed, l, t, r, b);
8991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
9091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        if (mAddPlusButton == null || mEditors == null || mEditors.getChildCount() < 2) {
9191d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov            return;
9291d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        }
9391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
9491d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        // Align the "+" button with the "-" button in the last editor
9591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        View lastEditor = mEditors.getChildAt(mEditors.getChildCount() - 1);
9691d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        int top = lastEditor.getTop();
9791d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        mAddPlusButtonContainer.layout(mAddPlusButtonContainer.getLeft(), top,
9891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov                mAddPlusButtonContainer.getRight(), top + mAddPlusButtonContainer.getHeight());
9991d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov    }
10091d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov
10102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    public boolean isReadOnly() {
10202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        return mReadOnly;
10302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    }
10402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
105aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    /** {@inheritDoc} */
106aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    @Override
107aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    protected void onFinishInflate() {
108aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        setDrawingCacheEnabled(true);
109aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        setAlwaysDrawnWithCacheEnabled(true);
110aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
111aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        mEditors = (ViewGroup)findViewById(R.id.kind_editors);
112aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
11391d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov        mAddPlusButtonContainer = findViewById(R.id.kind_plus_container);
1148d8e2e838babfcaca2eaff99862652ce3aceac29Daniel Lehmann        mAddPlusButton = (ImageButton) findViewById(R.id.kind_plus);
1158d8e2e838babfcaca2eaff99862652ce3aceac29Daniel Lehmann        mAddPlusButton.setOnClickListener(new OnClickListener() {
11679c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann            @Override
117bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann            public void onClick(View v) {
11879c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                // defer action so that the pressed state of the button is visible shortly
11979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                new Handler().post(new Runnable() {
12079c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    @Override
12179c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    public void run() {
12279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                        addItem();
12379c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                    }
12479c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann                });
125bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann            }
126bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        });
127aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
128aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        mTitle = (TextView)findViewById(R.id.kind_title);
129aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
130aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
1316f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    /** {@inheritDoc} */
13279c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann    @Override
133aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    public void onDeleted(Editor editor) {
1343f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        updateAddVisible();
135bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        updateVisible();
136aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
137aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
1386f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    /** {@inheritDoc} */
13979c9c5a8f849908d2b141c30af15923ea2b60f5bDaniel Lehmann    @Override
1406f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void onRequest(int request) {
1416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Ignore requests
1426f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
1436f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
1444b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public void setState(DataKind kind, EntityDelta state, boolean readOnly, ViewIdGenerator vig) {
145aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        mKind = kind;
146aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        mState = state;
14792525ff51e2cb06531447a7dcde5e22334669c8eMegha Joshi        mReadOnly = readOnly;
1484b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        mViewIdGenerator = vig;
1494b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1504b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        setId(mViewIdGenerator.getId(state, kind, null, ViewIdGenerator.NO_VIEW_INDEX));
151aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
152aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        // TODO: handle resources from remote packages
153f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann        mTitleString = (kind.titleRes == -1 || kind.titleRes == 0)
154f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann                ? ""
155cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann                : getResources().getString(kind.titleRes);
156ba3c2e541b17bc68ff86ed402e7ee2c0a84f7d80Dmitri Plotnikov        mTitle.setText(mTitleString);
157aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
158bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        rebuildFromState();
1593f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        updateAddVisible();
160bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        updateVisible();
161bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    }
162bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann
163f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann    public String getTitle() {
164f7ce5978a6a6314028fe9bbb1da99338b111750fDaniel Lehmann        return mTitleString;
165aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
166aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
167aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    /**
168aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey     * Build editors for all current {@link #mState} rows.
169aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey     */
170aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    public void rebuildFromState() {
171aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        // Remove any existing editors
172aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        mEditors.removeAllViews();
173aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
174da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann        // Check if we are displaying anything here
175da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann        boolean hasEntries = mState.hasMimeEntries(mKind.mimeType);
176da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann
177da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann        if (hasEntries) {
178da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann            for (ValuesDelta entry : mState.getMimeEntries(mKind.mimeType)) {
179da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann                // Skip entries that aren't visible
180da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann                if (!entry.isVisible()) continue;
1813e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann                if (isEmptyNoop(entry)) continue;
182da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann
183634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann                createEditorView(entry);
184da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann            }
185aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey        }
186aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
187aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey
188634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann
189634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann    /**
190634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann     * Creates an EditorView for the given entry. This function must be used while constructing
191634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann     * the views corresponding to the the object-model. The resulting EditorView is also added
192634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann     * to the end of mEditors
193634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann     */
194634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann    private View createEditorView(ValuesDelta entry) {
195634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        final View view;
196634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        if (mKind.editorClass == null) {
197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            view = new TextFieldsEditorView(mContext);
198634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        } else {
199634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            try {
200634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann                view = mKind.editorClass.getConstructor(Context.class).newInstance(
201634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann                        mContext);
202634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            } catch (Exception e) {
203634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann                throw new RuntimeException(
204634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann                        "Cannot allocate editor for " + mKind.editorClass);
205634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            }
206634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        }
207634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann
20802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        view.setEnabled(isEnabled());
20902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
210634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        if (view instanceof Editor) {
211634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            Editor editor = (Editor) view;
212634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);
213634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            editor.setEditorListener(this);
214634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann            editor.setDeletable(true);
215634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        }
216634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        mEditors.addView(view);
217634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        return view;
218634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann    }
219634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann
2209e83c84a7603eb6fca1b42631d894731d61f7a34Daniel Lehmann    /**
2213e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann     * Tests whether the given item has no changes (so it exists in the database) but is empty
2223e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann     */
2233e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann    private boolean isEmptyNoop(ValuesDelta item) {
2243e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann        if (!item.isNoop()) return false;
2253e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann        final int fieldCount = mKind.fieldList.size();
2263e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann        for (int i = 0; i < fieldCount; i++) {
2273e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann            final String column = mKind.fieldList.get(i).column;
2283e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann            final String value = item.getAsString(column);
2293e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann            if (!TextUtils.isEmpty(value)) return false;
2303e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann        }
2313e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann        return true;
2323e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann    }
2333e7436450f0fdd5ad939c3b46e7176e082c9ee11Daniel Lehmann
234bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    private void updateVisible() {
235bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        setVisibility(getEditorCount() != 0 ? VISIBLE : GONE);
236bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    }
237bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann
238bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann
2393f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann    protected void updateAddVisible() {
2403f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        final boolean isVisible;
2413f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        if (!mKind.isList) {
2423f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann            isVisible = false;
2433f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        } else {
2443f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann            // Set enabled state on the "add" view
2453f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann            final boolean canInsert = EntityModifier.canInsert(mState, mKind);
2463f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann            isVisible = !mReadOnly && canInsert;
2473f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        }
2483f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        mAddPlusButton.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
249aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
2506f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
251bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    public void addItem() {
25262bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        ValuesDelta values = null;
253bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        // if this is a list, we can freely add. if not, only allow adding the first
25462bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        if (!mKind.isList) {
25562bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            if (getEditorCount() == 1) {
25662bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov                return;
25762bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            }
25862bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov
25962bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            // If we already have an item, just make it visible
26062bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            ArrayList<ValuesDelta> entries = mState.getMimeEntries(mKind.mimeType);
26162bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            if (entries != null && entries.size() > 0) {
26262bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov                values = entries.get(0);
26362bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            }
26462bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        }
265da5fd9039bd303f5e4634a31ed9a00d58d679b39Daniel Lehmann
266634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        // Insert a new child, create its view and set its focus
26762bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        if (values == null) {
26862bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov            values = EntityModifier.insertChild(mState, mKind);
26962bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        }
27062bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov
27162bab31374dd66462643cbc04ebb2acece4b9b39Dmitri Plotnikov        final View newField = createEditorView(values);
272634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        newField.requestFocus();
2734b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
274634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        // For non-lists (e.g. Notes we can only have one field. in that case we need to disable
275634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        // the add button
2763f26e24c0cbc988b32d274b7a4e88c994355ef4fDaniel Lehmann        updateAddVisible();
277eeac4dc8dccb20466669525f16dc58fa593a3483Daniel Lehmann
278634ab3baaf2bc69bd7977153fcdebf0e737e207dDaniel Lehmann        // Ensure we are visible
279bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        updateVisible();
280bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    }
281bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann
282bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    public int getEditorCount() {
283bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        return mEditors.getChildCount();
284bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    }
285bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann
286bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann    public DataKind getKind() {
287bb556954e29ae0700b729f128d8cd09ecdd91ee3Daniel Lehmann        return mKind;
288aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey    }
289aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkey}
290