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.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 {
     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     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 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