Home | History | Annotate | Download | only in ui
      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.AbstractGalleryActivity;
     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 {
     48         public void onSelectionModeChange(int mode);
     49         public void onSelectionChange(Path path, boolean selected);
     50     }
     51 
     52     public SelectionManager(AbstractGalleryActivity activity, boolean isAlbumSet) {
     53         mDataManager = activity.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         mTotal = -1;
     73         enterSelectionMode();
     74         if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE);
     75     }
     76 
     77     public void deSelectAll() {
     78         leaveSelectionMode();
     79         mInverseSelection = false;
     80         mClickedSet.clear();
     81     }
     82 
     83     public boolean inSelectAllMode() {
     84         return mInverseSelection;
     85     }
     86 
     87     public boolean inSelectionMode() {
     88         return mInSelectionMode;
     89     }
     90 
     91     public void enterSelectionMode() {
     92         if (mInSelectionMode) return;
     93 
     94         mInSelectionMode = true;
     95         if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE);
     96     }
     97 
     98     public void leaveSelectionMode() {
     99         if (!mInSelectionMode) return;
    100 
    101         mInSelectionMode = false;
    102         mInverseSelection = false;
    103         mClickedSet.clear();
    104         if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE);
    105     }
    106 
    107     public boolean isItemSelected(Path itemId) {
    108         return mInverseSelection ^ mClickedSet.contains(itemId);
    109     }
    110 
    111     private int getTotalCount() {
    112         if (mSourceMediaSet == null) return -1;
    113 
    114         if (mTotal < 0) {
    115             mTotal = mIsAlbumSet
    116                     ? mSourceMediaSet.getSubMediaSetCount()
    117                     : mSourceMediaSet.getMediaItemCount();
    118         }
    119         return mTotal;
    120     }
    121 
    122     public int getSelectedCount() {
    123         int count = mClickedSet.size();
    124         if (mInverseSelection) {
    125             count = getTotalCount() - 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         // Convert to inverse selection mode if everything is selected.
    139         int count = getSelectedCount();
    140         if (count == getTotalCount()) {
    141             selectAll();
    142         }
    143 
    144         if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path));
    145         if (count == 0 && mAutoLeave) {
    146             leaveSelectionMode();
    147         }
    148     }
    149 
    150     private static boolean expandMediaSet(ArrayList<Path> items, MediaSet set, int maxSelection) {
    151         int subCount = set.getSubMediaSetCount();
    152         for (int i = 0; i < subCount; i++) {
    153             if (!expandMediaSet(items, set.getSubMediaSet(i), maxSelection)) {
    154                 return false;
    155             }
    156         }
    157         int total = set.getMediaItemCount();
    158         int batch = 50;
    159         int index = 0;
    160 
    161         while (index < total) {
    162             int count = index + batch < total
    163                     ? batch
    164                     : total - index;
    165             ArrayList<MediaItem> list = set.getMediaItem(index, count);
    166             if (list != null
    167                     && list.size() > (maxSelection - items.size())) {
    168                 return false;
    169             }
    170             for (MediaItem item : list) {
    171                 items.add(item.getPath());
    172             }
    173             index += batch;
    174         }
    175         return true;
    176     }
    177 
    178     public ArrayList<Path> getSelected(boolean expandSet) {
    179         return getSelected(expandSet, Integer.MAX_VALUE);
    180     }
    181 
    182     public ArrayList<Path> getSelected(boolean expandSet, int maxSelection) {
    183         ArrayList<Path> selected = new ArrayList<Path>();
    184         if (mIsAlbumSet) {
    185             if (mInverseSelection) {
    186                 int total = getTotalCount();
    187                 for (int i = 0; i < total; i++) {
    188                     MediaSet set = mSourceMediaSet.getSubMediaSet(i);
    189                     Path id = set.getPath();
    190                     if (!mClickedSet.contains(id)) {
    191                         if (expandSet) {
    192                             if (!expandMediaSet(selected, set, maxSelection)) {
    193                                 return null;
    194                             }
    195                         } else {
    196                             selected.add(id);
    197                             if (selected.size() > maxSelection) {
    198                                 return null;
    199                             }
    200                         }
    201                     }
    202                 }
    203             } else {
    204                 for (Path id : mClickedSet) {
    205                     if (expandSet) {
    206                         if (!expandMediaSet(selected, mDataManager.getMediaSet(id),
    207                                 maxSelection)) {
    208                             return null;
    209                         }
    210                     } else {
    211                         selected.add(id);
    212                         if (selected.size() > maxSelection) {
    213                             return null;
    214                         }
    215                     }
    216                 }
    217             }
    218         } else {
    219             if (mInverseSelection) {
    220                 int total = getTotalCount();
    221                 int index = 0;
    222                 while (index < total) {
    223                     int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT);
    224                     ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count);
    225                     for (MediaItem item : list) {
    226                         Path id = item.getPath();
    227                         if (!mClickedSet.contains(id)) {
    228                             selected.add(id);
    229                             if (selected.size() > maxSelection) {
    230                                 return null;
    231                             }
    232                         }
    233                     }
    234                     index += count;
    235                 }
    236             } else {
    237                 for (Path id : mClickedSet) {
    238                     selected.add(id);
    239                     if (selected.size() > maxSelection) {
    240                         return null;
    241                     }
    242                 }
    243             }
    244         }
    245         return selected;
    246     }
    247 
    248     public void setSourceMediaSet(MediaSet set) {
    249         mSourceMediaSet = set;
    250         mTotal = -1;
    251     }
    252 }
    253