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

Commit 75535725 authored by Ben Kwa's avatar Ben Kwa Committed by android-build-merger
Browse files

Merge "Allow multiple range selections using the shift key." into nyc-dev

am: 4a993b24

* commit '4a993b24':
  Allow multiple range selections using the shift key.
parents c17bb1ff 4a993b24
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -263,7 +263,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
        mSelectionManager.addCallback(selectionListener);
        mSelectionManager.addCallback(selectionListener);


        // Make sure this is done after the RecyclerView is set up.
        // Make sure this is done after the RecyclerView is set up.
        mFocusManager = new FocusManager(mRecView, mSelectionManager);
        mFocusManager = new FocusManager(mRecView);


        mModel = new Model();
        mModel = new Model();
        mModel.addUpdateListener(mAdapter);
        mModel.addUpdateListener(mAdapter);
@@ -1261,6 +1261,18 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
            }
            }


            if (mFocusManager.handleKey(doc, keyCode, event)) {
            if (mFocusManager.handleKey(doc, keyCode, event)) {
                // Handle range selection adjustments. Extending the selection will adjust the
                // bounds of the in-progress range selection. Each time an unshifted navigation
                // event is received, the range selection is restarted.
                if (shouldExtendSelection(event)) {
                    if (!mSelectionManager.isRangeSelectionActive()) {
                        // Start a range selection if one isn't active
                        mSelectionManager.startRangeSelection(doc.getAdapterPosition());
                    }
                    mSelectionManager.snapRangeSelection(mFocusManager.getFocusPosition());
                } else {
                    mSelectionManager.endRangeSelection();
                }
                return true;
                return true;
            }
            }


