Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 365e3cb1 authored by Steve McKay's avatar Steve McKay
Browse files

Cleanup of Selection APIs.

Improved consistency in naming, updated some docs...
    baby steps, much more documentation is needed.
    Replace "Manager" noun w/ "Helper" noun for better
    consistency with RecycleView naming standards.
Cleanup idiosyncracies in usage is DocumentsUI.
Make SelectionManager responsible for notifying RecyclerView of selection changes
    allowing all notifications to be isolated in the listener interface.
    This also eliminates a requirement that Adapter implementations add
    plumbing to dispatch item change notifications to RecyclerView.

Bug: 64847011
Test: Increased coverage.
Change-Id: Icdf3815f2f4bbce8751d740d362228a204666f35
parent 755b7881
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ import com.android.documentsui.roots.GetRootDocumentTask;
import com.android.documentsui.roots.LoadRootTask;
import com.android.documentsui.roots.ProvidersAccess;
import com.android.documentsui.selection.MutableSelection;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.selection.addons.ContentLock;
import com.android.documentsui.sidebar.EjectRootTask;
import com.android.documentsui.ui.Snackbars;
@@ -93,7 +93,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons>
    protected final ProvidersAccess mProviders;
    protected final DocumentsAccess mDocs;
    protected final FocusHandler mFocusHandler;
    protected final SelectionManager mSelectionMgr;
    protected final SelectionHelper mSelectionMgr;
    protected final SearchViewManager mSearchMgr;
    protected final Lookup<String, Executor> mExecutors;
    protected final Injector<?> mInjector;
+7 −40
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;
import android.view.ActionMode;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -35,22 +34,20 @@ import com.android.documentsui.base.ConfirmationCallback.Result;
import com.android.documentsui.base.EventHandler;
import com.android.documentsui.base.Menus;
import com.android.documentsui.selection.Selection;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.selection.SelectionHelper.StubSelectionObserver;
import com.android.documentsui.ui.MessageBuilder;

import java.util.function.Consumer;
import java.util.function.IntConsumer;

/**
 * A controller that listens to selection changes and manages life cycles of action modes.
 */
