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

Commit 6373bfda authored by Steve McKay's avatar Steve McKay
Browse files

API cleanup and purdy-fication.

- Move gesture initiation into TouchInputHandler (out of the Callback,
    it shouldn'ta been in the callback in the first place.)
- Make {Band,Gesture}SelectionHelper implement OnItemTouchListener directly.
- Minor cleanups in GestureSelectionHelper logic.
- Allow SelectionPredicate to answer the "can select multiple" question.

Bug: 64847011
Test: Added gesture initiation coverage.
Change-Id: Ic3b3e8613e6408ad0c611d3224b87ee9330183b7
parent 08d0d56f
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -337,7 +337,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
        mSelectionMgr.addObserver(mSelectionMetadata);
        mDetailsLookup = new DocsItemDetailsLookup(mRecView);

        GestureSelectionHelper gestureSel =
        GestureSelectionHelper gestureHelper =
                GestureSelectionHelper.create(mSelectionMgr, mRecView, mContentLock);

        if (mState.allowMultiple) {
@@ -380,8 +380,12 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
                mRecView,
                mState);

        MouseInputHandler mouseHandler = handlers.createMouseHandler(this::onContextMenuClick);
        TouchInputHandler touchHandler = handlers.createTouchHandler(gestureSel, dragStartListener);
        MouseInputHandler mouseHandler =
                handlers.createMouseHandler(this::onContextMenuClick);

        TouchInputHandler touchHandler =
                handlers.createTouchHandler(gestureHelper, dragStartListener);

        GestureRouter<MotionInputHandler> gestureRouter = new GestureRouter<>(touchHandler);
        gestureRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mouseHandler);

@@ -399,15 +403,12 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On

        GestureDetector gestureDetector = new GestureDetector(getContext(), gestureRouter);

        TouchEventRouter eventRouter =
                new TouchEventRouter(gestureDetector, gestureSel.getTouchListener());
        TouchEventRouter eventRouter = new TouchEventRouter(gestureDetector, gestureHelper);

        eventRouter.register(
                MotionEvent.TOOL_TYPE_MOUSE,
                new MouseDragEventInterceptor(
                        mDetailsLookup,
                        dragStartListener::onMouseDragEvent,
                        mBandSelector != null ? mBandSelector.getTouchListener() : null));
                        mDetailsLookup, dragStartListener::onMouseDragEvent, mBandSelector));

        mRecView.addOnItemTouchListener(eventRouter);

+6 −1
Original line number Diff line number Diff line
@@ -91,4 +91,9 @@ final class DocsSelectionPredicate extends SelectionPredicate {
        RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(position);
        return ModelBackedDocumentsAdapter.isContentType(vh.getItemViewType());
    }

    @Override
    public boolean canSelectMultiple() {
        return mState.allowMultiple;
    }
}
+4 −19
Original line number Diff line number Diff line
@@ -180,21 +180,16 @@ final class InputHandlers {
            }
        };

        return new MouseInputHandler(
                mSelectionHelper,
                mDetailsLookup,
                callbacks);
        return new MouseInputHandler(mSelectionHelper, mDetailsLookup, callbacks);
    }

    /**
     * Factory method for input touch delegate. Exists to reduce complexity in the
     * calling scope.
     * @param gestureHelper
     */
    TouchInputHandler createTouchHandler(
            GestureSelectionHelper gestureSel,
            DragStartListener dragStartListener) {

        checkArgument(gestureSel != null);
            GestureSelectionHelper gestureHelper, DragStartListener dragStartListener) {
        checkArgument(dragStartListener != null);

        TouchInputHandler.Callbacks callbacks = new TouchInputHandler.Callbacks() {
@@ -206,13 +201,6 @@ final class InputHandlers {
                        ActionHandler.VIEW_TYPE_REGULAR);
            }

            @Override
            public boolean onGestureInitiated(MotionEvent e) {
                return mState.allowMultiple
                        ? gestureSel.start()
                                : false;
            }

            @Override
            public boolean onDragInitiated(MotionEvent e) {
                return dragStartListener.onTouchDragEvent(e);
@@ -235,9 +223,6 @@ final class InputHandlers {
        };

        return new TouchInputHandler(
                mSelectionHelper,
                mDetailsLookup,
                mSelectionPredicate,
                callbacks);
                mSelectionHelper, mDetailsLookup, mSelectionPredicate, gestureHelper, callbacks);
    }
}
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -228,5 +228,10 @@ public abstract class SelectionHelper {

        /** @return true if the item at {@code id} can be set to {@code nextState}. */
        public abstract boolean canSetStateAtPosition(int position, boolean nextState);

        /** @return true if more than a single item can be selected. */
        public boolean canSelectMultiple() {
            return true;
        }
    }
}
+29 −50
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.documentsui.selection.addons;

