1dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee/* 2dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Copyright (C) 2013 The Android Open Source Project 3dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 4dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); 5dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * you may not use this file except in compliance with the License. 6dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * You may obtain a copy of the License at 7dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 8dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * http://www.apache.org/licenses/LICENSE-2.0 9dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 10dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Unless required by applicable law or agreed to in writing, software 11dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * distributed under the License is distributed on an "AS IS" BASIS, 12dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * See the License for the specific language governing permissions and 14dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * limitations under the License. 15dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 16dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leepackage com.android.dialer.list; 17dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 18765734c1d602c9a6d166d653b3684e6408b771c4Yorke Leeimport com.google.common.annotations.VisibleForTesting; 19765734c1d602c9a6d166d653b3684e6408b771c4Yorke Leeimport com.google.common.collect.ComparisonChain; 209b8cc3fa7ea04358624466162fe3ca942673963dYorke Leeimport com.google.common.collect.Lists; 21765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee 229b8cc3fa7ea04358624466162fe3ca942673963dYorke Leeimport android.content.ContentProviderOperation; 23dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.ContentUris; 2455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport android.content.ContentValues; 25dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.Context; 269b8cc3fa7ea04358624466162fe3ca942673963dYorke Leeimport android.content.OperationApplicationException; 27dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.content.res.Resources; 28dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.database.Cursor; 29dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.net.Uri; 309b8cc3fa7ea04358624466162fe3ca942673963dYorke Leeimport android.os.RemoteException; 319b8cc3fa7ea04358624466162fe3ca942673963dYorke Leeimport android.provider.ContactsContract; 32dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.Phone; 33dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.provider.ContactsContract.Contacts; 3455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport android.provider.ContactsContract.PinnedPositions; 354e741192ec40278d9189b46cf2ae6bc547d9071dYorke Leeimport android.text.TextUtils; 36dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.util.Log; 374e741192ec40278d9189b46cf2ae6bc547d9071dYorke Leeimport android.util.LongSparseArray; 38dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.View; 39dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.view.ViewGroup; 40dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.BaseAdapter; 41dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport android.widget.FrameLayout; 42dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 43dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactPhotoManager; 44dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.ContactTileLoaderFactory; 45dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactEntry; 4655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport com.android.contacts.common.list.ContactTileAdapter.DisplayType; 47dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport com.android.contacts.common.list.ContactTileView; 48fc6ed03fb6bd06cd0e0865d1e8a8cb065d5511f8Jeff Davidsonimport com.android.dialer.R; 4955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 50dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Leeimport java.util.ArrayList; 5155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport java.util.Comparator; 5255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport java.util.LinkedList; 5355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport java.util.List; 5455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Leeimport java.util.PriorityQueue; 55dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 56dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee/** 57dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Also allows for a configurable number of columns as well as a maximum row of tiled contacts. 58dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 5911ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Leepublic class PhoneFavoritesTileAdapter extends BaseAdapter implements 60475236caa815206b0d9fca8c2dc4b7a3a5b9c866Yorke Lee OnDragDropListener { 61316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private static final String TAG = PhoneFavoritesTileAdapter.class.getSimpleName(); 62316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private static final boolean DEBUG = false; 63dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 64765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee public static final int NO_ROW_LIMIT = -1; 65765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee 66765734c1d602c9a6d166d653b3684e6408b771c4Yorke Lee public static final int ROW_LIMIT_DEFAULT = NO_ROW_LIMIT; 67dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 68dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactTileView.Listener mListener; 69c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee private OnDataSetChangedForAnimationListener mDataSetChangedListener; 70c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 71dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Context mContext; 72dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private Resources mResources; 73316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 74316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Contact data stored in cache. This is used to populate the associated view. */ 75316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen protected ArrayList<ContactEntry> mContactEntries = null; 76316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Back up of the temporarily removed Contact during dragging. */ 77316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private ContactEntry mDraggedEntry = null; 78316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Position of the temporarily removed contact in the cache. */ 79316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mDraggedEntryIndex = -1; 80316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** New position of the temporarily removed contact in the cache. */ 81316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private int mDropEntryIndex = -1; 8272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang /** New position of the temporarily entered contact in the cache. */ 8372418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang private int mDragEnteredEntryIndex = -1; 84316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 855a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee private boolean mAwaitingRemove = false; 86670fd3f59160bdb81f38b6be2f176ba233915686Yorke Lee private boolean mDelayCursorUpdates = false; 875a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee 88dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private ContactPhotoManager mPhotoManager; 89dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNumFrequents; 906a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int mNumStarred; 91dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 92dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mIdIndex; 93dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mLookupIndex; 94dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPhotoUriIndex; 95dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mNameIndex; 96dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mPresenceIndex; 97dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected int mStatusIndex; 98dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 99dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberIndex; 100dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberTypeIndex; 101dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee private int mPhoneNumberLabelIndex; 10243f543900efac8edc10159851184da8cfca3d81aYorke Lee private int mIsDefaultNumberIndex; 103efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee private int mStarredIndex; 10455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee protected int mPinnedIndex; 105791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee protected int mContactIdIndex; 106dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 107316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Indicates whether a drag is in process. */ 108316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private boolean mInDragging = false; 109316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 1100a3ad7a81821da5b8f4bde566368f5dbc9889aadYorke Lee // Pinned positions start from 1, so there are a total of 20 maximum pinned contacts 1110a3ad7a81821da5b8f4bde566368f5dbc9889aadYorke Lee public static final int PIN_LIMIT = 21; 11255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 113d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang /** 114d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang * The soft limit on how many contact tiles to show. 115d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang * NOTE This soft limit would not restrict the number of starred contacts to show, rather 116d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang * 1. If the count of starred contacts is less than this limit, show 20 tiles total. 117d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang * 2. If the count of starred contacts is more than or equal to this limit, 118d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang * show all starred tiles and no frequents. 119d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang */ 120d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang private static final int TILES_SOFT_LIMIT = 20; 121d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang 12255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final Comparator<ContactEntry> mContactEntryComparator = new Comparator<ContactEntry>() { 12355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee @Override 12455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee public int compare(ContactEntry lhs, ContactEntry rhs) { 12555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee return ComparisonChain.start() 12655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee .compare(lhs.pinned, rhs.pinned) 12755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee .compare(lhs.name, rhs.name) 12855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee .result(); 12955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 13055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee }; 13155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 132c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public interface OnDataSetChangedForAnimationListener { 133c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public void onDataSetChangedForAnimation(long... idsInPlace); 134c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public void cacheOffsetsForDatasetChange(); 135c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee }; 136dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 137316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public PhoneFavoritesTileAdapter(Context context, ContactTileView.Listener listener, 138efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee OnDataSetChangedForAnimationListener dataSetChangedListener) { 139c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mDataSetChangedListener = dataSetChangedListener; 140dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mListener = listener; 141dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mContext = context; 142dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mResources = context.getResources(); 143dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNumFrequents = 0; 144316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries = new ArrayList<ContactEntry>(); 145efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee 146316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 147dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee bindColumnIndices(); 148dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 149dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 150dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setPhotoLoader(ContactPhotoManager photoLoader) { 151dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoManager = photoLoader; 152dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 153dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 154dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 155316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Indicates whether a drag is in process. 156316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 157316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param inDragging Boolean variable indicating whether there is a drag in process. 158316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 159316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void setInDragging(boolean inDragging) { 160670fd3f59160bdb81f38b6be2f176ba233915686Yorke Lee mDelayCursorUpdates = inDragging; 161316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mInDragging = inDragging; 162316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 163316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 164316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** Gets whether the drag is in process. */ 165316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public boolean getInDragging() { 166316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen return mInDragging; 167316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 168316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 169316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 170dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Sets the column indices for expected {@link Cursor} 171dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * based on {@link DisplayType}. 172dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 173dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void bindColumnIndices() { 174dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mIdIndex = ContactTileLoaderFactory.CONTACT_ID; 175dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mLookupIndex = ContactTileLoaderFactory.LOOKUP_KEY; 176dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhotoUriIndex = ContactTileLoaderFactory.PHOTO_URI; 177dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mNameIndex = ContactTileLoaderFactory.DISPLAY_NAME; 178dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStarredIndex = ContactTileLoaderFactory.STARRED; 179dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE; 180dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS; 181dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 182dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberIndex = ContactTileLoaderFactory.PHONE_NUMBER; 183dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberTypeIndex = ContactTileLoaderFactory.PHONE_NUMBER_TYPE; 184dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee mPhoneNumberLabelIndex = ContactTileLoaderFactory.PHONE_NUMBER_LABEL; 18543f543900efac8edc10159851184da8cfca3d81aYorke Lee mIsDefaultNumberIndex = ContactTileLoaderFactory.IS_DEFAULT_NUMBER; 18655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee mPinnedIndex = ContactTileLoaderFactory.PINNED; 187791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee mContactIdIndex = ContactTileLoaderFactory.CONTACT_ID_FOR_DATA; 188dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 189dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 190dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 191dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Gets the number of frequents from the passed in cursor. 192dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 193dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * This methods is needed so the GroupMemberTileAdapter can override this. 194dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 195dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * @param cursor The cursor to get number of frequents from. 196dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 197dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected void saveNumFrequentsFromCursor(Cursor cursor) { 1986a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee mNumFrequents = cursor.getCount() - mNumStarred; 199dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 200dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 201dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 202dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Creates {@link ContactTileView}s for each item in {@link Cursor}. 203dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * 204dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Else use {@link ContactTileLoaderFactory} 205dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 206dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public void setContactCursor(Cursor cursor) { 207670fd3f59160bdb81f38b6be2f176ba233915686Yorke Lee if (!mDelayCursorUpdates && cursor != null && !cursor.isClosed()) { 208316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mNumStarred = getNumStarredContacts(cursor); 209c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee if (mAwaitingRemove) { 210c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mDataSetChangedListener.cacheOffsetsForDatasetChange(); 211c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 212c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 213316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen saveNumFrequentsFromCursor(cursor); 214316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen saveCursorToCache(cursor); 215316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen // cause a refresh of any views that rely on this data 216316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 217c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee // about to start redraw 218efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee mDataSetChangedListener.onDataSetChangedForAnimation(); 219316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 220316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 221dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 222316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 223316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Saves the cursor data to the cache, to speed up UI changes. 224316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 225316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param cursor Returned cursor with data to populate the view. 226316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 227316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen private void saveCursorToCache(Cursor cursor) { 228316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mContactEntries.clear(); 22955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 230443d758d53d1f7ebb12e8ed39fc6195c9d5ed18dYorke Lee cursor.moveToPosition(-1); 23155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 2324e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final LongSparseArray<Object> duplicates = new LongSparseArray<Object>(cursor.getCount()); 233443d758d53d1f7ebb12e8ed39fc6195c9d5ed18dYorke Lee 234d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang // Track the length of {@link #mContactEntries} and compare to {@link #TILES_SOFT_LIMIT}. 235d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang int counter = 0; 236d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang 2374e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee while (cursor.moveToNext()) { 2384e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 2394e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final int starred = cursor.getInt(mStarredIndex); 2404e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final long id; 24155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 242791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee // We display a maximum of TILES_SOFT_LIMIT contacts, or the total number of starred 243791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee // whichever is greater. 244791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee if (starred < 1 && counter >= TILES_SOFT_LIMIT) { 245d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang break; 24655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } else { 247791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee id = cursor.getLong(mContactIdIndex); 24855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 2494e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 25043f543900efac8edc10159851184da8cfca3d81aYorke Lee final ContactEntry existing = (ContactEntry) duplicates.get(id); 25143f543900efac8edc10159851184da8cfca3d81aYorke Lee if (existing != null) { 25243f543900efac8edc10159851184da8cfca3d81aYorke Lee // Check if the existing number is a default number. If not, clear the phone number 25343f543900efac8edc10159851184da8cfca3d81aYorke Lee // and label fields so that the disambiguation dialog will show up. 25443f543900efac8edc10159851184da8cfca3d81aYorke Lee if (!existing.isDefaultNumber) { 25543f543900efac8edc10159851184da8cfca3d81aYorke Lee existing.phoneLabel = null; 25643f543900efac8edc10159851184da8cfca3d81aYorke Lee existing.phoneNumber = null; 25743f543900efac8edc10159851184da8cfca3d81aYorke Lee } 2584e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee continue; 2594e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee } 2604e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 2614e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final String photoUri = cursor.getString(mPhotoUriIndex); 2624e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final String lookupKey = cursor.getString(mLookupIndex); 2634e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final int pinned = cursor.getInt(mPinnedIndex); 2644e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final String name = cursor.getString(mNameIndex); 2659bead9c01ab09ebfbd1c2be8555d8c8d4e3cf6bdChristine Chen final boolean isStarred = cursor.getInt(mStarredIndex) > 0; 26643f543900efac8edc10159851184da8cfca3d81aYorke Lee final boolean isDefaultNumber = cursor.getInt(mIsDefaultNumberIndex) > 0; 2674e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 2684e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee final ContactEntry contact = new ContactEntry(); 2694e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 2704e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee contact.id = id; 2714e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee contact.name = (!TextUtils.isEmpty(name)) ? name : 2724e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee mResources.getString(R.string.missing_name); 273443d758d53d1f7ebb12e8ed39fc6195c9d5ed18dYorke Lee contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); 27456cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee contact.lookupKey = lookupKey; 27556cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee contact.lookupUri = ContentUris.withAppendedId( 276443d758d53d1f7ebb12e8ed39fc6195c9d5ed18dYorke Lee Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), id); 2779bead9c01ab09ebfbd1c2be8555d8c8d4e3cf6bdChristine Chen contact.isFavorite = isStarred; 27843f543900efac8edc10159851184da8cfca3d81aYorke Lee contact.isDefaultNumber = isDefaultNumber; 2794e741192ec40278d9189b46cf2ae6bc547d9071dYorke Lee 28043f543900efac8edc10159851184da8cfca3d81aYorke Lee // Set phone number and label 281791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee final int phoneNumberType = cursor.getInt(mPhoneNumberTypeIndex); 282791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee final String phoneNumberCustomLabel = cursor.getString(mPhoneNumberLabelIndex); 283791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee contact.phoneLabel = (String) Phone.getTypeLabel(mResources, phoneNumberType, 284791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee phoneNumberCustomLabel); 285791082e22b50db98de6749bb5ef878d3ec483e28Yorke Lee contact.phoneNumber = cursor.getString(mPhoneNumberIndex); 28655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 28755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee contact.pinned = pinned; 288443d758d53d1f7ebb12e8ed39fc6195c9d5ed18dYorke Lee mContactEntries.add(contact); 289d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang 29043f543900efac8edc10159851184da8cfca3d81aYorke Lee duplicates.put(id, contact); 29143f543900efac8edc10159851184da8cfca3d81aYorke Lee 292d954cd76c610e8fafd91aec857f4232ab49ef2cdHongwei Wang counter++; 293316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 29455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 2955a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee mAwaitingRemove = false; 2965a1db1cd6a8addc0401529454bde6e1d15f215a0Yorke Lee 29755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee arrangeContactsByPinnedPosition(mContactEntries); 29855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 29955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee notifyDataSetChanged(); 300dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 301dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 302dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 303dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Iterates over the {@link Cursor} 304dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns position of the first NON Starred Contact 305dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns -1 if {@link DisplayType#STARRED_ONLY} 306dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns 0 if {@link DisplayType#FREQUENT_ONLY} 307dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 3086a8402939f667ab70bd0043ed0859f8afbc012ecYorke Lee protected int getNumStarredContacts(Cursor cursor) { 309dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee cursor.moveToPosition(-1); 310dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee while (cursor.moveToNext()) { 311dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee if (cursor.getInt(mStarredIndex) == 0) { 312dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getPosition(); 313dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 314dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 315dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 316dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // There are not NON Starred contacts in cursor 317dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee // Set divider positon to end 318dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return cursor.getCount(); 319dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 320dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 321316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 322dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns the number of frequents that will be displayed in the list. 323dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 324dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getNumFrequents() { 325dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return mNumFrequents; 326dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 327dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 328dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 329dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getCount() { 330efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (mContactEntries == null) { 3314fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen return 0; 332dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 333dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 334efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return mContactEntries.size(); 335dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 336dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 337dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 338dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * Returns an ArrayList of the {@link ContactEntry}s that are to appear 339dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee * on the row for the given position. 340dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee */ 341dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 342efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee public ContactEntry getItem(int position) { 343efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return mContactEntries.get(position); 344dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 345dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 346c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee /** 347c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee * For the top row of tiled contacts, the item id is the position of the row of 348c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee * contacts. 349c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee * For frequent contacts, the item id is the maximum number of rows of tiled contacts + 350c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee * the actual contact id. Since contact ids are always greater than 0, this guarantees that 351c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee * all items within this adapter will always have unique ids. 352c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee */ 353dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 354dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public long getItemId(int position) { 355efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return getItem(position).id; 356c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee } 357c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee 358c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee @Override 359c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee public boolean hasStableIds() { 360c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee return true; 361dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 362dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 363dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 364dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean areAllItemsEnabled() { 365dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return true; 366dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 367dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 368dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 369dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public boolean isEnabled(int position) { 3704fdf594962b3928c6497b471dbb1ee7be56e18efChristine Chen return getCount() > 0; 371dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 372dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 373dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 374316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void notifyDataSetChanged() { 375316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (DEBUG) { 37655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee Log.v(TAG, "notifyDataSetChanged"); 377316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 378316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen super.notifyDataSetChanged(); 379316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 380316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 381316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen @Override 382dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public View getView(int position, View convertView, ViewGroup parent) { 38355d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee if (DEBUG) { 38455d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee Log.v(TAG, "get view for " + String.valueOf(position)); 38555d3bb4a7f70d4a4359c31b3240f5740b788e643Yorke Lee } 38618e7fdd55f67e3636c161462cb54e7f5555a04deYorke Lee 387dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee int itemViewType = getItemViewType(position); 388dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 389efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee PhoneFavoriteTileView tileView = null; 3901f06f0ad1229f3b4e00553c294e664ffa5234c90Christine Chen 391efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (convertView instanceof PhoneFavoriteTileView) { 392efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee tileView = (PhoneFavoriteTileView) convertView; 3931f06f0ad1229f3b4e00553c294e664ffa5234c90Christine Chen } 3946091473941d277ed3746143c1ca9bffdfbe2bd94Christine Chen 395efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (tileView == null) { 396efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee tileView = (PhoneFavoriteTileView) View.inflate(mContext, 397efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee R.layout.phone_favorite_tile_view, null); 398dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 399efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee tileView.setPhotoManager(mPhotoManager); 40001fb754b6b4b869c58c3fdcc74735e027f8cea97Yorke Lee tileView.setListener(mListener); 401efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee tileView.loadFromContact(getItem(position)); 402efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return tileView; 403dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 404dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 405dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 406dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getViewTypeCount() { 407dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee return ViewTypes.COUNT; 408dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 409dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 410dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee @Override 411dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee public int getItemViewType(int position) { 412efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return ViewTypes.TILE; 413dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 414dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee 415dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee /** 416316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Temporarily removes a contact from the list for UI refresh. Stores data for this contact 417316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * in the back-up variable. 418316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * 419316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * @param index Position of the contact to be removed. 420316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 421316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void popContactEntry(int index) { 42272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang if (isIndexInBound(index)) { 423316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = mContactEntries.get(index); 424316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntryIndex = index; 42572418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mDragEnteredEntryIndex = index; 42672418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang markDropArea(mDragEnteredEntryIndex); 42772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 42872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 42972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang 43072418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang /** 43172418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang * @param itemIndex Position of the contact in {@link #mContactEntries}. 43272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang * @return True if the given index is valid for {@link #mContactEntries}. 43372418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang */ 434e48124fa2d295c68cdb95f962ef8bd6d35a7c145Anthony Lee public boolean isIndexInBound(int itemIndex) { 43572418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang return itemIndex >= 0 && itemIndex < mContactEntries.size(); 43672418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 43772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang 43872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang /** 43972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang * Mark the tile as drop area by given the item index in {@link #mContactEntries}. 44072418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang * 44172418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang * @param itemIndex Position of the contact in {@link #mContactEntries}. 44272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang */ 44372418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang private void markDropArea(int itemIndex) { 444c57f6640569acb1df4fc5d7d2b026e824351b531Jay Shrauner if (mDraggedEntry != null && isIndexInBound(mDragEnteredEntryIndex) && 445c57f6640569acb1df4fc5d7d2b026e824351b531Jay Shrauner isIndexInBound(itemIndex)) { 4465b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang mDataSetChangedListener.cacheOffsetsForDatasetChange(); 44772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang // Remove the old placeholder item and place the new placeholder item. 4485b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang final int oldIndex = mDragEnteredEntryIndex; 44972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.remove(mDragEnteredEntryIndex); 45072418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mDragEnteredEntryIndex = itemIndex; 45172418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.add(mDragEnteredEntryIndex, ContactEntry.BLANK_ENTRY); 45272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang ContactEntry.BLANK_ENTRY.id = mDraggedEntry.id; 4535b2e21098d84e94fd629e5e07c3bbb66bf9b5d95Hongwei Wang mDataSetChangedListener.onDataSetChangedForAnimation(); 454316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen notifyDataSetChanged(); 455316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 456316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 457316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 458316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 459316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Drops the temporarily removed contact to the desired location in the list. 460316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 46172418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang public void handleDrop() { 46255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee boolean changed = false; 463316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen if (mDraggedEntry != null) { 4644911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang if (isIndexInBound(mDragEnteredEntryIndex) && 4654911300ae3fa7ab186ee271f8bc431b65a819a3cHongwei Wang mDragEnteredEntryIndex != mDraggedEntryIndex) { 46655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // Don't add the ContactEntry here (to prevent a double animation from occuring). 46755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // When we receive a new cursor the list of contact entries will automatically be 46855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // populated with the dragged ContactEntry at the correct spot. 46972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mDropEntryIndex = mDragEnteredEntryIndex; 47072418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.set(mDropEntryIndex, mDraggedEntry); 471c36684277aa45085999284bfe71cb8be71b3a464Yorke Lee mDataSetChangedListener.cacheOffsetsForDatasetChange(); 47255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee changed = true; 47372418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } else if (isIndexInBound(mDraggedEntryIndex)) { 47472418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang // If {@link #mDragEnteredEntryIndex} is invalid, 47572418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang // falls back to the original position of the contact. 47672418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.remove(mDragEnteredEntryIndex); 47772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.add(mDraggedEntryIndex, mDraggedEntry); 478316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDropEntryIndex = mDraggedEntryIndex; 47955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee notifyDataSetChanged(); 48055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 48155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 48255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee if (changed && mDropEntryIndex < PIN_LIMIT) { 4839b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee final ArrayList<ContentProviderOperation> operations = 4849b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee getReflowedPinningOperations(mContactEntries, mDraggedEntryIndex, 4859b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee mDropEntryIndex); 4869b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee if (!operations.isEmpty()) { 4879b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee // update the database here with the new pinned positions 4889b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee try { 4899b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, 4909b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee operations); 4919b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee } catch (RemoteException | OperationApplicationException e) { 4929b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee Log.e(TAG, "Exception thrown when pinning contacts", e); 4939b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee } 4949b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee } 495316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 496316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = null; 497316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 498316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 499316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 500316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 50101f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen * Invoked when the dragged item is dropped to unsupported location. We will then move the 50201f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen * contact back to where it was dragged from. 50301f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen */ 50401f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen public void dropToUnsupportedView() { 50572418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang if (isIndexInBound(mDragEnteredEntryIndex)) { 50672418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.remove(mDragEnteredEntryIndex); 50772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mContactEntries.add(mDraggedEntryIndex, mDraggedEntry); 50872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang notifyDataSetChanged(); 50972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 51001f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen } 51101f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen 51201f15ad65dfbc72d7c8f165bda8e602ba287b434Christine Chen /** 513316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen * Clears all temporary variables at a new interaction. 514316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen */ 515316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen public void cleanTempVariables() { 516316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntryIndex = -1; 517316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDropEntryIndex = -1; 51872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mDragEnteredEntryIndex = -1; 519316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen mDraggedEntry = null; 520316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen } 521316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen 522316b4713b2f8f26f393ecc4bb4760512a4a9f096Christine Chen /** 523efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee * Used when a contact is removed from speeddial. This will both unstar and set pinned position 524efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee * of the contact to PinnedPosition.DEMOTED so that it doesn't show up anymore in the favorites 525efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee * list. 52655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee */ 52755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee private void unstarAndUnpinContact(Uri contactUri) { 52855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final ContentValues values = new ContentValues(2); 52955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee values.put(Contacts.STARRED, false); 53055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee values.put(Contacts.PINNED, PinnedPositions.DEMOTED); 53155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee mContext.getContentResolver().update(contactUri, values, null, null); 53255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 53355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 53455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee /** 53555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * Given a list of contacts that each have pinned positions, rearrange the list (destructive) 53655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * such that all pinned contacts are in their defined pinned positions, and unpinned contacts 53755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * take the spaces between those pinned contacts. Demoted contacts should not appear in the 53855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * resulting list. 53955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * 54055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * This method also updates the pinned positions of pinned contacts so that they are all 54155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * unique positive integers within range from 0 to toArrange.size() - 1. This is because 54255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * when the contact entries are read from the database, it is possible for them to have 54355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * overlapping pin positions due to sync or modifications by third party apps. 54455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee */ 54555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee @VisibleForTesting 54655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee /* package */ void arrangeContactsByPinnedPosition(ArrayList<ContactEntry> toArrange) { 54755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final PriorityQueue<ContactEntry> pinnedQueue = 54855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee new PriorityQueue<ContactEntry>(PIN_LIMIT, mContactEntryComparator); 54955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 55055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final List<ContactEntry> unpinnedContacts = new LinkedList<ContactEntry>(); 55155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 55255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final int length = toArrange.size(); 55355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee for (int i = 0; i < length; i++) { 55455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final ContactEntry contact = toArrange.get(i); 55555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // Decide whether the contact is hidden(demoted), pinned, or unpinned 5560a3ad7a81821da5b8f4bde566368f5dbc9889aadYorke Lee if (contact.pinned > PIN_LIMIT || contact.pinned == PinnedPositions.UNPINNED) { 55755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee unpinnedContacts.add(contact); 55855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } else if (contact.pinned > PinnedPositions.DEMOTED) { 55955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // Demoted or contacts with negative pinned positions are ignored. 56055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // Pinned contacts go into a priority queue where they are ranked by pinned 56155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // position. This is required because the contacts provider does not return 56255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // contacts ordered by pinned position. 56355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee pinnedQueue.add(contact); 56455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 56555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 56655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 56755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final int maxToPin = Math.min(PIN_LIMIT, pinnedQueue.size() + unpinnedContacts.size()); 56855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 56955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toArrange.clear(); 5700a3ad7a81821da5b8f4bde566368f5dbc9889aadYorke Lee for (int i = 1; i < maxToPin + 1; i++) { 57155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee if (!pinnedQueue.isEmpty() && pinnedQueue.peek().pinned <= i) { 57255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final ContactEntry toPin = pinnedQueue.poll(); 57355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toPin.pinned = i; 57455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toArrange.add(toPin); 57555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } else if (!unpinnedContacts.isEmpty()) { 57655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toArrange.add(unpinnedContacts.remove(0)); 57755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 57855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 57955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 58055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // If there are still contacts in pinnedContacts at this point, it means that the pinned 58155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // positions of these pinned contacts exceed the actual number of contacts in the list. 58255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // For example, the user had 10 frequents, starred and pinned one of them at the last spot, 58355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // and then cleared frequents. Contacts in this situation should become unpinned. 58455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee while (!pinnedQueue.isEmpty()) { 58555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee final ContactEntry entry = pinnedQueue.poll(); 58655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee entry.pinned = PinnedPositions.UNPINNED; 58755f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toArrange.add(entry); 58855f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 58955f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 59055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // Any remaining unpinned contacts that weren't in the gaps between the pinned contacts 59155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee // now just get appended to the end of the list. 59255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee toArrange.addAll(unpinnedContacts); 59355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 59455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 59555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee /** 59655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * Given an existing list of contact entries and a single entry that is to be pinned at a 5979b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee * particular position, return a list of {@link ContentProviderOperation}s that contains new 5989b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee * pinned positions for all contacts that are forced to be pinned at new positions, trying as 5999b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee * much as possible to keep pinned contacts at their original location. 60055f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * 60155f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * At this point in time the pinned position of each contact in the list has already been 60255f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * updated by {@link #arrangeContactsByPinnedPosition}, so we can assume that all pinned 60355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee * positions(within {@link #PIN_LIMIT} are unique positive integers. 60455f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee */ 60555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee @VisibleForTesting 6069b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee /* package */ ArrayList<ContentProviderOperation> getReflowedPinningOperations( 6079b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee ArrayList<ContactEntry> list, int oldPos, int newPinPos) { 6089b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee final ArrayList<ContentProviderOperation> positions = Lists.newArrayList(); 60972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang final int lowerBound = Math.min(oldPos, newPinPos); 61072418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang final int upperBound = Math.max(oldPos, newPinPos); 61172418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang for (int i = lowerBound; i <= upperBound; i++) { 61272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang final ContactEntry entry = list.get(i); 61349447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee 61449447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee // Pinned positions in the database start from 1 instead of being zero-indexed like 61549447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee // arrays, so offset by 1. 61649447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee final int databasePinnedPosition = i + 1; 61749447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee if (entry.pinned == databasePinnedPosition) continue; 6189b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee 6199b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(entry.id)); 6209b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee final ContentValues values = new ContentValues(); 62149447a9859b6f45dd4eb4cb9302931c725257038Yorke Lee values.put(Contacts.PINNED, databasePinnedPosition); 6229b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee positions.add(ContentProviderOperation.newUpdate(uri).withValues(values).build()); 62355f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 6249b8cc3fa7ea04358624466162fe3ca942673963dYorke Lee return positions; 62555f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee } 62655f3ec9f882b2389e498ea68f68ce8670c5d4c73Yorke Lee 627dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee protected static class ViewTypes { 628efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee public static final int TILE = 0; 62964f9593c85ac00dbcdbc99d2d18c457c0bd0f68eYorke Lee public static final int COUNT = 1; 630dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee } 63111ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee 63211ee58b1b8711c6d3b2ade6a71835b6c102a08a7Yorke Lee @Override 633efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee public void onDragStarted(int x, int y, PhoneFavoriteSquareTileView view) { 6347639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang setInDragging(true); 635efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee final int itemIndex = mContactEntries.indexOf(view.getContactEntry()); 6367639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang popContactEntry(itemIndex); 63718e7fdd55f67e3636c161462cb54e7f5555a04deYorke Lee } 63872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang 6397639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang @Override 640efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee public void onDragHovered(int x, int y, PhoneFavoriteSquareTileView view) { 641efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee if (view == null) { 642efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee // The user is hovering over a view that is not a contact tile, no need to do 643efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee // anything here. 644efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee return; 645efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee } 646efb2d9c2e32ca4ed434ff785c4b3d18c9e08db6dYorke Lee final int itemIndex = mContactEntries.indexOf(view.getContactEntry()); 64772418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang if (mInDragging && 64872418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang mDragEnteredEntryIndex != itemIndex && 64972418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang isIndexInBound(itemIndex) && 6503cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee itemIndex < PIN_LIMIT && 6513cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee itemIndex >= 0) { 65272418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang markDropArea(itemIndex); 65372418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 65472418af9f84b7a97ff8cb08b99aa68b2db9ee1a9Hongwei Wang } 6557639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang 6567639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang @Override 6573cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee public void onDragFinished(int x, int y) { 6587639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang setInDragging(false); 6593cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee // A contact has been dragged to the RemoveView in order to be unstarred, so simply wait 6603cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee // for the new contact cursor which will cause the UI to be refreshed without the unstarred 6613cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee // contact. 6623cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee if (!mAwaitingRemove) { 6633cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee handleDrop(); 6643cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } 6653cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } 6663cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee 6673cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee @Override 6683cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee public void onDroppedOnRemove() { 6693cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee if (mDraggedEntry != null) { 67056cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee unstarAndUnpinContact(mDraggedEntry.lookupUri); 6713cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee mAwaitingRemove = true; 6723cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1Yorke Lee } 6737639fe9a3ecc9c197718a9f81d8a745d2f660cb3Hongwei Wang } 674dfb2eee7d98f8540fd1614db66bb03e8e1f3a26aYorke Lee} 675