blob: b8d9fe877e1cdf3261c24c4b287b24e6c81620e3 [file] [log] [blame]
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001/*
2 * Copyright (C) 2007 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;
18
19import android.content.Context;
20import android.net.Uri;
21import android.os.Parcel;
22import android.provider.Contacts.Organizations;
23import android.provider.Contacts.People;
24import android.view.LayoutInflater;
25import android.view.View;
26import android.view.ViewGroup;
27import android.widget.BaseAdapter;
28
29import java.util.ArrayList;
30
31public abstract class ContactEntryAdapter<E extends ContactEntryAdapter.Entry>
32 extends BaseAdapter {
33
34 public static final String[] CONTACT_PROJECTION = new String[] {
35 People._ID, // 0
36 People.NAME, // 1
37 People.NOTES, // 2
38 People.PRIMARY_PHONE_ID, // 3
39 People.PRESENCE_STATUS, // 4
40 People.STARRED, // 5
41 People.CUSTOM_RINGTONE, // 6
42 People.SEND_TO_VOICEMAIL, // 7
43 People.PHONETIC_NAME, // 8
44 };
45 public static final int CONTACT_ID_COLUMN = 0;
46 public static final int CONTACT_NAME_COLUMN = 1;
47 public static final int CONTACT_NOTES_COLUMN = 2;
48 public static final int CONTACT_PREFERRED_PHONE_COLUMN = 3;
49 public static final int CONTACT_SERVER_STATUS_COLUMN = 4;
50 public static final int CONTACT_STARRED_COLUMN = 5;
51 public static final int CONTACT_CUSTOM_RINGTONE_COLUMN = 6;
52 public static final int CONTACT_SEND_TO_VOICEMAIL_COLUMN = 7;
53 public static final int CONTACT_PHONETIC_NAME_COLUMN = 8;
54
55 public static final String[] PHONES_PROJECTION = new String[] {
56 People.Phones._ID, // 0
57 People.Phones.NUMBER, // 1
58 People.Phones.TYPE, // 2
59 People.Phones.LABEL, // 3
60 People.Phones.ISPRIMARY, // 4
61 };
62 public static final int PHONES_ID_COLUMN = 0;
63 public static final int PHONES_NUMBER_COLUMN = 1;
64 public static final int PHONES_TYPE_COLUMN = 2;
65 public static final int PHONES_LABEL_COLUMN = 3;
66 public static final int PHONES_ISPRIMARY_COLUMN = 4;
67
68 public static final String[] METHODS_PROJECTION = new String[] {
69 People.ContactMethods._ID, // 0
70 People.ContactMethods.KIND, // 1
71 People.ContactMethods.DATA, // 2
72 People.ContactMethods.TYPE, // 3
73 People.ContactMethods.LABEL, // 4
74 People.ContactMethods.ISPRIMARY, // 5
75 People.ContactMethods.AUX_DATA, // 6
76 };
77 public static final String[] METHODS_WITH_PRESENCE_PROJECTION = new String[] {
78 People.ContactMethods._ID, // 0
79 People.ContactMethods.KIND, // 1
80 People.ContactMethods.DATA, // 2
81 People.ContactMethods.TYPE, // 3
82 People.ContactMethods.LABEL, // 4
83 People.ContactMethods.ISPRIMARY, // 5
84 People.ContactMethods.AUX_DATA, // 6
85 People.PRESENCE_STATUS, // 7
86 };
87 public static final int METHODS_ID_COLUMN = 0;
88 public static final int METHODS_KIND_COLUMN = 1;
89 public static final int METHODS_DATA_COLUMN = 2;
90 public static final int METHODS_TYPE_COLUMN = 3;
91 public static final int METHODS_LABEL_COLUMN = 4;
92 public static final int METHODS_ISPRIMARY_COLUMN = 5;
93 public static final int METHODS_AUX_DATA_COLUMN = 6;
94 public static final int METHODS_STATUS_COLUMN = 7;
95
96 public static final String[] ORGANIZATIONS_PROJECTION = new String[] {
97 Organizations._ID, // 0
98 Organizations.TYPE, // 1
99 Organizations.LABEL, // 2
100 Organizations.COMPANY, // 3
101 Organizations.TITLE, // 4
102 Organizations.ISPRIMARY, // 5
103 };
104 public static final int ORGANIZATIONS_ID_COLUMN = 0;
105 public static final int ORGANIZATIONS_TYPE_COLUMN = 1;
106 public static final int ORGANIZATIONS_LABEL_COLUMN = 2;
107 public static final int ORGANIZATIONS_COMPANY_COLUMN = 3;
108 public static final int ORGANIZATIONS_TITLE_COLUMN = 4;
109 public static final int ORGANIZATIONS_ISPRIMARY_COLUMN = 5;
110
111 protected ArrayList<ArrayList<E>> mSections;
112 protected LayoutInflater mInflater;
113 protected Context mContext;
114 protected boolean mSeparators;
115
116 /**
117 * Base class for adapter entries.
118 */
119 public static class Entry {
120 /** Details from the person table */
121 public static final int KIND_CONTACT = -1;
122 /** Synthesized phone entry that will send an SMS instead of call the number */
123 public static final int KIND_SMS = -2;
124 /** A section separator */
The Android Open Source Projectcac191e2009-03-18 22:20:27 -0700125 public static final int KIND_SEPARATOR = -3;
126 /** Signifies a group row that is stored in the group membership table */
127 public static final int KIND_GROUP = -4;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800128
129 public String label;
130 public String data;
131 public Uri uri;
132 public long id = 0;
133 public int maxLines = 1;
134 public int kind;
135
136 /**
137 * Helper for making subclasses parcelable.
138 */
139 protected void writeToParcel(Parcel p) {
140 p.writeString(label);
141 p.writeString(data);
142 p.writeParcelable(uri, 0);
143 p.writeLong(id);
144 p.writeInt(maxLines);
145 p.writeInt(kind);
146 }
147
148 /**
149 * Helper for making subclasses parcelable.
150 */
151 protected void readFromParcel(Parcel p) {
152 label = p.readString();
153 data = p.readString();
154 uri = p.readParcelable(null);
155 id = p.readLong();
156 maxLines = p.readInt();
157 kind = p.readInt();
158 }
159 }
160
161 ContactEntryAdapter(Context context, ArrayList<ArrayList<E>> sections, boolean separators) {
162 mContext = context;
163 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
164 mSections = sections;
165 mSeparators = separators;
166 }
167
168 /**
169 * Resets the section data.
170 *
171 * @param sections the section data
172 */
173 public final void setSections(ArrayList<ArrayList<E>> sections, boolean separators) {
174 mSections = sections;
175 mSeparators = separators;
176 notifyDataSetChanged();
177 }
178
179 /**
180 * Resets the section data and returns the position of the given entry.
181 *
182 * @param sections the section data
183 * @param entry the entry to return the position for
184 * @return the position of entry, or -1 if it isn't found
185 */
186 public final int setSections(ArrayList<ArrayList<E>> sections, E entry) {
187 mSections = sections;
188 notifyDataSetChanged();
189
190 int numSections = mSections.size();
191 int position = 0;
192 for (int i = 0; i < numSections; i++) {
193 ArrayList<E> section = mSections.get(i);
194 int sectionSize = section.size();
195 for (int j = 0; j < sectionSize; j++) {
196 E e = section.get(j);
197 if (e.equals(entry)) {
198 position += j;
199 return position;
200 }
201 }
202 position += sectionSize;
203 }
204 return -1;
205 }
206
207 /**
208 * @see android.widget.ListAdapter#getCount()
209 */
210 public final int getCount() {
211 return countEntries(mSections, mSeparators);
212 }
213
214 /**
215 * @see android.widget.ListAdapter#hasSeparators()
216 */
217 @Override
218 public final boolean areAllItemsEnabled() {
219 return mSeparators == false;
220 }
221
222 /**
223 * @see android.widget.ListAdapter#isSeparator(int)
224 */
225 @Override
226 public final boolean isEnabled(int position) {
227 if (!mSeparators) {
228 return true;
229 }
230
231 int numSections = mSections.size();
232 for (int i = 0; i < numSections; i++) {
233 ArrayList<E> section = mSections.get(i);
234 int sectionSize = section.size();
235 if (sectionSize == 1) {
236 // The section only contains a separator and nothing else, skip it
237 continue;
238 }
239 if (position == 0) {
240 // The first item in a section is always the separator
241 return false;
242 }
243 position -= sectionSize;
244 }
245 return true;
246 }
247
248 /**
249 * @see android.widget.ListAdapter#getItem(int)
250 */
251 public final Object getItem(int position) {
252 return getEntry(mSections, position, mSeparators);
253 }
254
255 /**
256 * Get the entry for the given position.
257 *
258 * @param sections the list of sections
259 * @param position the position for the desired entry
260 * @return the ContactEntry for the given position
261 */
262 public final static <T extends Entry> T getEntry(ArrayList<ArrayList<T>> sections,
263 int position, boolean separators) {
264 int numSections = sections.size();
265 for (int i = 0; i < numSections; i++) {
266 ArrayList<T> section = sections.get(i);
267 int sectionSize = section.size();
268 if (separators && sectionSize == 1) {
269 // The section only contains a separator and nothing else, skip it
270 continue;
271 }
272 if (position < section.size()) {
273 return section.get(position);
274 }
275 position -= section.size();
276 }
277 return null;
278 }
279
280 /**
281 * Get the count of entries in all sections
282 *
283 * @param sections the list of sections
284 * @return the count of entries in all sections
285 */
286 public static <T extends Entry> int countEntries(ArrayList<ArrayList<T>> sections,
287 boolean separators) {
288 int count = 0;
289 int numSections = sections.size();
290 for (int i = 0; i < numSections; i++) {
291 ArrayList<T> section = sections.get(i);
292 int sectionSize = section.size();
293 if (separators && sectionSize == 1) {
294 // The section only contains a separator and nothing else, skip it
295 continue;
296 }
297 count += sections.get(i).size();
298 }
299 return count;
300 }
301
302 /**
303 * @see android.widget.ListAdapter#getItemId(int)
304 */
305 public final long getItemId(int position) {
306 Entry entry = getEntry(mSections, position, mSeparators);
307 if (entry != null) {
308 return entry.id;
309 } else {
310 return -1;
311 }
312 }
313
314 /**
315 * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
316 */
317 public View getView(int position, View convertView, ViewGroup parent) {
318 View v;
319 if (convertView == null) {
320 v = newView(position, parent);
321 } else {
322 v = convertView;
323 }
324 bindView(v, getEntry(mSections, position, mSeparators));
325 return v;
326 }
327
328 /**
329 * Create a new view for an entry.
330 *
331 * @parent the parent ViewGroup
332 * @return the newly created view
333 */
334 protected abstract View newView(int position, ViewGroup parent);
335
336 /**
337 * Binds the data from an entry to a view.
338 *
339 * @param view the view to display the entry in
340 * @param entry the data to bind
341 */
342 protected abstract void bindView(View view, E entry);
343}