JoinContactListAdapter.java revision e4d32d92b10c1c1ce89c7a3ee4111a030e6afcf9
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 com.android.contacts.R; 19 20import android.app.patterns.CursorLoader; 21import android.content.Context; 22import android.database.Cursor; 23import android.database.MatrixCursor; 24import android.net.Uri; 25import android.net.Uri.Builder; 26import android.provider.ContactsContract; 27import android.provider.ContactsContract.Contacts; 28import android.provider.ContactsContract.Contacts.AggregationSuggestions; 29import android.text.TextUtils; 30import android.view.LayoutInflater; 31import android.view.View; 32import android.view.ViewGroup; 33import android.widget.TextView; 34 35public class JoinContactListAdapter extends ContactListAdapter { 36 37 /** Maximum number of suggestions shown for joining aggregates */ 38 private static final int MAX_SUGGESTIONS = 4; 39 40 private Cursor mSuggestionsCursor; 41 private int mSuggestionsCursorCount; 42 private long mTargetContactId; 43 44 /** 45 * Determines whether we display a list item with the label 46 * "Show all contacts" or actually show all contacts 47 */ 48 private boolean mAllContactsListShown; 49 50 public JoinContactListAdapter(Context context) { 51 super(context); 52 setSectionHeaderDisplayEnabled(true); 53 } 54 55 public void setTargetContactId(long targetContactId) { 56 this.mTargetContactId = targetContactId; 57 } 58 59 @Override 60 public void configureLoader(CursorLoader cursorLoader) { 61 JoinContactLoader loader = (JoinContactLoader)cursorLoader; 62 loader.setLoadSuggestionsAndAllContacts(mAllContactsListShown); 63 64 Builder builder = Contacts.CONTENT_URI.buildUpon(); 65 builder.appendEncodedPath(String.valueOf(mTargetContactId)); 66 builder.appendEncodedPath(AggregationSuggestions.CONTENT_DIRECTORY); 67 68 String filter = getQueryString(); 69 if (!TextUtils.isEmpty(filter)) { 70 builder.appendEncodedPath(Uri.encode(filter)); 71 } 72 73 builder.appendQueryParameter("limit", String.valueOf(MAX_SUGGESTIONS)); 74 75 loader.setSuggestionUri(builder.build()); 76 77 // TODO simplify projection 78 loader.setProjection(PROJECTION); 79 80 if (mAllContactsListShown) { 81 loader.setUri(buildSectionIndexerUri(Contacts.CONTENT_URI)); 82 loader.setSelection(Contacts.IN_VISIBLE_GROUP + "=1 AND " + Contacts._ID + "!=?"); 83 loader.setSelectionArgs(new String[]{String.valueOf(mTargetContactId)}); 84 if (getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY) { 85 loader.setSortOrder(Contacts.SORT_KEY_PRIMARY); 86 } else { 87 loader.setSortOrder(Contacts.SORT_KEY_ALTERNATIVE); 88 } 89 } 90 } 91 92 @Override 93 public boolean isEmpty() { 94 return false; 95 } 96 97 private boolean hasSuggestions() { 98 return mSuggestionsCursorCount != 0; 99 } 100 101 public boolean isAllContactsListShown() { 102 return mAllContactsListShown; 103 } 104 105 public void setAllContactsListShown(boolean flag) { 106 mAllContactsListShown = flag; 107 } 108 109 public void setSuggestionsCursor(Cursor cursor) { 110 mSuggestionsCursor = cursor; 111 mSuggestionsCursorCount = cursor == null ? 0 : cursor.getCount(); 112 } 113 114 public boolean isShowAllContactsItemPosition(int position) { 115 return !mAllContactsListShown 116 && hasSuggestions() && position == mSuggestionsCursorCount + 2; 117 } 118 119 @Override 120 public View getView(int position, View convertView, ViewGroup parent) { 121 if (!mDataValid) { 122 throw new IllegalStateException( 123 "this should only be called when the cursor is valid"); 124 } 125 126 Cursor cursor; 127 boolean showingSuggestion = false; 128 if (hasSuggestions()) { 129 if (position == 0) { 130 // First section: "suggestions" 131 TextView view = (TextView) inflate(R.layout.list_separator, parent); 132 view.setText(R.string.separatorJoinAggregateSuggestions); 133 return view; 134 } else if (position < mSuggestionsCursorCount + 1) { 135 showingSuggestion = true; 136 cursor = mSuggestionsCursor; 137 cursor.moveToPosition(position - 1); 138 } else if (position == mSuggestionsCursorCount + 1) { 139 // Second section: "all contacts" 140 TextView view = (TextView) inflate(R.layout.list_separator, parent); 141 view.setText(R.string.separatorJoinAggregateAll); 142 return view; 143 } else if (!mAllContactsListShown && position == mSuggestionsCursorCount + 2) { 144 return inflate(R.layout.contacts_list_show_all_item, parent); 145 } else { 146 cursor = mCursor; 147 cursor.moveToPosition(position - mSuggestionsCursorCount - 2); 148 } 149 } else { 150 cursor = mCursor; 151 cursor.moveToPosition(position); 152 } 153 154 boolean newView; 155 View v; 156 if (convertView == null || convertView.getTag() == null) { 157 newView = true; 158 v = newView(getContext(), cursor, parent); 159 } else { 160 newView = false; 161 v = convertView; 162 } 163 bindView(position, v, cursor, showingSuggestion); 164 return v; 165 } 166 167 private View inflate(int layoutId, ViewGroup parent) { 168 return LayoutInflater.from(getContext()).inflate(layoutId, parent, false); 169 } 170 171 @Override 172 public void bindView(View view, Context context, Cursor cursor) { 173 // not used 174 } 175 176 public void bindView(int position, View itemView, Cursor cursor, boolean showingSuggestion) { 177 final ContactListItemView view = (ContactListItemView)itemView; 178 if (!showingSuggestion) { 179 bindSectionHeaderAndDivider(view, position); 180 } 181 bindPhoto(view, cursor); 182 bindName(view, cursor); 183 } 184 185 public Cursor getShowAllContactsLabelCursor() { 186 MatrixCursor matrixCursor = new MatrixCursor(PROJECTION); 187 Object[] row = new Object[PROJECTION.length]; 188 matrixCursor.addRow(row); 189 return matrixCursor; 190 } 191 192 @Override 193 public void changeCursor(Cursor cursor) { 194 if (cursor == null) { 195 setSuggestionsCursor(null); 196 } 197 198 super.changeCursor(cursor); 199 } 200 201 @Override 202 public int getItemViewType(int position) { 203 if (isShowAllContactsItemPosition(position)) { 204 return IGNORE_ITEM_VIEW_TYPE; 205 } 206 207 return super.getItemViewType(position); 208 } 209 210 @Override 211 public int getPositionForSection(int sectionIndex) { 212 if (mSuggestionsCursorCount == 0) { 213 return super.getPositionForSection(sectionIndex); 214 } 215 216 // Get section position in the full list 217 int position = super.getPositionForSection(sectionIndex); 218 return position + mSuggestionsCursorCount + 2; 219 } 220 221 @Override 222 public int getSectionForPosition(int position) { 223 if (mSuggestionsCursorCount == 0) { 224 return super.getSectionForPosition(position); 225 } 226 227 if (position < mSuggestionsCursorCount + 2) { 228 return -1; 229 } 230 231 return super.getSectionForPosition(position - mSuggestionsCursorCount - 2); 232 } 233 234 @Override 235 public boolean areAllItemsEnabled() { 236 return super.areAllItemsEnabled() && mSuggestionsCursorCount == 0; 237 } 238 239 @Override 240 public boolean isEnabled(int position) { 241 if (position == 0) { 242 return false; 243 } 244 245 if (mSuggestionsCursorCount > 0) { 246 return position != 0 && position != mSuggestionsCursorCount + 1; 247 } 248 return true; 249 } 250 251 @Override 252 public int getCount() { 253 if (!mDataValid) { 254 return 0; 255 } 256 int superCount = super.getCount(); 257 if (hasSuggestions()) { 258 // When showing suggestions, we have 2 additional list items: the "Suggestions" 259 // and "All contacts" headers. 260 return mSuggestionsCursorCount + superCount + 2; 261 } 262 return superCount; 263 } 264 265 public int getSuggestionsCursorCount() { 266 return mSuggestionsCursorCount; 267 } 268 269 @Override 270 public Object getItem(int pos) { 271 if (hasSuggestions()) { 272 // When showing suggestions, we have 2 additional list items: the "Suggestions" 273 // and "All contacts" separators. 274 if (pos == 0) { 275 return null; 276 } 277 else if (pos < mSuggestionsCursorCount + 1) { 278 // We are in the upper partition (Suggestions). Adjusting for the "Suggestions" 279 // separator. 280 mSuggestionsCursor.moveToPosition(pos - 1); 281 return mSuggestionsCursor; 282 } else if (pos == mSuggestionsCursorCount + 1) { 283 // This is the "All contacts" separator 284 return null; 285 } else { 286 if (!isAllContactsListShown()) { 287 // This is the "Show all contacts" item 288 return null; 289 } else { 290 // We are in the lower partition (All contacts). Adjusting for the size 291 // of the upper partition plus the two separators. 292 mCursor.moveToPosition(pos - mSuggestionsCursorCount - 2); 293 return mCursor; 294 } 295 } 296 } else if (mCursor != null) { 297 // No separators 298 mCursor.moveToPosition(pos); 299 return mCursor; 300 } else { 301 return null; 302 } 303 } 304 305 @Override 306 public long getItemId(int pos) { 307 Cursor cursor = (Cursor)getItem(pos); 308 return cursor == null ? 0 : cursor.getLong(mRowIDColumn); 309 } 310 311 public Uri getContactUri(int position) { 312 Cursor cursor = (Cursor)getItem(position); 313 long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX); 314 String lookupKey = cursor.getString(CONTACT_LOOKUP_KEY_COLUMN_INDEX); 315 return Contacts.getLookupUri(contactId, lookupKey); 316 } 317}