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 */ 16 17 package com.android.gallery3d.ui; 18 19 import com.android.gallery3d.app.GalleryContext; 20 import com.android.gallery3d.data.DataManager; 21 import com.android.gallery3d.data.MediaItem; 22 import com.android.gallery3d.data.MediaSet; 23 import com.android.gallery3d.data.Path; 24 25 import java.util.ArrayList; 26 import java.util.HashSet; 27 import java.util.Set; 28 29 public class SelectionManager { 30 @SuppressWarnings("unused") 31 private static final String TAG = "SelectionManager"; 32 33 public static final int ENTER_SELECTION_MODE = 1; 34 public static final int LEAVE_SELECTION_MODE = 2; 35 public static final int SELECT_ALL_MODE = 3; 36 37 private Set<Path> mClickedSet; 38 private MediaSet mSourceMediaSet; 39 private SelectionListener mListener; 40 private DataManager mDataManager; 41 private boolean mInverseSelection; 42 private boolean mIsAlbumSet; 43 private boolean mInSelectionMode; 44 private boolean mAutoLeave = true; 45 private int mTotal; 46 47 public interface SelectionListener { onSelectionModeChange(int mode)48 public void onSelectionModeChange(int mode); onSelectionChange(Path path, boolean selected)49 public void onSelectionChange(Path path, boolean selected); 50 } 51 SelectionManager(GalleryContext galleryContext, boolean isAlbumSet)52 public SelectionManager(GalleryContext galleryContext, boolean isAlbumSet) { 53 mDataManager = galleryContext.getDataManager(); 54 mClickedSet = new HashSet<Path>(); 55 mIsAlbumSet = isAlbumSet; 56 mTotal = -1; 57 } 58 59 // Whether we will leave selection mode automatically once the number of 60 // selected items is down to zero. setAutoLeaveSelectionMode(boolean enable)61 public void setAutoLeaveSelectionMode(boolean enable) { 62 mAutoLeave = enable; 63 } 64 setSelectionListener(SelectionListener listener)65 public void setSelectionListener(SelectionListener listener) { 66 mListener = listener; 67 } 68 selectAll()69 public void selectAll() { 70 mInverseSelection = true; 71 mClickedSet.clear(); 72 enterSelectionMode(); 73 if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE); 74 } 75 deSelectAll()76 public void deSelectAll() { 77 leaveSelectionMode(); 78 mInverseSelection = false; 79 mClickedSet.clear(); 80 } 81 inSelectAllMode()82 public boolean inSelectAllMode() { 83 return mInverseSelection; 84 } 85 inSelectionMode()86 public boolean inSelectionMode() { 87 return mInSelectionMode; 88 } 89 enterSelectionMode()90 public void enterSelectionMode() { 91 if (mInSelectionMode) return; 92 93 mInSelectionMode = true; 94 if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE); 95 } 96 leaveSelectionMode()97 public void leaveSelectionMode() { 98 if (!mInSelectionMode) return; 99 100 mInSelectionMode = false; 101 mInverseSelection = false; 102 mClickedSet.clear(); 103 if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE); 104 } 105 isItemSelected(Path itemId)106 public boolean isItemSelected(Path itemId) { 107 return mInverseSelection ^ mClickedSet.contains(itemId); 108 } 109 getTotalCount()110 private int getTotalCount() { 111 if (mSourceMediaSet == null) return -1; 112 113 if (mTotal < 0) { 114 mTotal = mIsAlbumSet 115 ? mSourceMediaSet.getSubMediaSetCount() 116 : mSourceMediaSet.getMediaItemCount(); 117 } 118 return mTotal; 119 } 120 getSelectedCount()121 public int getSelectedCount() { 122 int count = mClickedSet.size(); 123 if (mInverseSelection) { 124 count = getTotalCount() - count; 125 } 126 return count; 127 } 128 toggle(Path path)129 public void toggle(Path path) { 130 if (mClickedSet.contains(path)) { 131 mClickedSet.remove(path); 132 } else { 133 enterSelectionMode(); 134 mClickedSet.add(path); 135 } 136 137 // Convert to inverse selection mode if everything is selected. 138 int count = getSelectedCount(); 139 if (count == getTotalCount()) { 140 selectAll(); 141 } 142 143 if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path)); 144 if (count == 0 && mAutoLeave) { 145 leaveSelectionMode(); 146 } 147 } 148 expandMediaSet(ArrayList<Path> items, MediaSet set)149 private static void expandMediaSet(ArrayList<Path> items, MediaSet set) { 150 int subCount = set.getSubMediaSetCount(); 151 for (int i = 0; i < subCount; i++) { 152 expandMediaSet(items, set.getSubMediaSet(i)); 153 } 154 int total = set.getMediaItemCount(); 155 int batch = 50; 156 int index = 0; 157 158 while (index < total) { 159 int count = index + batch < total 160 ? batch 161 : total - index; 162 ArrayList<MediaItem> list = set.getMediaItem(index, count); 163 for (MediaItem item : list) { 164 items.add(item.getPath()); 165 } 166 index += batch; 167 } 168 } 169 170 public ArrayList<Path> getSelected(boolean expandSet) { 171 ArrayList<Path> selected = new ArrayList<Path>(); 172 if (mIsAlbumSet) { 173 if (mInverseSelection) { 174 int total = getTotalCount(); 175 for (int i = 0; i < total; i++) { 176 MediaSet set = mSourceMediaSet.getSubMediaSet(i); 177 Path id = set.getPath(); 178 if (!mClickedSet.contains(id)) { 179 if (expandSet) { 180 expandMediaSet(selected, set); 181 } else { 182 selected.add(id); 183 } 184 } 185 } 186 } else { 187 for (Path id : mClickedSet) { 188 if (expandSet) { 189 expandMediaSet(selected, mDataManager.getMediaSet(id)); 190 } else { 191 selected.add(id); 192 } 193 } 194 } 195 } else { 196 if (mInverseSelection) { 197 int total = getTotalCount(); 198 int index = 0; 199 while (index < total) { 200 int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT); 201 ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count); 202 for (MediaItem item : list) { 203 Path id = item.getPath(); 204 if (!mClickedSet.contains(id)) selected.add(id); 205 } 206 index += count; 207 } 208 } else { 209 for (Path id : mClickedSet) { 210 selected.add(id); 211 } 212 } 213 } 214 return selected; 215 } 216 217 public void setSourceMediaSet(MediaSet set) { 218 mSourceMediaSet = set; 219 mTotal = -1; 220 } 221 } 222