blob: c5b7ccfc4147538aaa2d23a31e9c526142bbde1e [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 */
125 public static final int KIND_SEPARATOR = -3;
126
127 public String label;
128 public String data;
129 public Uri uri;
130 public long id = 0;
131 public int maxLines = 1;
132 public int kind;
133
134 /**
135 * Helper for making subclasses parcelable.
136 */
137 protected void writeToParcel(Parcel p) {
138 p.writeString(label);
139 p.writeString(data);
140 p.writeParcelable(uri, 0);
141 p.writeLong(id);
142 p.writeInt(maxLines);
143 p.writeInt(kind);
144 }
145
146 /**
147 * Helper for making subclasses parcelable.
148 */
149 protected void readFromParcel(Parcel p) {
150 label = p.readString();
151 data = p.readString();
152 uri = p.readParcelable(null);
153 id = p.readLong();
154 maxLines = p.readInt();
155 kind = p.readInt();
156 }
157 }
158
159 ContactEntryAdapter(Context context, ArrayList<ArrayList<E>> sections, boolean separators) {
160 mContext = context;
161 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
162 mSections = sections;
163 mSeparators = separators;
164 }
165
166 /**
167 * Resets the section data.
168 *
169 * @param sections the section data
170 */
171 public final void setSections(ArrayList<ArrayList<E>> sections, boolean separators) {
172 mSections = sections;
173 mSeparators = separators;
174 notifyDataSetChanged();
175 }
176
177 /**
178 * Resets the section data and returns the position of the given entry.
179 *
180 * @param sections the section data
181 * @param entry the entry to return the position for
182 * @return the position of entry, or -1 if it isn't found
183 */
184 public final int setSections(ArrayList<ArrayList<E>> sections, E entry) {
185 mSections = sections;
186 notifyDataSetChanged();
187
188 int numSections = mSections.size();
189 int position = 0;
190 for (int i = 0; i < numSections; i++) {
191 ArrayList<E> section = mSections.get(i);
192 int sectionSize = section.size();
193 for (int j = 0; j < sectionSize; j++) {
194 E e = section.get(j);
195 if (e.equals(entry)) {
196 position += j;
197 return position;
198 }
199 }
200 position += sectionSize;
201 }
202 return -1;
203 }
204
205 /**
206 * @see android.widget.ListAdapter#getCount()
207 */
208 public final int getCount() {
209 return countEntries(mSections, mSeparators);
210 }
211
212 /**
213 * @see android.widget.ListAdapter#hasSeparators()
214 */
215 @Override
216 public final boolean areAllItemsEnabled() {
217 return mSeparators == false;
218 }
219
220 /**
221 * @see android.widget.ListAdapter#isSeparator(int)
222 */
223 @Override
224 public final boolean isEnabled(int position) {
225 if (!mSeparators) {
226 return true;
227 }
228
229 int numSections = mSections.size();
230 for (int i = 0; i < numSections; i++) {
231 ArrayList<E> section = mSections.get(i);
232 int sectionSize = section.size();
233 if (sectionSize == 1) {
234 // The section only contains a separator and nothing else, skip it
235 continue;
236 }
237 if (position == 0) {
238 // The first item in a section is always the separator
239 return false;
240 }
241 position -= sectionSize;
242 }
243 return true;
244 }
245
246 /**
247 * @see android.widget.ListAdapter#getItem(int)
248 */
249 public final Object getItem(int position) {
250 return getEntry(mSections, position, mSeparators);
251 }
252
253 /**
254 * Get the entry for the given position.
255 *
256 * @param sections the list of sections
257 * @param position the position for the desired entry
258 * @return the ContactEntry for the given position
259 */
260 public final static <T extends Entry> T getEntry(ArrayList<ArrayList<T>> sections,
261 int position, boolean separators) {
262 int numSections = sections.size();
263 for (int i = 0; i < numSections; i++) {
264 ArrayList<T> section = sections.get(i);
265 int sectionSize = section.size();
266 if (separators && sectionSize == 1) {
267 // The section only contains a separator and nothing else, skip it
268 continue;
269 }
270 if (position < section.size()) {
271 return section.get(position);
272 }
273 position -= section.size();
274 }
275 return null;
276 }
277
278 /**
279 * Get the count of entries in all sections
280 *
281 * @param sections the list of sections
282 * @return the count of entries in all sections
283 */
284 public static <T extends Entry> int countEntries(ArrayList<ArrayList<T>> sections,
285 boolean separators) {
286 int count = 0;
287 int numSections = sections.size();
288 for (int i = 0; i < numSections; i++) {
289 ArrayList<T> section = sections.get(i);
290 int sectionSize = section.size();
291 if (separators && sectionSize == 1) {
292 // The section only contains a separator and nothing else, skip it
293 continue;
294 }
295 count += sections.get(i).size();
296 }
297 return count;
298 }
299
300 /**
301 * @see android.widget.ListAdapter#getItemId(int)
302 */
303 public final long getItemId(int position) {
304 Entry entry = getEntry(mSections, position, mSeparators);
305 if (entry != null) {
306 return entry.id;
307 } else {
308 return -1;
309 }
310 }
311
312 /**
313 * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
314 */
315 public View getView(int position, View convertView, ViewGroup parent) {
316 View v;
317 if (convertView == null) {
318 v = newView(position, parent);
319 } else {
320 v = convertView;
321 }
322 bindView(v, getEntry(mSections, position, mSeparators));
323 return v;
324 }
325
326 /**
327 * Create a new view for an entry.
328 *
329 * @parent the parent ViewGroup
330 * @return the newly created view
331 */
332 protected abstract View newView(int position, ViewGroup parent);
333
334 /**
335 * Binds the data from an entry to a view.
336 *
337 * @param view the view to display the entry in
338 * @param entry the data to bind
339 */
340 protected abstract void bindView(View view, E entry);
341}