• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.model;
18 
19 import com.android.contacts.R;
20 import com.google.android.collect.Lists;
21 
22 import android.content.ContentValues;
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.database.Cursor;
26 import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
27 import android.provider.ContactsContract.CommonDataKinds.Email;
28 import android.provider.ContactsContract.CommonDataKinds.Event;
29 import android.provider.ContactsContract.CommonDataKinds.Im;
30 import android.provider.ContactsContract.CommonDataKinds.Nickname;
31 import android.provider.ContactsContract.CommonDataKinds.Note;
32 import android.provider.ContactsContract.CommonDataKinds.Organization;
33 import android.provider.ContactsContract.CommonDataKinds.Phone;
34 import android.provider.ContactsContract.CommonDataKinds.Photo;
35 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
36 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
37 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
38 import android.provider.ContactsContract.CommonDataKinds.Website;
39 import android.view.inputmethod.EditorInfo;
40 
41 import java.util.Locale;
42 
43 public class FallbackSource extends ContactsSource {
44     protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
45     protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT
46             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
47     protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
48             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
49     protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
50             | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
51     protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT
52             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
53     protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT
54             | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
55     protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT
56             | EditorInfo.TYPE_TEXT_VARIATION_URI;
57     protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
58             | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
59             | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
60     protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
61             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
62                                                              // basic format as email addresses
63 
FallbackSource()64     public FallbackSource() {
65         this.accountType = null;
66         this.titleRes = R.string.account_phone;
67         this.iconRes = R.drawable.ic_launcher_contacts;
68     }
69 
70     @Override
inflate(Context context, int inflateLevel)71     protected void inflate(Context context, int inflateLevel) {
72 
73         inflateStructuredName(context, inflateLevel);
74         inflateNickname(context, inflateLevel);
75         inflatePhone(context, inflateLevel);
76         inflateEmail(context, inflateLevel);
77         inflateStructuredPostal(context, inflateLevel);
78         inflateIm(context, inflateLevel);
79         inflateOrganization(context, inflateLevel);
80         inflatePhoto(context, inflateLevel);
81         inflateNote(context, inflateLevel);
82         inflateWebsite(context, inflateLevel);
83         inflateEvent(context, inflateLevel);
84         inflateSipAddress(context, inflateLevel);
85 
86         setInflatedLevel(inflateLevel);
87 
88     }
89 
buildPhoneType(int type)90     protected EditType buildPhoneType(int type) {
91         return new EditType(type, Phone.getTypeLabelResource(type));
92     }
93 
buildEmailType(int type)94     protected EditType buildEmailType(int type) {
95         return new EditType(type, Email.getTypeLabelResource(type));
96     }
97 
buildPostalType(int type)98     protected EditType buildPostalType(int type) {
99         return new EditType(type, StructuredPostal.getTypeLabelResource(type));
100     }
101 
buildImType(int type)102     protected EditType buildImType(int type) {
103         return new EditType(type, Im.getProtocolLabelResource(type));
104     }
105 
buildOrgType(int type)106     protected EditType buildOrgType(int type) {
107         return new EditType(type, Organization.getTypeLabelResource(type));
108     }
109 
inflateStructuredName(Context context, int inflateLevel)110     protected DataKind inflateStructuredName(Context context, int inflateLevel) {
111         DataKind kind = getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
112         if (kind == null) {
113             kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
114                     R.string.nameLabelsGroup, -1, -1, true));
115         }
116 
117         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
118             boolean displayOrderPrimary =
119                     context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
120 
121             kind.fieldList = Lists.newArrayList();
122             kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
123                     FLAGS_PERSON_NAME).setOptional(true));
124             if (!displayOrderPrimary) {
125                 kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
126                         FLAGS_PERSON_NAME));
127                 kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
128                         FLAGS_PERSON_NAME).setOptional(true));
129                 kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
130                         FLAGS_PERSON_NAME));
131                 kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
132                         FLAGS_PERSON_NAME).setOptional(true));
133                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
134                         R.string.name_phonetic_family, FLAGS_PHONETIC).setOptional(true));
135                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
136                         R.string.name_phonetic_middle, FLAGS_PHONETIC).setOptional(true));
137                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
138                         R.string.name_phonetic_given, FLAGS_PHONETIC).setOptional(true));
139             } else {
140                 kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
141                         FLAGS_PERSON_NAME));
142                 kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
143                         FLAGS_PERSON_NAME).setOptional(true));
144                 kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
145                         FLAGS_PERSON_NAME));
146                 kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
147                         FLAGS_PERSON_NAME).setOptional(true));
148                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
149                         R.string.name_phonetic_given, FLAGS_PHONETIC).setOptional(true));
150                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
151                         R.string.name_phonetic_middle, FLAGS_PHONETIC).setOptional(true));
152                 kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
153                         R.string.name_phonetic_family, FLAGS_PHONETIC).setOptional(true));
154             }
155         }
156 
157         return kind;
158     }
159 
inflateNickname(Context context, int inflateLevel)160     protected DataKind inflateNickname(Context context, int inflateLevel) {
161         DataKind kind = getKindForMimetype(Nickname.CONTENT_ITEM_TYPE);
162         if (kind == null) {
163             kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
164                     R.string.nicknameLabelsGroup, -1, 115, true));
165             kind.secondary = true;
166             kind.isList = false;
167             kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
168             kind.actionBody = new SimpleInflater(Nickname.NAME);
169         }
170 
171         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
172             kind.defaultValues = new ContentValues();
173             kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT);
174 
175             kind.fieldList = Lists.newArrayList();
176             kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup,
177                     FLAGS_PERSON_NAME));
178         }
179 
180         return kind;
181     }
182 
inflatePhone(Context context, int inflateLevel)183     protected DataKind inflatePhone(Context context, int inflateLevel) {
184         DataKind kind = getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
185         if (kind == null) {
186             kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
187                     android.R.drawable.sym_action_call, 10, true));
188             kind.iconAltRes = R.drawable.sym_action_sms;
189             kind.actionHeader = new PhoneActionInflater();
190             kind.actionAltHeader = new PhoneActionAltInflater();
191             kind.actionBody = new SimpleInflater(Phone.NUMBER);
192         }
193 
194         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
195             kind.typeColumn = Phone.TYPE;
196             kind.typeList = Lists.newArrayList();
197             kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
198             kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
199             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
200             kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
201             kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
202             kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
203             kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
204             kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
205                     Phone.LABEL));
206             kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true));
207             kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true));
208             kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true));
209             kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true));
210             kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true));
211             kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true));
212             kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
213             kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true));
214             kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true));
215             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true));
216             kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true));
217             kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true)
218                     .setCustomColumn(Phone.LABEL));
219             kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true));
220 
221             kind.fieldList = Lists.newArrayList();
222             kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
223         }
224 
225         return kind;
226     }
227 
inflateEmail(Context context, int inflateLevel)228     protected DataKind inflateEmail(Context context, int inflateLevel) {
229         DataKind kind = getKindForMimetype(Email.CONTENT_ITEM_TYPE);
230         if (kind == null) {
231             kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE,
232                     R.string.emailLabelsGroup, android.R.drawable.sym_action_email, 15, true));
233             kind.actionHeader = new EmailActionInflater();
234             kind.actionBody = new SimpleInflater(Email.DATA);
235         }
236 
237         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
238             kind.typeColumn = Email.TYPE;
239             kind.typeList = Lists.newArrayList();
240             kind.typeList.add(buildEmailType(Email.TYPE_HOME));
241             kind.typeList.add(buildEmailType(Email.TYPE_WORK));
242             kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
243             kind.typeList.add(buildEmailType(Email.TYPE_MOBILE));
244             kind.typeList.add(buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
245                     Email.LABEL));
246 
247             kind.fieldList = Lists.newArrayList();
248             kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
249         }
250 
251         return kind;
252     }
253 
inflateStructuredPostal(Context context, int inflateLevel)254     protected DataKind inflateStructuredPostal(Context context, int inflateLevel) {
255         DataKind kind = getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
256         if (kind == null) {
257             kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
258                     R.string.postalLabelsGroup, R.drawable.sym_action_map, 25, true));
259             kind.actionHeader = new PostalActionInflater();
260             kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
261         }
262 
263         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
264             final boolean useJapaneseOrder =
265                 Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage());
266             kind.typeColumn = StructuredPostal.TYPE;
267             kind.typeList = Lists.newArrayList();
268             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME));
269             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK));
270             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER));
271             kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true)
272                     .setCustomColumn(StructuredPostal.LABEL));
273 
274             kind.fieldList = Lists.newArrayList();
275 
276             if (useJapaneseOrder) {
277                 kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
278                         R.string.postal_country, FLAGS_POSTAL).setOptional(true));
279                 kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
280                         R.string.postal_postcode, FLAGS_POSTAL));
281                 kind.fieldList.add(new EditField(StructuredPostal.REGION,
282                         R.string.postal_region, FLAGS_POSTAL));
283                 kind.fieldList.add(new EditField(StructuredPostal.CITY,
284                         R.string.postal_city, FLAGS_POSTAL));
285                 kind.fieldList.add(new EditField(StructuredPostal.NEIGHBORHOOD,
286                         R.string.postal_neighborhood, FLAGS_POSTAL).setOptional(true));
287                 kind.fieldList.add(new EditField(StructuredPostal.STREET,
288                         R.string.postal_street, FLAGS_POSTAL));
289                 kind.fieldList.add(new EditField(StructuredPostal.POBOX,
290                         R.string.postal_pobox, FLAGS_POSTAL).setOptional(true));
291             } else {
292                 kind.fieldList.add(new EditField(StructuredPostal.STREET,
293                         R.string.postal_street, FLAGS_POSTAL));
294                 kind.fieldList.add(new EditField(StructuredPostal.POBOX,
295                         R.string.postal_pobox, FLAGS_POSTAL).setOptional(true));
296                 kind.fieldList.add(new EditField(StructuredPostal.NEIGHBORHOOD,
297                         R.string.postal_neighborhood, FLAGS_POSTAL).setOptional(true));
298                 kind.fieldList.add(new EditField(StructuredPostal.CITY,
299                         R.string.postal_city, FLAGS_POSTAL));
300                 kind.fieldList.add(new EditField(StructuredPostal.REGION,
301                         R.string.postal_region, FLAGS_POSTAL));
302                 kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
303                         R.string.postal_postcode, FLAGS_POSTAL));
304                 kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
305                         R.string.postal_country, FLAGS_POSTAL).setOptional(true));
306             }
307         }
308 
309         return kind;
310     }
311 
inflateIm(Context context, int inflateLevel)312     protected DataKind inflateIm(Context context, int inflateLevel) {
313         DataKind kind = getKindForMimetype(Im.CONTENT_ITEM_TYPE);
314         if (kind == null) {
315             kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
316                     android.R.drawable.sym_action_chat, 20, true));
317             kind.secondary = true;
318             kind.actionHeader = new ImActionInflater();
319             kind.actionBody = new SimpleInflater(Im.DATA);
320         }
321 
322         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
323             // NOTE: even though a traditional "type" exists, for editing
324             // purposes we're using the protocol to pick labels
325 
326             kind.defaultValues = new ContentValues();
327             kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER);
328 
329             kind.typeColumn = Im.PROTOCOL;
330             kind.typeList = Lists.newArrayList();
331             kind.typeList.add(buildImType(Im.PROTOCOL_AIM));
332             kind.typeList.add(buildImType(Im.PROTOCOL_MSN));
333             kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO));
334             kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE));
335             kind.typeList.add(buildImType(Im.PROTOCOL_QQ));
336             kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK));
337             kind.typeList.add(buildImType(Im.PROTOCOL_ICQ));
338             kind.typeList.add(buildImType(Im.PROTOCOL_JABBER));
339             kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn(
340                     Im.CUSTOM_PROTOCOL));
341 
342             kind.fieldList = Lists.newArrayList();
343             kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL));
344         }
345 
346         return kind;
347     }
348 
inflateOrganization(Context context, int inflateLevel)349     protected DataKind inflateOrganization(Context context, int inflateLevel) {
350         DataKind kind = getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
351         if (kind == null) {
352             kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
353                     R.string.organizationLabelsGroup, R.drawable.sym_action_organization, 30, true));
354             kind.actionHeader = new SimpleInflater(Organization.COMPANY);
355             kind.actionBody = new SimpleInflater(Organization.TITLE);
356         }
357 
358         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
359             kind.typeColumn = Organization.TYPE;
360             kind.typeList = Lists.newArrayList();
361             kind.typeList.add(buildOrgType(Organization.TYPE_WORK));
362             kind.typeList.add(buildOrgType(Organization.TYPE_OTHER));
363             kind.typeList.add(buildOrgType(Organization.TYPE_CUSTOM).setSecondary(true)
364                     .setCustomColumn(Organization.LABEL));
365 
366             kind.fieldList = Lists.newArrayList();
367             kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company,
368                     FLAGS_GENERIC_NAME));
369             kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title,
370                     FLAGS_GENERIC_NAME));
371         }
372 
373         return kind;
374     }
375 
inflatePhoto(Context context, int inflateLevel)376     protected DataKind inflatePhoto(Context context, int inflateLevel) {
377         DataKind kind = getKindForMimetype(Photo.CONTENT_ITEM_TYPE);
378         if (kind == null) {
379             kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true));
380         }
381 
382         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
383             kind.fieldList = Lists.newArrayList();
384             kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
385         }
386 
387         return kind;
388     }
389 
inflateNote(Context context, int inflateLevel)390     protected DataKind inflateNote(Context context, int inflateLevel) {
391         DataKind kind = getKindForMimetype(Note.CONTENT_ITEM_TYPE);
392         if (kind == null) {
393             kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
394                     R.string.label_notes, R.drawable.sym_note, 110, true));
395             kind.isList = false;
396             kind.secondary = true;
397             kind.actionHeader = new SimpleInflater(R.string.label_notes);
398             kind.actionBody = new SimpleInflater(Note.NOTE);
399         }
400 
401         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
402             kind.fieldList = Lists.newArrayList();
403             kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE));
404         }
405 
406         return kind;
407     }
408 
inflateWebsite(Context context, int inflateLevel)409     protected DataKind inflateWebsite(Context context, int inflateLevel) {
410         DataKind kind = getKindForMimetype(Website.CONTENT_ITEM_TYPE);
411         if (kind == null) {
412             kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
413                     R.string.websiteLabelsGroup, -1, 120, true));
414             kind.secondary = true;
415             kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
416             kind.actionBody = new SimpleInflater(Website.URL);
417         }
418 
419         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
420             kind.defaultValues = new ContentValues();
421             kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER);
422 
423             kind.fieldList = Lists.newArrayList();
424             kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE));
425         }
426 
427         return kind;
428     }
429 
inflateEvent(Context context, int inflateLevel)430     protected DataKind inflateEvent(Context context, int inflateLevel) {
431         DataKind kind = getKindForMimetype(Event.CONTENT_ITEM_TYPE);
432         if (kind == null) {
433             kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
434                     R.string.eventLabelsGroup, -1, 150, false));
435             kind.secondary = true;
436             kind.actionHeader = new EventActionInflater();
437             kind.actionBody = new SimpleInflater(Event.START_DATE);
438         }
439 
440         return kind;
441     }
442 
inflateSipAddress(Context context, int inflateLevel)443     protected DataKind inflateSipAddress(Context context, int inflateLevel) {
444         DataKind kind = getKindForMimetype(SipAddress.CONTENT_ITEM_TYPE);
445         if (kind == null) {
446             // The icon specified here is the one that gets displayed for
447             // "Internet call" items, in the "view contact" UI within the
448             // Contacts app.
449             //
450             // This is independent of the "SIP call" icon that gets
451             // displayed in the Quick Contacts widget, which comes from
452             // the android:icon attribute of the SIP-related
453             // intent-filters in the Phone app's manifest.
454 
455             kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
456                     R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
457 
458             kind.isList = false;
459             kind.secondary = true;
460             kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
461             kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
462         }
463 
464         if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
465             kind.fieldList = Lists.newArrayList();
466             kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
467                                              R.string.label_sip_address, FLAGS_SIP_ADDRESS));
468         }
469 
470         return kind;
471     }
472 
473     /**
474      * Simple inflater that assumes a string resource has a "%s" that will be
475      * filled from the given column.
476      */
477     public static class SimpleInflater implements StringInflater {
478         private final int mStringRes;
479         private final String mColumnName;
480 
SimpleInflater(int stringRes)481         public SimpleInflater(int stringRes) {
482             this(stringRes, null);
483         }
484 
SimpleInflater(String columnName)485         public SimpleInflater(String columnName) {
486             this(-1, columnName);
487         }
488 
SimpleInflater(int stringRes, String columnName)489         public SimpleInflater(int stringRes, String columnName) {
490             mStringRes = stringRes;
491             mColumnName = columnName;
492         }
493 
inflateUsing(Context context, Cursor cursor)494         public CharSequence inflateUsing(Context context, Cursor cursor) {
495             final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
496             final boolean validString = mStringRes > 0;
497             final boolean validColumn = index != -1;
498 
499             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
500             final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
501 
502             if (validString && validColumn) {
503                 return String.format(stringValue.toString(), columnValue);
504             } else if (validString) {
505                 return stringValue;
506             } else if (validColumn) {
507                 return columnValue;
508             } else {
509                 return null;
510             }
511         }
512 
inflateUsing(Context context, ContentValues values)513         public CharSequence inflateUsing(Context context, ContentValues values) {
514             final boolean validColumn = values.containsKey(mColumnName);
515             final boolean validString = mStringRes > 0;
516 
517             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
518             final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null;
519 
520             if (validString && validColumn) {
521                 return String.format(stringValue.toString(), columnValue);
522             } else if (validString) {
523                 return stringValue;
524             } else if (validColumn) {
525                 return columnValue;
526             } else {
527                 return null;
528             }
529         }
530     }
531 
532     public static abstract class CommonInflater implements StringInflater {
getTypeLabelResource(Integer type)533         protected abstract int getTypeLabelResource(Integer type);
534 
isCustom(Integer type)535         protected boolean isCustom(Integer type) {
536             return type == BaseTypes.TYPE_CUSTOM;
537         }
538 
getTypeColumn()539         protected String getTypeColumn() {
540             return Phone.TYPE;
541         }
542 
getLabelColumn()543         protected String getLabelColumn() {
544             return Phone.LABEL;
545         }
546 
getTypeLabel(Resources res, Integer type, CharSequence label)547         protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) {
548             final int labelRes = getTypeLabelResource(type);
549             if (type == null) {
550                 return res.getText(labelRes);
551             } else if (isCustom(type)) {
552                 return res.getString(labelRes, label == null ? "" : label);
553             } else {
554                 return res.getText(labelRes);
555             }
556         }
557 
inflateUsing(Context context, Cursor cursor)558         public CharSequence inflateUsing(Context context, Cursor cursor) {
559             final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
560             final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
561             return getTypeLabel(context.getResources(), type, label);
562         }
563 
inflateUsing(Context context, ContentValues values)564         public CharSequence inflateUsing(Context context, ContentValues values) {
565             final Integer type = values.getAsInteger(getTypeColumn());
566             final String label = values.getAsString(getLabelColumn());
567             return getTypeLabel(context.getResources(), type, label);
568         }
569     }
570 
571     public static class PhoneActionInflater extends CommonInflater {
572         @Override
isCustom(Integer type)573         protected boolean isCustom(Integer type) {
574             return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
575         }
576 
577         @Override
getTypeLabelResource(Integer type)578         protected int getTypeLabelResource(Integer type) {
579             if (type == null) return R.string.call_other;
580             switch (type) {
581                 case Phone.TYPE_HOME: return R.string.call_home;
582                 case Phone.TYPE_MOBILE: return R.string.call_mobile;
583                 case Phone.TYPE_WORK: return R.string.call_work;
584                 case Phone.TYPE_FAX_WORK: return R.string.call_fax_work;
585                 case Phone.TYPE_FAX_HOME: return R.string.call_fax_home;
586                 case Phone.TYPE_PAGER: return R.string.call_pager;
587                 case Phone.TYPE_OTHER: return R.string.call_other;
588                 case Phone.TYPE_CALLBACK: return R.string.call_callback;
589                 case Phone.TYPE_CAR: return R.string.call_car;
590                 case Phone.TYPE_COMPANY_MAIN: return R.string.call_company_main;
591                 case Phone.TYPE_ISDN: return R.string.call_isdn;
592                 case Phone.TYPE_MAIN: return R.string.call_main;
593                 case Phone.TYPE_OTHER_FAX: return R.string.call_other_fax;
594                 case Phone.TYPE_RADIO: return R.string.call_radio;
595                 case Phone.TYPE_TELEX: return R.string.call_telex;
596                 case Phone.TYPE_TTY_TDD: return R.string.call_tty_tdd;
597                 case Phone.TYPE_WORK_MOBILE: return R.string.call_work_mobile;
598                 case Phone.TYPE_WORK_PAGER: return R.string.call_work_pager;
599                 case Phone.TYPE_ASSISTANT: return R.string.call_assistant;
600                 case Phone.TYPE_MMS: return R.string.call_mms;
601                 default: return R.string.call_custom;
602             }
603         }
604     }
605 
606     public static class PhoneActionAltInflater extends CommonInflater {
607         @Override
isCustom(Integer type)608         protected boolean isCustom(Integer type) {
609             return (type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT);
610         }
611 
612         @Override
getTypeLabelResource(Integer type)613         protected int getTypeLabelResource(Integer type) {
614             if (type == null) return R.string.sms_other;
615             switch (type) {
616                 case Phone.TYPE_HOME: return R.string.sms_home;
617                 case Phone.TYPE_MOBILE: return R.string.sms_mobile;
618                 case Phone.TYPE_WORK: return R.string.sms_work;
619                 case Phone.TYPE_FAX_WORK: return R.string.sms_fax_work;
620                 case Phone.TYPE_FAX_HOME: return R.string.sms_fax_home;
621                 case Phone.TYPE_PAGER: return R.string.sms_pager;
622                 case Phone.TYPE_OTHER: return R.string.sms_other;
623                 case Phone.TYPE_CALLBACK: return R.string.sms_callback;
624                 case Phone.TYPE_CAR: return R.string.sms_car;
625                 case Phone.TYPE_COMPANY_MAIN: return R.string.sms_company_main;
626                 case Phone.TYPE_ISDN: return R.string.sms_isdn;
627                 case Phone.TYPE_MAIN: return R.string.sms_main;
628                 case Phone.TYPE_OTHER_FAX: return R.string.sms_other_fax;
629                 case Phone.TYPE_RADIO: return R.string.sms_radio;
630                 case Phone.TYPE_TELEX: return R.string.sms_telex;
631                 case Phone.TYPE_TTY_TDD: return R.string.sms_tty_tdd;
632                 case Phone.TYPE_WORK_MOBILE: return R.string.sms_work_mobile;
633                 case Phone.TYPE_WORK_PAGER: return R.string.sms_work_pager;
634                 case Phone.TYPE_ASSISTANT: return R.string.sms_assistant;
635                 case Phone.TYPE_MMS: return R.string.sms_mms;
636                 default: return R.string.sms_custom;
637             }
638         }
639     }
640 
641     public static class EmailActionInflater extends CommonInflater {
642         @Override
getTypeLabelResource(Integer type)643         protected int getTypeLabelResource(Integer type) {
644             if (type == null) return R.string.email;
645             switch (type) {
646                 case Email.TYPE_HOME: return R.string.email_home;
647                 case Email.TYPE_WORK: return R.string.email_work;
648                 case Email.TYPE_OTHER: return R.string.email_other;
649                 case Email.TYPE_MOBILE: return R.string.email_mobile;
650                 default: return R.string.email_custom;
651             }
652         }
653     }
654 
655     public static class EventActionInflater extends CommonInflater {
656         @Override
getTypeLabelResource(Integer type)657         protected int getTypeLabelResource(Integer type) {
658             return Event.getTypeResource(type);
659         }
660     }
661 
662     public static class PostalActionInflater extends CommonInflater {
663         @Override
getTypeLabelResource(Integer type)664         protected int getTypeLabelResource(Integer type) {
665             if (type == null) return R.string.map_other;
666             switch (type) {
667                 case StructuredPostal.TYPE_HOME: return R.string.map_home;
668                 case StructuredPostal.TYPE_WORK: return R.string.map_work;
669                 case StructuredPostal.TYPE_OTHER: return R.string.map_other;
670                 default: return R.string.map_custom;
671             }
672         }
673     }
674 
675     public static class ImActionInflater extends CommonInflater {
676         @Override
getTypeColumn()677         protected String getTypeColumn() {
678             return Im.PROTOCOL;
679         }
680 
681         @Override
getLabelColumn()682         protected String getLabelColumn() {
683             return Im.CUSTOM_PROTOCOL;
684         }
685 
686         @Override
getTypeLabelResource(Integer type)687         protected int getTypeLabelResource(Integer type) {
688             if (type == null) return R.string.chat;
689             switch (type) {
690                 case Im.PROTOCOL_AIM: return R.string.chat_aim;
691                 case Im.PROTOCOL_MSN: return R.string.chat_msn;
692                 case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo;
693                 case Im.PROTOCOL_SKYPE: return R.string.chat_skype;
694                 case Im.PROTOCOL_QQ: return R.string.chat_qq;
695                 case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk;
696                 case Im.PROTOCOL_ICQ: return R.string.chat_icq;
697                 case Im.PROTOCOL_JABBER: return R.string.chat_jabber;
698                 case Im.PROTOCOL_NETMEETING: return R.string.chat;
699                 default: return R.string.chat;
700             }
701         }
702     }
703 
704     @Override
getHeaderColor(Context context)705     public int getHeaderColor(Context context) {
706         return 0xff7f93bc;
707     }
708 
709     @Override
getSideBarColor(Context context)710     public int getSideBarColor(Context context) {
711         return 0xffbdc7b8;
712     }
713 }
714