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         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     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 
    121     public int getSelectedCount() {
    122         int count = mClickedSet.size();
    123         if (mInverseSelection) {
    124             count = getTotalCount() - count;
    125         }
    126         return count;
    127     }
    128 
    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 
    149     private static boolean expandMediaSet(ArrayList<Path> items, MediaSet set, int maxSelection) {
    150         int subCount = set.getSubMediaSetCount();
    151         for (int i = 0; i < subCount; i++) {
    152             if (!expandMediaSet(items, set.getSubMediaSet(i), maxSelection)) {
    153                 return false;
    154             }
    155         }
    156         int total = set.getMediaItemCount();
    157         int batch = 50;
    158         int index = 0;
    159 
    160         while (index < total) {
    161             int count = index + batch < total
    162                     ? batch
    163                     : total - index;
    164             ArrayList<MediaItem> list = set.getMediaItem(index, count);
    165             if (list != null
    166                     && list.size() > (maxSelection - items.size())) {
    167                 return false;
    168             }
    169             for (MediaItem item : list) {
    170                 items.add(item.getPath());
    171             }
    172             index += batch;
    173         }
    174         return true;
    175     }
    176 
    177     public ArrayList<Path> getSelected(boolean expandSet) {
    178         return getSelected(expandSet, Integer.MAX_VALUE);
    179     }
    180 
    181     public ArrayList<Path> getSelected(boolean expandSet, int maxSelection) {
    182         ArrayList<Path> selected = new ArrayList<Path>();
    183         if (mIsAlbumSet) {
    184             if (mInverseSelection) {
    185                 int total = getTotalCount();
    186                 for (int i = 0; i < total; i++) {
    187                     MediaSet set = mSourceMediaSet.getSubMediaSet(i);
    188                     Path id = set.getPath();
    189                     if (!mClickedSet.contains(id)) {
    190                         if (expandSet) {
    191                             if (!expandMediaSet(selected, set, maxSelection)) {
    192                                 return null;
    193                             }
    194                         } else {
    195                             selected.add(id);
    196                             if (selected.size() > maxSelection) {
    197                                 return null;
    198                             }
    199                         }
    200                     }
    201                 }
    202             } else {
    203                 for (Path id : mClickedSet) {
    204                     if (expandSet) {
    205                         if (!expandMediaSet(selected, mDataManager.getMediaSet(id),
    206                                 maxSelection)) {
    207                             return null;
    208                         }
    209                     } else {
    210                         selected.add(id);
    211                         if (selected.size() > maxSelection) {
    212                             return null;
    213                         }
    214                     }
    215                 }
    216             }
    217         } else {
    218             if (mInverseSelection) {
    219                 int total = getTotalCount();
    220                 int index = 0;
    221                 while (index < total) {
    222                     int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT);
    223                     ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count);
    224                     for (MediaItem item : list) {
    225                         Path id = item.getPath();
    226                         if (!mClickedSet.contains(id)) {
    227                             selected.add(id);
    228                             if (selected.size() > maxSelection) {
    229                                 return null;
    230                             }
    231                         }
    232                     }
    233                     index += count;
    234                 }
    235             } else {
    236                 for (Path id : mClickedSet) {
    237                     selected.add(id);
    238                     if (selected.size() > maxSelection) {
    239                         return null;
    240                     }
    241                 }
    242             }
    243         }
    244         return selected;
    245     }
    246 
    247     public void setSourceMediaSet(MediaSet set) {
    248         mSourceMediaSet = set;
    249         mTotal = -1;
    250     }
    251 }
    252