Loading src/com/android/documentsui/dirlist/DragStartListener.java +27 −19 Original line number Diff line number Diff line Loading @@ -97,18 +97,18 @@ interface DragStartListener { @Override public final boolean onMouseDragEvent(InputEvent event) { assert(Events.isMouseDragEvent(event)); return startDrag(mViewFinder.findView(event.getX(), event.getY())); return startDrag(mViewFinder.findView(event.getX(), event.getY()), event); } @Override 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. */ private final boolean startDrag(@Nullable View view) { private final boolean startDrag(@Nullable View view, InputEvent event) { if (view == null) { if (DEBUG) Log.d(TAG, "Ignoring drag event, null view."); Loading @@ -121,22 +121,7 @@ interface DragStartListener { return false; } 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); } Selection selection = getSelectionToBeCopied(modelId, event); final List<DocumentInfo> invalidDest = mDocsConverter.apply(selection); invalidDest.add(mState.stack.peek()); Loading @@ -158,6 +143,29 @@ interface DragStartListener { 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. */ Loading tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.view.MotionEvent; import android.view.View; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.DragStartListener.ActiveListener; import com.android.documentsui.base.Events.InputEvent; import com.android.documentsui.selection.SelectionManager; import com.android.documentsui.selection.Selection; Loading @@ -35,7 +36,7 @@ import java.util.ArrayList; @SmallTest public class DragStartListenerTest extends AndroidTestCase { private DragStartListener mListener; private ActiveListener mListener; private TestEvent.Builder mEvent; private SelectionManager mMultiSelectManager; private String mViewModelId; Loading Loading @@ -91,6 +92,11 @@ public class DragStartListenerTest extends AndroidTestCase { .primary(); } @Override protected void tearDown() throws Exception { mMultiSelectManager.clearSelection(); } public void testDragStarted_OnMouseMove() { assertTrue(mListener.onMouseDragEvent(mEvent.build())); assertTrue(mDragStarted); Loading Loading @@ -121,6 +127,51 @@ public class DragStartListenerTest extends AndroidTestCase { 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) { try { assertFalse(mListener.onMouseDragEvent(e)); Loading Loading
src/com/android/documentsui/dirlist/DragStartListener.java +27 −19 Original line number Diff line number Diff line Loading @@ -97,18 +97,18 @@ interface DragStartListener { @Override public final boolean onMouseDragEvent(InputEvent event) { assert(Events.isMouseDragEvent(event)); return startDrag(mViewFinder.findView(event.getX(), event.getY())); return startDrag(mViewFinder.findView(event.getX(), event.getY()), event); } @Override 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. */ private final boolean startDrag(@Nullable View view) { private final boolean startDrag(@Nullable View view, InputEvent event) { if (view == null) { if (DEBUG) Log.d(TAG, "Ignoring drag event, null view."); Loading @@ -121,22 +121,7 @@ interface DragStartListener { return false; } 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); } Selection selection = getSelectionToBeCopied(modelId, event); final List<DocumentInfo> invalidDest = mDocsConverter.apply(selection); invalidDest.add(mState.stack.peek()); Loading @@ -158,6 +143,29 @@ interface DragStartListener { 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. */ Loading
tests/unit/com/android/documentsui/dirlist/DragStartListenerTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.view.MotionEvent; import android.view.View; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.DragStartListener.ActiveListener; import com.android.documentsui.base.Events.InputEvent; import com.android.documentsui.selection.SelectionManager; import com.android.documentsui.selection.Selection; Loading @@ -35,7 +36,7 @@ import java.util.ArrayList; @SmallTest public class DragStartListenerTest extends AndroidTestCase { private DragStartListener mListener; private ActiveListener mListener; private TestEvent.Builder mEvent; private SelectionManager mMultiSelectManager; private String mViewModelId; Loading Loading @@ -91,6 +92,11 @@ public class DragStartListenerTest extends AndroidTestCase { .primary(); } @Override protected void tearDown() throws Exception { mMultiSelectManager.clearSelection(); } public void testDragStarted_OnMouseMove() { assertTrue(mListener.onMouseDragEvent(mEvent.build())); assertTrue(mDragStarted); Loading Loading @@ -121,6 +127,51 @@ public class DragStartListenerTest extends AndroidTestCase { 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) { try { assertFalse(mListener.onMouseDragEvent(e)); Loading