• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.documentsui.selection;
18 
19 import java.util.List;
20 import java.util.Set;
21 
22 /**
23  * SelectionManager provides support for managing selection within a RecyclerView instance.
24  *
25  * @see DefaultSelectionHelper for details on instantiation.
26  */
27 public abstract class SelectionHelper {
28 
29     /**
30      * This value is included in the payload when SelectionHelper implementations
31      * notify RecyclerView of changes. Clients can look for this in
32      * {@code onBindViewHolder} to know if the bind event is occurring in response
33      * to a selection state change.
34      */
35     public static final String SELECTION_CHANGED_MARKER = "Selection-Changed";
36 
37     /**
38      * Adds {@code observe} to be notified when changes to selection occur.
39      *
40      * @param observer
41      */
addObserver(SelectionObserver observer)42     public abstract void addObserver(SelectionObserver observer);
43 
hasSelection()44     public abstract boolean hasSelection();
45 
46     /**
47      * Returns a Selection object that provides a live view on the current selection.
48      *
49      * @see #copySelection(Selection) on how to get a snapshot
50      *     of the selection that will not reflect future changes
51      *     to selection.
52      *
53      * @return The current selection.
54      */
getSelection()55     public abstract Selection getSelection();
56 
57     /**
58      * Updates {@code dest} to reflect the current selection.
59      * @param dest
60      */
copySelection(Selection dest)61     public abstract void copySelection(Selection dest);
62 
63     /**
64      * @return true if the item specified by its id is selected. Shorthand for
65      * {@code getSelection().contains(String)}.
66      */
isSelected(String id)67     public abstract boolean isSelected(String id);
68 
69     /**
70      * Restores the selected state of specified items. Used in cases such as restore the selection
71      * after rotation etc. Provisional selection, being provisional 'n all, isn't restored.
72      */
restoreSelection(Selection other)73     public abstract void restoreSelection(Selection other);
74 
75     /**
76      * Sets the selected state of the specified items. Note that the callback will NOT
77      * be consulted to see if an item can be selected.
78      *
79      * @param ids
80      * @param selected
81      * @return
82      */
setItemsSelected(Iterable<String> ids, boolean selected)83     public abstract boolean setItemsSelected(Iterable<String> ids, boolean selected);
84 
85     /**
86      * Clears the selection and notifies (if something changes).
87      */
clearSelection()88     public abstract void clearSelection();
89 
90     /**
91      * Attempts to select an item.
92      *
93      * @return true if the item was selected. False if the item was not selected, or was
94      *         was already selected prior to the method being called.
95      */
select(String itemId)96     public abstract boolean select(String itemId);
97 
98     /**
99      * Attempts to deselect an item.
100      *
101      * @return true if the item was deselected. False if the item was not deselected, or was
102      *         was already deselected prior to the method being called.
103      */
deselect(String itemId)104     public abstract boolean deselect(String itemId);
105 
106     /**
107      * Starts a range selection. If a range selection is already active, this will start a new range
108      * selection (which will reset the range anchor).
109      *
110      * @param pos The anchor position for the selection range.
111      */
startRange(int pos)112     public abstract void startRange(int pos);
113 
114     /**
115      * Sets the end point for the active range selection.
116      *
117      * <p>This function should only be called when a range selection is active
118      * (see {@link #isRangeActive()}. Items in the range [anchor, end] will be
119      * selected.
120      *
121      * @param pos The new end position for the selection range.
122      * @param type The type of selection the range should utilize.
123      *
124      * @throws IllegalStateException if a range selection is not active. Range selection
125      *         must have been started by a call to {@link #startRange(int)}.
126      */
extendRange(int pos)127     public abstract void extendRange(int pos);
128 
129     /**
130      * Stops an in-progress range selection. All selection done with
131      * {@link #extendProvisionalRange(int)} will be lost if
132      * {@link Selection#mergeProvisionalSelection()} is not called beforehand.
133      */
endRange()134     public abstract void endRange();
135 
136     /**
137      * @return Whether or not there is a current range selection active.
138      */
isRangeActive()139     public abstract boolean isRangeActive();
140 
141     /**
142      * Sets the magic location at which a selection range begins (the selection anchor). This value
143      * is consulted when determining how to extend, and modify selection ranges. Calling this when a
144      * range selection is active will reset the range selection.
145      */
anchorRange(int position)146     public abstract void anchorRange(int position);
147 
148     /**
149      * @param pos
150      */
151     // TODO: This is smelly. Maybe this type of logic needs to move into range selection,
152     // then selection manager can have a startProvisionalRange and startRange. Or
153     // maybe ranges always start life as provisional.
extendProvisionalRange(int pos)154     public abstract void extendProvisionalRange(int pos);
155 
156     /**
157      * @param newSelection
158      */
setProvisionalSelection(Set<String> newSelection)159     public abstract void setProvisionalSelection(Set<String> newSelection);
160 
161     /**
162      *
163      */
clearProvisionalSelection()164     public abstract void clearProvisionalSelection();
165 
mergeProvisionalSelection()166     public abstract void mergeProvisionalSelection();
167 
168     /**
169      * Observer interface providing access to information about Selection state changes.
170      */
171     public static abstract class SelectionObserver {
172 
173         /**
174          * Called when state of an item has been changed.
175          */
onItemStateChanged(String id, boolean selected)176         public void onItemStateChanged(String id, boolean selected) {}
177 
178         /**
179          * Called when the underlying data set has change. After this method is called
180          * the selection manager will attempt traverse the existing selection,
181          * calling {@link #onItemStateChanged(String, boolean)} for each selected item,
182          * and deselecting any items that cannot be selected given the updated dataset.
183          */
onSelectionReset()184         public void onSelectionReset() {}
185 
186         /**
187          * Called immediately after completion of any set of changes, excluding
188          * those resulting in calls to {@link #onSelectionReset()} and
189          * {@link #onSelectionRestored()}.
190          */
onSelectionChanged()191         public void onSelectionChanged() {}
192 
193         /**
194          * Called immediately after selection is restored.
195          * {@link #onItemStateChanged(String, boolean)} will not be called
196          * for individual items in the selection.
197          */
onSelectionRestored()198         public void onSelectionRestored() {}
199     }
200 
201     /**
202      * Facilitates the use of stable ids.
203      */
204     public static abstract class StableIdProvider {
205         /**
206          * @return The model ID of the item at the given adapter position.
207          */
getStableId(int position)208         public abstract String getStableId(int position);
209 
210         /**
211          * @return the position of a stable ID, or RecyclerView.NO_POSITION.
212          */
getPosition(String id)213         public abstract int getPosition(String id);
214 
215         /**
216          * @return A list of all known stable IDs.
217          */
getStableIds()218         public abstract List<String> getStableIds();
219     }
220 
221     /**
222      * Implement SelectionPredicate to control when items can be selected or unselected.
223      */
224     public static abstract class SelectionPredicate {
225 
226         /** @return true if the item at {@code id} can be set to {@code nextState}. */
canSetStateForId(String id, boolean nextState)227         public abstract boolean canSetStateForId(String id, boolean nextState);
228 
229         /** @return true if the item at {@code id} can be set to {@code nextState}. */
canSetStateAtPosition(int position, boolean nextState)230         public abstract boolean canSetStateAtPosition(int position, boolean nextState);
231 
232         /** @return true if more than a single item can be selected. */
canSelectMultiple()233         public boolean canSelectMultiple() {
234             return true;
235         }
236     }
237 }
238