summaryrefslogtreecommitdiffstats
path: root/src/com/android/contacts/common/list/ContactListAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/contacts/common/list/ContactListAdapter.java')
-rw-r--r--src/com/android/contacts/common/list/ContactListAdapter.java362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/com/android/contacts/common/list/ContactListAdapter.java b/src/com/android/contacts/common/list/ContactListAdapter.java
new file mode 100644
index 00000000..1be48c42
--- /dev/null
+++ b/src/com/android/contacts/common/list/ContactListAdapter.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.common.list;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.ContactCounts;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.SearchSnippetColumns;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import com.android.contacts.common.R;
+
+/**
+ * A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type.
+ * Also includes support for including the {@link ContactsContract.Profile} record in the
+ * list.
+ */
+public abstract class ContactListAdapter extends ContactEntryListAdapter {
+
+ protected static class ContactQuery {
+ private static final String[] CONTACT_PROJECTION_PRIMARY = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_PRIMARY, // 1
+ Contacts.CONTACT_PRESENCE, // 2
+ Contacts.CONTACT_STATUS, // 3
+ Contacts.PHOTO_ID, // 4
+ Contacts.PHOTO_THUMBNAIL_URI, // 5
+ Contacts.LOOKUP_KEY, // 6
+ Contacts.IS_USER_PROFILE, // 7
+ };
+
+ private static final String[] CONTACT_PROJECTION_ALTERNATIVE = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_ALTERNATIVE, // 1
+ Contacts.CONTACT_PRESENCE, // 2
+ Contacts.CONTACT_STATUS, // 3
+ Contacts.PHOTO_ID, // 4
+ Contacts.PHOTO_THUMBNAIL_URI, // 5
+ Contacts.LOOKUP_KEY, // 6
+ Contacts.IS_USER_PROFILE, // 7
+ };
+
+ private static final String[] FILTER_PROJECTION_PRIMARY = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_PRIMARY, // 1
+ Contacts.CONTACT_PRESENCE, // 2
+ Contacts.CONTACT_STATUS, // 3
+ Contacts.PHOTO_ID, // 4
+ Contacts.PHOTO_THUMBNAIL_URI, // 5
+ Contacts.LOOKUP_KEY, // 6
+ Contacts.IS_USER_PROFILE, // 7
+ SearchSnippetColumns.SNIPPET, // 8
+ };
+
+ private static final String[] FILTER_PROJECTION_ALTERNATIVE = new String[] {
+ Contacts._ID, // 0
+ Contacts.DISPLAY_NAME_ALTERNATIVE, // 1
+ Contacts.CONTACT_PRESENCE, // 2
+ Contacts.CONTACT_STATUS, // 3
+ Contacts.PHOTO_ID, // 4
+ Contacts.PHOTO_THUMBNAIL_URI, // 5
+ Contacts.LOOKUP_KEY, // 6
+ Contacts.IS_USER_PROFILE, // 7
+ SearchSnippetColumns.SNIPPET, // 8
+ };
+
+ public static final int CONTACT_ID = 0;
+ public static final int CONTACT_DISPLAY_NAME = 1;
+ public static final int CONTACT_PRESENCE_STATUS = 2;
+ public static final int CONTACT_CONTACT_STATUS = 3;
+ public static final int CONTACT_PHOTO_ID = 4;
+ public static final int CONTACT_PHOTO_URI = 5;
+ public static final int CONTACT_LOOKUP_KEY = 6;
+ public static final int CONTACT_IS_USER_PROFILE = 7;
+ public static final int CONTACT_SNIPPET = 8;
+ }
+
+ private CharSequence mUnknownNameText;
+
+ private long mSelectedContactDirectoryId;
+ private String mSelectedContactLookupKey;
+ private long mSelectedContactId;
+
+ public ContactListAdapter(Context context) {
+ super(context);
+
+ mUnknownNameText = context.getText(R.string.missing_name);
+ }
+
+ public CharSequence getUnknownNameText() {
+ return mUnknownNameText;
+ }
+
+ public long getSelectedContactDirectoryId() {
+ return mSelectedContactDirectoryId;
+ }
+
+ public String getSelectedContactLookupKey() {
+ return mSelectedContactLookupKey;
+ }
+
+ public long getSelectedContactId() {
+ return mSelectedContactId;
+ }
+
+ public void setSelectedContact(long selectedDirectoryId, String lookupKey, long contactId) {
+ mSelectedContactDirectoryId = selectedDirectoryId;
+ mSelectedContactLookupKey = lookupKey;
+ mSelectedContactId = contactId;
+ }
+
+ protected static Uri buildSectionIndexerUri(Uri uri) {
+ return uri.buildUpon()
+ .appendQueryParameter(ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, "true").build();
+ }
+
+ @Override
+ public String getContactDisplayName(int position) {
+ return ((Cursor) getItem(position)).getString(ContactQuery.CONTACT_DISPLAY_NAME);
+ }
+
+ /**
+ * Builds the {@link Contacts#CONTENT_LOOKUP_URI} for the given
+ * {@link ListView} position.
+ */
+ public Uri getContactUri(int position) {
+ int partitionIndex = getPartitionForPosition(position);
+ Cursor item = (Cursor)getItem(position);
+ return item != null ? getContactUri(partitionIndex, item) : null;
+ }
+
+ public Uri getContactUri(int partitionIndex, Cursor cursor) {
+ long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
+ String lookupKey = cursor.getString(ContactQuery.CONTACT_LOOKUP_KEY);
+ Uri uri = Contacts.getLookupUri(contactId, lookupKey);
+ long directoryId = ((DirectoryPartition)getPartition(partitionIndex)).getDirectoryId();
+ if (directoryId != Directory.DEFAULT) {
+ uri = uri.buildUpon().appendQueryParameter(
+ ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
+ }
+ return uri;
+ }
+
+ /**
+ * Returns true if the specified contact is selected in the list. For a
+ * contact to be shown as selected, we need both the directory and and the
+ * lookup key to be the same. We are paying no attention to the contactId,
+ * because it is volatile, especially in the case of directories.
+ */
+ public boolean isSelectedContact(int partitionIndex, Cursor cursor) {
+ long directoryId = ((DirectoryPartition)getPartition(partitionIndex)).getDirectoryId();
+ if (getSelectedContactDirectoryId() != directoryId) {
+ return false;
+ }
+ String lookupKey = getSelectedContactLookupKey();
+ if (lookupKey != null && TextUtils.equals(lookupKey,
+ cursor.getString(ContactQuery.CONTACT_LOOKUP_KEY))) {
+ return true;
+ }
+
+ return directoryId != Directory.DEFAULT && directoryId != Directory.LOCAL_INVISIBLE
+ && getSelectedContactId() == cursor.getLong(ContactQuery.CONTACT_ID);
+ }
+
+ @Override
+ protected View newView(Context context, int partition, Cursor cursor, int position,
+ ViewGroup parent) {
+ ContactListItemView view = new ContactListItemView(context, null);
+ view.setUnknownNameText(mUnknownNameText);
+ view.setQuickContactEnabled(isQuickContactEnabled());
+ view.setActivatedStateSupported(isSelectionVisible());
+ return view;
+ }
+
+ protected void bindSectionHeaderAndDivider(ContactListItemView view, int position,
+ Cursor cursor) {
+ if (isSectionHeaderDisplayEnabled()) {
+ Placement placement = getItemPlacementInSection(position);
+
+ // First position, set the contacts number string
+ if (position == 0 && cursor.getInt(ContactQuery.CONTACT_IS_USER_PROFILE) == 1) {
+ view.setCountView(getContactsCount());
+ } else {
+ view.setCountView(null);
+ }
+ view.setSectionHeader(placement.sectionHeader);
+ view.setDividerVisible(!placement.lastInSection);
+ } else {
+ view.setSectionHeader(null);
+ view.setDividerVisible(true);
+ view.setCountView(null);
+ }
+ }
+
+ protected void bindPhoto(final ContactListItemView view, int partitionIndex, Cursor cursor) {
+ if (!isPhotoSupported(partitionIndex)) {
+ view.removePhotoView();
+ return;
+ }
+
+ // Set the photo, if available
+ long photoId = 0;
+ if (!cursor.isNull(ContactQuery.CONTACT_PHOTO_ID)) {
+ photoId = cursor.getLong(ContactQuery.CONTACT_PHOTO_ID);
+ }
+
+ if (photoId != 0) {
+ getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false);
+ } else {
+ final String photoUriString = cursor.getString(ContactQuery.CONTACT_PHOTO_URI);
+ final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
+ getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false);
+ }
+ }
+
+ protected void bindName(final ContactListItemView view, Cursor cursor) {
+ view.showDisplayName(
+ cursor, ContactQuery.CONTACT_DISPLAY_NAME, getContactNameDisplayOrder());
+ // Note: we don't show phonetic any more (See issue 5265330)
+ }
+
+ protected void bindPresenceAndStatusMessage(final ContactListItemView view, Cursor cursor) {
+ view.showPresenceAndStatusMessage(cursor, ContactQuery.CONTACT_PRESENCE_STATUS,
+ ContactQuery.CONTACT_CONTACT_STATUS);
+ }
+
+ protected void bindSearchSnippet(final ContactListItemView view, Cursor cursor) {
+ view.showSnippet(cursor, ContactQuery.CONTACT_SNIPPET);
+ }
+
+ public int getSelectedContactPosition() {
+ if (mSelectedContactLookupKey == null && mSelectedContactId == 0) {
+ return -1;
+ }
+
+ Cursor cursor = null;
+ int partitionIndex = -1;
+ int partitionCount = getPartitionCount();
+ for (int i = 0; i < partitionCount; i++) {
+ DirectoryPartition partition = (DirectoryPartition) getPartition(i);
+ if (partition.getDirectoryId() == mSelectedContactDirectoryId) {
+ partitionIndex = i;
+ break;
+ }
+ }
+ if (partitionIndex == -1) {
+ return -1;
+ }
+
+ cursor = getCursor(partitionIndex);
+ if (cursor == null) {
+ return -1;
+ }
+
+ cursor.moveToPosition(-1); // Reset cursor
+ int offset = -1;
+ while (cursor.moveToNext()) {
+ if (mSelectedContactLookupKey != null) {
+ String lookupKey = cursor.getString(ContactQuery.CONTACT_LOOKUP_KEY);
+ if (mSelectedContactLookupKey.equals(lookupKey)) {
+ offset = cursor.getPosition();
+ break;
+ }
+ }
+ if (mSelectedContactId != 0 && (mSelectedContactDirectoryId == Directory.DEFAULT
+ || mSelectedContactDirectoryId == Directory.LOCAL_INVISIBLE)) {
+ long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
+ if (contactId == mSelectedContactId) {
+ offset = cursor.getPosition();
+ break;
+ }
+ }
+ }
+ if (offset == -1) {
+ return -1;
+ }
+
+ int position = getPositionForPartition(partitionIndex) + offset;
+ if (hasHeader(partitionIndex)) {
+ position++;
+ }
+ return position;
+ }
+
+ public boolean hasValidSelection() {
+ return getSelectedContactPosition() != -1;
+ }
+
+ public Uri getFirstContactUri() {
+ int partitionCount = getPartitionCount();
+ for (int i = 0; i < partitionCount; i++) {
+ DirectoryPartition partition = (DirectoryPartition) getPartition(i);
+ if (partition.isLoading()) {
+ continue;
+ }
+
+ Cursor cursor = getCursor(i);
+ if (cursor == null) {
+ continue;
+ }
+
+ if (!cursor.moveToFirst()) {
+ continue;
+ }
+
+ return getContactUri(i, cursor);
+ }
+
+ return null;
+ }
+
+ @Override
+ public void changeCursor(int partitionIndex, Cursor cursor) {
+ super.changeCursor(partitionIndex, cursor);
+
+ // Check if a profile exists
+ if (cursor != null && cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ setProfileExists(cursor.getInt(ContactQuery.CONTACT_IS_USER_PROFILE) == 1);
+ }
+ }
+
+ /**
+ * @return Projection useful for children.
+ */
+ protected final String[] getProjection(boolean forSearch) {
+ final int sortOrder = getContactNameDisplayOrder();
+ if (forSearch) {
+ if (sortOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ return ContactQuery.FILTER_PROJECTION_PRIMARY;
+ } else {
+ return ContactQuery.FILTER_PROJECTION_ALTERNATIVE;
+ }
+ } else {
+ if (sortOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ return ContactQuery.CONTACT_PROJECTION_PRIMARY;
+ } else {
+ return ContactQuery.CONTACT_PROJECTION_ALTERNATIVE;
+ }
+ }
+ }
+}