public class ActionModeController
        implements SelectionManager.EventListener, ActionMode.Callback, ActionModeAddons {
public class ActionModeController extends StubSelectionObserver
        implements ActionMode.Callback, ActionModeAddons {

    private static final String TAG = "ActionModeController";

    private final Activity mActivity;
    private final SelectionManager mSelectionMgr;
    private final SelectionHelper mSelectionMgr;
    private final MenuManager mMenuManager;
    private final MessageBuilder mMessages;

@@ -62,7 +59,7 @@ public class ActionModeController

    public ActionModeController(
            Activity activity,
            SelectionManager selectionMgr,
            SelectionHelper selectionMgr,
            MenuManager menuManager,
            MessageBuilder messages) {

@@ -99,37 +96,7 @@ public class ActionModeController

    @Override
    public void onSelectionRestored() {
        mSelectionMgr.copySelection(mSelected);
        if (mSelected.size() > 0) {
            if (mActionMode == null) {
                if (DEBUG) Log.d(TAG, "Starting action mode.");
                mActionMode = mActivity.startActionMode(this);
            }
            updateActionMenu();
        } else {
            if (mActionMode != null) {
                if (DEBUG) Log.d(TAG, "Finishing action mode.");
                mActionMode.finish();
            }
        }

        if (mActionMode != null) {
            assert(!mSelected.isEmpty());
            final String title = mMessages.getQuantityString(
                    R.plurals.elements_selected, mSelected.size());
            mActionMode.setTitle(title);
            mActivity.getWindow().setTitle(title);
        }
    }

    @Override
    public void onItemStateChanged(String id, boolean selected) {
        // Not utilized.
    }

    @Override
    public void onSelectionReset() {
        // Not utilized.
        onSelectionChanged();
    }

    // Called when the user exits the action mode
+38 −33
Original line number Diff line number Diff line
@@ -19,10 +19,10 @@ package com.android.documentsui;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;

import com.android.documentsui.selection.DefaultSelectionManager;
import com.android.documentsui.selection.DefaultSelectionManager.SelectionMode;
import com.android.documentsui.selection.DefaultSelectionHelper;
import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode;
import com.android.documentsui.selection.Selection;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionHelper;

import java.util.Set;

@@ -32,20 +32,20 @@ import javax.annotation.Nullable;
 * DocumentsUI SelectManager implementation that creates delegate instances
 * each time reset is called.
 */
public final class DocsSelectionManager implements SelectionManager {
public final class DocsSelectionHelper implements SelectionHelper {

    private final DelegateFactory mFactory;
    private final @SelectionMode int mSelectionMode;

    private @Nullable SelectionManager mDelegate;
    private @Nullable SelectionHelper mDelegate;

    @VisibleForTesting
    DocsSelectionManager(DelegateFactory factory, @SelectionMode int mode) {
    DocsSelectionHelper(DelegateFactory factory, @SelectionMode int mode) {
        mFactory = factory;
        mSelectionMode = mode;
    }

    public SelectionManager reset(
    public SelectionHelper reset(
            RecyclerView.Adapter<?> adapter,
            StableIdProvider stableIds,
            SelectionPredicate canSetState) {
@@ -59,8 +59,8 @@ public final class DocsSelectionManager implements SelectionManager {
    }

    @Override
    public void addEventListener(EventListener listener) {
        mDelegate.addEventListener(listener);
    public void addObserver(SelectionObserver listener) {
        mDelegate.addObserver(listener);
    }

    @Override
@@ -78,6 +78,11 @@ public final class DocsSelectionManager implements SelectionManager {
        mDelegate.copySelection(dest);
    }

    @Override
    public boolean isSelected(String id) {
        return mDelegate.isSelected(id);
    }

    @VisibleForTesting
    public void replaceSelection(Iterable<String> ids) {
        mDelegate.clearSelection();
@@ -100,28 +105,28 @@ public final class DocsSelectionManager implements SelectionManager {
    }

    @Override
    public void toggleSelection(String modelId) {
        mDelegate.toggleSelection(modelId);
    public boolean select(String modelId) {
        return mDelegate.select(modelId);
    }

    @Override
    public void startRangeSelection(int pos) {
        mDelegate.startRangeSelection(pos);
    public boolean deselect(String modelId) {
        return mDelegate.deselect(modelId);
    }

    @Override
    public void snapRangeSelection(int pos) {
        mDelegate.snapRangeSelection(pos);
    public void startRange(int pos) {
        mDelegate.startRange(pos);
    }

    @Override
    public void formNewSelectionRange(int startPos, int endPos) {
        mDelegate.formNewSelectionRange(startPos, endPos);
    public void extendRange(int pos) {
        mDelegate.extendRange(pos);
    }

    @Override
    public void snapProvisionalRangeSelection(int pos) {
        mDelegate.snapProvisionalRangeSelection(pos);
    public void extendProvisionalRange(int pos) {
        mDelegate.extendProvisionalRange(pos);
    }

    @Override
@@ -140,30 +145,30 @@ public final class DocsSelectionManager implements SelectionManager {
    }

    @Override
    public void endRangeSelection() {
        mDelegate.endRangeSelection();
    public void endRange() {
        mDelegate.endRange();
    }

    @Override
    public boolean isRangeSelectionActive() {
        return mDelegate.isRangeSelectionActive();
    public boolean isRangeActive() {
        return mDelegate.isRangeActive();
    }

    @Override
    public void setSelectionRangeBegin(int position) {
        mDelegate.setSelectionRangeBegin(position);
    public void anchorRange(int position) {
        mDelegate.anchorRange(position);
    }

    public static DocsSelectionManager createMultiSelect() {
        return new DocsSelectionManager(
    public static DocsSelectionHelper createMultiSelect() {
        return new DocsSelectionHelper(
                DelegateFactory.INSTANCE,
                DefaultSelectionManager.MODE_MULTIPLE);
                DefaultSelectionHelper.MODE_MULTIPLE);
    }

    public static DocsSelectionManager createSingleSelect() {
        return new DocsSelectionManager(
    public static DocsSelectionHelper createSingleSelect() {
        return new DocsSelectionHelper(
                DelegateFactory.INSTANCE,
                DefaultSelectionManager.MODE_SINGLE);
                DefaultSelectionHelper.MODE_SINGLE);
    }

    /**
@@ -174,13 +179,13 @@ public final class DocsSelectionManager implements SelectionManager {
    static class DelegateFactory {
        static final DelegateFactory INSTANCE = new DelegateFactory();

        SelectionManager create(
        SelectionHelper create(
                @SelectionMode int mode,
                RecyclerView.Adapter<?> adapter,
                StableIdProvider stableIds,
                SelectionPredicate canSetState) {

            return new DefaultSelectionManager(mode, adapter, stableIds, canSetState);
            return new DefaultSelectionHelper(mode, adapter, stableIds, canSetState);
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import com.android.documentsui.base.Procedure;
import com.android.documentsui.dirlist.DocumentHolder;
import com.android.documentsui.dirlist.DocumentsAdapter;
import com.android.documentsui.dirlist.FocusHandler;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.Model.Update;

import java.util.ArrayList;
@@ -61,7 +61,7 @@ public final class FocusManager implements FocusHandler {
    private final ContentScope mScope = new ContentScope();

    private final Features mFeatures;
    private final SelectionManager mSelectionMgr;
    private final SelectionHelper mSelectionMgr;
    private final DrawerController mDrawer;
    private final Procedure mRootsFocuser;
    private final TitleSearchHelper mSearchHelper;
@@ -70,7 +70,7 @@ public final class FocusManager implements FocusHandler {

    public FocusManager(
            Features features,
            SelectionManager selectionMgr,
            SelectionHelper selectionMgr,
            DrawerController drawer,
            Procedure rootsFocuser,
            @ColorRes int color) {
+8 −8
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import com.android.documentsui.base.RootInfo;
import com.android.documentsui.dirlist.DocumentsAdapter;
import com.android.documentsui.prefs.ScopedPreferences;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionHelper;
import com.android.documentsui.selection.addons.ContentLock;
import com.android.documentsui.ui.DialogController;
import com.android.documentsui.ui.MessageBuilder;
@@ -70,7 +70,7 @@ public class Injector<T extends ActionHandler> {
    public FocusManager focusManager;

    @ContentScoped
    public DocsSelectionManager selectionMgr;
    public DocsSelectionHelper selectionMgr;

    private final Model mModel;

@@ -119,8 +119,8 @@ public class Injector<T extends ActionHandler> {
        return focusManager.reset(view, model);
    }

    public SelectionManager getSelectionManager(
            DocumentsAdapter adapter, SelectionManager.SelectionPredicate canSetState) {
    public SelectionHelper getSelectionManager(
            DocumentsAdapter adapter, SelectionHelper.SelectionPredicate canSetState) {
        return selectionMgr.reset(adapter, adapter, canSetState);
    }

@@ -133,10 +133,10 @@ public class Injector<T extends ActionHandler> {
     * Obtains action handler and resets it if necessary.
     *
     * @param contentLock the lock held by
     *            {@link com.android.documentsui.selection.addons.BandSelector} and
     *            {@link com.android.documentsui.selection.addons.GestureSelector} to prevent loader
     *            from updating result during band/gesture selection. May be {@code null} if called
     *            from {@link com.android.documentsui.sidebar.RootsFragment}.
     *            {@link com.android.documentsui.selection.addons.BandSelectionHelper} and
     *            {@link com.android.documentsui.selection.addons.GestureSelectionHelper} to prevent
     *            loader from updating result during band/gesture selection. May be {@code null} if
     *            called from {@link com.android.documentsui.sidebar.RootsFragment}.
     * @return the action handler
     */
    public T getActionHandler(@Nullable ContentLock contentLock) {
Loading