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 package com.android.documentsui.dirlist; 17 18 import static androidx.core.util.Preconditions.checkArgument; 19 20 import static com.android.documentsui.base.DocumentInfo.getCursorInt; 21 import static com.android.documentsui.base.DocumentInfo.getCursorString; 22 23 import android.database.Cursor; 24 import android.provider.DocumentsContract.Document; 25 import android.util.Log; 26 27 import androidx.recyclerview.selection.SelectionTracker.SelectionPredicate; 28 import androidx.recyclerview.widget.RecyclerView; 29 30 import com.android.documentsui.ActivityConfig; 31 import com.android.documentsui.Model; 32 import com.android.documentsui.base.State; 33 34 /** 35 * Class embodying the logic as to whether an item (specified by id or position) 36 * can be selected (or not). 37 */ 38 final class DocsSelectionPredicate extends SelectionPredicate<String> { 39 40 private ActivityConfig mConfig; 41 private Model mModel; 42 private RecyclerView mRecView; 43 private State mState; 44 DocsSelectionPredicate( ActivityConfig config, State state, Model model, RecyclerView recView)45 DocsSelectionPredicate( 46 ActivityConfig config, State state, Model model, RecyclerView recView) { 47 48 checkArgument(config != null); 49 checkArgument(state != null); 50 checkArgument(model != null); 51 checkArgument(recView != null); 52 53 mConfig = config; 54 mState = state; 55 mModel = model; 56 mRecView = recView; 57 58 } 59 60 @Override canSetStateForKey(String id, boolean nextState)61 public boolean canSetStateForKey(String id, boolean nextState) { 62 if (nextState) { 63 // Check if an item can be selected 64 final Cursor cursor = mModel.getItem(id); 65 if (cursor == null) { 66 Log.w(DirectoryFragment.TAG, "Couldn't obtain cursor for id: " + id); 67 return false; 68 } 69 70 final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); 71 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); 72 return mConfig.canSelectType(docMimeType, docFlags, mState); 73 } 74 75 // Right now all selected items can be deselected. 76 return true; 77 } 78 79 @Override canSetStateAtPosition(int position, boolean nextState)80 public boolean canSetStateAtPosition(int position, boolean nextState) { 81 // This method features a nextState arg for symmetry. 82 // But, there are no current uses for checking un-selecting state by position. 83 // So rather than have some unsuspecting client think canSetState(int, false) 84 // will ever do anything. Let's just be grumpy about it. 85 assert nextState == true; 86 87 // NOTE: Given that we have logic in some places disallowing selection, 88 // it may be a bug that Band and Gesture based selections don't 89 // also verify something can be unselected. 90 91 // The band selection model only operates on documents and directories. 92 // Exclude other types of adapter items like whitespace and dividers. 93 final RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(position); 94 if (vh == null) { 95 return false; 96 } else { 97 return ModelBackedDocumentsAdapter.isContentType(vh.getItemViewType()); 98 } 99 } 100 101 @Override canSelectMultiple()102 public boolean canSelectMultiple() { 103 return mState.allowMultiple; 104 } 105 } 106