Home | History | Annotate | Download | only in list
      1 /*
      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 
     17 package com.android.contacts.list;
     18 
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.provider.ContactsContract;
     22 import android.view.View;
     23 import android.widget.CheckBox;
     24 
     25 import com.android.contacts.ContactPhotoManager;
     26 import com.android.contacts.group.GroupUtil;
     27 
     28 import java.util.TreeSet;
     29 
     30 /**
     31  * An extension of the default contact adapter that adds checkboxes and the ability
     32  * to select multiple contacts.
     33  */
     34 public abstract class MultiSelectEntryContactListAdapter extends ContactEntryListAdapter {
     35 
     36     private SelectedContactsListener mSelectedContactsListener;
     37     private DeleteContactListener mDeleteContactListener;
     38     private TreeSet<Long> mSelectedContactIds = new TreeSet<>();
     39     private boolean mDisplayCheckBoxes;
     40     private final int mContactIdColumnIndex;
     41 
     42     public interface SelectedContactsListener {
     43         void onSelectedContactsChanged();
     44     }
     45 
     46     public interface DeleteContactListener {
     47         void onContactDeleteClicked(int position);
     48     }
     49 
     50     /**
     51      * @param contactIdColumnIndex the column index of the contact ID in the underlying cursor;
     52      *         it is passed in so that this adapter can support different kinds of contact
     53      *         lists (e.g. aggregate contacts or raw contacts).
     54      */
     55     public MultiSelectEntryContactListAdapter(Context context, int contactIdColumnIndex) {
     56         super(context);
     57         mContactIdColumnIndex = contactIdColumnIndex;
     58     }
     59 
     60     /**
     61      * Returns the column index of the contact ID in the underlying cursor; the contact ID
     62      * retrieved using this index is the value that is selected by this adapter (and returned
     63      * by {@link #getSelectedContactIds}).
     64      */
     65     public int getContactColumnIdIndex() {
     66         return mContactIdColumnIndex;
     67     }
     68 
     69     public DeleteContactListener getDeleteContactListener() {
     70         return mDeleteContactListener;
     71     }
     72 
     73     public void setDeleteContactListener(DeleteContactListener deleteContactListener) {
     74         mDeleteContactListener = deleteContactListener;
     75     }
     76 
     77     public void setSelectedContactsListener(SelectedContactsListener listener) {
     78         mSelectedContactsListener = listener;
     79     }
     80 
     81     /**
     82      * Returns set of selected contacts.
     83      */
     84     public TreeSet<Long> getSelectedContactIds() {
     85         return mSelectedContactIds;
     86     }
     87 
     88     public boolean hasSelectedItems() {
     89         return mSelectedContactIds.size() > 0;
     90     }
     91 
     92     /**
     93      * Returns the selected contacts as an array.
     94      */
     95     public long[] getSelectedContactIdsArray() {
     96         return GroupUtil.convertLongSetToLongArray(mSelectedContactIds);
     97     }
     98 
     99     /**
    100      * Update set of selected contacts. This changes which checkboxes are set.
    101      */
    102     public void setSelectedContactIds(TreeSet<Long> selectedContactIds) {
    103         this.mSelectedContactIds = selectedContactIds;
    104         notifyDataSetChanged();
    105         if (mSelectedContactsListener != null) {
    106             mSelectedContactsListener.onSelectedContactsChanged();
    107         }
    108     }
    109 
    110     /**
    111      * Shows checkboxes beside contacts if {@param displayCheckBoxes} is {@code TRUE}.
    112      * Not guaranteed to work with all configurations of this adapter.
    113      */
    114     public void setDisplayCheckBoxes(boolean showCheckBoxes) {
    115         mDisplayCheckBoxes = showCheckBoxes;
    116         notifyDataSetChanged();
    117         if (mSelectedContactsListener != null) {
    118             mSelectedContactsListener.onSelectedContactsChanged();
    119         }
    120     }
    121 
    122     /**
    123      * Checkboxes are being displayed beside contacts.
    124      */
    125     public boolean isDisplayingCheckBoxes() {
    126         return mDisplayCheckBoxes;
    127     }
    128 
    129     /**
    130      * Toggle the checkbox beside the contact for {@param contactId}.
    131      */
    132     public void toggleSelectionOfContactId(long contactId) {
    133         if (mSelectedContactIds.contains(contactId)) {
    134             mSelectedContactIds.remove(contactId);
    135         } else {
    136             mSelectedContactIds.add(contactId);
    137         }
    138         notifyDataSetChanged();
    139         if (mSelectedContactsListener != null) {
    140             mSelectedContactsListener.onSelectedContactsChanged();
    141         }
    142     }
    143 
    144     @Override
    145     public long getItemId(int position) {
    146         Cursor cursor = (Cursor) getItem(position);
    147         if (cursor != null) {
    148             return cursor.getLong(getContactColumnIdIndex());
    149         }
    150         return 0;
    151     }
    152 
    153     @Override
    154     protected void bindView(View itemView, int partition, Cursor cursor, int position) {
    155         super.bindView(itemView, partition, cursor, position);
    156         final ContactListItemView view = (ContactListItemView) itemView;
    157         bindViewId(view, cursor, getContactColumnIdIndex());
    158         bindCheckBox(view, cursor, partition == ContactsContract.Directory.DEFAULT);
    159     }
    160 
    161     /**
    162       * Loads the photo for the photo view.
    163       * @param photoIdColumn Index of the photo id column
    164       * @param lookUpKeyColumn Index of the lookup key column
    165       * @param displayNameColumn Index of the display name column
    166       */
    167     protected void bindPhoto(final ContactListItemView view, final Cursor cursor,
    168            final int photoIdColumn, final int lookUpKeyColumn, final int displayNameColumn) {
    169         final long photoId = cursor.isNull(photoIdColumn)
    170             ? 0 : cursor.getLong(photoIdColumn);
    171         final ContactPhotoManager.DefaultImageRequest imageRequest = photoId == 0
    172             ? getDefaultImageRequestFromCursor(cursor, displayNameColumn,
    173             lookUpKeyColumn)
    174             : null;
    175         getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, getCircularPhotos(),
    176                 imageRequest);
    177     }
    178 
    179     private void bindCheckBox(ContactListItemView view, Cursor cursor, boolean isLocalDirectory) {
    180         // Disable clicking on all contacts from remote directories when showing check boxes. We do
    181         // this by telling the view to handle clicking itself.
    182         view.setClickable(!isLocalDirectory && mDisplayCheckBoxes);
    183         // Only show checkboxes if mDisplayCheckBoxes is enabled. Also, never show the
    184         // checkbox for other directory contacts except local directory.
    185         if (!mDisplayCheckBoxes || !isLocalDirectory) {
    186             view.hideCheckBox();
    187             return;
    188         }
    189         final CheckBox checkBox = view.getCheckBox();
    190         final long contactId = cursor.getLong(mContactIdColumnIndex);
    191         checkBox.setChecked(mSelectedContactIds.contains(contactId));
    192         checkBox.setClickable(false);
    193         checkBox.setTag(contactId);
    194     }
    195 }
    196