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