blob: 4aabf0ec799d6d093268ef78b78bb8978fbd8356 [file] [log] [blame]
Walter Jangcab3dce2015-02-09 17:48:03 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.contacts.editor;
18
19import com.android.contacts.R;
20import com.android.contacts.common.model.AccountTypeManager;
21import com.android.contacts.common.model.RawContactDelta;
22import com.android.contacts.common.model.RawContactDeltaList;
Walter Jange720fde2015-02-17 10:54:14 -080023import com.android.contacts.common.model.RawContactModifier;
Walter Jangcab3dce2015-02-09 17:48:03 -080024import com.android.contacts.common.model.ValuesDelta;
25import com.android.contacts.common.model.account.AccountType;
26import com.android.contacts.common.model.account.AccountType.EditField;
Walter Jang2d3f31c2015-06-18 23:15:31 -070027import com.android.contacts.common.model.account.AccountWithDataSet;
Walter Jangcab3dce2015-02-09 17:48:03 -080028import com.android.contacts.common.model.dataitem.DataKind;
Walter Jang708ea9e2015-09-10 15:42:05 -070029import com.android.contacts.common.util.AccountsListAdapter;
Walter Jangf46abd82015-02-20 16:52:04 -080030import com.android.contacts.common.util.MaterialColorMapUtils;
Walter Jang3efae4a2015-02-18 11:12:00 -080031import com.android.contacts.editor.CompactContactEditorFragment.PhotoHandler;
Walter Jang708ea9e2015-09-10 15:42:05 -070032import com.android.contacts.util.UiClosables;
Walter Jangcab3dce2015-02-09 17:48:03 -080033
34import android.content.Context;
Walter Jang3efae4a2015-02-18 11:12:00 -080035import android.graphics.Bitmap;
Walter Jang41b3ea12015-03-09 17:30:06 -070036import android.net.Uri;
Walter Jangcab3dce2015-02-09 17:48:03 -080037import android.provider.ContactsContract.CommonDataKinds.Email;
38import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
Walter Jang3efae4a2015-02-18 11:12:00 -080039import android.provider.ContactsContract.CommonDataKinds.Nickname;
Walter Jangcab3dce2015-02-09 17:48:03 -080040import android.provider.ContactsContract.CommonDataKinds.Phone;
41import android.provider.ContactsContract.CommonDataKinds.Photo;
Walter Jangcab3dce2015-02-09 17:48:03 -080042import android.provider.ContactsContract.CommonDataKinds.StructuredName;
43import android.text.TextUtils;
44import android.util.AttributeSet;
45import android.util.Log;
Walter Jang2d3f31c2015-06-18 23:15:31 -070046import android.util.Pair;
Walter Jangcab3dce2015-02-09 17:48:03 -080047import android.view.LayoutInflater;
Walter Jangb1c87622015-02-13 17:51:38 -080048import android.view.View;
Walter Jangcab3dce2015-02-09 17:48:03 -080049import android.view.ViewGroup;
Walter Jang708ea9e2015-09-10 15:42:05 -070050import android.widget.AdapterView;
Walter Jangcab3dce2015-02-09 17:48:03 -080051import android.widget.LinearLayout;
Walter Jang708ea9e2015-09-10 15:42:05 -070052import android.widget.ListPopupWindow;
Walter Jang2d3f31c2015-06-18 23:15:31 -070053import android.widget.TextView;
Walter Jangcab3dce2015-02-09 17:48:03 -080054
55import java.util.ArrayList;
Walter Jang19d985f2015-07-01 13:36:27 -070056import java.util.HashMap;
Walter Jangcab3dce2015-02-09 17:48:03 -080057import java.util.List;
Walter Jang19d985f2015-07-01 13:36:27 -070058import java.util.Map;
Walter Jang708ea9e2015-09-10 15:42:05 -070059import java.util.Objects;
Walter Jangcab3dce2015-02-09 17:48:03 -080060
61/**
62 * View to display information from multiple {@link RawContactDelta}s grouped together
63 * (e.g. all the phone numbers from a {@link com.android.contacts.common.model.Contact} together.
64 */
Walter Jangb6ca2722015-02-20 11:10:25 -080065public class CompactRawContactsEditorView extends LinearLayout implements View.OnClickListener {
Walter Jangcab3dce2015-02-09 17:48:03 -080066
67 private static final String TAG = "CompactEditorView";
68
Walter Jangb6ca2722015-02-20 11:10:25 -080069 /**
70 * Callbacks for hosts of {@link CompactRawContactsEditorView}s.
71 */
72 public interface Listener {
73
74 /**
75 * Invoked when the compact editor should be expanded to show all fields.
76 */
77 public void onExpandEditor();
Walter Jang151f3e62015-02-26 15:29:40 -080078
79 /**
80 * Invoked when the structured name editor field has changed.
81 *
82 * @param rawContactId The raw contact ID from the underlying {@link RawContactDelta}.
83 * @param valuesDelta The values from the underlying {@link RawContactDelta}.
84 */
85 public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta);
Walter Jang708ea9e2015-09-10 15:42:05 -070086
87 /**
88 * Invoked when the compact editor should rebind editors for a new account.
89 *
90 * @param oldState Old data being edited.
91 * @param oldAccount Old account associated with oldState.
92 * @param newAccount New account to be used.
93 */
94 public void onRebindEditorsForNewContact(RawContactDelta oldState,
95 AccountWithDataSet oldAccount, AccountWithDataSet newAccount);
Walter Jang151f3e62015-02-26 15:29:40 -080096 }
97
98 /**
99 * Marks a name as super primary when it is changed.
100 *
101 * This is for the case when two or more raw contacts with names are joined where neither is
102 * marked as super primary. If the user hits back (which causes a save) after changing the
103 * name that was arbitrarily displayed, we want that to be the name that is used.
104 *
105 * Should only be set when a super primary name does not already exist since we only show
106 * one name field.
107 */
108 static final class NameEditorListener implements Editor.EditorListener {
109
110 private final ValuesDelta mValuesDelta;
111 private final long mRawContactId;
112 private final Listener mListener;
113
114 public NameEditorListener(ValuesDelta valuesDelta, long rawContactId,
115 Listener listener) {
116 mValuesDelta = valuesDelta;
117 mRawContactId = rawContactId;
118 mListener = listener;
119 }
120
121 @Override
122 public void onRequest(int request) {
123 if (request == Editor.EditorListener.FIELD_CHANGED) {
124 mValuesDelta.setSuperPrimary(true);
125 if (mListener != null) {
126 mListener.onNameFieldChanged(mRawContactId, mValuesDelta);
127 }
128 } else if (request == Editor.EditorListener.FIELD_TURNED_EMPTY) {
129 mValuesDelta.setSuperPrimary(false);
130 }
131 }
132
133 @Override
134 public void onDeleteRequested(Editor editor) {
135 }
Walter Jangb6ca2722015-02-20 11:10:25 -0800136 }
137
138 private Listener mListener;
139
Walter Jangcab3dce2015-02-09 17:48:03 -0800140 private AccountTypeManager mAccountTypeManager;
141 private LayoutInflater mLayoutInflater;
Walter Jangd35e5ef2015-02-24 09:18:16 -0800142
Walter Jangcab3dce2015-02-09 17:48:03 -0800143 private ViewIdGenerator mViewIdGenerator;
Walter Jangf46abd82015-02-20 16:52:04 -0800144 private MaterialColorMapUtils.MaterialPalette mMaterialPalette;
Walter Jang708ea9e2015-09-10 15:42:05 -0700145 private long mPhotoId;
146 private long mNameId;
147 private String mReadOnlyDisplayName;
148 private boolean mHasNewContact;
149 private boolean mIsUserProfile;
150 private AccountWithDataSet mPrimaryAccount;
151 private RawContactDelta mPrimaryRawContactDelta;
Walter Jang363d3fd2015-09-16 10:29:07 -0700152 private Map<String,List<KindSectionData>> mKindSectionDataMap = new HashMap<>();
Walter Jangcab3dce2015-02-09 17:48:03 -0800153
Walter Jang708ea9e2015-09-10 15:42:05 -0700154 // Account header
155 private View mAccountHeaderContainer;
156 private TextView mAccountHeaderType;
157 private TextView mAccountHeaderName;
158
159 // Account selector
160 private View mAccountSelectorContainer;
161 private View mAccountSelector;
162 private TextView mAccountSelectorType;
163 private TextView mAccountSelectorName;
164
Walter Janga5e4bb22015-02-24 13:08:16 -0800165 private CompactPhotoEditorView mPhoto;
Walter Jangcab3dce2015-02-09 17:48:03 -0800166 private ViewGroup mNames;
Walter Jangb1c87622015-02-13 17:51:38 -0800167 private ViewGroup mPhoneticNames;
168 private ViewGroup mNicknames;
Walter Jangcab3dce2015-02-09 17:48:03 -0800169 private ViewGroup mPhoneNumbers;
170 private ViewGroup mEmails;
Walter Jang995bb4a2015-07-06 12:21:36 -0700171 private ViewGroup mOtherTypes;
172 private Map<String,LinearLayout> mOtherTypesMap = new HashMap<>();
Walter Jangb6ca2722015-02-20 11:10:25 -0800173 private View mMoreFields;
Walter Jangcab3dce2015-02-09 17:48:03 -0800174
Walter Jang151f3e62015-02-26 15:29:40 -0800175 // The ValuesDelta for the non super primary name that was displayed to the user.
176 private ValuesDelta mNameValuesDelta;
177
Walter Jang3efae4a2015-02-18 11:12:00 -0800178 private long mPhotoRawContactId;
179
Walter Jang363d3fd2015-09-16 10:29:07 -0700180 private boolean mUsingDefaultNameEditorView;
Walter Jang06f73a12015-06-17 11:15:48 -0700181 private StructuredNameEditorView mDefaultNameEditorView;
182
Walter Jangcab3dce2015-02-09 17:48:03 -0800183 public CompactRawContactsEditorView(Context context) {
184 super(context);
185 }
186
187 public CompactRawContactsEditorView(Context context, AttributeSet attrs) {
188 super(context, attrs);
189 }
190
Walter Jangb6ca2722015-02-20 11:10:25 -0800191 /**
192 * Sets the receiver for {@link CompactRawContactsEditorView} callbacks.
193 */
194 public void setListener(Listener listener) {
195 mListener = listener;
196 }
197
Walter Jangcab3dce2015-02-09 17:48:03 -0800198 @Override
199 protected void onFinishInflate() {
200 super.onFinishInflate();
201
202 mAccountTypeManager = AccountTypeManager.getInstance(getContext());
203 mLayoutInflater = (LayoutInflater)
204 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
205
Walter Jang708ea9e2015-09-10 15:42:05 -0700206 // Account header
207 mAccountHeaderContainer = findViewById(R.id.account_container);
208 mAccountHeaderType = (TextView) findViewById(R.id.account_type);
209 mAccountHeaderName = (TextView) findViewById(R.id.account_name);
210
211 // Account selector
212 mAccountSelectorContainer = findViewById(R.id.account_selector_container);
213 mAccountSelector = findViewById(R.id.account);
214 mAccountSelectorType = (TextView) findViewById(R.id.account_type_selector);
215 mAccountSelectorName = (TextView) findViewById(R.id.account_name_selector);
216
Walter Janga5e4bb22015-02-24 13:08:16 -0800217 mPhoto = (CompactPhotoEditorView) findViewById(R.id.photo_editor);
Walter Jangcab3dce2015-02-09 17:48:03 -0800218 mNames = (LinearLayout) findViewById(R.id.names);
Walter Jangb1c87622015-02-13 17:51:38 -0800219 mPhoneticNames = (LinearLayout) findViewById(R.id.phonetic_names);
220 mNicknames = (LinearLayout) findViewById(R.id.nicknames);
Walter Jangcab3dce2015-02-09 17:48:03 -0800221 mPhoneNumbers = (LinearLayout) findViewById(R.id.phone_numbers);
222 mEmails = (LinearLayout) findViewById(R.id.emails);
Walter Jang995bb4a2015-07-06 12:21:36 -0700223 mOtherTypes = (LinearLayout) findViewById(R.id.other);
Walter Jangb6ca2722015-02-20 11:10:25 -0800224 mMoreFields = findViewById(R.id.more_fields);
225 mMoreFields.setOnClickListener(this);
226 }
227
Walter Jangb6ca2722015-02-20 11:10:25 -0800228 @Override
229 public void onClick(View view) {
230 if (view.getId() == R.id.more_fields && mListener != null ) {
231 mListener.onExpandEditor();
232 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800233 }
234
235 @Override
236 public void setEnabled(boolean enabled) {
237 super.setEnabled(enabled);
238 setEnabled(enabled, mNames);
Walter Jangb1c87622015-02-13 17:51:38 -0800239 setEnabled(enabled, mPhoneticNames);
240 setEnabled(enabled, mNicknames);
Walter Jangcab3dce2015-02-09 17:48:03 -0800241 setEnabled(enabled, mPhoneNumbers);
242 setEnabled(enabled, mEmails);
Walter Jang995bb4a2015-07-06 12:21:36 -0700243 for (Map.Entry<String,LinearLayout> otherType : mOtherTypesMap.entrySet()) {
244 setEnabled(enabled, otherType.getValue());
Walter Jang19d985f2015-07-01 13:36:27 -0700245 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800246 }
247
248 private void setEnabled(boolean enabled, ViewGroup viewGroup) {
249 if (viewGroup != null) {
250 final int childCount = viewGroup.getChildCount();
251 for (int i = 0; i < childCount; i++) {
252 viewGroup.getChildAt(i).setEnabled(enabled);
253 }
254 }
255 }
256
Walter Jang3efae4a2015-02-18 11:12:00 -0800257 /**
Walter Janga5e4bb22015-02-24 13:08:16 -0800258 * Pass through to {@link CompactPhotoEditorView#setPhotoHandler}.
Walter Jang3efae4a2015-02-18 11:12:00 -0800259 */
260 public void setPhotoHandler(PhotoHandler photoHandler) {
Walter Janga5e4bb22015-02-24 13:08:16 -0800261 mPhoto.setPhotoHandler(photoHandler);
Walter Jang3efae4a2015-02-18 11:12:00 -0800262 }
263
264 /**
Walter Janga5e4bb22015-02-24 13:08:16 -0800265 * Pass through to {@link CompactPhotoEditorView#setPhoto}.
Walter Jang3efae4a2015-02-18 11:12:00 -0800266 */
267 public void setPhoto(Bitmap bitmap) {
Walter Janga5e4bb22015-02-24 13:08:16 -0800268 mPhoto.setPhoto(bitmap);
Walter Jang3efae4a2015-02-18 11:12:00 -0800269 }
270
271 /**
Walter Jang41b3ea12015-03-09 17:30:06 -0700272 * Pass through to {@link CompactPhotoEditorView#setFullSizedPhoto(Uri)}.
273 */
274 public void setFullSizePhoto(Uri photoUri) {
275 mPhoto.setFullSizedPhoto(photoUri);
276 }
277
278 /**
Walter Janga5e4bb22015-02-24 13:08:16 -0800279 * Pass through to {@link CompactPhotoEditorView#isWritablePhotoSet}.
Walter Jang3efae4a2015-02-18 11:12:00 -0800280 */
281 public boolean isWritablePhotoSet() {
Walter Janga5e4bb22015-02-24 13:08:16 -0800282 return mPhoto.isWritablePhotoSet();
Walter Jang3efae4a2015-02-18 11:12:00 -0800283 }
284
285 /**
Walter Jang3efae4a2015-02-18 11:12:00 -0800286 * Get the raw contact ID for the CompactHeaderView photo.
287 */
Walter Jang3efae4a2015-02-18 11:12:00 -0800288 public long getPhotoRawContactId() {
289 return mPhotoRawContactId;
290 }
291
Walter Jang06f73a12015-06-17 11:15:48 -0700292 public StructuredNameEditorView getDefaultNameEditorView() {
293 return mDefaultNameEditorView;
294 }
295
Walter Jangd35e5ef2015-02-24 09:18:16 -0800296 public StructuredNameEditorView getStructuredNameEditorView() {
297 // We only ever show one StructuredName
298 return mNames.getChildCount() == 0
299 ? null : (StructuredNameEditorView) mNames.getChildAt(0);
300 }
301
Walter Jangbf63a6d2015-05-05 09:14:35 -0700302 public PhoneticNameEditorView getFirstPhoneticNameEditorView() {
303 // There should only ever be one phonetic name
304 return mPhoneticNames.getChildCount() == 0
305 ? null : (PhoneticNameEditorView) mPhoneticNames.getChildAt(0);
306 }
307
Walter Jangd35e5ef2015-02-24 09:18:16 -0800308 public View getAggregationAnchorView() {
309 // Since there is only one structured name we can just return it as the anchor for
310 // the aggregation suggestions popup
311 if (mNames.getChildCount() == 0) {
312 return null;
313 }
314 return mNames.getChildAt(0).findViewById(R.id.anchor_view);
315 }
316
Walter Jang06f73a12015-06-17 11:15:48 -0700317 /**
318 * @param readOnlyDisplayName The display name to set on the new raw contact created in order
319 * to edit a read-only contact.
320 */
Walter Jangf46abd82015-02-20 16:52:04 -0800321 public void setState(RawContactDeltaList rawContactDeltas,
Walter Jang06f73a12015-06-17 11:15:48 -0700322 MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
Walter Jang2d3f31c2015-06-18 23:15:31 -0700323 long photoId, long nameId, String readOnlyDisplayName, boolean hasNewContact,
Walter Jang708ea9e2015-09-10 15:42:05 -0700324 boolean isUserProfile, AccountWithDataSet primaryAccount) {
Walter Jang363d3fd2015-09-16 10:29:07 -0700325 mKindSectionDataMap.clear();
326
Walter Jangcab3dce2015-02-09 17:48:03 -0800327 mNames.removeAllViews();
Walter Jangb1c87622015-02-13 17:51:38 -0800328 mPhoneticNames.removeAllViews();
329 mNicknames.removeAllViews();
Walter Jangcab3dce2015-02-09 17:48:03 -0800330 mPhoneNumbers.removeAllViews();
331 mEmails.removeAllViews();
Walter Jang995bb4a2015-07-06 12:21:36 -0700332 mOtherTypes.removeAllViews();
333 mOtherTypesMap.clear();
Walter Jang363d3fd2015-09-16 10:29:07 -0700334 mMoreFields.setVisibility(View.VISIBLE);
Walter Jangcab3dce2015-02-09 17:48:03 -0800335
336 if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
337 return;
338 }
339
340 mViewIdGenerator = viewIdGenerator;
Walter Jangcab3dce2015-02-09 17:48:03 -0800341 setId(mViewIdGenerator.getId(rawContactDeltas.get(0), /* dataKind =*/ null,
342 /* valuesDelta =*/ null, ViewIdGenerator.NO_VIEW_INDEX));
Walter Jangf46abd82015-02-20 16:52:04 -0800343 mMaterialPalette = materialPalette;
Walter Jang708ea9e2015-09-10 15:42:05 -0700344 mPhotoId = photoId;
345 mNameId = nameId;
346 mReadOnlyDisplayName = readOnlyDisplayName;
347 mHasNewContact = hasNewContact;
348 mIsUserProfile = isUserProfile;
349 mPrimaryAccount = primaryAccount;
350 if (mPrimaryAccount == null) {
351 mPrimaryAccount = ContactEditorUtils.getInstance(getContext()).getDefaultAccount();
352 }
353 vlog("state: primary " + mPrimaryAccount);
Walter Jangcab3dce2015-02-09 17:48:03 -0800354
Walter Jang708ea9e2015-09-10 15:42:05 -0700355 vlog("state: setting compact editor state from " + rawContactDeltas);
356 parseRawContactDeltas(rawContactDeltas);
357 addAccountInfo();
Walter Jang363d3fd2015-09-16 10:29:07 -0700358 addPhotoView();
359 addStructuredNameView();
Walter Jang3efae4a2015-02-18 11:12:00 -0800360 addEditorViews(rawContactDeltas);
Walter Jang19d985f2015-07-01 13:36:27 -0700361 updateKindEditorEmptyFields(mPhoneNumbers);
362 updateKindEditorIcons(mPhoneNumbers);
363 updateKindEditorEmptyFields(mEmails);
364 updateKindEditorIcons(mEmails);
Walter Jang995bb4a2015-07-06 12:21:36 -0700365 for (Map.Entry<String,LinearLayout> otherTypes : mOtherTypesMap.entrySet()) {
366 updateKindEditorIcons(otherTypes.getValue());
Walter Jang19d985f2015-07-01 13:36:27 -0700367 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800368 }
369
Walter Jang708ea9e2015-09-10 15:42:05 -0700370 private void parseRawContactDeltas(RawContactDeltaList rawContactDeltas) {
371 // Get the raw contact delta for the primary account (the one displayed at the top)
Walter Jang03cea2e2015-09-18 17:04:21 -0700372 if (mPrimaryAccount == null || TextUtils.isEmpty(mPrimaryAccount.name)
373 || !TextUtils.isEmpty(mReadOnlyDisplayName)) {
374 // Use the first writable contact if this is an insert for a read-only contact.
375 // In this case we can assume the first writable raw contact is the newly created one
376 // because inserts have a raw contact delta list of size 1 and read-only contacts have
377 // a list of size 2.
Walter Jang708ea9e2015-09-10 15:42:05 -0700378 for (RawContactDelta rawContactDelta : rawContactDeltas) {
379 if (!rawContactDelta.isVisible()) continue;
380 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
381 if (accountType != null && accountType.areContactsWritable()) {
382 vlog("parse: using first writable raw contact as primary");
383 mPrimaryRawContactDelta = rawContactDelta;
384 break;
385 }
386 }
387 } else {
388 // Use the first writable contact that matches the primary account
389 for (RawContactDelta rawContactDelta : rawContactDeltas) {
390 if (!rawContactDelta.isVisible()) continue;
391 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
392 if (accountType != null && accountType.areContactsWritable()
393 && Objects.equals(mPrimaryAccount.name, rawContactDelta.getAccountName())
394 && Objects.equals(mPrimaryAccount.type, rawContactDelta.getAccountType())
395 && Objects.equals(mPrimaryAccount.dataSet, rawContactDelta.getDataSet())) {
396 vlog("parse: matched the primary account raw contact");
397 mPrimaryRawContactDelta = rawContactDelta;
398 break;
399 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700400 }
401 }
Walter Jang708ea9e2015-09-10 15:42:05 -0700402 if (mPrimaryRawContactDelta == null) {
403 // Fall back to the first writable raw contact
404 for (RawContactDelta rawContactDelta : rawContactDeltas) {
405 if (!rawContactDelta.isVisible()) continue;
406 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
407 if (accountType != null && accountType.areContactsWritable()) {
408 vlog("parse: falling back to the first writable raw contact as primary");
409 mPrimaryRawContactDelta = rawContactDelta;
410 break;
411 }
412 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700413 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700414
Walter Jang363d3fd2015-09-16 10:29:07 -0700415 RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
416 mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
417 StructuredName.CONTENT_ITEM_TYPE);
Walter Jangfa127a12015-06-18 09:48:18 -0700418
Walter Jang363d3fd2015-09-16 10:29:07 -0700419 RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
420 mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
421 Photo.CONTENT_ITEM_TYPE);
Walter Jangfa127a12015-06-18 09:48:18 -0700422
Walter Jang363d3fd2015-09-16 10:29:07 -0700423 // Build the kind section data list map
Walter Jangcab3dce2015-02-09 17:48:03 -0800424 for (RawContactDelta rawContactDelta : rawContactDeltas) {
Walter Jang363d3fd2015-09-16 10:29:07 -0700425 if (rawContactDelta == null || !rawContactDelta.isVisible()) continue;
Walter Jangcab3dce2015-02-09 17:48:03 -0800426 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
Walter Jang363d3fd2015-09-16 10:29:07 -0700427 if (accountType == null) continue;
428 final List<DataKind> dataKinds = accountType.getSortedDataKinds();
429 final int dataKindSize = dataKinds == null ? 0 : dataKinds.size();
430 vlog("parse: " + dataKindSize + " dataKinds(s)");
431 for (int i = 0; i < dataKindSize; i++) {
432 final DataKind dataKind = dataKinds.get(i);
433 // Don't show read only values
434 if (dataKind == null || !dataKind.editable) continue;
435 // Get the kind section data list to add the new field to
436 List<KindSectionData> kindSectionDataList =
437 mKindSectionDataMap.get(dataKind.mimeType);
438 if (kindSectionDataList == null) {
439 kindSectionDataList = new ArrayList<>();
440 mKindSectionDataMap.put(dataKind.mimeType, kindSectionDataList);
Walter Jangac679af2015-06-01 12:17:06 -0700441 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700442 final KindSectionData kindSectionData =
443 new KindSectionData(accountType, dataKind, rawContactDelta);
444 kindSectionDataList.add(kindSectionData);
445 vlog("parse: " + i + " " + dataKind.mimeType + " " +
446 (kindSectionData.hasValuesDeltas()
447 ? kindSectionData.getValuesDeltas().size() : null) + " value(s)");
Walter Jangac679af2015-06-01 12:17:06 -0700448 }
449 }
Walter Jang3efae4a2015-02-18 11:12:00 -0800450 }
451
Walter Jang708ea9e2015-09-10 15:42:05 -0700452 private void addAccountInfo() {
453 if (mPrimaryRawContactDelta == null) {
Walter Jang708ea9e2015-09-10 15:42:05 -0700454 mAccountHeaderContainer.setVisibility(View.GONE);
455 mAccountSelectorContainer.setVisibility(View.GONE);
456 return;
457 }
458
459 // Get the account information for the primary raw contact delta
460 final Pair<String,String> accountInfo = EditorUiUtils.getAccountInfo(getContext(),
461 mIsUserProfile, mPrimaryRawContactDelta.getAccountName(),
462 mPrimaryRawContactDelta.getAccountType(mAccountTypeManager));
463
464 // The account header and selector show the same information so both shouldn't be visible
465 // at the same time
466 final List<AccountWithDataSet> accounts =
467 AccountTypeManager.getInstance(getContext()).getAccounts(true);
468 if (mHasNewContact && !mIsUserProfile && accounts.size() > 1) {
469 mAccountHeaderContainer.setVisibility(View.GONE);
470 addAccountSelector(accountInfo);
471 } else {
472 addAccountHeader(accountInfo);
473 mAccountSelectorContainer.setVisibility(View.GONE);
474 }
475 }
476
477 private void addAccountHeader(Pair<String,String> accountInfo) {
Walter Jang03cea2e2015-09-18 17:04:21 -0700478 if (TextUtils.isEmpty(accountInfo.first)) {
Walter Jang708ea9e2015-09-10 15:42:05 -0700479 // Hide this view so the other text view will be centered vertically
480 mAccountHeaderName.setVisibility(View.GONE);
481 } else {
482 mAccountHeaderName.setVisibility(View.VISIBLE);
483 mAccountHeaderName.setText(accountInfo.first);
484 }
485 mAccountHeaderType.setText(accountInfo.second);
486
487 mAccountHeaderContainer.setContentDescription(
488 EditorUiUtils.getAccountInfoContentDescription(
489 accountInfo.first, accountInfo.second));
490 }
491
492 private void addAccountSelector(Pair<String,String> accountInfo) {
493 mAccountSelectorContainer.setVisibility(View.VISIBLE);
494
Walter Jang03cea2e2015-09-18 17:04:21 -0700495 if (TextUtils.isEmpty(accountInfo.first)) {
Walter Jang708ea9e2015-09-10 15:42:05 -0700496 // Hide this view so the other text view will be centered vertically
497 mAccountSelectorName.setVisibility(View.GONE);
498 } else {
499 mAccountSelectorName.setVisibility(View.VISIBLE);
500 mAccountSelectorName.setText(accountInfo.first);
501 }
502 mAccountSelectorType.setText(accountInfo.second);
503
504 mAccountSelectorContainer.setContentDescription(
505 EditorUiUtils.getAccountInfoContentDescription(
506 accountInfo.first, accountInfo.second));
507
508 mAccountSelector.setOnClickListener(new View.OnClickListener() {
509 @Override
510 public void onClick(View v) {
511 final ListPopupWindow popup = new ListPopupWindow(getContext(), null);
512 final AccountsListAdapter adapter =
513 new AccountsListAdapter(getContext(),
514 AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
515 mPrimaryAccount);
516 popup.setWidth(mAccountSelectorContainer.getWidth());
517 popup.setAnchorView(mAccountSelectorContainer);
518 popup.setAdapter(adapter);
519 popup.setModal(true);
520 popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
521 popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
522 @Override
523 public void onItemClick(AdapterView<?> parent, View view, int position,
524 long id) {
525 UiClosables.closeQuietly(popup);
526 final AccountWithDataSet newAccount = adapter.getItem(position);
527 if (mListener != null && !mPrimaryAccount.equals(newAccount)) {
528 mListener.onRebindEditorsForNewContact(
529 mPrimaryRawContactDelta,
530 mPrimaryAccount,
531 newAccount);
532 }
533 }
534 });
535 popup.show();
536 }
537 });
538 }
539
Walter Jang363d3fd2015-09-16 10:29:07 -0700540 private void addPhotoView() {
541 // Get the kind section data and values delta that will back the photo view
542 final String mimeType = Photo.CONTENT_ITEM_TYPE;
543 Pair<KindSectionData,ValuesDelta> pair = getPrimaryKindSectionData(mimeType, mPhotoId);
544 if (pair == null) {
545 wlog(mimeType + ": no kind section data parsed");
546 return;
547 }
548 final KindSectionData kindSectionData = pair.first;
549 final ValuesDelta valuesDelta = pair.second;
Walter Jang06f73a12015-06-17 11:15:48 -0700550
Walter Jang363d3fd2015-09-16 10:29:07 -0700551 // If we're editing a read-only contact we want to display the photo from the
552 // read-only contact in a photo editor backed by the new raw contact
553 // that was created. The new raw contact is the first writable one.
554 // See go/editing-read-only-contacts
555 if (mReadOnlyDisplayName != null) {
556 mPhotoRawContactId = mPrimaryRawContactDelta.getRawContactId();
557 }
Walter Jang06f73a12015-06-17 11:15:48 -0700558
Walter Jang363d3fd2015-09-16 10:29:07 -0700559 mPhotoRawContactId = kindSectionData.getRawContactDelta().getRawContactId();
560 mPhoto.setValues(kindSectionData.getDataKind(), valuesDelta,
561 kindSectionData.getRawContactDelta(),
562 !kindSectionData.getAccountType().areContactsWritable(), mMaterialPalette,
563 mViewIdGenerator);
564 }
565
566 private void addStructuredNameView() {
567 // Get the kind section data and values delta that will back the name view
568 final String mimeType = StructuredName.CONTENT_ITEM_TYPE;
569 Pair<KindSectionData,ValuesDelta> pair = getPrimaryKindSectionData(mimeType, mNameId);
570 if (pair == null) {
571 wlog(mimeType + ": no kind section data parsed");
572 return;
573 }
574 final KindSectionData kindSectionData = pair.first;
575 final ValuesDelta valuesDelta = pair.second;
576
577 // If we're editing a read-only contact we want to display the name from the
578 // read-only contact in the name editor backed by the new raw contact
579 // that was created. The new raw contact is the first writable one.
580 // See go/editing-read-only-contacts
581 // TODO
582 if (!TextUtils.isEmpty(mReadOnlyDisplayName)) {
583 for (KindSectionData data : mKindSectionDataMap.get(mimeType)) {
584 if (data.getAccountType().areContactsWritable()) {
585 vlog(mimeType + ": using name from read-only contact");
586 mUsingDefaultNameEditorView = true;
587 break;
Walter Jang06f73a12015-06-17 11:15:48 -0700588 }
589 }
590 }
591
Walter Jang363d3fd2015-09-16 10:29:07 -0700592 final NameEditorListener nameEditorListener = new NameEditorListener(valuesDelta,
593 kindSectionData.getRawContactDelta().getRawContactId(), mListener);
594 final StructuredNameEditorView nameEditorView = inflateStructuredNameEditorView(
595 mNames, kindSectionData.getAccountType(), valuesDelta,
596 kindSectionData.getRawContactDelta(), nameEditorListener,
597 !kindSectionData.getAccountType().areContactsWritable());
598 mNames.addView(nameEditorView);
Walter Jang10446452015-02-20 13:51:16 -0800599
Walter Jang363d3fd2015-09-16 10:29:07 -0700600 // TODO: Remove this after eliminating the full editor
601 mNameValuesDelta = valuesDelta;
602 if (mUsingDefaultNameEditorView) {
603 mDefaultNameEditorView = nameEditorView;
604 }
605 }
Walter Jang10446452015-02-20 13:51:16 -0800606
Walter Jang363d3fd2015-09-16 10:29:07 -0700607 private Pair<KindSectionData,ValuesDelta> getPrimaryKindSectionData(String mimeType, long id) {
608 final List<KindSectionData> kindSectionDataList = mKindSectionDataMap.get(mimeType);
609 if (kindSectionDataList == null || kindSectionDataList.isEmpty()) {
610 wlog(mimeType + ": no kind section data parsed");
611 return null;
612 }
Walter Jang151f3e62015-02-26 15:29:40 -0800613
Walter Jang363d3fd2015-09-16 10:29:07 -0700614 KindSectionData resultKindSectionData = null;
615 ValuesDelta resultValuesDelta = null;
616 if (id > 0) {
617 // Look for a match for the ID that was passed in
618 for (KindSectionData kindSectionData : kindSectionDataList) {
619 resultValuesDelta = kindSectionData.getValuesDeltaById(id);
620 if (resultValuesDelta != null) {
621 vlog(mimeType + ": matched kind section data by ID");
622 resultKindSectionData = kindSectionData;
623 break;
Walter Jang398cd4b2015-06-16 11:17:53 -0700624 }
625 }
626 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700627 if (resultKindSectionData == null) {
628 // Look for a super primary photo
629 for (KindSectionData kindSectionData : kindSectionDataList) {
630 resultValuesDelta = kindSectionData.getSuperPrimaryValuesDelta();
631 if (resultValuesDelta != null) {
632 wlog(mimeType + ": matched super primary kind section data");
633 resultKindSectionData = kindSectionData;
634 break;
635 }
Walter Jang151f3e62015-02-26 15:29:40 -0800636 }
637 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700638 if (resultKindSectionData == null) {
639 // Fall back to the first non-empty value
640 for (KindSectionData kindSectionData : kindSectionDataList) {
641 resultValuesDelta = kindSectionData.getFirstNonEmptyValuesDelta();
642 if (resultValuesDelta != null) {
643 vlog(mimeType + ": using first non empty value");
644 resultKindSectionData = kindSectionData;
645 break;
646 }
Walter Jang151f3e62015-02-26 15:29:40 -0800647 }
648 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700649 if (resultKindSectionData == null || resultValuesDelta == null) {
650 final List<ValuesDelta> valuesDeltaList = kindSectionDataList.get(0).getValuesDeltas();
651 if (valuesDeltaList != null && !valuesDeltaList.isEmpty()) {
652 vlog(mimeType + ": falling back to first empty entry");
653 resultValuesDelta = valuesDeltaList.get(0);
654 resultKindSectionData = kindSectionDataList.get(0);
Walter Jang10446452015-02-20 13:51:16 -0800655 }
656 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700657 return resultKindSectionData != null && resultValuesDelta != null
658 ? new Pair<>(resultKindSectionData, resultValuesDelta) : null;
Walter Jang10446452015-02-20 13:51:16 -0800659 }
660
Walter Jang3efae4a2015-02-18 11:12:00 -0800661 private void addEditorViews(RawContactDeltaList rawContactDeltas) {
662 for (RawContactDelta rawContactDelta : rawContactDeltas) {
Walter Jangab50e6f2015-06-15 08:57:22 -0700663 if (!rawContactDelta.isVisible()) continue;
Walter Jang3efae4a2015-02-18 11:12:00 -0800664 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
665
Walter Jangcab3dce2015-02-09 17:48:03 -0800666 for (DataKind dataKind : accountType.getSortedDataKinds()) {
Walter Jangab50e6f2015-06-15 08:57:22 -0700667 if (!dataKind.editable) continue;
668
Walter Jangcab3dce2015-02-09 17:48:03 -0800669 final String mimeType = dataKind.mimeType;
Walter Jangbf63a6d2015-05-05 09:14:35 -0700670 vlog(mimeType + " " + dataKind.fieldList.size() + " field(s)");
Walter Jangcab3dce2015-02-09 17:48:03 -0800671 if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)
Walter Jang10446452015-02-20 13:51:16 -0800672 || StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)
Walter Jangcab3dce2015-02-09 17:48:03 -0800673 || GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang151f3e62015-02-26 15:29:40 -0800674 // Photos and structured names are handled separately and
675 // group membership is not supported
Walter Jangcab3dce2015-02-09 17:48:03 -0800676 continue;
Walter Jangcab3dce2015-02-09 17:48:03 -0800677 } else if (DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
Walter Jang151f3e62015-02-26 15:29:40 -0800678 // Only add phonetic names if there is a non-empty one. Note the use of
679 // StructuredName mimeType below, even though we matched a pseudo mime type.
Walter Jang3a37a1a2015-03-04 07:41:32 -0800680 final ValuesDelta valuesDelta = rawContactDelta.getSuperPrimaryEntry(
681 StructuredName.CONTENT_ITEM_TYPE, /* forceSelection =*/ true);
682 if (hasNonEmptyValue(dataKind, valuesDelta)) {
683 mPhoneticNames.addView(inflatePhoneticNameEditorView(
684 mPhoneticNames, accountType, valuesDelta, rawContactDelta));
Walter Jangcab3dce2015-02-09 17:48:03 -0800685 }
686 } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang995bb4a2015-07-06 12:21:36 -0700687 // Add all non-empty nicknames
688 final List<ValuesDelta> valuesDeltas = getNonEmptyValuesDeltas(
689 rawContactDelta, Nickname.CONTENT_ITEM_TYPE, dataKind);
690 if (valuesDeltas != null && !valuesDeltas.isEmpty()) {
Walter Jangae9c9ec2015-07-07 16:10:41 -0700691 for (ValuesDelta valuesDelta : valuesDeltas) {
Walter Jang995bb4a2015-07-06 12:21:36 -0700692 mNicknames.addView(inflateNicknameEditorView(
693 mNicknames, dataKind, valuesDelta, rawContactDelta));
694 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800695 }
696 } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang4a9351d2015-06-30 14:09:10 -0700697 final KindSectionView kindSectionView =
698 inflateKindSectionView(mPhoneNumbers, dataKind, rawContactDelta);
699 kindSectionView.setListener(new KindSectionView.Listener() {
700 @Override
Walter Jang995bb4a2015-07-06 12:21:36 -0700701 public void onDeleteRequested(Editor editor) {
702 if (kindSectionView.getEditorCount() == 1) {
703 kindSectionView.markForRemoval();
704 EditorAnimator.getInstance().removeEditorView(kindSectionView);
705 } else {
706 editor.deleteEditor();
707 }
Walter Jang19d985f2015-07-01 13:36:27 -0700708 updateKindEditorEmptyFields(mPhoneNumbers);
709 updateKindEditorIcons(mPhoneNumbers);
Walter Jang4a9351d2015-06-30 14:09:10 -0700710 }
711 });
712 mPhoneNumbers.addView(kindSectionView);
Walter Jangcab3dce2015-02-09 17:48:03 -0800713 } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
Walter Jang4a9351d2015-06-30 14:09:10 -0700714 final KindSectionView kindSectionView =
715 inflateKindSectionView(mEmails, dataKind, rawContactDelta);
716 kindSectionView.setListener(new KindSectionView.Listener() {
717 @Override
Walter Jang995bb4a2015-07-06 12:21:36 -0700718 public void onDeleteRequested(Editor editor) {
719 if (kindSectionView.getEditorCount() == 1) {
720 kindSectionView.markForRemoval();
721 EditorAnimator.getInstance().removeEditorView(kindSectionView);
722 } else {
723 editor.deleteEditor();
724 }
Walter Jang19d985f2015-07-01 13:36:27 -0700725 updateKindEditorEmptyFields(mEmails);
726 updateKindEditorIcons(mEmails);
Walter Jang4a9351d2015-06-30 14:09:10 -0700727 }
728 });
729 mEmails.addView(kindSectionView);
Walter Jangcab3dce2015-02-09 17:48:03 -0800730 } else if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
Walter Jang995bb4a2015-07-06 12:21:36 -0700731 final LinearLayout otherTypeViewGroup;
732 if (mOtherTypesMap.containsKey(mimeType)) {
733 otherTypeViewGroup = mOtherTypesMap.get(mimeType);
Walter Jang19d985f2015-07-01 13:36:27 -0700734 } else {
Walter Jang995bb4a2015-07-06 12:21:36 -0700735 otherTypeViewGroup = new LinearLayout(getContext());
736 otherTypeViewGroup.setOrientation(LinearLayout.VERTICAL);
737 mOtherTypes.addView(otherTypeViewGroup);
738 mOtherTypesMap.put(mimeType, otherTypeViewGroup);
Walter Jang19d985f2015-07-01 13:36:27 -0700739 }
740 final KindSectionView kindSectionView =
Walter Jang995bb4a2015-07-06 12:21:36 -0700741 inflateKindSectionView(mOtherTypes, dataKind, rawContactDelta);
Walter Jang19d985f2015-07-01 13:36:27 -0700742 kindSectionView.setListener(new KindSectionView.Listener() {
743 @Override
Walter Jang995bb4a2015-07-06 12:21:36 -0700744 public void onDeleteRequested(Editor editor) {
745 if (kindSectionView.getEditorCount() == 1) {
746 kindSectionView.markForRemoval();
747 EditorAnimator.getInstance().removeEditorView(kindSectionView);
748 } else {
749 editor.deleteEditor();
Walter Jang19d985f2015-07-01 13:36:27 -0700750 }
Walter Jang995bb4a2015-07-06 12:21:36 -0700751 updateKindEditorIcons(otherTypeViewGroup);
Walter Jang19d985f2015-07-01 13:36:27 -0700752 }
753 });
Walter Jang995bb4a2015-07-06 12:21:36 -0700754 otherTypeViewGroup.addView(kindSectionView);
Walter Jangcab3dce2015-02-09 17:48:03 -0800755 }
756 }
757 }
758 }
759
Walter Jang19d985f2015-07-01 13:36:27 -0700760 private static void updateKindEditorEmptyFields(ViewGroup viewGroup) {
761 KindSectionView lastVisibleKindSectionView = null;
762 for (int i = 0; i < viewGroup.getChildCount(); i++) {
763 if (viewGroup.getChildAt(i).getVisibility() == View.VISIBLE) {
764 lastVisibleKindSectionView = (KindSectionView) viewGroup.getChildAt(i);
Walter Jangb1c87622015-02-13 17:51:38 -0800765 }
Walter Jang4a9351d2015-06-30 14:09:10 -0700766 }
Walter Jang19d985f2015-07-01 13:36:27 -0700767 // Only the last editor should show an empty editor
768 if (lastVisibleKindSectionView != null) {
Walter Jangae9c9ec2015-07-07 16:10:41 -0700769 // Hide all empty kind sections except the last one
770 for (int i = 0; i < viewGroup.getChildCount(); i++) {
771 final KindSectionView kindSectionView = (KindSectionView) viewGroup.getChildAt(i);
772 if (kindSectionView != lastVisibleKindSectionView
773 && kindSectionView.areAllEditorsEmpty()) {
774 kindSectionView.setVisibility(View.GONE);
775 }
776 }
777 // Set the last editor to show empty editor fields
Walter Jang19d985f2015-07-01 13:36:27 -0700778 lastVisibleKindSectionView.setShowOneEmptyEditor(true);
779 lastVisibleKindSectionView.updateEmptyEditors(/* shouldAnimate =*/ false);
780 }
781 }
Walter Jang4a9351d2015-06-30 14:09:10 -0700782
Walter Jang19d985f2015-07-01 13:36:27 -0700783 private static void updateKindEditorIcons(ViewGroup viewGroup) {
Walter Jang4a9351d2015-06-30 14:09:10 -0700784 // Show the icon on the first visible kind editor
785 boolean iconVisible = false;
786 for (int i = 0; i < viewGroup.getChildCount(); i++) {
787 final KindSectionView kindSectionView = (KindSectionView) viewGroup.getChildAt(i);
Walter Jang995bb4a2015-07-06 12:21:36 -0700788 if (kindSectionView.getVisibility() != View.VISIBLE
789 || kindSectionView.isMarkedForRemoval()) {
Walter Jang4a9351d2015-06-30 14:09:10 -0700790 continue;
791 }
792 if (!iconVisible) {
793 kindSectionView.setIconVisibility(true);
794 iconVisible = true;
795 } else {
796 kindSectionView.setIconVisibility(false);
Walter Jangb1c87622015-02-13 17:51:38 -0800797 }
798 }
799 }
800
Walter Jangcab3dce2015-02-09 17:48:03 -0800801 private static boolean hasNonEmptyValuesDelta(RawContactDelta rawContactDelta,
802 String mimeType, DataKind dataKind) {
803 return !getNonEmptyValuesDeltas(rawContactDelta, mimeType, dataKind).isEmpty();
804 }
805
Walter Jang151f3e62015-02-26 15:29:40 -0800806 private static ValuesDelta getNonEmptySuperPrimaryValuesDeltas(RawContactDelta rawContactDelta,
807 String mimeType, DataKind dataKind) {
808 for (ValuesDelta valuesDelta : getNonEmptyValuesDeltas(
809 rawContactDelta, mimeType, dataKind)) {
810 if (valuesDelta.isSuperPrimary()) {
811 return valuesDelta;
812 }
813 }
814 return null;
815 }
816
817 static List<ValuesDelta> getNonEmptyValuesDeltas(RawContactDelta rawContactDelta,
Walter Jangcab3dce2015-02-09 17:48:03 -0800818 String mimeType, DataKind dataKind) {
819 final List<ValuesDelta> result = new ArrayList<>();
820 if (rawContactDelta == null) {
Walter Jangbf63a6d2015-05-05 09:14:35 -0700821 vlog("Null RawContactDelta");
Walter Jangcab3dce2015-02-09 17:48:03 -0800822 return result;
823 }
824 if (!rawContactDelta.hasMimeEntries(mimeType)) {
Walter Jangbf63a6d2015-05-05 09:14:35 -0700825 vlog("No ValueDeltas");
Walter Jangcab3dce2015-02-09 17:48:03 -0800826 return result;
827 }
828 for (ValuesDelta valuesDelta : rawContactDelta.getMimeEntries(mimeType)) {
Walter Jang3a37a1a2015-03-04 07:41:32 -0800829 if (hasNonEmptyValue(dataKind, valuesDelta)) {
830 result.add(valuesDelta);
Walter Jangcab3dce2015-02-09 17:48:03 -0800831 }
832 }
833 return result;
834 }
835
Walter Jang3a37a1a2015-03-04 07:41:32 -0800836 private static boolean hasNonEmptyValue(DataKind dataKind, ValuesDelta valuesDelta) {
837 if (valuesDelta == null) {
Walter Jangbf63a6d2015-05-05 09:14:35 -0700838 vlog("Null valuesDelta");
Walter Jang3a37a1a2015-03-04 07:41:32 -0800839 return false;
840 }
841 for (EditField editField : dataKind.fieldList) {
842 final String column = editField.column;
843 final String value = valuesDelta == null ? null : valuesDelta.getAsString(column);
Walter Jangbf63a6d2015-05-05 09:14:35 -0700844 vlog("Field " + column + " empty=" + TextUtils.isEmpty(value) + " value=" + value);
Walter Jang3a37a1a2015-03-04 07:41:32 -0800845 if (!TextUtils.isEmpty(value)) {
846 return true;
847 }
848 }
849 return false;
850 }
851
Walter Jangcab3dce2015-02-09 17:48:03 -0800852 private StructuredNameEditorView inflateStructuredNameEditorView(ViewGroup viewGroup,
Walter Jang151f3e62015-02-26 15:29:40 -0800853 AccountType accountType, ValuesDelta valuesDelta, RawContactDelta rawContactDelta,
Walter Jang65d35202015-06-16 13:08:34 -0700854 NameEditorListener nameEditorListener, boolean readOnly) {
Walter Jangcab3dce2015-02-09 17:48:03 -0800855 final StructuredNameEditorView result = (StructuredNameEditorView) mLayoutInflater.inflate(
856 R.layout.structured_name_editor_view, viewGroup, /* attachToRoot =*/ false);
Walter Jang151f3e62015-02-26 15:29:40 -0800857 if (nameEditorListener != null) {
858 result.setEditorListener(nameEditorListener);
859 }
Walter Jang3a37a1a2015-03-04 07:41:32 -0800860 result.setDeletable(false);
Walter Jangcab3dce2015-02-09 17:48:03 -0800861 result.setValues(
862 accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME),
863 valuesDelta,
864 rawContactDelta,
Walter Jang65d35202015-06-16 13:08:34 -0700865 readOnly,
Walter Jangcab3dce2015-02-09 17:48:03 -0800866 mViewIdGenerator);
867 return result;
868 }
869
870 private PhoneticNameEditorView inflatePhoneticNameEditorView(ViewGroup viewGroup,
871 AccountType accountType, ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
872 final PhoneticNameEditorView result = (PhoneticNameEditorView) mLayoutInflater.inflate(
873 R.layout.phonetic_name_editor_view, viewGroup, /* attachToRoot =*/ false);
Walter Jang3a37a1a2015-03-04 07:41:32 -0800874 result.setDeletable(false);
Walter Jangcab3dce2015-02-09 17:48:03 -0800875 result.setValues(
876 accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME),
877 valuesDelta,
878 rawContactDelta,
879 /* readOnly =*/ false,
880 mViewIdGenerator);
881 return result;
882 }
883
Walter Jang995bb4a2015-07-06 12:21:36 -0700884 private TextFieldsEditorView inflateNicknameEditorView(ViewGroup viewGroup, DataKind dataKind,
885 ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
886 final TextFieldsEditorView result = (TextFieldsEditorView) mLayoutInflater.inflate(
887 R.layout.nick_name_editor_view, viewGroup, /* attachToRoot =*/ false);
888 result.setDeletable(false);
889 result.setValues(
890 dataKind,
891 valuesDelta,
892 rawContactDelta,
893 /* readOnly =*/ false,
894 mViewIdGenerator);
895 return result;
896 }
897
898
Walter Jangcab3dce2015-02-09 17:48:03 -0800899 private KindSectionView inflateKindSectionView(ViewGroup viewGroup, DataKind dataKind,
Walter Jang88b0a8c2015-06-08 13:15:56 -0700900 RawContactDelta rawContactDelta) {
Walter Jangcab3dce2015-02-09 17:48:03 -0800901 final KindSectionView result = (KindSectionView) mLayoutInflater.inflate(
902 R.layout.item_kind_section, viewGroup, /* attachToRoot =*/ false);
903 result.setState(
904 dataKind,
905 rawContactDelta,
906 /* readOnly =*/ false,
Walter Jangcab3dce2015-02-09 17:48:03 -0800907 mViewIdGenerator);
908 return result;
909 }
910
Walter Jangbf63a6d2015-05-05 09:14:35 -0700911 private static void vlog(String message) {
912 if (Log.isLoggable(TAG, Log.VERBOSE)) {
913 Log.v(TAG, message);
Walter Jangcab3dce2015-02-09 17:48:03 -0800914 }
915 }
Walter Jang363d3fd2015-09-16 10:29:07 -0700916
917 private static void wlog(String message) {
918 if (Log.isLoggable(TAG, Log.WARN)) {
919 Log.w(TAG, message);
920 }
921 }
922
923 private static void elog(String message) {
924 Log.e(TAG, message);
925 }
Walter Jangcab3dce2015-02-09 17:48:03 -0800926}