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