/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui; import android.os.Bundle; import android.view.MotionEvent; import androidx.annotation.VisibleForTesting; import androidx.recyclerview.selection.ItemDetailsLookup; import androidx.recyclerview.selection.ItemKeyProvider; import androidx.recyclerview.selection.MutableSelection; import androidx.recyclerview.selection.Selection; import androidx.recyclerview.selection.SelectionTracker; import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import java.util.Set; /** * DocumentsUI SelectManager implementation that creates delegate instances * each time reset is called. */ public final class DocsSelectionHelper extends SelectionTracker { private final DelegateFactory mFactory; // initialize to a stub object incase we get some input // event drive calls before we're properly initialized. // See: b/69306667. private SelectionTracker mDelegate = new StubSelectionTracker<>(); @VisibleForTesting DocsSelectionHelper(DelegateFactory factory) { mFactory = factory; } public void reset(SelectionTracker selectionTracker) { if (mDelegate != null) { mDelegate.clearSelection(); } mDelegate = mFactory.create(selectionTracker); } @Override public void addObserver(SelectionObserver listener) { mDelegate.addObserver(listener); } @Override public boolean hasSelection() { return mDelegate.hasSelection(); } @Override public Selection getSelection() { return mDelegate.getSelection(); } @Override public void copySelection(MutableSelection dest) { mDelegate.copySelection(dest); } @Override public boolean isSelected(String id) { return mDelegate.isSelected(id); } @VisibleForTesting public void replaceSelection(Iterable ids) { mDelegate.clearSelection(); mDelegate.setItemsSelected(ids, true); } @Override public boolean setItemsSelected(Iterable ids, boolean selected) { return mDelegate.setItemsSelected(ids, selected); } @Override public boolean clearSelection() { return mDelegate.clearSelection(); } @Override public boolean select(String modelId) { return mDelegate.select(modelId); } @Override public boolean deselect(String modelId) { return mDelegate.deselect(modelId); } @Override public void startRange(int pos) { mDelegate.startRange(pos); } @Override public void extendRange(int pos) { mDelegate.extendRange(pos); } @Override public void endRange() { mDelegate.endRange(); } @Override public boolean isRangeActive() { return mDelegate.isRangeActive(); } @Override public void anchorRange(int position) { mDelegate.anchorRange(position); } @Override public void onSaveInstanceState(Bundle state) { mDelegate.onSaveInstanceState(state); } @Override public void onRestoreInstanceState(Bundle state) { mDelegate.onRestoreInstanceState(state); } // Below overridden protected methods are not used for delegation. These empty implementations // are just required by abstract declaration of parent class. @Override protected void restoreSelection(Selection selection) { } @Override protected AdapterDataObserver getAdapterDataObserver() { return null; } @Override protected void extendProvisionalRange(int position) { } @Override protected void setProvisionalSelection(Set newSelection) { } @Override protected void clearProvisionalSelection() { } @Override protected void mergeProvisionalSelection() { } public static DocsSelectionHelper create() { return new DocsSelectionHelper(DelegateFactory.INSTANCE); } /** * Use of a factory to create selection manager instances allows testable instances to * be inject from tests. */ @VisibleForTesting static class DelegateFactory { static final DelegateFactory INSTANCE = new DelegateFactory(); SelectionTracker create(SelectionTracker selectionTracker) { return selectionTracker; } } /** * Facilitates the use of ItemDetailsLookup. */ public static abstract class DocDetailsLookup extends ItemDetailsLookup { // Override as public for usages in other packages. @Override public boolean overItemWithSelectionKey(MotionEvent e) { return super.overItemWithSelectionKey(e); } } /** * Facilitates the use of stable ids. */ public static abstract class StableIdProvider extends ItemKeyProvider { protected StableIdProvider() { super(ItemKeyProvider.SCOPE_MAPPED); } } }