import static android.support.v4.util.Preconditions.checkArgument;
import static android.support.v4.util.Preconditions.checkState;

import android.graphics.Point;
import android.graphics.Rect;
@@ -48,7 +49,7 @@ import java.util.Set;
 *
 * <p><pre>TODO</pre>
 */
public class BandSelectionHelper {
public class BandSelectionHelper implements OnItemTouchListener {

    static final boolean DEBUG = false;
    static final String TAG = "BandController";
@@ -178,20 +179,6 @@ public class BandSelectionHelper {
        return mModel != null;
    }

    private boolean onInterceptTouchEvent(MotionEvent e) {
        if (shouldStart(e)) {
            if (!MotionEvents.isCtrlKeyPressed(e)) {
                mSelectionHelper.clearSelection();
            }

            startBandSelect(MotionEvents.getOrigin(e));
        } else if (shouldStop(e)) {
            endBandSelect();
        }

        return isActive();
    }

    /**
     * Adds a new listener to be notified when band is created.
     */
@@ -235,7 +222,8 @@ public class BandSelectionHelper {
        // mouse moves, or else starting band selection on mouse down can cause problems as events
        // don't get routed correctly to onTouchEvent.
        return !isActive()
                && MotionEvents.isActionMove(e) // the initial button move via mouse-touch (ie. down press)
                && MotionEvents.isActionMove(e)
                // the initial button move via mouse-touch (ie. down press)
                // The adapter inserts items for UI layout purposes that aren't
                // associated with files. Checking against actual modelIds count
                // effectively ignores those UI layout items.
@@ -251,13 +239,32 @@ public class BandSelectionHelper {
                        || MotionEvents.isActionCancel(e));
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView unused, MotionEvent e) {
        if (shouldStart(e)) {
            if (!MotionEvents.isCtrlKeyPressed(e)) {
                mSelectionHelper.clearSelection();
            }

            startBandSelect(MotionEvents.getOrigin(e));
            return isActive();
        }

        if (shouldStop(e)) {
            endBandSelect();
            checkState(mModel == null);
            // fall through to return false, because the band eeess done!
        }

        return false;
    }

    /**
     * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
     * @param input
     */
    private void onTouchEvent(MotionEvent e) {
        assert MotionEvents.isMouseEvent(e);

    @Override
    public void onTouchEvent(RecyclerView unused, MotionEvent e) {
        if (shouldStop(e)) {
            endBandSelect();
            return;
@@ -279,6 +286,9 @@ public class BandSelectionHelper {
        resizeBandSelectRectangle();
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}

    /**
     * Starts band select by adding the drawable to the RecyclerView's overlay.
     */
@@ -356,37 +366,6 @@ public class BandSelectionHelper {
        resizeBandSelectRectangle();
    }

    public OnItemTouchListener getTouchListener() {
        return new EventPreprocessor(this);
    }

    private static class EventPreprocessor implements OnItemTouchListener {

        private final BandSelectionHelper mBandController;

        public EventPreprocessor(BandSelectionHelper bandController) {
            checkArgument(bandController != null);

            mBandController = bandController;
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            if (mBandController.shouldStart(e) || mBandController.shouldStop(e)) {
                return mBandController.onInterceptTouchEvent(e);
            }
            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
            mBandController.onTouchEvent(e);
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
    }

    /**
     * Provides functionality for BandController. Exists primarily to tests that are
     * fully isolated from RecyclerView.
Loading