1 /* 2 * Copyright (C) 2015 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; 18 19 import android.support.annotation.VisibleForTesting; 20 import android.support.v7.widget.RecyclerView; 21 22 import com.android.documentsui.selection.DefaultSelectionHelper; 23 import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode; 24 import com.android.documentsui.selection.MutableSelection; 25 import com.android.documentsui.selection.Selection; 26 import com.android.documentsui.selection.SelectionHelper; 27 28 import java.util.Set; 29 30 import javax.annotation.Nullable; 31 32 /** 33 * DocumentsUI SelectManager implementation that creates delegate instances 34 * each time reset is called. 35 */ 36 public final class DocsSelectionHelper extends SelectionHelper { 37 38 private final DelegateFactory mFactory; 39 private final @SelectionMode int mSelectionMode; 40 41 // initialize to a dummy object incase we get some input 42 // event drive calls before we're properly initialized. 43 // See: b/69306667. 44 private SelectionHelper mDelegate = new DummySelectionHelper(); 45 46 @VisibleForTesting 47 DocsSelectionHelper(DelegateFactory factory, @SelectionMode int mode) { 48 mFactory = factory; 49 mSelectionMode = mode; 50 } 51 52 public SelectionHelper reset( 53 RecyclerView.Adapter<?> adapter, 54 StableIdProvider stableIds, 55 SelectionPredicate canSetState) { 56 57 if (mDelegate != null) { 58 mDelegate.clearSelection(); 59 } 60 61 mDelegate = mFactory.create(mSelectionMode, adapter, stableIds, canSetState); 62 return this; 63 } 64 65 @Override 66 public void addObserver(SelectionObserver listener) { 67 mDelegate.addObserver(listener); 68 } 69 70 @Override 71 public boolean hasSelection() { 72 return mDelegate.hasSelection(); 73 } 74 75 @Override 76 public Selection getSelection() { 77 return mDelegate.getSelection(); 78 } 79 80 @Override 81 public void copySelection(Selection dest) { 82 mDelegate.copySelection(dest); 83 } 84 85 @Override 86 public boolean isSelected(String id) { 87 return mDelegate.isSelected(id); 88 } 89 90 @VisibleForTesting 91 public void replaceSelection(Iterable<String> ids) { 92 mDelegate.clearSelection(); 93 mDelegate.setItemsSelected(ids, true); 94 } 95 96 @Override 97 public void restoreSelection(Selection other) { 98 mDelegate.restoreSelection(other); 99 } 100 101 @Override 102 public boolean setItemsSelected(Iterable<String> ids, boolean selected) { 103 return mDelegate.setItemsSelected(ids, selected); 104 } 105 106 @Override 107 public void clearSelection() { 108 mDelegate.clearSelection(); 109 } 110 111 @Override 112 public boolean select(String modelId) { 113 return mDelegate.select(modelId); 114 } 115 116 @Override 117 public boolean deselect(String modelId) { 118 return mDelegate.deselect(modelId); 119 } 120 121 @Override 122 public void startRange(int pos) { 123 mDelegate.startRange(pos); 124 } 125 126 @Override 127 public void extendRange(int pos) { 128 mDelegate.extendRange(pos); 129 } 130 131 @Override 132 public void extendProvisionalRange(int pos) { 133 mDelegate.extendProvisionalRange(pos); 134 } 135 136 @Override 137 public void clearProvisionalSelection() { 138 mDelegate.clearProvisionalSelection(); 139 } 140 141 @Override 142 public void setProvisionalSelection(Set<String> newSelection) { 143 mDelegate.setProvisionalSelection(newSelection); 144 } 145 146 @Override 147 public void mergeProvisionalSelection() { 148 mDelegate.mergeProvisionalSelection(); 149 } 150 151 @Override 152 public void endRange() { 153 mDelegate.endRange(); 154 } 155 156 @Override 157 public boolean isRangeActive() { 158 return mDelegate.isRangeActive(); 159 } 160 161 @Override 162 public void anchorRange(int position) { 163 mDelegate.anchorRange(position); 164 } 165 166 public static DocsSelectionHelper createMultiSelect() { 167 return new DocsSelectionHelper( 168 DelegateFactory.INSTANCE, 169 DefaultSelectionHelper.MODE_MULTIPLE); 170 } 171 172 public static DocsSelectionHelper createSingleSelect() { 173 return new DocsSelectionHelper( 174 DelegateFactory.INSTANCE, 175 DefaultSelectionHelper.MODE_SINGLE); 176 } 177 178 /** 179 * Use of a factory to create selection manager instances allows testable instances to 180 * be inject from tests. 181 */ 182 @VisibleForTesting 183 static class DelegateFactory { 184 static final DelegateFactory INSTANCE = new DelegateFactory(); 185 186 SelectionHelper create( 187 @SelectionMode int mode, 188 RecyclerView.Adapter<?> adapter, 189 StableIdProvider stableIds, 190 SelectionPredicate canSetState) { 191 192 return new DefaultSelectionHelper(mode, adapter, stableIds, canSetState); 193 } 194 } 195 196 /** 197 * A dummy SelectHelper used by DocsSelectionHelper before a real 198 * SelectionHelper has been initialized by DirectoryFragment. 199 */ 200 private static final class DummySelectionHelper extends SelectionHelper { 201 202 @Override 203 public void addObserver(SelectionObserver listener) { 204 } 205 206 @Override 207 public boolean hasSelection() { 208 return false; 209 } 210 211 @Override 212 public Selection getSelection() { 213 return new MutableSelection(); 214 } 215 216 @Override 217 public void copySelection(Selection dest) { 218 } 219 220 @Override 221 public boolean isSelected(String id) { 222 return false; 223 } 224 225 @VisibleForTesting 226 public void replaceSelection(Iterable<String> ids) { 227 } 228 229 @Override 230 public void restoreSelection(Selection other) { 231 } 232 233 @Override 234 public boolean setItemsSelected(Iterable<String> ids, boolean selected) { 235 return false; 236 } 237 238 @Override 239 public void clearSelection() { 240 } 241 242 @Override 243 public boolean select(String modelId) { 244 return false; 245 } 246 247 @Override 248 public boolean deselect(String modelId) { 249 return false; 250 } 251 252 @Override 253 public void startRange(int pos) { 254 } 255 256 @Override 257 public void extendRange(int pos) { 258 } 259 260 @Override 261 public void extendProvisionalRange(int pos) { 262 } 263 264 @Override 265 public void clearProvisionalSelection() { 266 } 267 268 @Override 269 public void setProvisionalSelection(Set<String> newSelection) { 270 } 271 272 @Override 273 public void mergeProvisionalSelection() { 274 } 275 276 @Override 277 public void endRange() { 278 } 279 280 @Override 281 public boolean isRangeActive() { 282 return false; 283 } 284 285 @Override 286 public void anchorRange(int position) { 287 } 288 } 289 } 290