SelectionManager.java revision 21c2e665fdc1d1af0c91ab9c104d13fb7dc2444e
1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.app.GalleryContext; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.DataManager; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashSet; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Set; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class SelectionManager { 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "SelectionManager"; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int ENTER_SELECTION_MODE = 1; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int LEAVE_SELECTION_MODE = 2; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int SELECT_ALL_MODE = 3; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Set<Path> mClickedSet; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private MediaSet mSourceMediaSet; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private SelectionListener mListener; 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private DataManager mDataManager; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mInverseSelection; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mIsAlbumSet; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mInSelectionMode; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mAutoLeave = true; 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mTotal; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public interface SelectionListener { 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSelectionModeChange(int mode); 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSelectionChange(Path path, boolean selected); 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public SelectionManager(GalleryContext galleryContext, boolean isAlbumSet) { 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDataManager = galleryContext.getDataManager(); 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet = new HashSet<Path>(); 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIsAlbumSet = isAlbumSet; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTotal = -1; 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Whether we will leave selection mode automatically once the number of 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // selected items is down to zero. 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setAutoLeaveSelectionMode(boolean enable) { 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAutoLeave = enable; 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setSelectionListener(SelectionListener listener) { 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener = listener; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void selectAll() { 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInverseSelection = true; 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet.clear(); 72e3c968f892585490b938ea2bcef81f8dca4a81f8Ray Chen enterSelectionMode(); 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE); 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void deSelectAll() { 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin leaveSelectionMode(); 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInverseSelection = false; 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet.clear(); 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean inSelectAllMode() { 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mInverseSelection; 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean inSelectionMode() { 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mInSelectionMode; 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void enterSelectionMode() { 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mInSelectionMode) return; 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInSelectionMode = true; 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE); 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void leaveSelectionMode() { 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mInSelectionMode) return; 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInSelectionMode = false; 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInverseSelection = false; 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet.clear(); 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE); 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean isItemSelected(Path itemId) { 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mInverseSelection ^ mClickedSet.contains(itemId); 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 11021c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen private int getTotalCount() { 11121c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen if (mSourceMediaSet == null) return -1; 11221c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen 11321c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen if (mTotal < 0) { 11421c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen mTotal = mIsAlbumSet 11521c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen ? mSourceMediaSet.getSubMediaSetCount() 11621c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen : mSourceMediaSet.getMediaItemCount(); 11721c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen } 11821c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen return mTotal; 11921c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen } 12021c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getSelectedCount() { 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int count = mClickedSet.size(); 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mInverseSelection) { 12421c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen count = getTotalCount() - count; 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return count; 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void toggle(Path path) { 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mClickedSet.contains(path)) { 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet.remove(path); 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin enterSelectionMode(); 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mClickedSet.add(path); 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 13721c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen // Convert to inverse selection mode if everything is selected. 13821c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen int count = getSelectedCount(); 13921c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen if (count == getTotalCount()) { 14021c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen selectAll(); 14121c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen } 14221c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path)); 14421c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen if (count == 0 && mAutoLeave) { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin leaveSelectionMode(); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static void expandMediaSet(ArrayList<Path> items, MediaSet set) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int subCount = set.getSubMediaSetCount(); 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < subCount; i++) { 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin expandMediaSet(items, set.getSubMediaSet(i)); 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int total = set.getMediaItemCount(); 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int batch = 50; 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int index = 0; 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin while (index < total) { 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int count = index + batch < total 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ? batch 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin : total - index; 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> list = set.getMediaItem(index, count); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaItem item : list) { 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin items.add(item.getPath()); 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin index += batch; 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ArrayList<Path> getSelected(boolean expandSet) { 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<Path> selected = new ArrayList<Path>(); 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mIsAlbumSet) { 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mInverseSelection) { 17421c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen int total = getTotalCount(); 17521c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen for (int i = 0; i < total; i++) { 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSet set = mSourceMediaSet.getSubMediaSet(i); 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path id = set.getPath(); 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mClickedSet.contains(id)) { 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (expandSet) { 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin expandMediaSet(selected, set); 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin selected.add(id); 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (Path id : mClickedSet) { 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (expandSet) { 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin expandMediaSet(selected, mDataManager.getMediaSet(id)); 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin selected.add(id); 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mInverseSelection) { 19721c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen int total = getTotalCount(); 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int index = 0; 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin while (index < total) { 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT); 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count); 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (MediaItem item : list) { 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path id = item.getPath(); 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mClickedSet.contains(id)) selected.add(id); 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin index += count; 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (Path id : mClickedSet) { 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin selected.add(id); 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return selected; 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setSourceMediaSet(MediaSet set) { 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSourceMediaSet = set; 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mTotal = -1; 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 222