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 com.android.contacts.common.list.ContactListItemView;
20 import com.android.contacts.common.list.DefaultContactListAdapter;
21 
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.provider.ContactsContract;
25 import android.view.View;
26 import android.view.View.OnClickListener;
27 import android.widget.CheckBox;
28 
29 import java.util.TreeSet;
30 
31 /**
32  * An extension of the default contact adapter that adds checkboxes and the ability
33  * to select multiple contacts.
34  */
35 public class MultiSelectEntryContactListAdapter extends DefaultContactListAdapter {
36 
37     private SelectedContactsListener mSelectedContactsListener;
38     private TreeSet<Long> mSelectedContactIds = new TreeSet<Long>();
39     private boolean mDisplayCheckBoxes;
40 
41     public interface SelectedContactsListener {
onSelectedContactsChanged()42         void onSelectedContactsChanged();
onSelectedContactsChangedViaCheckBox()43         void onSelectedContactsChangedViaCheckBox();
44     }
45 
MultiSelectEntryContactListAdapter(Context context)46     public MultiSelectEntryContactListAdapter(Context context) {
47         super(context);
48     }
49 
setSelectedContactsListener(SelectedContactsListener listener)50     public void setSelectedContactsListener(SelectedContactsListener listener) {
51         mSelectedContactsListener = listener;
52     }
53 
54     /**
55      * Returns set of selected contacts.
56      */
getSelectedContactIds()57     public TreeSet<Long> getSelectedContactIds() {
58         return mSelectedContactIds;
59     }
60 
61     /**
62      * Update set of selected contacts. This changes which checkboxes are set.
63      */
setSelectedContactIds(TreeSet<Long> selectedContactIds)64     public void setSelectedContactIds(TreeSet<Long> selectedContactIds) {
65         this.mSelectedContactIds = selectedContactIds;
66         notifyDataSetChanged();
67         if (mSelectedContactsListener != null) {
68             mSelectedContactsListener.onSelectedContactsChanged();
69         }
70     }
71 
72     /**
73      * Shows checkboxes beside contacts if {@param displayCheckBoxes} is {@code TRUE}.
74      * Not guaranteed to work with all configurations of this adapter.
75      */
setDisplayCheckBoxes(boolean showCheckBoxes)76     public void setDisplayCheckBoxes(boolean showCheckBoxes) {
77         if (!mDisplayCheckBoxes && showCheckBoxes) {
78             setSelectedContactIds(new TreeSet<Long>());
79         }
80         mDisplayCheckBoxes = showCheckBoxes;
81         notifyDataSetChanged();
82         if (mSelectedContactsListener != null) {
83             mSelectedContactsListener.onSelectedContactsChanged();
84         }
85     }
86 
87     /**
88      * Checkboxes are being displayed beside contacts.
89      */
isDisplayingCheckBoxes()90     public boolean isDisplayingCheckBoxes() {
91         return mDisplayCheckBoxes;
92     }
93 
94     /**
95      * Toggle the checkbox beside the contact for {@param contactId}.
96      */
toggleSelectionOfContactId(long contactId)97     public void toggleSelectionOfContactId(long contactId) {
98         if (mSelectedContactIds.contains(contactId)) {
99             mSelectedContactIds.remove(contactId);
100         } else {
101             mSelectedContactIds.add(contactId);
102         }
103         notifyDataSetChanged();
104         if (mSelectedContactsListener != null) {
105             mSelectedContactsListener.onSelectedContactsChanged();
106         }
107     }
108 
109     @Override
bindView(View itemView, int partition, Cursor cursor, int position)110     protected void bindView(View itemView, int partition, Cursor cursor, int position) {
111         super.bindView(itemView, partition, cursor, position);
112         final ContactListItemView view = (ContactListItemView) itemView;
113         bindCheckBox(view, cursor, position, partition == ContactsContract.Directory.DEFAULT);
114     }
115 
bindCheckBox(ContactListItemView view, Cursor cursor, int position, boolean isLocalDirectory)116     private void bindCheckBox(ContactListItemView view, Cursor cursor, int position,
117             boolean isLocalDirectory) {
118         // Disable clicking on the ME profile and all contacts from remote directories
119         // when showing check boxes. We do this by telling the view to handle clicking itself.
120         view.setClickable((position == 0 && hasProfile() || !isLocalDirectory)
121                 && mDisplayCheckBoxes);
122         // Only show checkboxes if mDisplayCheckBoxes is enabled. Also, never show the
123         // checkbox for the Me profile entry and other directory contacts except local directory.
124         if (position == 0 && hasProfile() || !mDisplayCheckBoxes || !isLocalDirectory) {
125             view.hideCheckBox();
126             return;
127         }
128         final CheckBox checkBox = view.getCheckBox();
129         final long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
130         checkBox.setChecked(mSelectedContactIds.contains(contactId));
131         checkBox.setTag(contactId);
132         checkBox.setOnClickListener(mCheckBoxClickListener);
133     }
134 
135     private final OnClickListener mCheckBoxClickListener = new OnClickListener() {
136         @Override
137         public void onClick(View v) {
138             final CheckBox checkBox = (CheckBox) v;
139             final Long contactId = (Long) checkBox.getTag();
140             if (checkBox.isChecked()) {
141                 mSelectedContactIds.add(contactId);
142             } else {
143                 mSelectedContactIds.remove(contactId);
144             }
145             if (mSelectedContactsListener != null) {
146                 mSelectedContactsListener.onSelectedContactsChangedViaCheckBox();
147             }
148         }
149     };
150 }
151