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

Commit 329eb937 authored by Ben Lin's avatar Ben Lin
Browse files

Allow Drag and Drop to form new selection with CTRL held down.

Bug: 31992361
Change-Id: I90036b1b9b3573de289a7bce2d2fb07f69ef5651
parent 0fa2a2cf
Loading
Loading
Loading
Loading
+27 −19
Original line number Original line Diff line number Diff line
@@ -97,18 +97,18 @@ interface DragStartListener {
        @Override
        @Override
        public final boolean onMouseDragEvent(InputEvent event) {
        public final boolean onMouseDragEvent(InputEvent event) {
            assert(Events.isMouseDragEvent(event));
            assert(Events.isMouseDragEvent(event));
            return startDrag(mViewFinder.findView(event.getX(), event.getY()));
            return startDrag(mViewFinder.findView(event.getX(), event.getY()), event);
        }
        }


        @Override
        @Override
        public final boolean onTouchDragEvent(InputEvent event) {
        public final boolean onTouchDragEvent(InputEvent event) {
            return startDrag(mViewFinder.findView(event.getX(), event.getY()));
            return startDrag(mViewFinder.findView(event.getX(), event.getY()), event);
        }
        }


        /**
        /**
         * May be called externally when drag is initiated from other event handling code.
         * May be called externally when drag is initiated from other event handling code.
         */
         */
        private final boolean startDrag(@Nullable View view) {
        private final boolean startDrag(@Nullable View view, InputEvent event) {


            if (view == null) {
            if (view == null) {
                if (DEBUG) Log.d(TAG, "Ignoring drag event, null view.");
                if (DEBUG) Log.d(TAG, "Ignoring drag event, null view.");
@@ -121,22 +121,7 @@ interface DragStartListener {
                return false;
                return false;
            }
            }



            Selection selection = getSelectionToBeCopied(modelId, event);
            Selection selection = new Selection();

            // User can drag an unselected item. Ideally if CTRL key was pressed
            // we'd extend the selection, if not, the selection would be cleared.
            // Buuuuuut, there's an impedance mismatch between event-handling policies,
            // and drag and drop. So we only initiate drag of a single item when
            // drag starts on an item that is unselected. This behavior
            // would look like a bug, if it were not for the implicitly coupled
            // behavior where we clear the selection in the UI (finish action mode)
            // in DirectoryFragment#onDragStart.
            if (!mSelectionMgr.getSelection().contains(modelId)) {
                selection.add(modelId);
            } else {
                mSelectionMgr.getSelection(selection);
            }


            final List<DocumentInfo> invalidDest = mDocsConverter.apply(selection);
            final List<DocumentInfo> invalidDest = mDocsConverter.apply(selection);
            invalidDest.add(mState.stack.peek());
            invalidDest.add(mState.stack.peek());
@@ -158,6 +143,29 @@ interface DragStartListener {
            return true;
            return true;
        }
        }


        /**
         * Given the InputEvent (for CTRL case) and modelId of the view associated with the
         * coordinates of the event, return a valid selection for drag and drop operation
         */
        @VisibleForTesting
        Selection getSelectionToBeCopied(String modelId, InputEvent event) {
            Selection selection = new Selection();
            // If CTRL-key is held down and there's other existing selection, add item to
            // selection (if not already selected)
            if (event.isCtrlKeyDown() && !mSelectionMgr.getSelection().contains(modelId)
                    && mSelectionMgr.hasSelection()) {
                mSelectionMgr.toggleSelection(modelId);
            }

            if (mSelectionMgr.getSelection().contains(modelId)) {
                mSelectionMgr.getSelection(selection);
            } else {
                selection.add(modelId);
                mSelectionMgr.clearSelection();
            }
            return selection;
        }

        /**
        /**
         * This exists as a testing workaround since {@link View#startDragAndDrop} is final.
         * This exists as a testing workaround since {@link View#startDragAndDrop} is final.
         */
         */
+52 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View;


import com.android.documentsui.base.State;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.DragStartListener.ActiveListener;
import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.base.Events.InputEvent;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.Selection;
import com.android.documentsui.selection.Selection;
@@ -35,7 +36,7 @@ import java.util.ArrayList;
@SmallTest
@SmallTest
public class DragStartListenerTest extends AndroidTestCase {
public class DragStartListenerTest extends AndroidTestCase {


    private DragStartListener mListener;
    private ActiveListener mListener;
    private TestEvent.Builder mEvent;
    private TestEvent.Builder mEvent;
    private SelectionManager mMultiSelectManager;
    private SelectionManager mMultiSelectManager;
    private String mViewModelId;
    private String mViewModelId;
@@ -91,6 +92,11 @@ public class DragStartListenerTest extends AndroidTestCase {
                .primary();
                .primary();
    }
    }


    @Override
    protected void tearDown() throws Exception {
        mMultiSelectManager.clearSelection();
    }

    public void testDragStarted_OnMouseMove() {
    public void testDragStarted_OnMouseMove() {
        assertTrue(mListener.onMouseDragEvent(mEvent.build()));
        assertTrue(mListener.onMouseDragEvent(mEvent.build()));
        assertTrue(mDragStarted);
        assertTrue(mDragStarted);
@@ -121,6 +127,51 @@ public class DragStartListenerTest extends AndroidTestCase {
        assertThrows(mEvent.at(-1).build());
        assertThrows(mEvent.at(-1).build());
    }
    }


    public void testDragStart_nonSelectedItem() {
        Selection selection = mListener.getSelectionToBeCopied("1234",
                mEvent.action(MotionEvent.ACTION_MOVE).build());
        assertTrue(selection.size() == 1);
        assertTrue(selection.contains("1234"));
    }

    public void testDragStart_selectedItem() {
        Selection selection = new Selection();
        selection.add("1234");
        selection.add("5678");
        mMultiSelectManager.replaceSelection(selection);

        selection = mListener.getSelectionToBeCopied("1234",
                mEvent.action(MotionEvent.ACTION_MOVE).build());
        assertTrue(selection.size() == 2);
        assertTrue(selection.contains("1234"));
        assertTrue(selection.contains("5678"));
    }

    public void testDragStart_newNonSelectedItem() {
        Selection selection = new Selection();
        selection.add("5678");
        mMultiSelectManager.replaceSelection(selection);

        selection = mListener.getSelectionToBeCopied("1234",
                mEvent.action(MotionEvent.ACTION_MOVE).build());
        assertTrue(selection.size() == 1);
        assertTrue(selection.contains("1234"));
        // After this, selection should be cleared
        assertFalse(mMultiSelectManager.hasSelection());
    }

    public void testCtrlDragStart_newNonSelectedItem() {
        Selection selection = new Selection();
        selection.add("5678");
        mMultiSelectManager.replaceSelection(selection);

        selection = mListener.getSelectionToBeCopied("1234",
                mEvent.action(MotionEvent.ACTION_MOVE).ctrl().build());
        assertTrue(selection.size() == 2);
        assertTrue(selection.contains("1234"));
        assertTrue(selection.contains("5678"));
    }

    private void assertThrows(InputEvent e) {
    private void assertThrows(InputEvent e) {
        try {
        try {
            assertFalse(mListener.onMouseDragEvent(e));
            assertFalse(mListener.onMouseDragEvent(e));