JoinContactListAdapter.java revision e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9
16e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov/*
26e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
36e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov *
46e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
56e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * you may not use this file except in compliance with the License.
66e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * You may obtain a copy of the License at
76e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov *
86e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
96e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov *
106e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
116e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
126e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * See the License for the specific language governing permissions and
146e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov * limitations under the License.
156e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov */
166e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovpackage com.android.contacts.list;
176e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
186e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport com.android.contacts.R;
196e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
20e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.app.patterns.CursorLoader;
21e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.content.Context;
226e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport android.database.Cursor;
23e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.database.MatrixCursor;
24e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.net.Uri;
25e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.net.Uri.Builder;
26e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.provider.ContactsContract;
27e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
28e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.AggregationSuggestions;
29e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovimport android.text.TextUtils;
306e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport android.view.LayoutInflater;
316e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport android.view.View;
326e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport android.view.ViewGroup;
336e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikovimport android.widget.TextView;
346e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
35e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikovpublic class JoinContactListAdapter extends ContactListAdapter {
36e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
37e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    /** Maximum number of suggestions shown for joining aggregates */
38e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private static final int MAX_SUGGESTIONS = 4;
39e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
40e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private Cursor mSuggestionsCursor;
41e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private int mSuggestionsCursorCount;
42e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private long mTargetContactId;
436e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
446e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    /**
456e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov     * Determines whether we display a list item with the label
466e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov     * "Show all contacts" or actually show all contacts
476e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov     */
48e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private boolean mAllContactsListShown;
496e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
50e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public JoinContactListAdapter(Context context) {
516e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        super(context);
52e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        setSectionHeaderDisplayEnabled(true);
536e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
546e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
55e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void setTargetContactId(long targetContactId) {
56e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        this.mTargetContactId = targetContactId;
576e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
586e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
59e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
60e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void configureLoader(CursorLoader cursorLoader) {
61e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        JoinContactLoader loader = (JoinContactLoader)cursorLoader;
62e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        loader.setLoadSuggestionsAndAllContacts(mAllContactsListShown);
63e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
64e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        Builder builder = Contacts.CONTENT_URI.buildUpon();
65e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        builder.appendEncodedPath(String.valueOf(mTargetContactId));
66e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        builder.appendEncodedPath(AggregationSuggestions.CONTENT_DIRECTORY);
67e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
68e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        String filter = getQueryString();
69e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (!TextUtils.isEmpty(filter)) {
70e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            builder.appendEncodedPath(Uri.encode(filter));
71e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        }
72e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
73e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        builder.appendQueryParameter("limit", String.valueOf(MAX_SUGGESTIONS));
74e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
75e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        loader.setSuggestionUri(builder.build());
76e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
77e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        // TODO simplify projection
78e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        loader.setProjection(PROJECTION);
79e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
80e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (mAllContactsListShown) {
81e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            loader.setUri(buildSectionIndexerUri(Contacts.CONTENT_URI));
82e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            loader.setSelection(Contacts.IN_VISIBLE_GROUP + "=1 AND " + Contacts._ID + "!=?");
83e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            loader.setSelectionArgs(new String[]{String.valueOf(mTargetContactId)});
84e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            if (getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY) {
85e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                loader.setSortOrder(Contacts.SORT_KEY_PRIMARY);
86e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else {
87e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                loader.setSortOrder(Contacts.SORT_KEY_ALTERNATIVE);
88e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            }
89e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        }
90e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
91e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
92e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
93e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public boolean isEmpty() {
94e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return false;
95e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
96e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
97e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private boolean hasSuggestions() {
98e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return mSuggestionsCursorCount != 0;
99e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
100e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
101e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public boolean isAllContactsListShown() {
102e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return mAllContactsListShown;
103e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
104e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
105e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void setAllContactsListShown(boolean flag) {
106e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        mAllContactsListShown = flag;
1076e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
1086e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
1096e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public void setSuggestionsCursor(Cursor cursor) {
1106e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        mSuggestionsCursor = cursor;
1116e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        mSuggestionsCursorCount = cursor == null ? 0 : cursor.getCount();
1126e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
1136e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
114e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public boolean isShowAllContactsItemPosition(int position) {
115e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return !mAllContactsListShown
116e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                && hasSuggestions() && position == mSuggestionsCursorCount + 2;
1176e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
1186e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
1196e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
1206e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public View getView(int position, View convertView, ViewGroup parent) {
1216e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (!mDataValid) {
1226e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            throw new IllegalStateException(
1236e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov                    "this should only be called when the cursor is valid");
1246e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
1256e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
1266e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        Cursor cursor;
127e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        boolean showingSuggestion = false;
128e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (hasSuggestions()) {
129e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            if (position == 0) {
130e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                // First section: "suggestions"
131e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                TextView view = (TextView) inflate(R.layout.list_separator, parent);
132e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                view.setText(R.string.separatorJoinAggregateSuggestions);
133e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return view;
134e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else if (position < mSuggestionsCursorCount + 1) {
135e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                showingSuggestion = true;
136e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                cursor = mSuggestionsCursor;
137e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                cursor.moveToPosition(position - 1);
138e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else if (position == mSuggestionsCursorCount + 1) {
139e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                // Second section: "all contacts"
140e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                TextView view = (TextView) inflate(R.layout.list_separator, parent);
141e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                view.setText(R.string.separatorJoinAggregateAll);
142e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return view;
143e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else if (!mAllContactsListShown && position == mSuggestionsCursorCount + 2) {
144e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return inflate(R.layout.contacts_list_show_all_item, parent);
145e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else {
146e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                cursor = mCursor;
147e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                cursor.moveToPosition(position - mSuggestionsCursorCount - 2);
148e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            }
1496e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        } else {
1506e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            cursor = mCursor;
151e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            cursor.moveToPosition(position);
1526e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
1536e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
1546e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        boolean newView;
1556e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        View v;
1566e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (convertView == null || convertView.getTag() == null) {
1576e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            newView = true;
1586e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            v = newView(getContext(), cursor, parent);
1596e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        } else {
1606e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            newView = false;
1616e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            v = convertView;
1626e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
163e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        bindView(position, v, cursor, showingSuggestion);
1646e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return v;
1656e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
1666e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
167e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    private View inflate(int layoutId, ViewGroup parent) {
168e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return LayoutInflater.from(getContext()).inflate(layoutId, parent, false);
169e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
170e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
171e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
172e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void bindView(View view, Context context, Cursor cursor) {
173e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        // not used
174e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
175e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
176e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public void bindView(int position, View itemView, Cursor cursor, boolean showingSuggestion) {
177e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        final ContactListItemView view = (ContactListItemView)itemView;
178e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (!showingSuggestion) {
179e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            bindSectionHeaderAndDivider(view, position);
180e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        }
181e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        bindPhoto(view, cursor);
182e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        bindName(view, cursor);
183e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
184e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
185e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public Cursor getShowAllContactsLabelCursor() {
186e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        MatrixCursor matrixCursor = new MatrixCursor(PROJECTION);
187e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        Object[] row = new Object[PROJECTION.length];
188e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        matrixCursor.addRow(row);
189e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return matrixCursor;
190e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
191e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
1926e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
1936e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public void changeCursor(Cursor cursor) {
1946e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (cursor == null) {
1956e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            setSuggestionsCursor(null);
1966e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
1976e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
1986e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        super.changeCursor(cursor);
1996e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
200e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
2016e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
2026e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public int getItemViewType(int position) {
2036e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (isShowAllContactsItemPosition(position)) {
2046e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            return IGNORE_ITEM_VIEW_TYPE;
2056e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
2066e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2076e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return super.getItemViewType(position);
2086e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2096e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
210e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
211e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public int getPositionForSection(int sectionIndex) {
212e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (mSuggestionsCursorCount == 0) {
213e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            return super.getPositionForSection(sectionIndex);
2146e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
215e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
216e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        // Get section position in the full list
217e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        int position = super.getPositionForSection(sectionIndex);
218e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return position + mSuggestionsCursorCount + 2;
219e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    }
220e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
221e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    @Override
222e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public int getSectionForPosition(int position) {
223e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (mSuggestionsCursorCount == 0) {
224e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            return super.getSectionForPosition(position);
225e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        }
226e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
227e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (position < mSuggestionsCursorCount + 2) {
228e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            return -1;
229e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        }
230e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov
231e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return super.getSectionForPosition(position - mSuggestionsCursorCount - 2);
2326e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2336e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2346e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
2356e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public boolean areAllItemsEnabled() {
2366e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return super.areAllItemsEnabled() && mSuggestionsCursorCount == 0;
2376e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2386e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2396e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
2406e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public boolean isEnabled(int position) {
2416e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (position == 0) {
2426e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            return false;
2436e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
2446e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2456e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (mSuggestionsCursorCount > 0) {
2466e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            return position != 0 && position != mSuggestionsCursorCount + 1;
2476e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
2486e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return true;
2496e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2506e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2516e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
2526e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public int getCount() {
2536e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        if (!mDataValid) {
2546e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            return 0;
2556e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
2566e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        int superCount = super.getCount();
257e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (hasSuggestions()) {
2586e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            // When showing suggestions, we have 2 additional list items: the "Suggestions"
2596e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            // and "All contacts" headers.
2606e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            return mSuggestionsCursorCount + superCount + 2;
2616e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
2626e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return superCount;
2636e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2646e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2656e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    public int getSuggestionsCursorCount() {
2666e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        return mSuggestionsCursorCount;
2676e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
2686e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
2696e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
270e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public Object getItem(int pos) {
271e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        if (hasSuggestions()) {
2726e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            // When showing suggestions, we have 2 additional list items: the "Suggestions"
2736e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            // and "All contacts" separators.
274e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            if (pos == 0) {
275e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return null;
276e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            }
277e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            else if (pos < mSuggestionsCursorCount + 1) {
2786e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov                // We are in the upper partition (Suggestions). Adjusting for the "Suggestions"
2796e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov                // separator.
280e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                mSuggestionsCursor.moveToPosition(pos - 1);
281e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return mSuggestionsCursor;
282e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            } else if (pos == mSuggestionsCursorCount + 1) {
283e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                // This is the "All contacts" separator
284e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                return null;
2856e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            } else {
286e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                if (!isAllContactsListShown()) {
287e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    // This is the "Show all contacts" item
288e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    return null;
289e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                } else {
290e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    // We are in the lower partition (All contacts). Adjusting for the size
291e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    // of the upper partition plus the two separators.
292e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    mCursor.moveToPosition(pos - mSuggestionsCursorCount - 2);
293e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                    return mCursor;
294e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov                }
2956e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov            }
296e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        } else if (mCursor != null) {
297e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            // No separators
298e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            mCursor.moveToPosition(pos);
299e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            return mCursor;
3006e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        } else {
301e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov            return null;
3026e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov        }
3036e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
3046e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
3056e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    @Override
306e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public long getItemId(int pos) {
307e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        Cursor cursor = (Cursor)getItem(pos);
308e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return cursor == null ? 0 : cursor.getLong(mRowIDColumn);
3096e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
3106e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov
311e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov    public Uri getContactUri(int position) {
312e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        Cursor cursor = (Cursor)getItem(position);
313e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX);
314e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        String lookupKey = cursor.getString(CONTACT_LOOKUP_KEY_COLUMN_INDEX);
315e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9Dmitri Plotnikov        return Contacts.getLookupUri(contactId, lookupKey);
3166e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov    }
3176e2009d58fdcf098cab033729d4a3b2444c2181cDmitri Plotnikov}