1/*
2 * Copyright (C) 2010 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 */
16package com.android.contacts.list;
17
18import android.content.Context;
19import android.content.CursorLoader;
20import android.database.Cursor;
21import android.net.Uri;
22import android.net.Uri.Builder;
23import android.provider.ContactsContract;
24import android.provider.ContactsContract.Contacts;
25import android.provider.ContactsContract.Contacts.AggregationSuggestions;
26import android.provider.ContactsContract.Directory;
27import android.text.TextUtils;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
31import android.widget.TextView;
32
33import com.android.contacts.R;
34import com.android.contacts.common.list.ContactListAdapter;
35import com.android.contacts.common.list.ContactListItemView;
36import com.android.contacts.common.list.DirectoryListLoader;
37import com.android.contacts.common.preference.ContactsPreferences;
38
39public class JoinContactListAdapter extends ContactListAdapter {
40
41    /** Maximum number of suggestions shown for joining aggregates */
42    private static final int MAX_SUGGESTIONS = 4;
43
44    public static final int PARTITION_SUGGESTIONS = 0;
45    public static final int PARTITION_ALL_CONTACTS = 1;
46
47    private long mTargetContactId;
48
49    public JoinContactListAdapter(Context context) {
50        super(context);
51        setPinnedPartitionHeadersEnabled(true);
52        setSectionHeaderDisplayEnabled(true);
53        setIndexedPartition(PARTITION_ALL_CONTACTS);
54        setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
55    }
56
57    @Override
58    protected void addPartitions() {
59        // Partition 0: suggestions
60        addPartition(false, true);
61
62        // Partition 1: All contacts
63        addPartition(createDefaultDirectoryPartition());
64    }
65
66    public void setTargetContactId(long targetContactId) {
67        this.mTargetContactId = targetContactId;
68    }
69
70    @Override
71    public void configureLoader(CursorLoader cursorLoader, long directoryId) {
72        JoinContactLoader loader = (JoinContactLoader) cursorLoader;
73
74        final Builder builder = Contacts.CONTENT_URI.buildUpon();
75        builder.appendEncodedPath(String.valueOf(mTargetContactId));
76        builder.appendEncodedPath(AggregationSuggestions.CONTENT_DIRECTORY);
77
78        final String filter = getQueryString();
79        if (!TextUtils.isEmpty(filter)) {
80            builder.appendEncodedPath(Uri.encode(filter));
81        }
82
83        builder.appendQueryParameter("limit", String.valueOf(MAX_SUGGESTIONS));
84
85        loader.setSuggestionUri(builder.build());
86
87        // TODO simplify projection
88        loader.setProjection(getProjection(false));
89        final Uri allContactsUri;
90        if (!TextUtils.isEmpty(filter)) {
91            allContactsUri = buildSectionIndexerUri(Contacts.CONTENT_FILTER_URI).buildUpon()
92                .appendEncodedPath(Uri.encode(filter))
93                .appendQueryParameter(
94                        ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
95                .build();
96        } else {
97            allContactsUri = buildSectionIndexerUri(Contacts.CONTENT_URI).buildUpon()
98                .appendQueryParameter(
99                        ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
100                .build();
101        }
102        loader.setUri(allContactsUri);
103        loader.setSelection(Contacts._ID + "!=?");
104        loader.setSelectionArgs(new String[]{ String.valueOf(mTargetContactId) });
105        if (getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY) {
106            loader.setSortOrder(Contacts.SORT_KEY_PRIMARY);
107        } else {
108            loader.setSortOrder(Contacts.SORT_KEY_ALTERNATIVE);
109        }
110    }
111
112    @Override
113    public boolean isEmpty() {
114        return false;
115    }
116
117    public void setSuggestionsCursor(Cursor cursor) {
118        changeCursor(PARTITION_SUGGESTIONS, cursor);
119    }
120
121    @Override
122    public void changeCursor(Cursor cursor) {
123        changeCursor(PARTITION_ALL_CONTACTS, cursor);
124    }
125
126    @Override
127    public void configureDefaultPartition(boolean showIfEmpty, boolean hasHeader) {
128         // Don't change default partition parameters from these defaults
129        super.configureDefaultPartition(false, true);
130    }
131
132    @Override
133    public int getViewTypeCount() {
134        return super.getViewTypeCount();
135    }
136
137    @Override
138    public int getItemViewType(int partition, int position) {
139        return super.getItemViewType(partition, position);
140    }
141
142    @Override
143    protected View newHeaderView(Context context, int partition, Cursor cursor,
144            ViewGroup parent) {
145        switch (partition) {
146            case PARTITION_SUGGESTIONS: {
147                View view = inflate(R.layout.join_contact_picker_section_header, parent);
148                ((TextView) view.findViewById(R.id.text)).setText(
149                        R.string.separatorJoinAggregateSuggestions);
150                return view;
151            }
152            case PARTITION_ALL_CONTACTS: {
153                View view = inflate(R.layout.join_contact_picker_section_header, parent);
154                ((TextView) view.findViewById(R.id.text)).setText(
155                        R.string.separatorJoinAggregateAll);
156                return view;
157            }
158        }
159
160        return null;
161    }
162
163    @Override
164    protected void bindHeaderView(View view, int partitionIndex, Cursor cursor) {
165        // Header views are static - nothing needs to be bound
166    }
167
168    @Override
169    protected ContactListItemView newView(
170            Context context, int partition, Cursor cursor, int position, ViewGroup parent) {
171        switch (partition) {
172            case PARTITION_SUGGESTIONS:
173            case PARTITION_ALL_CONTACTS:
174                return super.newView(context, partition, cursor, position, parent);
175        }
176        return null;
177    }
178
179    private View inflate(int layoutId, ViewGroup parent) {
180        return LayoutInflater.from(getContext()).inflate(layoutId, parent, false);
181    }
182
183    @Override
184    protected void bindView(View itemView, int partition, Cursor cursor, int position) {
185        super.bindView(itemView, partition, cursor, position);
186        switch (partition) {
187            case PARTITION_SUGGESTIONS: {
188                final ContactListItemView view = (ContactListItemView) itemView;
189                view.setSectionHeader(null);
190                bindPhoto(view, partition, cursor);
191                bindNameAndViewId(view, cursor);
192                break;
193            }
194            case PARTITION_ALL_CONTACTS: {
195                final ContactListItemView view = (ContactListItemView) itemView;
196                bindSectionHeaderAndDivider(view, position, cursor);
197                bindPhoto(view, partition, cursor);
198                bindNameAndViewId(view, cursor);
199                break;
200            }
201        }
202    }
203
204    @Override
205    public Uri getContactUri(int partitionIndex, Cursor cursor) {
206        long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
207        String lookupKey = cursor.getString(ContactQuery.CONTACT_LOOKUP_KEY);
208        return Contacts.getLookupUri(contactId, lookupKey);
209    }
210}
211