ContactEditorFragment.java revision 87270e1b58e669354bb1571ced686421c56deb7a
1cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann/*
2ef3f8f045ed4150caa64749742227acd0e6b85d8Daniel Lehmann * Copyright (C) 2010 The Android Open Source Project
3cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann *
4cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License");
5cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * you may not use this file except in compliance with the License.
6cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * You may obtain a copy of the License at
7cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann *
8cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann *      http://www.apache.org/licenses/LICENSE-2.0
9cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann *
10cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * Unless required by applicable law or agreed to in writing, software
11cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS,
12cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * See the License for the specific language governing permissions and
14cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann * limitations under the License
15cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann */
16cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor;
18cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
1918ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.ContactLoader;
2018ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.ContactSaveService;
2118ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.GroupMetaDataLoader;
22cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport com.android.contacts.R;
230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuanimport com.android.contacts.activities.ContactEditorAccountsChangedActivity;
242b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikovimport com.android.contacts.activities.ContactEditorActivity;
25d21ddb2c96e71f43eaf7addc25e163181d1ca87dDmitri Plotnikovimport com.android.contacts.activities.JoinContactActivity;
266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoroimport com.android.contacts.detail.PhotoSelectionHandler;
2718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
2818ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovimport com.android.contacts.editor.Editor.EditorListener;
294597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType;
30a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikovimport com.android.contacts.model.AccountTypeManager;
312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoroimport com.android.contacts.model.AccountWithDataSet;
32f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport com.android.contacts.model.EntityDelta;
33f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityDelta.ValuesDelta;
34ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmannimport com.android.contacts.model.EntityDeltaList;
35f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport com.android.contacts.model.EntityModifier;
3635769b804fbfd5a1fc0b2c36cd0a786d662c4334Daniel Lehmannimport com.android.contacts.model.GoogleAccountType;
37d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.util.AccountsListAdapter;
386f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onukiimport com.android.contacts.util.AccountsListAdapter.AccountListFilter;
39692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chuimport com.android.contacts.util.HelpUtils;
40f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
41f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.accounts.Account;
42cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.app.Activity;
43bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.AlertDialog;
44bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.Dialog;
45bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.app.DialogFragment;
46222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.Fragment;
47222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager;
48222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks;
49cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentUris;
50cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.ContentValues;
51cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Context;
52e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikovimport android.content.CursorLoader;
53bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikovimport android.content.DialogInterface;
54e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikovimport android.content.Entity;
55cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Intent;
56cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.content.Loader;
57f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.database.Cursor;
58f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport android.graphics.Bitmap;
5928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargusimport android.graphics.BitmapFactory;
60cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.net.Uri;
61cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.os.Bundle;
629767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmannimport android.os.SystemClock;
63cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email;
64362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Event;
65362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Organization;
66cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone;
67362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
68f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
69be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuanimport android.provider.ContactsContract.Groups;
702013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmannimport android.provider.ContactsContract.Intents;
71f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
72cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.util.Log;
73cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.LayoutInflater;
74cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.Menu;
75cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuInflater;
76cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.MenuItem;
77cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.View;
78cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.view.ViewGroup;
79d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.AdapterView;
806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener;
816c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawaimport android.widget.BaseAdapter;
8280d527c94389cab477e2c75ded03eec877ea6835Daniel Lehmannimport android.widget.LinearLayout;
83d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.widget.ListPopupWindow;
84cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport android.widget.Toast;
85cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
86f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.io.File;
87cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmannimport java.util.ArrayList;
88f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Collections;
89f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmannimport java.util.Comparator;
90f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikovimport java.util.List;
91f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
92a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmannpublic class ContactEditorFragment extends Fragment implements
93d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        SplitContactConfirmationDialogFragment.Listener,
94fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
952b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann        RawContactReadOnlyEditorView.Listener {
96cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
972245870a1354df03512010e4968b144840894fb7Frank Sposaro    private static final String TAG = ContactEditorFragment.class.getSimpleName();
98cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
99f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final int LOADER_DATA = 1;
100e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    private static final int LOADER_GROUPS = 2;
101f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
102d364314c460152db7089b304beec81b3675893baDmitri Plotnikov    private static final String KEY_URI = "uri";
103d364314c460152db7089b304beec81b3675893baDmitri Plotnikov    private static final String KEY_ACTION = "action";
104f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final String KEY_EDIT_STATE = "state";
105f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester";
106f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final String KEY_CURRENT_PHOTO_FILE = "currentphotofile";
108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin";
109623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann    private static final String KEY_CONTACT_WRITABLE_FOR_JOIN = "contactwritableforjoin";
1109302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov    private static final String KEY_SHOW_JOIN_SUGGESTIONS = "showJoinSuggestions";
11102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    private static final String KEY_ENABLED = "enabled";
112ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov    private static final String KEY_STATUS = "status";
113ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson    private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
114ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson    private static final String KEY_IS_USER_PROFILE = "isUserProfile";
11528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    private static final String KEY_UPDATED_PHOTOS = "updatedPhotos";
116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
117a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov    public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
118a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov
11915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann    /**
1207d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov     * An intent extra that forces the editor to add the edited contact
1217d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov     * to the default group (e.g. "My Contacts").
1227d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov     */
1237d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov    public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
1247d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov
125ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson    public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
126ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson
1277d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov    /**
12815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann     * Modes that specify what the AsyncTask has to perform after saving
12915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann     */
1309df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov    public interface SaveMode {
13115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        /**
13215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         * Close the editor after saving
13315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         */
13415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        public static final int CLOSE = 0;
13515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann
13615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        /**
13715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         * Reload the data so that the user can continue editing
13815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         */
13915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        public static final int RELOAD = 1;
14015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann
14115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        /**
14215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         * Split the contact after saving
14315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         */
14415972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        public static final int SPLIT = 2;
14515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann
14615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        /**
14715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         * Join another contact after saving
14815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann         */
14915972398b530b91612418dc11d41c356d4f43739Daniel Lehmann        public static final int JOIN = 3;
1509df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov
1519df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov        /**
1529df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov         * Navigate to Contacts Home activity after saving.
1539df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov         */
1549df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov        public static final int HOME = 4;
15515972398b530b91612418dc11d41c356d4f43739Daniel Lehmann    }
156a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
157825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann    private interface Status {
158825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        /**
159825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         * The loader is fetching data
160825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         */
161825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        public static final int LOADING = 0;
162825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
163825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        /**
164825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         * Not currently busy. We are waiting for the user to enter data
165825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         */
166825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        public static final int EDITING = 1;
167825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
168825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        /**
169f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov         * The data is currently being saved. This is used to prevent more
170f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov         * auto-saves (they shouldn't overlap)
171825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         */
172825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        public static final int SAVING = 2;
173825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
174825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        /**
175a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann         * Prevents any more saves. This is used if in the following cases:
176a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann         * - After Save/Close
177a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann         * - After Revert
178a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann         * - After the user has accepted an edit suggestion
179825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann         */
180825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        public static final int CLOSING = 3;
181f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov
182f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov        /**
183f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov         * Prevents saving while running a child activity.
184f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov         */
185f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov        public static final int SUB_ACTIVITY = 4;
186825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann    }
187825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
188a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann    private static final int REQUEST_CODE_JOIN = 0;
1896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
190f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
191f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private long mRawContactIdRequestingPhoto = -1;
1926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private PhotoSelectionHandler mPhotoSelectionHandler;
193cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
194f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private final EntityDeltaComparator mComparator = new EntityDeltaComparator();
195f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
196e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    private Cursor mGroupMetaData;
197e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
198f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private File mCurrentPhotoFile;
19928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    private Bundle mUpdatedPhotos = new Bundle();
200cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
201cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    private Context mContext;
202f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private String mAction;
203b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann    private Uri mLookupUri;
204f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private Bundle mIntentExtras;
205cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    private Listener mListener;
206cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
207f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private long mContactIdForJoin;
208623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann    private boolean mContactWritableForJoin;
209cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
2100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan    private ContactEditorUtils mEditorUtils;
2110353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
212f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private LinearLayout mContent;
213ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann    private EntityDeltaList mState;
214cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
215f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private ViewIdGenerator mViewIdGenerator;
216cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
2179767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann    private long mLoaderStartTime;
2189767e09ae37332d74b5558a3ec16ded20a9328dcDaniel Lehmann
219825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann    private int mStatus;
220825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
221f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    private AggregationSuggestionEngine mAggregationSuggestionEngine;
2229302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov    private long mAggregationSuggestionsRawContactId;
2239302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov    private View mAggregationSuggestionView;
224f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
2256c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa    private ListPopupWindow mAggregationSuggestionPopup;
2266c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2276c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa    private static final class AggregationSuggestionAdapter extends BaseAdapter {
2286c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        private final Activity mActivity;
2296c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        private final boolean mSetNewContact;
2306c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        private final AggregationSuggestionView.Listener mListener;
2316c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        private final List<Suggestion> mSuggestions;
2326c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2336c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public AggregationSuggestionAdapter(Activity activity, boolean setNewContact,
2346c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) {
2356c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mActivity = activity;
2366c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mSetNewContact = setNewContact;
2376c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mListener = listener;
2386c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mSuggestions = suggestions;
2396c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2406c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2416c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        @Override
2426c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public View getView(int position, View convertView, ViewGroup parent) {
2436c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            Suggestion suggestion = (Suggestion) getItem(position);
2446c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            LayoutInflater inflater = mActivity.getLayoutInflater();
2456c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            AggregationSuggestionView suggestionView =
2466c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                    (AggregationSuggestionView) inflater.inflate(
2476c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                            R.layout.aggregation_suggestions_item, null);
2486c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            suggestionView.setNewContact(mSetNewContact);
2496c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            suggestionView.setListener(mListener);
2506c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            suggestionView.bindSuggestion(suggestion);
2516c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            return suggestionView;
2526c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2536c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2546c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        @Override
2556c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public long getItemId(int position) {
2566c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            return position;
2576c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2586c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2596c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        @Override
2606c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public Object getItem(int position) {
2616c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            return mSuggestions.get(position);
2626c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2636c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2646c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        @Override
2656c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public int getCount() {
2666c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            return mSuggestions.size();
2676c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2686c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa    }
2696c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2706c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa    private OnItemClickListener mAggregationSuggestionItemClickListener =
2716c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            new OnItemClickListener() {
2726c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        @Override
2736c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
2746c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view;
2756c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            suggestionView.handleItemClickEvent();
2766c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mAggregationSuggestionPopup.dismiss();
2776c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mAggregationSuggestionPopup = null;
2786c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        }
2796c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa    };
2806c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa
2817d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov    private boolean mAutoAddToDefaultGroup;
2827d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov
28302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    private boolean mEnabled = true;
284eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov    private boolean mRequestFocus;
285ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson    private boolean mNewLocalProfile = false;
286ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson    private boolean mIsUserProfile = false;
28702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
288cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    public ContactEditorFragment() {
289cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
290cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
29102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    public void setEnabled(boolean enabled) {
29202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        if (mEnabled != enabled) {
29302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mEnabled = enabled;
29402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            if (mContent != null) {
29502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                int count = mContent.getChildCount();
29602bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                for (int i = 0; i < count; i++) {
29702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                    mContent.getChildAt(i).setEnabled(enabled);
29802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov                }
29902bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            }
300a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov            setAggregationSuggestionViewEnabled(enabled);
30102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            final Activity activity = getActivity();
30202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            if (activity != null) activity.invalidateOptionsMenu();
30302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        }
30402bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov    }
30502bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
306cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    @Override
307cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    public void onAttach(Activity activity) {
308cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        super.onAttach(activity);
309cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        mContext = activity;
3100353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        mEditorUtils = ContactEditorUtils.getInstance(mContext);
311cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
312cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
313cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    @Override
314f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    public void onStop() {
315f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        super.onStop();
316f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        if (mAggregationSuggestionEngine != null) {
317f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            mAggregationSuggestionEngine.quit();
318f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        }
319248fba273e867616b1f8973dac6ce3e5ee1ba544Dmitri Plotnikov
320825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        // If anything was left unsaved, save it now but keep the editor open.
321f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov        if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) {
322623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann            save(SaveMode.RELOAD);
323825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        }
324f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    }
325f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
326f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    @Override
327cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
328cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        final View view = inflater.inflate(R.layout.contact_editor_fragment, container, false);
329cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
330f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mContent = (LinearLayout) view.findViewById(R.id.editors);
331e8767a1136d2a2f9cb3e3ca5f44b2142baab9709Daniel Lehmann
3323648d2ea76a6649230d1fdd3dba92797ae7cfb26Daniel Lehmann        setHasOptionsMenu(true);
333cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
334825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        // If we are in an orientation change, we already have mState (it was loaded by onCreate)
335825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        if (mState != null) {
336825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            bindEditors();
337825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        }
338825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
339cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        return view;
340cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
341cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
342222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    @Override
343222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    public void onActivityCreated(Bundle savedInstanceState) {
344222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        super.onActivityCreated(savedInstanceState);
345222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann
346825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        // Handle initial actions only when existing state missing
3474a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann        final boolean hasIncomingState = savedInstanceState != null;
348825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann
349825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        if (!hasIncomingState) {
350825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            if (Intent.ACTION_EDIT.equals(mAction)) {
351825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann                getLoaderManager().initLoader(LOADER_DATA, null, mDataLoaderListener);
352825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            } else if (Intent.ACTION_INSERT.equals(mAction)) {
3532013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                final Account account = mIntentExtras == null ? null :
3542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT);
3552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                final String dataSet = mIntentExtras == null ? null :
3562b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        mIntentExtras.getString(Intents.Insert.DATA_SET);
3572013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann
3582013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                if (account != null) {
3592013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                    // Account specified in Intent
3602b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    createContact(new AccountWithDataSet(account.name, account.type, dataSet));
3612013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                } else {
3622013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                    // No Account specified. Let the user choose
36340bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov                    // Load Accounts async so that we can present them
3640353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    selectAccountAndCreateContact();
3652013058703aa110a1d7aac87ef408c96a3919472Daniel Lehmann                }
366a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov            } else if (ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(mAction)) {
367a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                // do nothing
368825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            } else throw new IllegalArgumentException("Unknown Action String " + mAction +
369825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann                    ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
370825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        }
371222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    }
372222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann
373e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    @Override
374e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    public void onStart() {
375e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
376e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        super.onStart();
377e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    }
378e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
3791015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov    public void load(String action, Uri lookupUri, Bundle intentExtras) {
380f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mAction = action;
381b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann        mLookupUri = lookupUri;
382f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mIntentExtras = intentExtras;
3837d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov        mAutoAddToDefaultGroup = mIntentExtras != null
3847d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov                && mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
385ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        mNewLocalProfile = mIntentExtras != null
38636d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro                && mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
387f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
388f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
389f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    public void setListener(Listener value) {
390f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mListener = value;
391cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
392cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
393cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    @Override
394f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    public void onCreate(Bundle savedState) {
395d364314c460152db7089b304beec81b3675893baDmitri Plotnikov        if (savedState != null) {
396d364314c460152db7089b304beec81b3675893baDmitri Plotnikov            // Restore mUri before calling super.onCreate so that onInitializeLoaders
397d364314c460152db7089b304beec81b3675893baDmitri Plotnikov            // would already have a uri and an action to work with
398b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann            mLookupUri = savedState.getParcelable(KEY_URI);
399d364314c460152db7089b304beec81b3675893baDmitri Plotnikov            mAction = savedState.getString(KEY_ACTION);
400d364314c460152db7089b304beec81b3675893baDmitri Plotnikov        }
401d364314c460152db7089b304beec81b3675893baDmitri Plotnikov
402f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        super.onCreate(savedState);
403f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
404f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        if (savedState == null) {
405f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // If savedState is non-null, onRestoreInstanceState() will restore the generator.
406f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mViewIdGenerator = new ViewIdGenerator();
407f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        } else {
408825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            // Read state from savedState. No loading involved here
409ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann            mState = savedState.<EntityDeltaList> getParcelable(KEY_EDIT_STATE);
410f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mRawContactIdRequestingPhoto = savedState.getLong(
411f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    KEY_RAW_CONTACT_ID_REQUESTING_PHOTO);
412f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
413f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            String fileName = savedState.getString(KEY_CURRENT_PHOTO_FILE);
414f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (fileName != null) {
415f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                mCurrentPhotoFile = new File(fileName);
416cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann            }
417f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN);
418623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann            mContactWritableForJoin = savedState.getBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN);
4199302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            mAggregationSuggestionsRawContactId = savedState.getLong(KEY_SHOW_JOIN_SUGGESTIONS);
42002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            mEnabled = savedState.getBoolean(KEY_ENABLED);
421ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov            mStatus = savedState.getInt(KEY_STATUS);
422ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson            mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
423ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson            mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
42428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
425cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        }
426cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
427cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
428bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann    public void setData(ContactLoader.Result data) {
429d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann        // If we have already loaded data, we do not want to change it here to not confuse the user
430d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann        if (mState != null) {
431d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann            Log.v(TAG, "Ignoring background change. This will have to be rebased later");
432d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann            return;
433d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann        }
434d3f1e3128b709d7d9a0229f1d1843f015f4977baDaniel Lehmann
435fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        // See if this edit operation needs to be redirected to a custom editor
436fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        ArrayList<Entity> entities = data.getEntities();
437fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        if (entities.size() == 1) {
438fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            Entity entity = entities.get(0);
439fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            ContentValues entityValues = entity.getEntityValues();
440fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
4412b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
4422b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType(
4432b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    type, dataSet);
4442b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann            if (accountType.getEditContactActivityClassName() != null &&
4452b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann                    !accountType.areContactsWritable()) {
446fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                if (mListener != null) {
447fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                    String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME);
448fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                    long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
4492b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    mListener.onCustomEditContactActivityRequested(
4502b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                            new AccountWithDataSet(name, type, dataSet),
451fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                            ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
452fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                            mIntentExtras, true);
453fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                }
454fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                return;
455fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            }
456fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        }
457fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
458fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        bindEditorsForExistingContact(data);
459fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov    }
460fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
461fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov    @Override
4622b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro    public void onExternalEditorRequest(AccountWithDataSet account, Uri uri) {
463fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        mListener.onCustomEditContactActivityRequested(account, uri, null, false);
464fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov    }
465fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
466e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus    private void bindEditorsForExistingContact(ContactLoader.Result contact) {
46702bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        setEnabled(true);
46802bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov
469e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        mState = contact.createEntityDeltaList();
4701ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        setIntentExtras(mIntentExtras);
4711ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        mIntentExtras = null;
472e579a175bdc18153014da00d989cf0a5343d25a9Dmitri Plotnikov
473ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        // For user profile, change the contacts query URI
474e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        mIsUserProfile = contact.isUserProfile();
47548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson        boolean localProfileExists = false;
47648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson
477ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        if (mIsUserProfile) {
478ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson            for (EntityDelta state : mState) {
47948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                // For profile contacts, we need a different query URI
480ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson                state.setProfileQueryUri();
48148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                // Try to find a local profile contact
48248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                if (state.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) {
48348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                    localProfileExists = true;
48448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                }
48548ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson            }
48648ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson            // Editor should always present a local profile for editing
48748ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson            if (!localProfileExists) {
48848ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                final ContentValues values = new ContentValues();
48948ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                values.putNull(RawContacts.ACCOUNT_NAME);
49048ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                values.putNull(RawContacts.ACCOUNT_TYPE);
49148ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                values.putNull(RawContacts.DATA_SET);
49248ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
49348ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                insert.setProfileQueryUri();
49448ed982e078de00f6be49319ccf09bbb2aaadf5eIsaac Katzenelson                mState.add(insert);
495ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson            }
496ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        }
497eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov        mRequestFocus = true;
498eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov
4991ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        bindEditors();
5001ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov    }
5011ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov
5021ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov    /**
5031ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov     * Merges extras from the intent.
5041ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov     */
5051ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov    public void setIntentExtras(Bundle extras) {
5061ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        if (extras == null || extras.size() == 0) {
5071ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov            return;
508bb11be3f5867453e7561cdc7bebe6a380eff6881Daniel Lehmann        }
509916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov
510a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
5111ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        for (EntityDelta state : mState) {
5121ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov            final String accountType = state.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
5132b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final String dataSet = state.getValues().getAsString(RawContacts.DATA_SET);
5142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
51596e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann            if (type.areContactsWritable()) {
5161ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov                // Apply extras to the first writable raw contact only
51769f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov                EntityModifier.parseExtras(mContext, type, state, extras);
5181ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov                break;
5191ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov            }
5201ac58b6f2a925c5a4f759346e5244dfd174acd08Dmitri Plotnikov        }
521f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
522cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
5230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan    private void selectAccountAndCreateContact() {
5240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // If this is a local profile, then skip the logic about showing the accounts changed
5250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // activity and create a phone-local contact.
5260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        if (mNewLocalProfile) {
5270353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            createContact(null);
5280353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            return;
5290353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        }
5300353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
5310353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // If there is no default account or the accounts have changed such that we need to
5320353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // prompt the user again, then launch the account prompt.
5330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        if (mEditorUtils.shouldShowAccountChangedNotification()) {
5340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
5350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            mStatus = Status.SUB_ACTIVITY;
5360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
5370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        } else {
5380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            // Otherwise, there should be a default account. Then either create a local contact
5390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            // (if default account is null) or create a contact with the specified account.
5400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            AccountWithDataSet defaultAccount = mEditorUtils.getDefaultAccount();
5410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            if (defaultAccount == null) {
5420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                createContact(null);
5430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            } else {
5440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                createContact(defaultAccount);
5450353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            }
5460353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        }
5470353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan    }
5480353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
549d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    /**
5500353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan     * Create a contact by automatically selecting the first account. If there's no available
5510353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan     * account, a device-local contact should be created.
552d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     */
553d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    private void createContact() {
5542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        final List<AccountWithDataSet> accounts =
555a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov                AccountTypeManager.getInstance(mContext).getAccounts(true);
5560353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // No Accounts available. Create a phone-local contact.
5570353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        if (accounts.isEmpty()) {
55840bb481d29bf490fddc65b88c957dd4b5dbc4d82Dmitri Plotnikov            createContact(null);
5590353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            return;
560f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
561cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
562d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // We have an account switcher in "create-account" screen, so don't need to ask a user to
563d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // select an account here.
564d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        createContact(accounts.get(0));
565cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
566cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
567cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    /**
568d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * Shows account creation screen associated with a given account.
569d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     *
570d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * @param account may be null to signal a device-local contact should be created.
571cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann     */
5722b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro    private void createContact(AccountWithDataSet account) {
573a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
574b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType accountType =
5752b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                accountTypes.getAccountType(account != null ? account.type : null,
5762b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        account != null ? account.dataSet : null);
577fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
578b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        if (accountType.getCreateContactActivityClassName() != null) {
579fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            if (mListener != null) {
580fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                mListener.onCustomCreateContactActivityRequested(account, mIntentExtras);
581fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            }
582fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        } else {
583b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov            bindEditorsForNewContact(account, accountType);
584fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        }
585fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov    }
586fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
587d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    /**
588d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
589d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * Some of old data are reused with new restriction enforced by the new account.
590d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     *
5912b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro     * @param oldState Old data being edited.
592d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * @param oldAccount Old account associated with oldState.
593d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     * @param newAccount New account to be used.
594d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa     */
595d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    private void rebindEditorsForNewContact(
5962b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            EntityDelta oldState, AccountWithDataSet oldAccount, AccountWithDataSet newAccount) {
597d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
5982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        AccountType oldAccountType = accountTypes.getAccountType(
5992b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                oldAccount.type, oldAccount.dataSet);
6002b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        AccountType newAccountType = accountTypes.getAccountType(
6012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                newAccount.type, newAccount.dataSet);
602d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
603d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        if (newAccountType.getCreateContactActivityClassName() != null) {
604d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            Log.w(TAG, "external activity called in rebind situation");
605d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            if (mListener != null) {
606d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras);
607d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            }
608d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        } else {
609d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            mState = null;
610d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType);
611d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        }
612d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
613d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
6142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro    private void bindEditorsForNewContact(AccountWithDataSet account,
6152b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType accountType) {
616d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        bindEditorsForNewContact(account, accountType, null, null);
617d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
618d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
6192b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro    private void bindEditorsForNewContact(AccountWithDataSet newAccount,
6202b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType newAccountType, EntityDelta oldState, AccountType oldAccountType) {
621a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        mStatus = Status.EDITING;
622a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov
623f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        final ContentValues values = new ContentValues();
624d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        if (newAccount != null) {
625d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            values.put(RawContacts.ACCOUNT_NAME, newAccount.name);
626d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            values.put(RawContacts.ACCOUNT_TYPE, newAccount.type);
6272b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            values.put(RawContacts.DATA_SET, newAccount.dataSet);
628f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        } else {
629f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            values.putNull(RawContacts.ACCOUNT_NAME);
630f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            values.putNull(RawContacts.ACCOUNT_TYPE);
6312b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            values.putNull(RawContacts.DATA_SET);
632cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        }
633cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
634f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
635d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        if (oldState == null) {
636d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            // Parse any values from incoming intent
637d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            EntityModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras);
638d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        } else {
639d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            EntityModifier.migrateStateForNewContact(mContext, oldState, insert,
640d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                    oldAccountType, newAccountType);
641d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        }
642f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
64369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov        // Ensure we have some default fields (if the account type does not support a field,
644362acdb3da27524d42c4bb44423d6276c5738616Daniel Lehmann        // ensureKind will not add it, so it is safe to add e.g. Event)
645d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE);
646d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE);
647d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE);
648d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE);
649d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE);
650f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
651ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        // Set the correct URI for saving the contact as a profile
652ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        if (mNewLocalProfile) {
653ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson            insert.setProfileQueryUri();
654ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        }
655ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson
656f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        if (mState == null) {
657f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Create state if none exists yet
658ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann            mState = EntityDeltaList.fromSingle(insert);
659f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        } else {
660f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Add contact onto end of existing state
661f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mState.add(insert);
662cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        }
663f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
664eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov        mRequestFocus = true;
665eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov
666f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        bindEditors();
667cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
668cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
669f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private void bindEditors() {
670f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        // Sort the editors
671f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        Collections.sort(mState, mComparator);
672cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
673f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        // Remove any existing editors and rebuild any visible
674f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mContent.removeAllViews();
675cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
676f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
677f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                Context.LAYOUT_INFLATER_SERVICE);
678a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
679a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan        int numRawContacts = mState.size();
680a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan        for (int i = 0; i < numRawContacts; i++) {
681f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // TODO ensure proper ordering of entities in the list
682f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            final EntityDelta entity = mState.get(i);
683f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            final ValuesDelta values = entity.getValues();
684f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (!values.isVisible()) continue;
685f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
686f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
6872b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final String dataSet = values.getAsString(RawContacts.DATA_SET);
6882b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
689f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            final long rawContactId = values.getAsLong(RawContacts._ID);
690f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
69172af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann            final BaseRawContactEditorView editor;
6922b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann            if (!type.areContactsWritable()) {
693fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                editor = (BaseRawContactEditorView) inflater.inflate(
6942b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann                        R.layout.raw_contact_readonly_editor_view, mContent, false);
6952b3ee0f34801444c7d775ce747125459f69712bbDaniel Lehmann                ((RawContactReadOnlyEditorView) editor).setListener(this);
696fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov            } else {
697fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view,
698fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan                        mContent, false);
699cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann            }
700a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan            if (Intent.ACTION_INSERT.equals(mAction) && numRawContacts == 1) {
7012b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                final List<AccountWithDataSet> accounts =
702d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        AccountTypeManager.getInstance(mContext).getAccounts(true);
703ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson                if (accounts.size() > 1 && !mNewLocalProfile) {
704d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                    addAccountSwitcher(mState.get(0), editor);
705a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan                } else {
706a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan                    disableAccountSwitcher(editor);
707d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                }
708a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan            } else {
709a3e69af03dd35124941a48c3bfaea87468d66863Katherine Kuan                disableAccountSwitcher(editor);
710d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            }
711a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan
71202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            editor.setEnabled(mEnabled);
713cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
714f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            mContent.addView(editor);
7157d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov
716681f36cc7cc49be781eedc4685eda2d1b2c0444cIsaac Katzenelson            editor.setState(entity, type, mViewIdGenerator, isEditingUserProfile());
717f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
7186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            // Set up the photo handler.
7196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            bindPhotoHandler(editor, type, mState);
7206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
72128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            // If a new photo was chosen but not yet saved, we need to
72228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            // update the thumbnail to reflect this.
72328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            Bitmap bitmap = updatedBitmapForRawContact(rawContactId);
72428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            if (bitmap != null) editor.setPhotoBitmap(bitmap);
72528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
72672af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann            if (editor instanceof RawContactEditorView) {
7272828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                final Activity activity = getActivity();
72872af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann                final RawContactEditorView rawContactEditor = (RawContactEditorView) editor;
7295ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                EditorListener listener = new EditorListener() {
730f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
731f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                    @Override
732f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                    public void onRequest(int request) {
7332828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                        if (activity.isFinishing()) { // Make sure activity is still running.
7342828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                            return;
7352828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                        }
7362bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson                        if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) {
7372828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                            acquireAggregationSuggestions(activity, rawContactEditor);
73811bb73bcdf4290ced99e3e06b1f76d4c37357aeaDmitri Plotnikov                        }
739f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                    }
740f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
741f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                    @Override
7422293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan                    public void onDeleteRequested(Editor removedEditor) {
743f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                    }
7445ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                };
7455ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov
7465ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor();
7475ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                if (mRequestFocus) {
7485ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                    nameEditor.requestFocus();
7495ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                    mRequestFocus = false;
7505ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                }
7515ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                nameEditor.setEditorListener(listener);
752f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
7535ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                final TextFieldsEditorView phoneticNameEditor =
7545ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                        rawContactEditor.getPhoneticNameEditor();
7555ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov                phoneticNameEditor.setEditorListener(listener);
7567d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov                rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup);
7577d901bb3d4118762e21f4db19e35fc937dcf96feDmitri Plotnikov
7589302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov                if (rawContactId == mAggregationSuggestionsRawContactId) {
7592828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki                    acquireAggregationSuggestions(activity, rawContactEditor);
760f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov                }
761f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            }
762cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        }
763f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
764eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov        mRequestFocus = false;
765eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov
766e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        bindGroupMetaData();
767e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
768f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        // Show editor now that we've loaded state
769f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mContent.setVisibility(View.VISIBLE);
770a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
771a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann        // Refresh Action Bar as the visibility of the join command
772825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        // Activity can be null if we have been detached from the Activity
773825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        final Activity activity = getActivity();
774825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        if (activity != null) activity.invalidateOptionsMenu();
7756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    }
776eeb68a341734ded343004d4eecb585420e70605bDmitri Plotnikov
77728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    /**
77828eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus     * If we've stashed a temporary file containing a contact's new photo,
77928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus     * decode it and return the bitmap.
78028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus     * @param rawContactId identifies the raw-contact whose Bitmap we'll try to return.
78128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus     * @return Bitmap of photo for specified raw-contact, or null
78228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    */
78328eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    private Bitmap updatedBitmapForRawContact(long rawContactId) {
78428eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus        String path = mUpdatedPhotos.getString(String.valueOf(rawContactId));
78528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus        return BitmapFactory.decodeFile(path);
78628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus    }
78728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
7886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type,
7896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            EntityDeltaList state) {
7906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        final int mode;
7916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (type.areContactsWritable()) {
7926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            if (editor.hasSetPhoto()) {
7936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (hasMoreThanOnePhoto()) {
794ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus                    mode = PhotoActionPopup.Modes.PHOTO_ALLOW_PRIMARY;
7956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                } else {
796ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus                    mode = PhotoActionPopup.Modes.PHOTO_DISALLOW_PRIMARY;
7976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
7986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            } else {
799ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus                mode = PhotoActionPopup.Modes.NO_PHOTO;
8006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
8016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        } else {
8026fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            if (editor.hasSetPhoto() && hasMoreThanOnePhoto()) {
803ced983d7a816256d93fdea1f81e63e4598c18875Josh Gargus                mode = PhotoActionPopup.Modes.READ_ONLY_ALLOW_PRIMARY;
8046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            } else {
8056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // Read-only and either no photo or the only photo ==> no options
806740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann                editor.getPhotoEditor().setEditorListener(null);
8076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                return;
8086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
8096fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
8106fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        mPhotoSelectionHandler = new PhotoHandler(mContext, editor, mode, state);
8116fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        editor.getPhotoEditor().setEditorListener(
8126fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                (PhotoHandler.PhotoEditorListener) mPhotoSelectionHandler.getListener());
813cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
814cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
815e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    private void bindGroupMetaData() {
816e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        if (mGroupMetaData == null) {
817e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov            return;
818e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        }
819e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
820e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        int editorCount = mContent.getChildCount();
821e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        for (int i = 0; i < editorCount; i++) {
82272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann            BaseRawContactEditorView editor = (BaseRawContactEditorView) mContent.getChildAt(i);
823e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov            editor.setGroupMetaData(mGroupMetaData);
824e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        }
825e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    }
826e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
8270353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan    private void saveDefaultAccountIfNecessary() {
8280353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // Verify that this is a newly created contact, that the contact is composed of only
8290353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // 1 raw contact, and that the contact is not a user profile.
8300353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        if (!Intent.ACTION_INSERT.equals(mAction) && mState.size() == 1 &&
8310353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                !isEditingUserProfile()) {
8320353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            return;
8330353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        }
8340353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
8350353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // Find the associated account for this contact (retrieve it here because there are
8360353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // multiple paths to creating a contact and this ensures we always have the correct
8370353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // account).
8380353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        final EntityDelta entity = mState.get(0);
8390353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        final ValuesDelta values = entity.getValues();
8400353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        String name = values.getAsString(RawContacts.ACCOUNT_NAME);
8410353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        String type = values.getAsString(RawContacts.ACCOUNT_TYPE);
8420353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        String dataSet = values.getAsString(RawContacts.DATA_SET);
8430353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
8440353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        AccountWithDataSet account = (name == null || type == null) ? null :
8450353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                new AccountWithDataSet(name, type, dataSet);
8460353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        mEditorUtils.saveDefaultAndAllAccounts(account);
8470353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan    }
8480353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
849d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    private void addAccountSwitcher(
850d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            final EntityDelta currentState, BaseRawContactEditorView editor) {
851d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ValuesDelta values = currentState.getValues();
8522b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        final AccountWithDataSet currentAccount = new AccountWithDataSet(
853d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                values.getAsString(RawContacts.ACCOUNT_NAME),
8542b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                values.getAsString(RawContacts.ACCOUNT_TYPE),
8552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                values.getAsString(RawContacts.DATA_SET));
856d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        final View accountView = editor.findViewById(R.id.account);
857fd70903236883f47b21f23b8cb49a1ccacdfcdf1Katherine Kuan        final View anchorView = editor.findViewById(R.id.account_container);
858d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        accountView.setOnClickListener(new View.OnClickListener() {
859d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            @Override
860d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            public void onClick(View v) {
861d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                final ListPopupWindow popup = new ListPopupWindow(mContext, null);
862a6c8f2daa80f1816dd25237457d7f6287c6b1b7cDaisuke Miyakawa                final AccountsListAdapter adapter =
8636f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki                        new AccountsListAdapter(mContext,
8646f74c0f3313cbb08ee8a8fbb79bfefc5b03fe215Makoto Onuki                        AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, currentAccount);
865d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setWidth(anchorView.getWidth());
866d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setAnchorView(anchorView);
867d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setAdapter(adapter);
868d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setModal(true);
869d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
870d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
871d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                    @Override
872d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                    public void onItemClick(AdapterView<?> parent, View view, int position,
873d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                            long id) {
874d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        popup.dismiss();
8752b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        AccountWithDataSet newAccount = adapter.getItem(position);
876d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        if (!newAccount.equals(currentAccount)) {
877d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                            rebindEditorsForNewContact(currentState, currentAccount, newAccount);
878d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        }
879d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                    }
880d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                });
881d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                popup.show();
882d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa            }
883d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        });
884d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
885d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
886a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan    private void disableAccountSwitcher(BaseRawContactEditorView editor) {
887a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan        // Remove the pressed state from the account header because the user cannot switch accounts
888a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan        // on an existing contact
889a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan        final View accountView = editor.findViewById(R.id.account);
890740552201d103b80bc49ea8a39a30536222672eaDaniel Lehmann        accountView.setBackground(null);
891a94859f61c216d4e137a631995026d3ddefbbf70Katherine Kuan        accountView.setEnabled(false);
892a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan    }
893a7c3d4d726b91f645431af14d8cceadd2245f4ceKatherine Kuan
894b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann    @Override
895eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn    public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
896c6b8afe730255537978f2c938cca6986cae63c34Katherine Kuan        inflater.inflate(R.menu.edit_contact, menu);
897cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
898cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
899b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann    @Override
900eb4d1bf9868dfddd958d8f028e36a4d2da7a8731Dianne Hackborn    public void onPrepareOptionsMenu(Menu menu) {
9019b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan        // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
9029b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan        // because the custom action bar contains the "save" button now (not the overflow menu).
9039b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan        // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
904692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        final MenuItem doneMenu = menu.findItem(R.id.menu_done);
905692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        final MenuItem splitMenu = menu.findItem(R.id.menu_split);
906692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        final MenuItem joinMenu = menu.findItem(R.id.menu_join);
907692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        final MenuItem helpMenu = menu.findItem(R.id.menu_help);
908692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu
909692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        // Set visibility of menus
910692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        doneMenu.setVisible(false);
9119b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan
91203587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson        // Split only if more than one raw profile and not a user profile
913692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        splitMenu.setVisible(mState != null && mState.size() > 1 && !isEditingUserProfile());
91403587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson
915692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        // Cannot join a user profile
916692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        joinMenu.setVisible(!isEditingUserProfile());
917692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu
918692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        // help menu depending on whether this is inserting or editing
919692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        if (Intent.ACTION_INSERT.equals(mAction)) {
920692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            // inserting
921692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            HelpUtils.prepareHelpMenuItem(getActivity(), helpMenu, R.string.help_url_people_add);
922692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        } else if (Intent.ACTION_EDIT.equals(mAction)) {
923692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            // editing
924692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            HelpUtils.prepareHelpMenuItem(getActivity(), helpMenu, R.string.help_url_people_edit);
925692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        } else {
926692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            // something else, so don't show the help menu
927692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu            helpMenu.setVisible(false);
928692d46364f2f0e32fd481b977c9e16832e70de5cMaurice Chu        }
92903587ecd46c0a524f3cdc5ffd2959be2bc30bb34Isaac Katzenelson
93002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        int size = menu.size();
93102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        for (int i = 0; i < size; i++) {
93202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov            menu.getItem(i).setEnabled(mEnabled);
93302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        }
934cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
935cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
936b85b83ee4adc8b72fe68499f669ca530d58e6815Daniel Lehmann    @Override
937cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    public boolean onOptionsItemSelected(MenuItem item) {
938cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        switch (item.getItemId()) {
939f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            case R.id.menu_done:
9409df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov                return save(SaveMode.CLOSE);
941f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            case R.id.menu_discard:
942d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                return revert();
943f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            case R.id.menu_split:
944f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return doSplitContactAction();
945f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            case R.id.menu_join:
946f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return doJoinContactAction();
947f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
948f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        return false;
949f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
950cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
951f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private boolean doSplitContactAction() {
952f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        if (!hasValidState()) return false;
953f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
954a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann        final SplitContactConfirmationDialogFragment dialog =
9554a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann                new SplitContactConfirmationDialogFragment();
9564a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann        dialog.setTargetFragment(this, 0);
9574a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann        dialog.show(getFragmentManager(), SplitContactConfirmationDialogFragment.TAG);
958f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        return true;
959f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
960f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
961f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private boolean doJoinContactAction() {
9624c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov        if (!hasValidState()) {
9634c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov            return false;
9644c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov        }
9654c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov
9664c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov        // If we just started creating a new contact and haven't added any data, it's too
9674c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov        // early to do a join
968764637aba745612a9fdc07adb99c615263916fa8Josh Gargus        if (mState.size() == 1 && mState.get(0).isContactInsert() && !hasPendingChanges()) {
969a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov            Toast.makeText(getActivity(), R.string.toast_join_with_empty_contact,
970a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                            Toast.LENGTH_LONG).show();
971a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov            return true;
9724c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov        }
9734c699fc698763b3e271efb7654fb5e38ffb6f556Dmitri Plotnikov
9749df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov        return save(SaveMode.JOIN);
975f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
976f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
977f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
978f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * Check if our internal {@link #mState} is valid, usually checked before
979f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * performing user actions.
980f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     */
981f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private boolean hasValidState() {
982f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        return mState != null && mState.size() > 0;
983f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
984f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
985f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
986764637aba745612a9fdc07adb99c615263916fa8Josh Gargus     * Return true if there are any edits to the current contact which need to
987764637aba745612a9fdc07adb99c615263916fa8Josh Gargus     * be saved.
988764637aba745612a9fdc07adb99c615263916fa8Josh Gargus     */
989764637aba745612a9fdc07adb99c615263916fa8Josh Gargus    private boolean hasPendingChanges() {
990764637aba745612a9fdc07adb99c615263916fa8Josh Gargus        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
991764637aba745612a9fdc07adb99c615263916fa8Josh Gargus        return EntityModifier.hasChanges(mState, accountTypes);
992764637aba745612a9fdc07adb99c615263916fa8Josh Gargus    }
993764637aba745612a9fdc07adb99c615263916fa8Josh Gargus
994764637aba745612a9fdc07adb99c615263916fa8Josh Gargus    /**
995f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * Saves or creates the contact based on the mode, and if successful
996f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * finishes the activity.
997f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     */
9989df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov    public boolean save(int saveMode) {
999a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        if (!hasValidState() || mStatus != Status.EDITING) {
1000f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            return false;
1001f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1002f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
10038c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov        // If we are about to close the editor - there is no need to refresh the data
1004a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.SPLIT) {
10059d2bcfb40d0ee107886eb99eba13a840e944ba43Dianne Hackborn            getLoaderManager().destroyLoader(LOADER_DATA);
10068c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov        }
10078c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov
1008825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        mStatus = Status.SAVING;
10096cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov
1010764637aba745612a9fdc07adb99c615263916fa8Josh Gargus        if (!hasPendingChanges()) {
1011ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann            if (mLookupUri == null && saveMode == SaveMode.RELOAD) {
1012ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann                // We don't have anything to save and there isn't even an existing contact yet.
1013ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann                // Nothing to do, simply go back to editing mode
1014ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann                mStatus = Status.EDITING;
1015ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann                return true;
1016ba69014263332f2056263cddc41cc6d7cfd7b7caDaniel Lehmann            }
101736d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro            onSaveCompleted(false, saveMode, mLookupUri != null, mLookupUri);
10186cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov            return true;
10196cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov        }
10206cb8fe23106bc05139798318f19b29c569140628Dmitri Plotnikov
1021a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        setEnabled(false);
1022f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
10230353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // Store account as default account, only if this is a new contact
10240353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        saveDefaultAccountIfNecessary();
10250353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan
10260353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan        // Save contact
1027a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        Intent intent = ContactSaveService.createSaveContactIntent(getActivity(), mState,
1028e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(), getActivity().getClass(),
1029e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                ContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos);
1030a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        getActivity().startService(intent);
103187270e1b58e669354bb1571ced686421c56deb7aJosh Gargus
103287270e1b58e669354bb1571ced686421c56deb7aJosh Gargus        // Don't try to save the same photos twice.
103387270e1b58e669354bb1571ced686421c56deb7aJosh Gargus        mUpdatedPhotos = new Bundle();
103487270e1b58e669354bb1571ced686421c56deb7aJosh Gargus
1035f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        return true;
1036f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1037f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1038d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov    public static class CancelEditDialogFragment extends DialogFragment {
1039d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov
1040d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        public static void show(ContactEditorFragment fragment) {
1041d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            CancelEditDialogFragment dialog = new CancelEditDialogFragment();
1042d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            dialog.setTargetFragment(fragment, 0);
1043d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            dialog.show(fragment.getFragmentManager(), "cancelEditor");
1044d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        }
1045d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov
1046d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        @Override
1047d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        public Dialog onCreateDialog(Bundle savedInstanceState) {
1048d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            AlertDialog dialog = new AlertDialog.Builder(getActivity())
10494292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov                    .setIconAttribute(android.R.attr.alertDialogIcon)
1050d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                    .setMessage(R.string.cancel_confirmation_dialog_message)
10511ba8b6fea4c3f82ded19305874e72a326612aed1Katherine Kuan                    .setPositiveButton(android.R.string.ok,
1052d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                        new DialogInterface.OnClickListener() {
1053d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                            @Override
1054f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann                            public void onClick(DialogInterface dialogInterface, int whichButton) {
1055d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                                ((ContactEditorFragment)getTargetFragment()).doRevertAction();
1056d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                            }
1057d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                        }
1058d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                    )
1059d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                    .setNegativeButton(android.R.string.cancel, null)
1060d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov                    .create();
1061d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            return dialog;
1062d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        }
1063d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov    }
1064d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov
1065d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov    private boolean revert() {
1066764637aba745612a9fdc07adb99c615263916fa8Josh Gargus        if (mState == null || !hasPendingChanges()) {
1067d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            doRevertAction();
1068d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        } else {
1069d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov            CancelEditDialogFragment.show(this);
1070d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        }
1071d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov        return true;
1072d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov    }
1073d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov
1074d3eedfc5f518a081d76d6b9e31a39c5adf988bc0Dmitri Plotnikov    private void doRevertAction() {
1075825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        // When this Fragment is closed we don't want it to auto-save
1076825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann        mStatus = Status.CLOSING;
107722fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann        if (mListener != null) mListener.onReverted();
1078f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1079f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
10809b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan    public void doSaveAction() {
10819b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan        save(SaveMode.CLOSE);
10829b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan    }
10839b3dfd0bc36568558bfdc32a5d4c30f2d0df5fedKatherine Kuan
10842b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov    public void onJoinCompleted(Uri uri) {
108536d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro        onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri);
10862b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov    }
10872b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov
108836d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro    public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
108936d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro            Uri contactLookupUri) {
1090a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        Log.d(TAG, "onSaveCompleted(" + saveMode + ", " + contactLookupUri);
1091a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        if (hadChanges) {
109236d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro            if (saveSucceeded) {
1093a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                if (saveMode != SaveMode.JOIN) {
1094a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                    Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show();
1095a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                }
1096a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov            } else {
1097a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
1098a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov            }
1099a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov        }
1100f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        switch (saveMode) {
110115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann            case SaveMode.CLOSE:
11029df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov            case SaveMode.HOME:
1103f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                final Intent resultIntent;
110436d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro                if (saveSucceeded && contactLookupUri != null) {
1105b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann                    final String requestAuthority =
1106b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann                            mLookupUri == null ? null : mLookupUri.getAuthority();
1107f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1108f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    final String legacyAuthority = "contacts";
1109f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1110f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    resultIntent = new Intent();
11115649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan                    resultIntent.setAction(Intent.ACTION_VIEW);
1112f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    if (legacyAuthority.equals(requestAuthority)) {
1113f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        // Build legacy Uri when requested by caller
1114f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        final long contactId = ContentUris.parseId(Contacts.lookupContact(
1115f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                                mContext.getContentResolver(), contactLookupUri));
1116f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        final Uri legacyContentUri = Uri.parse("content://contacts/people");
1117f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        final Uri legacyUri = ContentUris.withAppendedId(
1118f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                                legacyContentUri, contactId);
1119f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        resultIntent.setData(legacyUri);
1120f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    } else {
1121f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        // Otherwise pass back a lookup-style Uri
1122f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                        resultIntent.setData(contactLookupUri);
1123f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    }
1124f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1125f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                } else {
1126f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    resultIntent = null;
1127f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                }
1128825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann                // It is already saved, so prevent that it is saved again
1129825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann                mStatus = Status.CLOSING;
11305649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan                if (mListener != null) mListener.onSaveFinished(resultIntent);
1131f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                break;
1132a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov
113315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann            case SaveMode.RELOAD:
1134dd0dee6c55ea83d541b28e90cd4ad87ffd026f68Dmitri Plotnikov            case SaveMode.JOIN:
113536d24d7ede42a252c82c4aa783b2231c5e2eea79Dave Santoro                if (saveSucceeded && contactLookupUri != null) {
1136623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann                    // If it was a JOIN, we are now ready to bring up the join activity.
1137623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann                    if (saveMode == SaveMode.JOIN) {
1138623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann                        showJoinAggregateActivity(contactLookupUri);
1139623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann                    }
1140623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann
114115972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                    // If this was in INSERT, we are changing into an EDIT now.
114215972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                    // If it already was an EDIT, we are changing to the new Uri now
114315972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                    mState = null;
11441015d629f848de9d331a47c819f55854549d661dDmitri Plotnikov                    load(Intent.ACTION_EDIT, contactLookupUri, null);
1145825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann                    mStatus = Status.LOADING;
114615972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                    getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener);
114715972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                }
114815972398b530b91612418dc11d41c356d4f43739Daniel Lehmann                break;
1149a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov
115015972398b530b91612418dc11d41c356d4f43739Daniel Lehmann            case SaveMode.SPLIT:
1151a011414b12955a91c8f3efe528f374654d930098Dmitri Plotnikov                mStatus = Status.CLOSING;
1152a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann                if (mListener != null) {
11538c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov                    mListener.onContactSplit(contactLookupUri);
1154a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann                } else {
1155a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann                    Log.d(TAG, "No listener registered, can not call onSplitFinished");
1156a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann                }
1157f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                break;
1158f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1159f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1160f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1161f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
1162f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * Shows a list of aggregates that can be joined into the currently viewed aggregate.
1163f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     *
1164f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * @param contactLookupUri the fresh URI for the currently edited contact (after saving it)
1165f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     */
1166f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private void showJoinAggregateActivity(Uri contactLookupUri) {
116773a45b4ad96b21f468dbacde0da213d190979835Dmitri Plotnikov        if (contactLookupUri == null || !isAdded()) {
1168f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            return;
1169f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1170f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1171f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        mContactIdForJoin = ContentUris.parseId(contactLookupUri);
1172623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann        mContactWritableForJoin = isContactWritable();
1173f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        final Intent intent = new Intent(JoinContactActivity.JOIN_CONTACT);
1174f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        intent.putExtra(JoinContactActivity.EXTRA_TARGET_CONTACT_ID, mContactIdForJoin);
1175a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann        startActivityForResult(intent, REQUEST_CODE_JOIN);
1176f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1177f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1178f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
1179f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     * Performs aggregation with the contact selected by the user from suggestions or A-Z list.
1180f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann     */
1181f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private void joinAggregate(final long contactId) {
11822b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov        Intent intent = ContactSaveService.createJoinContactsIntent(mContext, mContactIdForJoin,
1183623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann                contactId, mContactWritableForJoin,
11842b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov                ContactEditorActivity.class, ContactEditorActivity.ACTION_JOIN_COMPLETED);
11852b46f0301c51973d6e3b02b78b398af097244af9Dmitri Plotnikov        mContext.startService(intent);
1186f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1187f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1188f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
1189ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov     * Returns true if there is at least one writable raw contact in the current contact.
1190ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov     */
1191ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov    private boolean isContactWritable() {
1192a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
1193ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov        int size = mState.size();
1194ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov        for (int i = 0; i < size; i++) {
1195ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov            ValuesDelta values = mState.get(i).getValues();
1196ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov            final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
11972b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final String dataSet = values.getAsString(RawContacts.DATA_SET);
11982b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType type = accountTypes.getAccountType(accountType, dataSet);
119996e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann            if (type.areContactsWritable()) {
1200ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov                return true;
1201ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov            }
1202ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov        }
1203ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov        return false;
1204ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov    }
1205ec502e886a94d23f03282ed2ee0cd8400678e8d7Dmitri Plotnikov
12062bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson    private boolean isEditingUserProfile() {
12072bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson        return mNewLocalProfile || mIsUserProfile;
12082bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson    }
12092bbfae8f92d5c218c83a49621a4c8f98f4d7a394Isaac Katzenelson
1210cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    public static interface Listener {
1211cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        /**
121222fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann         * Contact was not found, so somehow close this fragment. This is raised after a contact
121322fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann         * is removed via Menu/Delete (unless it was a new contact)
1214cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann         */
121522fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann        void onContactNotFound();
1216f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1217f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        /**
12188c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov         * Contact was split, so we can close now.
1219a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann         * @param newLookupUri The lookup uri of the new contact that should be shown to the user.
1220a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann         * The editor tries best to chose the most natural contact here.
1221f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         */
12228c91dfb9ef1c7ac1a4b2feed0b9a8585d4873542Dmitri Plotnikov        void onContactSplit(Uri newLookupUri);
1223f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1224f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        /**
1225f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         * User has tapped Revert, close the fragment now.
1226f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         */
122722fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann        void onReverted();
1228f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1229f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        /**
123022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann         * Contact was saved and the Fragment can now be closed safely.
1231f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         */
12325649a12fe551855f00c8dbeacfc96511c2a5fb71Katherine Kuan        void onSaveFinished(Intent resultIntent);
1233b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann
1234b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann        /**
1235e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov         * User switched to editing a different contact (a suggestion from the
1236e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov         * aggregation engine).
1237e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov         */
1238e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov        void onEditOtherContactRequested(
1239e47dd262a9880121fc2b75fe82b002bc101fc682Dmitri Plotnikov                Uri contactLookupUri, ArrayList<ContentValues> contentValues);
1240fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
1241fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        /**
1242fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         * Contact is being created for an external account that provides its own
1243fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         * new contact activity.
1244fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         */
12452b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        void onCustomCreateContactActivityRequested(AccountWithDataSet account,
12462b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                Bundle intentExtras);
1247fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov
1248fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov        /**
1249fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         * The edited raw contact belongs to an external account that provides
1250fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         * its own edit activity.
1251fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         *
1252fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         * @param redirect indicates that the current editor should be closed
1253fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         *            before the custom editor is shown.
1254fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov         */
12552b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro        void onCustomEditContactActivityRequested(AccountWithDataSet account, Uri rawContactUri,
1256fff6f07a02d3e3bbeff2ecf94a703782b71aea66Dmitri Plotnikov                Bundle intentExtras, boolean redirect);
1257f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1258f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1259f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    private class EntityDeltaComparator implements Comparator<EntityDelta> {
1260f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        /**
1261f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         * Compare EntityDeltas for sorting the stack of editors.
1262f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann         */
12634a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann        @Override
1264f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        public int compare(EntityDelta one, EntityDelta two) {
1265f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Check direct equality
1266f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (one.equals(two)) {
1267f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return 0;
1268f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1269f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1270a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov            final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
12712b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            String accountType1 = one.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
12722b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            String dataSet1 = one.getValues().getAsString(RawContacts.DATA_SET);
12732b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType type1 = accountTypes.getAccountType(accountType1, dataSet1);
12742b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            String accountType2 = two.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
12752b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            String dataSet2 = two.getValues().getAsString(RawContacts.DATA_SET);
12762b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro            final AccountType type2 = accountTypes.getAccountType(accountType2, dataSet2);
1277f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1278f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Check read-only
127996e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann            if (!type1.areContactsWritable() && type2.areContactsWritable()) {
1280f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return 1;
128196e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann            } else if (type1.areContactsWritable() && !type2.areContactsWritable()) {
1282f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return -1;
1283f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1284f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1285f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Check account type
1286f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            boolean skipAccountTypeCheck = false;
1287b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov            boolean isGoogleAccount1 = type1 instanceof GoogleAccountType;
1288b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov            boolean isGoogleAccount2 = type2 instanceof GoogleAccountType;
128969f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov            if (isGoogleAccount1 && !isGoogleAccount2) {
1290f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return -1;
129169f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov            } else if (!isGoogleAccount1 && isGoogleAccount2) {
1292f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return 1;
129369f9e6f0cd9b5401da55f251e9bd98e69643d7dfDmitri Plotnikov            } else if (isGoogleAccount1 && isGoogleAccount2){
1294f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                skipAccountTypeCheck = true;
1295f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1296f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1297f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            int value;
1298f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (!skipAccountTypeCheck) {
1299b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov                if (type1.accountType == null) {
13002776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru                    return 1;
13012776c7fe8117773fdf773396f61ed047238470f9Jean-Baptiste Queru                }
1302b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov                value = type1.accountType.compareTo(type2.accountType);
1303f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                if (value != 0) {
1304f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    return value;
13052b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                } else {
13062b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    // Fall back to data set.
13072b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    if (type1.dataSet != null) {
13082b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        value = type1.dataSet.compareTo(type2.dataSet);
13092b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        if (value != 0) {
13102b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                            return value;
13112b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        }
13122b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    } else if (type2.dataSet != null) {
13132b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                        return 1;
13142b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                    }
1315f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                }
1316f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1317f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1318f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Check account name
1319f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            ValuesDelta oneValues = one.getValues();
1320f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            String oneAccount = oneValues.getAsString(RawContacts.ACCOUNT_NAME);
1321f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (oneAccount == null) oneAccount = "";
1322f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            ValuesDelta twoValues = two.getValues();
1323f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            String twoAccount = twoValues.getAsString(RawContacts.ACCOUNT_NAME);
1324f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (twoAccount == null) twoAccount = "";
1325f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            value = oneAccount.compareTo(twoAccount);
1326f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (value != 0) {
1327f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return value;
1328f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1329f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1330f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Both are in the same account, fall back to contact ID
1331f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            Long oneId = oneValues.getAsLong(RawContacts._ID);
1332f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            Long twoId = twoValues.getAsLong(RawContacts._ID);
1333f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            if (oneId == null) {
1334f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return -1;
1335f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            } else if (twoId == null) {
1336f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                return 1;
1337f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
1338f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1339f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            return (int)(oneId - twoId);
1340f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1341f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1342f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1343f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    /**
1344f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov     * Returns the contact ID for the currently edited contact or 0 if the contact is new.
1345f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov     */
1346f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    protected long getContactId() {
1347c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov        if (mState != null) {
1348c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov            for (EntityDelta rawContact : mState) {
1349c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov                Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
1350c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov                if (contactId != null) {
1351c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov                    return contactId;
1352c76c2e872b4d8deb0e8ac26e9558fa360d525fdeDmitri Plotnikov                }
1353f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            }
1354f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        }
1355f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        return 0;
1356f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    }
1357f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
1358f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    /**
1359f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov     * Triggers an asynchronous search for aggregation suggestions.
1360f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov     */
13612828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki    private void acquireAggregationSuggestions(Context context,
13622828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki            RawContactEditorView rawContactEditor) {
13639302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        long rawContactId = rawContactEditor.getRawContactId();
13649302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        if (mAggregationSuggestionsRawContactId != rawContactId
13659302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov                && mAggregationSuggestionView != null) {
13669302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            mAggregationSuggestionView.setVisibility(View.GONE);
13679302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            mAggregationSuggestionView = null;
13689302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            mAggregationSuggestionEngine.reset();
13699302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        }
13709302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov
13719302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        mAggregationSuggestionsRawContactId = rawContactId;
13729302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov
1373f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        if (mAggregationSuggestionEngine == null) {
13742828c48cc4537fe981918f80297d5408bedc87b5Makoto Onuki            mAggregationSuggestionEngine = new AggregationSuggestionEngine(context);
1375f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            mAggregationSuggestionEngine.setListener(this);
1376f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            mAggregationSuggestionEngine.start();
1377f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        }
1378f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
1379916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov        mAggregationSuggestionEngine.setContactId(getContactId());
1380916cf2661ada41a83556884d8f5b322d32ef452bDmitri Plotnikov
1381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        LabeledEditorView nameEditor = rawContactEditor.getNameEditor();
1382f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        mAggregationSuggestionEngine.onNameChange(nameEditor.getValues());
1383f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    }
1384f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
1385f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    @Override
1386f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov    public void onAggregationSuggestionChange() {
1387a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        if (!isAdded() || mState == null || mStatus != Status.EDITING) {
138802cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov            return;
138902cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov        }
139002cbf8b0e73a7e169445e341f387356242f0334dDmitri Plotnikov
13916c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        if (mAggregationSuggestionPopup != null && mAggregationSuggestionPopup.isShowing()) {
13926c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa            mAggregationSuggestionPopup.dismiss();
13939302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        }
1394f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
13956c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) {
1396f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov            return;
1397f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov        }
1398f491ae914769f1062a4d9c31fcbec5ff0e01e4e6Dmitri Plotnikov
13996c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        final RawContactEditorView rawContactView =
14006c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId);
140102a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki        if (rawContactView == null) {
140202a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki            return; // Raw contact deleted?
140302a54ebd3185948e2c1c0f39b7718cb9abaea934Makoto Onuki        }
14046c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        final View anchorView = rawContactView.findViewById(R.id.anchor_view);
14056c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup = new ListPopupWindow(mContext, null);
14066c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.setAnchorView(anchorView);
14076c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.setWidth(anchorView.getWidth());
14086c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
14096c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.setAdapter(
14106c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                new AggregationSuggestionAdapter(getActivity(),
14116c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                        mState.size() == 1 && mState.get(0).isContactInsert(),
14126c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa                        this, mAggregationSuggestionEngine.getSuggestions()));
14136c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.setOnItemClickListener(mAggregationSuggestionItemClickListener);
14146c8c0777c823e2a2fef69299c0b36ca4a40e1feaDaisuke Miyakawa        mAggregationSuggestionPopup.show();
1415bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1416bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1417bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    @Override
1418bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    public void onJoinAction(long contactId, List<Long> rawContactIdList) {
1419bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        long rawContactIds[] = new long[rawContactIdList.size()];
1420bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        for (int i = 0; i < rawContactIds.length; i++) {
1421bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov            rawContactIds[i] = rawContactIdList.get(i);
1422bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        }
1423bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        JoinSuggestedContactDialogFragment dialog =
1424bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                new JoinSuggestedContactDialogFragment();
1425bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        Bundle args = new Bundle();
1426bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        args.putLongArray("rawContactIds", rawContactIds);
1427bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        dialog.setArguments(args);
1428bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        dialog.setTargetFragment(this, 0);
142974f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov        try {
143074f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov            dialog.show(getFragmentManager(), "join");
143174f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov        } catch (Exception ex) {
143274f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov            // No problem - the activity is no longer available to display the dialog
143374f519f81f257cd2f962fdf12e6ee9ec6fe6a5f0Dmitri Plotnikov        }
1434bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1435bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1436bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    public static class JoinSuggestedContactDialogFragment extends DialogFragment {
1437bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1438bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        @Override
1439bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        public Dialog onCreateDialog(Bundle savedInstanceState) {
1440bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov            return new AlertDialog.Builder(getActivity())
14414292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov                    .setIconAttribute(android.R.attr.alertDialogIcon)
1442bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setMessage(R.string.aggregation_suggestion_join_dialog_message)
1443bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setPositiveButton(android.R.string.yes,
1444bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                        new DialogInterface.OnClickListener() {
1445f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann                            @Override
1446bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                            public void onClick(DialogInterface dialog, int whichButton) {
1447bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                ContactEditorFragment targetFragment =
1448bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                        (ContactEditorFragment) getTargetFragment();
1449bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                long rawContactIds[] =
1450bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                        getArguments().getLongArray("rawContactIds");
1451bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                targetFragment.doJoinSuggestedContact(rawContactIds);
1452bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                            }
1453bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                        }
1454bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    )
1455bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setNegativeButton(android.R.string.no, null)
1456bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .create();
1457bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        }
1458bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1459bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1460bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    /**
1461bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     * Joins the suggested contact (specified by the id's of constituent raw
1462bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     * contacts), save all changes, and stay in the editor.
1463bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     */
1464bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    protected void doJoinSuggestedContact(long[] rawContactIds) {
1465cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov        if (!hasValidState() || mStatus != Status.EDITING) {
1466cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov            return;
1467cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov        }
1468cd1b9a29458d30ec74cf94dc9945cbdb6186a68eDmitri Plotnikov
1469bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        mState.setJoinWithRawContacts(rawContactIds);
14709df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov        save(SaveMode.RELOAD);
1471bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1472bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1473bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    @Override
1474bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    public void onEditAction(Uri contactLookupUri) {
1475bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        SuggestionEditConfirmationDialogFragment dialog =
1476bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                new SuggestionEditConfirmationDialogFragment();
1477bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        Bundle args = new Bundle();
1478bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        args.putParcelable("contactUri", contactLookupUri);
1479bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        dialog.setArguments(args);
1480bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        dialog.setTargetFragment(this, 0);
1481bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        dialog.show(getFragmentManager(), "edit");
1482bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1483bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1484bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    public static class SuggestionEditConfirmationDialogFragment extends DialogFragment {
1485bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1486bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        @Override
1487bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        public Dialog onCreateDialog(Bundle savedInstanceState) {
1488bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov            return new AlertDialog.Builder(getActivity())
14894292dfa46123a6c0e1de9862b4d8694bfb87875aDmitri Plotnikov                    .setIconAttribute(android.R.attr.alertDialogIcon)
1490bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setMessage(R.string.aggregation_suggestion_edit_dialog_message)
1491bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setPositiveButton(android.R.string.yes,
1492bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                        new DialogInterface.OnClickListener() {
1493f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann                            @Override
1494bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                            public void onClick(DialogInterface dialog, int whichButton) {
1495bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                ContactEditorFragment targetFragment =
1496bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                        (ContactEditorFragment) getTargetFragment();
1497bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                Uri contactUri =
1498bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                        getArguments().getParcelable("contactUri");
1499bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                                targetFragment.doEditSuggestedContact(contactUri);
1500bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                            }
1501bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                        }
1502bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    )
1503bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .setNegativeButton(android.R.string.no, null)
1504bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    .create();
1505bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        }
1506bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1507bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1508bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    /**
1509bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     * Abandons the currently edited contact and switches to editing the suggested
1510bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     * one, transferring all the data there
1511bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov     */
1512bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    protected void doEditSuggestedContact(Uri contactUri) {
1513bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        if (mListener != null) {
1514a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann            // make sure we don't save this contact when closing down
1515a10775d625339d168337e03de05d02f5e0a4f55dDaniel Lehmann            mStatus = Status.CLOSING;
1516bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov            mListener.onEditOtherContactRequested(
1517bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov                    contactUri, mState.get(0).getContentValues());
1518bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        }
1519bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    }
1520bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov
1521a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov    public void setAggregationSuggestionViewEnabled(boolean enabled) {
1522a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        if (mAggregationSuggestionView == null) {
1523a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov            return;
1524a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        }
1525a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov
1526a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        LinearLayout itemList = (LinearLayout) mAggregationSuggestionView.findViewById(
1527a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov                R.id.aggregation_suggestions);
1528a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        int count = itemList.getChildCount();
1529a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        for (int i = 0; i < count; i++) {
1530a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov            itemList.getChildAt(i).setEnabled(enabled);
1531a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov        }
1532a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov    }
1533a9333790f027d59a2edfd4a98c0392b144577416Dmitri Plotnikov
1534f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    @Override
1535f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    public void onSaveInstanceState(Bundle outState) {
1536b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann        outState.putParcelable(KEY_URI, mLookupUri);
1537d364314c460152db7089b304beec81b3675893baDmitri Plotnikov        outState.putString(KEY_ACTION, mAction);
1538d364314c460152db7089b304beec81b3675893baDmitri Plotnikov
1539f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        if (hasValidState()) {
1540f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            // Store entities with modifications
1541f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            outState.putParcelable(KEY_EDIT_STATE, mState);
1542f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1543f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1544f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto);
1545f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
1546f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        if (mCurrentPhotoFile != null) {
1547f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            outState.putString(KEY_CURRENT_PHOTO_FILE, mCurrentPhotoFile.toString());
1548f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1549f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin);
1550623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann        outState.putBoolean(KEY_CONTACT_WRITABLE_FOR_JOIN, mContactWritableForJoin);
15519302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        outState.putLong(KEY_SHOW_JOIN_SUGGESTIONS, mAggregationSuggestionsRawContactId);
155202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov        outState.putBoolean(KEY_ENABLED, mEnabled);
1553ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
1554ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson        outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
1555ce37f3017c666bcea483a75322e80d5cc1ba6f64Dmitri Plotnikov        outState.putInt(KEY_STATUS, mStatus);
155628eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus        outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
155728eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
1558f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        super.onSaveInstanceState(outState);
1559f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    }
1560f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
1561d364314c460152db7089b304beec81b3675893baDmitri Plotnikov    @Override
1562f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann    public void onActivityResult(int requestCode, int resultCode, Intent data) {
1563f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov        if (mStatus == Status.SUB_ACTIVITY) {
1564f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov            mStatus = Status.EDITING;
1565f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov        }
1566f9ca423c867ab2cd4f0d9025a95436489c41d405Dmitri Plotnikov
15676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        // See if the photo selection handler handles this result.
15686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        if (mPhotoSelectionHandler != null && mPhotoSelectionHandler.handlePhotoActivityResult(
15696fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                requestCode, resultCode, data)) {
15706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            return;
15716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        }
1572f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann
15736fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        switch (requestCode) {
1574a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann            case REQUEST_CODE_JOIN: {
15750353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // Ignore failed requests
15760353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                if (resultCode != Activity.RESULT_OK) return;
1577f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                if (data != null) {
1578f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    final long contactId = ContentUris.parseId(data.getData());
1579f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                    joinAggregate(contactId);
1580f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann                }
15814a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann                break;
1582f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann            }
15830353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            case REQUEST_CODE_ACCOUNTS_CHANGED: {
15840353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // Bail if the account selector was not successful.
15850353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                if (resultCode != Activity.RESULT_OK) {
15860353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    mListener.onReverted();
15870353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    return;
15880353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                }
15890353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // If there's an account specified, use it.
15900353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                if (data != null) {
15910353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    AccountWithDataSet account = data.getParcelableExtra(Intents.Insert.ACCOUNT);
15920353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    if (account != null) {
15930353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                        createContact(account);
15940353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                        return;
15950353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                    }
15960353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                }
15970353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // If there isn't an account specified, then this is likely a phone-local
15980353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // contact, so we should continue setting up the editor by automatically selecting
15990353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                // the most appropriate account.
16000353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                createContact();
16010353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan                break;
16020353a24d97cc0266eb9bf0ee6c7d6821aeb1896eKatherine Kuan            }
1603f319cf8549738feca5965a598af9a310869e1f3dDaniel Lehmann        }
1604cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    }
16059cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov
1606c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann    /**
1607c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann     * Sets the photo stored in mPhoto and writes it to the RawContact with the given id
1608c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann     */
1609e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus    private void setPhoto(long rawContact, Bitmap photo, File photoFile) {
1610bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov        BaseRawContactEditorView requestingEditor = getRawContactEditorView(rawContact);
1611e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus
1612e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus        if (photo == null || photo.getHeight() < 0 || photo.getWidth() < 0) {
1613e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus            // This is unexpected.
1614e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus            Log.w(TAG, "Invalid bitmap passed to setPhoto()");
1615e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus        }
1616e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus
16179302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        if (requestingEditor != null) {
16189302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            requestingEditor.setPhotoBitmap(photo);
16199302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        } else {
16209302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov            Log.w(TAG, "The contact that requested the photo is no longer present.");
16219302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        }
1622e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus
1623e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus        mUpdatedPhotos.putString(String.valueOf(rawContact), photoFile.getAbsolutePath());
16249302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov    }
16259302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov
16269302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov    /**
16279302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov     * Finds raw contact editor view for the given rawContactId.
16289302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov     */
1629bd0c12c63bb0adbc78715d9d13ba588c8ae61839Dmitri Plotnikov    public BaseRawContactEditorView getRawContactEditorView(long rawContactId) {
1630c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann        for (int i = 0; i < mContent.getChildCount(); i++) {
1631c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann            final View childView = mContent.getChildAt(i);
163272af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann            if (childView instanceof BaseRawContactEditorView) {
163372af89f9e497bb8ef54fe3deeec7e8477d192242Daniel Lehmann                final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView;
16349302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov                if (editor.getRawContactId() == rawContactId) {
16359302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov                    return editor;
1636c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann                }
1637c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann            }
1638c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann        }
16399302ba7bc47d995c88eba7604aeea00a7e41779fDmitri Plotnikov        return null;
1640c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann    }
1641c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann
1642fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann    /**
1643fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann     * Returns true if there is currently more than one photo on screen.
1644fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann     */
1645fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann    private boolean hasMoreThanOnePhoto() {
1646fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann        int count = mContent.getChildCount();
1647fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann        int countWithPicture = 0;
1648fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann        for (int i = 0; i < count; i++) {
1649fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann            final View childView = mContent.getChildAt(i);
1650fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann            if (childView instanceof BaseRawContactEditorView) {
1651fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann                final BaseRawContactEditorView editor = (BaseRawContactEditorView) childView;
1652fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann                if (editor.hasSetPhoto()) {
1653fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann                    countWithPicture++;
1654fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann                    if (countWithPicture > 1) return true;
1655fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann                }
1656fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann            }
1657fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann        }
1658fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann
1659fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann        return false;
16609cd1708f333eda622dc6a4fed2a0df9058193a9dDmitri Plotnikov    }
1661222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann
1662222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    /**
1663222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann     * The listener for the data loader
1664222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann     */
1665222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDataLoaderListener =
1666222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            new LoaderCallbacks<ContactLoader.Result>() {
1667222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        @Override
1668222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
1669222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            mLoaderStartTime = SystemClock.elapsedRealtime();
1670b846fc117b2c4c0c3ed5eb3e9ce32591986a0253Daniel Lehmann            return new ContactLoader(mContext, mLookupUri);
1671222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        }
1672222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann
1673222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        @Override
1674222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
1675222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            final long loaderCurrentTime = SystemClock.elapsedRealtime();
1676222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
16772621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki            if (!data.isLoaded()) {
1678222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann                // Item has been deleted
1679222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann                Log.i(TAG, "No contact found. Closing activity");
168022fb2053fe2bfe98376bf1a0e564f23ae9cecdedDaniel Lehmann                if (mListener != null) mListener.onContactNotFound();
1681222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann                return;
1682222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            }
1683222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann
1684825cb62b7df3cfe208651d488278e1b57c863884Daniel Lehmann            mStatus = Status.EDITING;
16856caccaeeed943db323be89853a108f422e670760Dmitri Plotnikov            mLookupUri = data.getLookupUri();
1686222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            final long setDataStartTime = SystemClock.elapsedRealtime();
1687222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            setData(data);
1688222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            final long setDataEndTime = SystemClock.elapsedRealtime();
1689c1406450bb2a1a214ff35e99a173ee1a28b926faDaniel Lehmann
1690222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann            Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime-setDataStartTime));
1691222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann        }
16924ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn
1693623932de8c18e9b83b6fd941afe415ab2e6c730bDaniel Lehmann        @Override
16944ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn        public void onLoaderReset(Loader<ContactLoader.Result> loader) {
16954ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn        }
1696222744ea3cd7233677f0ef88804eb3e2db710e43Daniel Lehmann    };
1697a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
1698e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    /**
1699be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan     * The listener for the group meta data loader for all groups.
1700e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov     */
1701e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
1702e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov            new LoaderCallbacks<Cursor>() {
1703e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
1704e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        @Override
1705e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        public CursorLoader onCreateLoader(int id, Bundle args) {
1706be18de05d6f6a107c552e369bce58f51c946fde7Katherine Kuan            return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI);
1707e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        }
1708e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
1709e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        @Override
1710e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
1711e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov            mGroupMetaData = data;
1712e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov            bindGroupMetaData();
1713e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov        }
17144ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn
1715f30723782e801deaf159aea2443e9507596ef11dDaniel Lehmann        @Override
17164ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn        public void onLoaderReset(Loader<Cursor> loader) {
17174ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn        }
1718e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov    };
1719e843f916942fff482ec162eee2a23914e32182cfDmitri Plotnikov
1720a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann    @Override
1721a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann    public void onSplitContactConfirmed() {
1722b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa        if (mState == null) {
1723b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa            // This may happen when this Fragment is recreated by the system during users
1724b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa            // confirming the split action (and thus this method is called just before onCreate()),
1725b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa            // for example.
1726b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa            Log.e(TAG, "mState became null during the user's confirming split action. " +
1727b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa                    "Cannot perform the save action.");
1728b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa            return;
1729b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa        }
1730b9e60280603f2fa57083c13952e4b25e2585b833Daisuke Miyakawa
1731a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann        mState.markRawContactsForSplitting();
17329df61ed9eeecb81043e7e6662ff3da83428d6865Dmitri Plotnikov        save(SaveMode.SPLIT);
1733a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann    }
1734a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
17356fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    /**
17366fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * Custom photo handler for the editor.  The inner listener that this creates also has a
17376fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * reference to the editor and acts as an {@link EditorListener}, and uses that editor to hold
17386fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     * state information in several of the listener methods.
17396fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro     */
17406fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    private final class PhotoHandler extends PhotoSelectionHandler {
174128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
174228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus        final long mRawContactId;
1743e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        private final BaseRawContactEditorView mEditor;
17449a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann        private PhotoActionListener mPhotoEditorListener;
174528eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
17466fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode,
17476fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                EntityDeltaList state) {
17486fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            super(context, editor.getPhotoEditor(), photoMode, false, state);
1749e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus            mEditor = editor;
175028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus            mRawContactId = editor.getRawContactId();
17519a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann            mPhotoEditorListener = new PhotoEditorListener();
1752e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        }
1753e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus
1754e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        @Override
1755e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        public PhotoActionListener getListener() {
17569a409d474b2b4f2e4261657f864eeb866fcb8816Daniel Lehmann            return mPhotoEditorListener;
1757e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        }
1758e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus
1759e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        @Override
1760e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus        public void startPhotoActivity(Intent intent, int requestCode, File photoFile) {
1761e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus            mRawContactIdRequestingPhoto = mEditor.getRawContactId();
1762e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus            mStatus = Status.SUB_ACTIVITY;
1763e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus            mCurrentPhotoFile = photoFile;
1764e5d3f897689c8ba0f275c7679c72eacb190ae9b8Josh Gargus            ContactEditorFragment.this.startActivityForResult(intent, requestCode);
17659442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann        }
17669442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann
17676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro        private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener
17686fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                implements EditorListener {
1769fe22aff8c87374cfa80a7a02ec29b442f2453d8cDaniel Lehmann
17706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
17716fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onRequest(int request) {
17726fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (!hasValidState()) return;
1773a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
17746fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                if (request == EditorListener.REQUEST_PICK_PHOTO) {
17756fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    onClick(mEditor.getPhotoEditor());
17769442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann                }
17779442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann            }
1778a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
17796fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
17806fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onDeleteRequested(Editor removedEditor) {
17816fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // The picture cannot be deleted, it can only be removed, which is handled by
17826fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // onRemovePictureChosen()
17836fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
1784a35a7e2aabc4edfafb9b4171e279bdb4c0c03d44Daniel Lehmann
17856fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            /**
17866fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro             * User has chosen to set the selected photo as the (super) primary photo
17876fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro             */
17886fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
17896fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onUseAsPrimaryChosen() {
17906fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // Set the IsSuperPrimary for each editor
17916fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                int count = mContent.getChildCount();
17926fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                for (int i = 0; i < count; i++) {
17936fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    final View childView = mContent.getChildAt(i);
17946fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    if (childView instanceof BaseRawContactEditorView) {
17956fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        final BaseRawContactEditorView editor =
17966fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                                (BaseRawContactEditorView) childView;
17976fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        final PhotoEditorView photoEditor = editor.getPhotoEditor();
17986fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                        photoEditor.setSuperPrimary(editor == mEditor);
17996fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                    }
18006fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                }
18016fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
18029442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann
18036fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            /**
18046fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro             * User has chosen to remove a picture
18056fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro             */
18066fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
18076fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onRemovePictureChosen() {
18086fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mEditor.setPhotoBitmap(null);
180928eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus
181028eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus                // Prevent bitmap from being restored if rotate the device.
181128eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus                // (only if we first chose a new photo before removing it)
181228eadab78531e22a0d9fa22fbbcd61c451005890Josh Gargus                mUpdatedPhotos.remove(String.valueOf(mRawContactId));
18136fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
18146fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
18156fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
18166fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onPhotoSelected(Bitmap bitmap) {
1817e692e010ca02200087997280e7c239ebf94aa8f9Josh Gargus                setPhoto(mRawContactIdRequestingPhoto, bitmap, mCurrentPhotoFile);
18186fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                mRawContactIdRequestingPhoto = -1;
18196fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
18206fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
18216fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
18226fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public File getCurrentPhotoFile() {
18236fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                return mCurrentPhotoFile;
18246fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            }
18256fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro
18266fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            @Override
18276fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro            public void onPhotoSelectionDismissed() {
18286fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro                // Nothing to do.
18299442ef4d2667eab16f65535b63757a7ffe4ccf69Daniel Lehmann            }
18304a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann        }
18314a62be4f5a365e5afde71becfd446381f2baa494Daniel Lehmann    }
18322ae666ec99ae9318936a9326e5243987e4e1c586Jeff Sharkey}
1833