@@ -1275,6 +1287,11 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi


            return false;
            return false;
        }
        }

        private boolean shouldExtendSelection(KeyEvent event) {
            return Events.isNavigationKeyCode(event.getKeyCode()) &&
                    event.isShiftPressed();
        }
    }
    }


    private final class ModelUpdateListener implements Model.UpdateListener {
    private final class ModelUpdateListener implements Model.UpdateListener {
+8 −10
Original line number Original line Diff line number Diff line
@@ -33,15 +33,13 @@ class FocusManager implements View.OnFocusChangeListener {
    private RecyclerView mView;
    private RecyclerView mView;
    private RecyclerView.Adapter<?> mAdapter;
    private RecyclerView.Adapter<?> mAdapter;
    private LinearLayoutManager mLayout;
    private LinearLayoutManager mLayout;
    private MultiSelectManager mSelectionManager;


    private int mLastFocusPosition = RecyclerView.NO_POSITION;
    private int mLastFocusPosition = RecyclerView.NO_POSITION;


    public FocusManager(RecyclerView view, MultiSelectManager selectionManager) {
    public FocusManager(RecyclerView view) {
        mView = view;
        mView = view;
        mAdapter = view.getAdapter();
        mAdapter = view.getAdapter();
        mLayout = (LinearLayoutManager) view.getLayoutManager();
        mLayout = (LinearLayoutManager) view.getLayoutManager();
        mSelectionManager = selectionManager;
    }
    }


    /**
    /**
@@ -72,13 +70,6 @@ class FocusManager implements View.OnFocusChangeListener {


            if (endPos != RecyclerView.NO_POSITION) {
            if (endPos != RecyclerView.NO_POSITION) {
                focusItem(endPos);
                focusItem(endPos);
                boolean extendSelection = event.isShiftPressed();

                // Handle any necessary adjustments to selection.
                if (extendSelection) {
                    int startPos = doc.getAdapterPosition();
                    mSelectionManager.selectRange(startPos, endPos);
                }
            }
            }
            // Swallow all navigation keystrokes. Otherwise they go to the app's global
            // Swallow all navigation keystrokes. Otherwise they go to the app's global
            // key-handler, which will route them back to the DF and cause focus to be reset.
            // key-handler, which will route them back to the DF and cause focus to be reset.
@@ -108,6 +99,13 @@ class FocusManager implements View.OnFocusChangeListener {
        }
        }
    }
    }


    /**
     * @return The adapter position of the last focused item.
     */
    public int getFocusPosition() {
        return mLastFocusPosition;
    }

    /**
    /**
     * Finds the destination position where the focus should land for a given navigation event.
     * Finds the destination position where the focus should land for a given navigation event.
     *
     *
+26 −24
Original line number Original line Diff line number Diff line
@@ -370,39 +370,41 @@ public final class MultiSelectManager {
    }
    }


    /**
    /**
     * Handle a range selection event.
     * Starts a range selection. If a range selection is already active, this will start a new range
     * <li> If the MSM is currently in single-select mode, only the last item in the range will
     * selection (which will reset the range anchor).
     * actually be selected.
     * <li>If a range selection is not already active, one will be started, and the given range of
     * items will be selected.  The given startPos becomes the anchor for the range selection.
     * <li>If a range selection is already active, the anchor is not changed. The range is extended
     * from its current anchor to endPos.
     *
     *
     * @param startPos
     * @param pos The anchor position for the selection range.
     * @param endPos
     */
     */
    public void selectRange(int startPos, int endPos) {
    void startRangeSelection(int pos) {
        // In single-select mode, just select the last item in the range.
      attemptSelect(mAdapter.getModelId(pos));
        if (mSingleSelect) {
      setSelectionRangeBegin(pos);
            attemptSelect(mAdapter.getModelId(endPos));
            return;
    }
    }


        // In regular (i.e. multi-select) mode
    /**
        if (!isRangeSelectionActive()) {
     * Sets the end point for the current range selection, started by a call to
            // If a range selection isn't active, start one up
     * {@link #startRangeSelection(int)}. This function should only be called when a range selection
            attemptSelect(mAdapter.getModelId(startPos));
     * is active (see {@link #isRangeSelectionActive()}. Items in the range [anchor, end] will be
            setSelectionRangeBegin(startPos);
     * selected.
        }
     *
        // Extend the range selection
     * @param pos The new end position for the selection range.
        mRanger.snapSelection(endPos);
     */
    void snapRangeSelection(int pos) {
        checkNotNull(mRanger);
        mRanger.snapSelection(pos);
        notifySelectionChanged();
        notifySelectionChanged();
    }
    }


    /**
     * Stops an in-progress range selection.
     */
    void endRangeSelection() {
        mRanger = null;
    }

    /**
    /**
     * @return Whether or not there is a current range selection active.
     * @return Whether or not there is a current range selection active.
     */
     */
    private boolean isRangeSelectionActive() {
    boolean isRangeSelectionActive() {
        return mRanger != null;
        return mRanger != null;
    }
    }


+48 −0
Original line number Original line Diff line number Diff line
@@ -189,6 +189,54 @@ public class MultiSelectManagerTest extends AndroidTestCase {
        assertSelection(items.get(20));
        assertSelection(items.get(20));
    }
    }


    public void testRangeSelection() {
        mManager.startRangeSelection(15);
        mManager.snapRangeSelection(19);
        assertRangeSelection(15, 19);
    }

    public void testRangeSelection_snapExpand() {
        mManager.startRangeSelection(15);
        mManager.snapRangeSelection(19);
        mManager.snapRangeSelection(27);
        assertRangeSelection(15, 27);
    }

    public void testRangeSelection_snapContract() {
        mManager.startRangeSelection(15);
        mManager.snapRangeSelection(27);
        mManager.snapRangeSelection(19);
        assertRangeSelection(15, 19);
    }

    public void testRangeSelection_snapInvert() {
        mManager.startRangeSelection(15);
        mManager.snapRangeSelection(27);
        mManager.snapRangeSelection(3);
        assertRangeSelection(3, 15);
    }

    public void testRangeSelection_multiple() {
        mManager.startRangeSelection(15);
        mManager.snapRangeSelection(27);
        mManager.endRangeSelection();
        mManager.startRangeSelection(42);
        mManager.snapRangeSelection(57);
        assertSelectionSize(29);
        assertRangeSelected(15, 27);
        assertRangeSelected(42, 57);

    }

    public void testRangeSelection_singleSelect() {
        mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE, null);
        mManager.addCallback(mCallback);
        mManager.startRangeSelection(11);
        mManager.snapRangeSelection(19);
        assertSelectionSize(1);
        assertSelection(items.get(19));
    }

    public void testProvisionalSelection() {
    public void testProvisionalSelection() {
        Selection s = mManager.getSelection();
        Selection s = mManager.getSelection();
        assertSelection();
        assertSelection();