blob: 5c822ba7690aa8425dc462ca7afb7f065b90f941 [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.contacts;
import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts.Data;
import android.provider.ContactsContract.RawContacts;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.account.AccountType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* A list view for constituent contacts of an aggregate. Shows the contact name, source icon
* and additional data such as a nickname, email address or phone number, whichever
* is available.
*/
public class SplitAggregateView extends ListView {
private static final String TAG = "SplitAggregateView";
private interface SplitQuery {
String[] COLUMNS = new String[] {
Data.MIMETYPE, RawContacts.ACCOUNT_TYPE, RawContacts.DATA_SET, Data.RAW_CONTACT_ID,
Data.IS_PRIMARY, StructuredName.DISPLAY_NAME, Nickname.NAME, Email.DATA,
Phone.NUMBER
};
int MIMETYPE = 0;
int ACCOUNT_TYPE = 1;
int DATA_SET = 2;
int RAW_CONTACT_ID = 3;
int IS_PRIMARY = 4;
int DISPLAY_NAME = 5;
int NICKNAME = 6;
int EMAIL = 7;
int PHONE = 8;
}
private final Uri mAggregateUri;
private OnContactSelectedListener mListener;
private AccountTypeManager mAccountTypes;
/**
* Listener interface that gets the contact ID of the user-selected contact.
*/
public interface OnContactSelectedListener {
void onContactSelected(long rawContactId);
}
/**
* Constructor.
*/
public SplitAggregateView(Context context, Uri aggregateUri) {
super(context);
mAggregateUri = aggregateUri;
mAccountTypes = AccountTypeManager.getInstance(context);
final List<RawContactInfo> list = loadData();
setAdapter(new SplitAggregateAdapter(context, list));
setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListener.onContactSelected(list.get(position).rawContactId);
}
});
}
/**
* Sets a contact selection listener.
*/
public void setOnContactSelectedListener(OnContactSelectedListener listener) {
mListener = listener;
}
/**
* Contact information loaded from the content provider.
*/
private static class RawContactInfo implements Comparable<RawContactInfo> {
final long rawContactId;
String accountType;
String dataSet;
String name;
String phone;
String email;
String nickname;
public RawContactInfo(long rawContactId) {
this.rawContactId = rawContactId;
}
public String getAdditionalData() {
if (nickname != null) {
return nickname;
}
if (email != null) {
return email;
}
if (phone != null) {
return phone;
}
return "";
}
public int compareTo(RawContactInfo another) {
String thisAccount = accountType != null ? accountType : "";
String thatAccount = another.accountType != null ? another.accountType : "";
return thisAccount.compareTo(thatAccount);
}
}
/**
* Loads data from the content provider, organizes it into {@link RawContactInfo} objects
* and returns a sorted list of {@link RawContactInfo}'s.
*/
private List<RawContactInfo> loadData() {
HashMap<Long, RawContactInfo> rawContactInfos = new HashMap<Long, RawContactInfo>();
Uri dataUri = Uri.withAppendedPath(mAggregateUri, Data.CONTENT_DIRECTORY);
Cursor cursor = getContext().getContentResolver().query(dataUri,
SplitQuery.COLUMNS, null, null, null);
if (cursor == null) {
return Collections.emptyList();
}
try {
while (cursor.moveToNext()) {
long rawContactId = cursor.getLong(SplitQuery.RAW_CONTACT_ID);
RawContactInfo info = rawContactInfos.get(rawContactId);
if (info == null) {
info = new RawContactInfo(rawContactId);
rawContactInfos.put(rawContactId, info);
info.accountType = cursor.getString(SplitQuery.ACCOUNT_TYPE);
info.dataSet = cursor.getString(SplitQuery.DATA_SET);
}
String mimetype = cursor.getString(SplitQuery.MIMETYPE);
if (StructuredName.CONTENT_ITEM_TYPE.equals(mimetype)) {
loadStructuredName(cursor, info);
} else if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
loadPhoneNumber(cursor, info);
} else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
loadEmail(cursor, info);
} else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) {
loadNickname(cursor, info);
}
}
} finally {
cursor.close();
}
List<RawContactInfo> list = new ArrayList<RawContactInfo>(rawContactInfos.values());
Collections.sort(list);
return list;
}
private void loadStructuredName(Cursor cursor, RawContactInfo info) {
info.name = cursor.getString(SplitQuery.DISPLAY_NAME);
}
private void loadNickname(Cursor cursor, RawContactInfo info) {
if (info.nickname == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) {
info.nickname = cursor.getString(SplitQuery.NICKNAME);
}
}
private void loadEmail(Cursor cursor, RawContactInfo info) {
if (info.email == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) {
info.email = cursor.getString(SplitQuery.EMAIL);
}
}
private void loadPhoneNumber(Cursor cursor, RawContactInfo info) {
if (info.phone == null || cursor.getInt(SplitQuery.IS_PRIMARY) != 0) {
info.phone = cursor.getString(SplitQuery.PHONE);
}
}
private static class SplitAggregateItemCache {
TextView name;
TextView additionalData;
ImageView sourceIcon;
}
/**
* List adapter for the list of {@link RawContactInfo} objects.
*/
private class SplitAggregateAdapter extends ArrayAdapter<RawContactInfo> {
private LayoutInflater mInflater;
public SplitAggregateAdapter(Context context, List<RawContactInfo> sources) {
super(context, 0, sources);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.split_aggregate_list_item, parent, false);
}
SplitAggregateItemCache cache = (SplitAggregateItemCache)convertView.getTag();
if (cache == null) {
cache = new SplitAggregateItemCache();
cache.name = (TextView)convertView.findViewById(R.id.name);
cache.additionalData = (TextView)convertView.findViewById(R.id.additionalData);
cache.sourceIcon = (ImageView)convertView.findViewById(R.id.sourceIcon);
convertView.setTag(cache);
}
final RawContactInfo info = getItem(position);
cache.name.setText(info.name);
cache.additionalData.setText(info.getAdditionalData());
Drawable icon = null;
AccountType accountType = mAccountTypes.getAccountType(info.accountType, info.dataSet);
if (accountType != null) {
icon = accountType.getDisplayIcon(getContext());
}
if (icon != null) {
cache.sourceIcon.setImageDrawable(icon);
} else {
cache.sourceIcon.setImageResource(R.drawable.unknown_source);
}
return convertView;
}
}
}