SelectionManager.java revision e99a6ba365b388985bb5f4238002d90c2df28251
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 java.util.ArrayList;
26import java.util.HashSet;
27import java.util.Set;
28
29public 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 {
48        public void onSelectionModeChange(int mode);
49        public void onSelectionChange(Path path, boolean selected);
50    }
51
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.
61    public void setAutoLeaveSelectionMode(boolean enable) {
62        mAutoLeave = enable;
63    }
64
65    public void setSelectionListener(SelectionListener listener) {
66        mListener = listener;
67    }
68
69    public void selectAll() {
70        mInverseSelection = true;
71        mClickedSet.clear();
72        enterSelectionMode();
73        if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE);
74    }
75
76    public void deSelectAll() {
77        leaveSelectionMode();
78        mInverseSelection = false;
79        mClickedSet.clear();
80    }
81
82    public boolean inSelectAllMode() {
83        return mInverseSelection;
84    }
85
86    public boolean inSelectionMode() {
87        return mInSelectionMode;
88    }
89
90    public void enterSelectionMode() {
91        if (mInSelectionMode) return;
92
93        mInSelectionMode = true;
94        if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE);
95    }
96
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
106    public boolean isItemSelected(Path itemId) {
107        return mInverseSelection ^ mClickedSet.contains(itemId);
108    }
109
110    public int getSelectedCount() {
111        int count = mClickedSet.size();
112        if (mInverseSelection) {
113            if (mTotal < 0) {
114                mTotal = mIsAlbumSet
115                        ? mSourceMediaSet.getSubMediaSetCount()
116                        : mSourceMediaSet.getMediaItemCount();
117            }
118            count = mTotal - count;
119        }
120        return count;
121    }
122
123    public void toggle(Path path) {
124        if (mClickedSet.contains(path)) {
125            mClickedSet.remove(path);
126        } else {
127            enterSelectionMode();
128            mClickedSet.add(path);
129        }
130
131        if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path));
132        if (getSelectedCount() == 0 && mAutoLeave) {
133            leaveSelectionMode();
134        }
135    }
136
137    private static void expandMediaSet(ArrayList<Path> items, MediaSet set) {
138        int subCount = set.getSubMediaSetCount();
139        for (int i = 0; i < subCount; i++) {
140            expandMediaSet(items, set.getSubMediaSet(i));
141        }
142        int total = set.getMediaItemCount();
143        int batch = 50;
144        int index = 0;
145
146        while (index < total) {
147            int count = index + batch < total
148                    ? batch
149                    : total - index;
150            ArrayList<MediaItem> list = set.getMediaItem(index, count);
151            for (MediaItem item : list) {
152                items.add(item.getPath());
153            }
154            index += batch;
155        }
156    }
157
158    public ArrayList<Path> getSelected(boolean expandSet) {
159        ArrayList<Path> selected = new ArrayList<Path>();
160        if (mIsAlbumSet) {
161            if (mInverseSelection) {
162                int max = mSourceMediaSet.getSubMediaSetCount();
163                for (int i = 0; i < max; i++) {
164                    MediaSet set = mSourceMediaSet.getSubMediaSet(i);
165                    Path id = set.getPath();
166                    if (!mClickedSet.contains(id)) {
167                        if (expandSet) {
168                            expandMediaSet(selected, set);
169                        } else {
170                            selected.add(id);
171                        }
172                    }
173                }
174            } else {
175                for (Path id : mClickedSet) {
176                    if (expandSet) {
177                        expandMediaSet(selected, mDataManager.getMediaSet(id));
178                    } else {
179                        selected.add(id);
180                    }
181                }
182            }
183        } else {
184            if (mInverseSelection) {
185
186                int total = mSourceMediaSet.getMediaItemCount();
187                int index = 0;
188                while (index < total) {
189                    int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT);
190                    ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count);
191                    for (MediaItem item : list) {
192                        Path id = item.getPath();
193                        if (!mClickedSet.contains(id)) selected.add(id);
194                    }
195                    index += count;
196                }
197            } else {
198                for (Path id : mClickedSet) {
199                    selected.add(id);
200                }
201            }
202        }
203        return selected;
204    }
205
206    public void setSourceMediaSet(MediaSet set) {
207        mSourceMediaSet = set;
208        mTotal = -1;
209    }
210}
211