Loading src/com/android/documentsui/dirlist/MultiSelectManager.java +8 −14 Original line number Diff line number Diff line Loading @@ -903,7 +903,7 @@ public final class MultiSelectManager { public Selection createFromParcel(Parcel in, ClassLoader loader) { return new Selection( in.readString(), (ArrayList<String>) in.readArrayList(loader)); in.readArrayList(loader)); } @Override Loading Loading @@ -931,7 +931,6 @@ public final class MultiSelectManager { Rect getAbsoluteRectForChildViewAt(int index); int getAdapterPositionAt(int index); int getColumnCount(); int getRowCount(); int getChildCount(); int getVisibleChildCount(); /** Loading Loading @@ -1007,13 +1006,6 @@ public final class MultiSelectManager { return 1; } @Override public int getRowCount() { int numFullColumns = getChildCount() / getColumnCount(); boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0; return numFullColumns + (hasPartiallyFullColumn ? 1 : 0); } @Override public int getHeight() { return mView.getHeight(); Loading Loading @@ -1202,6 +1194,7 @@ public final class MultiSelectManager { } mCurrentPosition = input.getOrigin(); mModel.resizeSelection(input.getOrigin()); scrollViewIfNecessary(); resizeBandSelectRectangle(); } Loading Loading @@ -1549,11 +1542,7 @@ public final class MultiSelectManager { mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right)); } if (mRowBounds.size() != mHelper.getRowCount()) { // If not all y-limits have been recorded, record this one. recordLimits( mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); } recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); SparseIntArray columnList = mColumns.get(absoluteChildRect.left); if (columnList == null) { Loading Loading @@ -1747,6 +1736,11 @@ public final class MultiSelectManager { return ((Limits) other).lowerLimit == lowerLimit && ((Limits) other).upperLimit == upperLimit; } @Override public String toString() { return "(" + lowerLimit + ", " + upperLimit + ")"; } } /** Loading tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java +216 −88 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.documentsui.dirlist.MultiSelectManager.GridModel; import java.util.ArrayList; import java.util.List; import java.util.Set; @SmallTest Loading @@ -42,6 +43,17 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private Set<String> lastSelection; private int viewWidth; // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and // #resizeSelection methods instead. // // The reason for this is that selection is stateful and involves operations that take the // current UI state (e.g scrolling) into account. This test maintains its own copy of the // selection bounds as control data for verifying selections. Keep this data in sync by calling // #startSelection and // #resizeSelection. private Point mSelectionOrigin; private Point mSelectionPoint; private void initData(final int numChildren, int numColumns) { env = new TestEnvironment(numChildren, numColumns); adapter = new TestDocumentsAdapter(new ArrayList<String>()) { Loading Loading @@ -76,139 +88,241 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public void testSelectionLeftOfItems() { initData(20, 5); model.startSelection(new Point(0, 10)); model.resizeSelection(new Point(1, 11)); assertSelected(); startSelection(new Point(0, 10)); resizeSelection(new Point(1, 11)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionRightOfItems() { initData(20, 4); model.startSelection(new Point(viewWidth - 1, 10)); model.resizeSelection(new Point(viewWidth - 2, 11)); assertSelected(); startSelection(new Point(viewWidth - 1, 10)); resizeSelection(new Point(viewWidth - 2, 11)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionAboveItems() { initData(20, 4); model.startSelection(new Point(10, 0)); model.resizeSelection(new Point(11, 1)); assertSelected(); startSelection(new Point(10, 0)); resizeSelection(new Point(11, 1)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionBelowItems() { initData(5, 4); model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); assertSelected(); startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testVerticalSelectionBetweenItems() { initData(20, 4); model.startSelection(new Point(106, 0)); model.resizeSelection(new Point(107, 200)); assertSelected(); startSelection(new Point(106, 0)); resizeSelection(new Point(107, 200)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testHorizontalSelectionBetweenItems() { initData(20, 4); model.startSelection(new Point(0, 105)); model.resizeSelection(new Point(200, 106)); assertSelected(); startSelection(new Point(0, 105)); resizeSelection(new Point(200, 106)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testGrowingAndShrinkingSelection() { initData(20, 4); model.startSelection(new Point(0, 0)); model.resizeSelection(new Point(5, 5)); assertSelected(0); model.resizeSelection(new Point(109, 109)); assertSelected(0); model.resizeSelection(new Point(110, 109)); assertSelected(0, 1); model.resizeSelection(new Point(110, 110)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(214, 214)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(215, 214)); assertSelected(0, 1, 2, 4, 5, 6); model.resizeSelection(new Point(214, 214)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(110, 110)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(110, 109)); assertSelected(0, 1); model.resizeSelection(new Point(109, 109)); assertSelected(0); model.resizeSelection(new Point(5, 5)); assertSelected(0); model.resizeSelection(new Point(0, 0)); assertSelected(); startSelection(new Point(0, 0)); resizeSelection(new Point(5, 5)); verifySelection(); resizeSelection(new Point(109, 109)); verifySelection(); resizeSelection(new Point(110, 109)); verifySelection(); resizeSelection(new Point(110, 110)); verifySelection(); resizeSelection(new Point(214, 214)); verifySelection(); resizeSelection(new Point(215, 214)); verifySelection(); resizeSelection(new Point(214, 214)); verifySelection(); resizeSelection(new Point(110, 110)); verifySelection(); resizeSelection(new Point(110, 109)); verifySelection(); resizeSelection(new Point(109, 109)); verifySelection(); resizeSelection(new Point(5, 5)); verifySelection(); resizeSelection(new Point(0, 0)); verifySelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionMovingAroundOrigin() { initData(16, 4); model.startSelection(new Point(210, 210)); model.resizeSelection(new Point(viewWidth - 1, 0)); assertSelected(2, 3, 6, 7); model.resizeSelection(new Point(0, 0)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(0, 420)); assertSelected(8, 9, 12, 13); model.resizeSelection(new Point(viewWidth - 1, 420)); assertSelected(10, 11, 14, 15); assertEquals(10, model.getPositionNearestOrigin()); startSelection(new Point(210, 210)); resizeSelection(new Point(viewWidth - 1, 0)); verifySelection(); resizeSelection(new Point(0, 0)); verifySelection(); resizeSelection(new Point(0, 420)); verifySelection(); resizeSelection(new Point(viewWidth - 1, 420)); verifySelection(); // This is manually figured and will need to be adjusted if the separator position is // changed. assertEquals(7, model.getPositionNearestOrigin()); } public void testScrollingBandSelect() { initData(40, 4); model.startSelection(new Point(0, 0)); model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); assertSelected(0, 4, 8, 12, 16); startSelection(new Point(0, 0)); resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); verifySelection(); scroll(CHILD_VIEW_EDGE_PX); assertSelected(0, 4, 8, 12, 16, 20); model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21); verifySelection(); resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); verifySelection(); scroll(CHILD_VIEW_EDGE_PX); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25); verifySelection(); scroll(-2 * CHILD_VIEW_EDGE_PX); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17); model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); assertSelected(0, 4, 8, 12, 16); verifySelection(); resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); verifySelection(); assertEquals(0, model.getPositionNearestOrigin()); } private void assertSelected(int... selectedPositions) { assertEquals(selectedPositions.length, lastSelection.size()); for (int position : selectedPositions) { assertTrue(lastSelection.contains(Integer.toString(position))); /** Returns the current selection area as a Rect. */ private Rect getSelectionArea() { // Construct a rect from the two selection points. Rect selectionArea = new Rect( mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y); selectionArea.union(mSelectionPoint.x, mSelectionPoint.y); // Rect intersection tests are exclusive of bounds, while the MSM's selection code is // inclusive. Expand the rect by 1 pixel in all directions to account for this. selectionArea.inset(-1, -1); return selectionArea; } /** Asserts that the selection is currently empty. */ private void assertNoSelection() { assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(), 0, lastSelection.size()); } /** Verifies the selection using actual bbox checks. */ private void verifySelection() { Rect selectionArea = getSelectionArea(); for (TestEnvironment.Item item: env.items) { if (Rect.intersects(selectionArea, item.rect)) { assertTrue("Expected item " + item + " was not in selection " + selectionArea, lastSelection.contains(item.name)); } else { assertFalse("Unexpected item " + item + " in selection" + selectionArea, lastSelection.contains(item.name)); } } } private void startSelection(Point p) { model.startSelection(p); mSelectionOrigin = env.createAbsolutePoint(p); } private void resizeSelection(Point p) { model.resizeSelection(p); mSelectionPoint = env.createAbsolutePoint(p); } private void scroll(int dy) { assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight()); env.verticalOffset += dy; // Correct the cached selection point as well. mSelectionPoint.y += dy; model.onScrolled(null, 0, dy); } private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment { public int horizontalOffset = 0; public int verticalOffset = 0; private final int mNumColumns; private final int mNumRows; private final int mNumChildren; private final int mSeparatorPosition; public int horizontalOffset = 0; public int verticalOffset = 0; private List<Item> items = new ArrayList<>(); public TestEnvironment(int numChildren, int numColumns) { mNumChildren = numChildren; mNumColumns = numColumns; mNumRows = (int) Math.ceil((double) numChildren / mNumColumns); mSeparatorPosition = mNumColumns + 1; mNumRows = setupGrid(); } private int setupGrid() { // Split the input set into folders and documents. Do this such that there is a // partially-populated row in the middle of the grid, to test corner cases in layout // code. int y = VIEW_PADDING_PX; int i = 0; int numRows = 0; while (i < mNumChildren) { int top = y; int height = CHILD_VIEW_EDGE_PX; int width = CHILD_VIEW_EDGE_PX; for (int j = 0; j < mNumColumns && i < mNumChildren; j++) { int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX)); items.add(new Item( Integer.toString(i), new Rect( left, top, left + width - 1, top + height - 1))); // Create a partially populated row at the separator position. if (++i == mSeparatorPosition) { break; } } y += height + VIEW_PADDING_PX; numRows++; } return numRows; } private int getTotalHeight() { Loading @@ -227,8 +341,16 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private int getNumItemsInRow(int index) { assertTrue(index >= 0 && index < mNumRows); if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) { return mNumChildren % mNumColumns; int mod = mSeparatorPosition % mNumColumns; if (index == (mSeparatorPosition / mNumColumns)) { // The row containing the separator may be incomplete return mod > 0 ? mod : mNumColumns; } // Account for the partial separator row in the final row tally. if (index == mNumRows - 1) { // The last row may be incomplete int finalRowCount = (mNumChildren - mod) % mNumColumns; return finalRowCount > 0 ? finalRowCount : mNumColumns; } return mNumColumns; Loading Loading @@ -257,21 +379,18 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { @Override public int getAdapterPositionAt(int index) { return index + mNumColumns * (getFirstVisibleRowIndex()); // Account for partial rows by actually tallying up the items in hidden rows. int hiddenCount = 0; for (int i = 0; i < getFirstVisibleRowIndex(); i++) { hiddenCount += getNumItemsInRow(i); } return index + hiddenCount; } @Override public Rect getAbsoluteRectForChildViewAt(int index) { int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index; int rowIndex = adapterPosition / mNumColumns; int columnIndex = adapterPosition % mNumColumns; Rect rect = new Rect(); rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1; rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1; return rect; int adapterPosition = getAdapterPositionAt(index); return items.get(adapterPosition).rect; } @Override Loading @@ -284,11 +403,6 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { return mNumColumns; } @Override public int getRowCount() { return mNumRows; } @Override public void showBand(Rect rect) { throw new UnsupportedOperationException(); Loading Loading @@ -328,5 +442,19 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public boolean isLayoutItem(int adapterPosition) { return false; } public static final class Item { public String name; public Rect rect; public Item(String n, Rect r) { name = n; rect = r; } public String toString() { return name + ": " + rect; } } } } tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java +0 −5 Original line number Diff line number Diff line Loading @@ -86,11 +86,6 @@ public class TestSelectionEnvironment implements SelectionEnvironment { return 0; } @Override public int getRowCount() { return 0; } @Override public int getChildCount() { return 0; Loading Loading
src/com/android/documentsui/dirlist/MultiSelectManager.java +8 −14 Original line number Diff line number Diff line Loading @@ -903,7 +903,7 @@ public final class MultiSelectManager { public Selection createFromParcel(Parcel in, ClassLoader loader) { return new Selection( in.readString(), (ArrayList<String>) in.readArrayList(loader)); in.readArrayList(loader)); } @Override Loading Loading @@ -931,7 +931,6 @@ public final class MultiSelectManager { Rect getAbsoluteRectForChildViewAt(int index); int getAdapterPositionAt(int index); int getColumnCount(); int getRowCount(); int getChildCount(); int getVisibleChildCount(); /** Loading Loading @@ -1007,13 +1006,6 @@ public final class MultiSelectManager { return 1; } @Override public int getRowCount() { int numFullColumns = getChildCount() / getColumnCount(); boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0; return numFullColumns + (hasPartiallyFullColumn ? 1 : 0); } @Override public int getHeight() { return mView.getHeight(); Loading Loading @@ -1202,6 +1194,7 @@ public final class MultiSelectManager { } mCurrentPosition = input.getOrigin(); mModel.resizeSelection(input.getOrigin()); scrollViewIfNecessary(); resizeBandSelectRectangle(); } Loading Loading @@ -1549,11 +1542,7 @@ public final class MultiSelectManager { mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right)); } if (mRowBounds.size() != mHelper.getRowCount()) { // If not all y-limits have been recorded, record this one. recordLimits( mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); } recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); SparseIntArray columnList = mColumns.get(absoluteChildRect.left); if (columnList == null) { Loading Loading @@ -1747,6 +1736,11 @@ public final class MultiSelectManager { return ((Limits) other).lowerLimit == lowerLimit && ((Limits) other).upperLimit == upperLimit; } @Override public String toString() { return "(" + lowerLimit + ", " + upperLimit + ")"; } } /** Loading
tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java +216 −88 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.documentsui.dirlist.MultiSelectManager.GridModel; import java.util.ArrayList; import java.util.List; import java.util.Set; @SmallTest Loading @@ -42,6 +43,17 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private Set<String> lastSelection; private int viewWidth; // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and // #resizeSelection methods instead. // // The reason for this is that selection is stateful and involves operations that take the // current UI state (e.g scrolling) into account. This test maintains its own copy of the // selection bounds as control data for verifying selections. Keep this data in sync by calling // #startSelection and // #resizeSelection. private Point mSelectionOrigin; private Point mSelectionPoint; private void initData(final int numChildren, int numColumns) { env = new TestEnvironment(numChildren, numColumns); adapter = new TestDocumentsAdapter(new ArrayList<String>()) { Loading Loading @@ -76,139 +88,241 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public void testSelectionLeftOfItems() { initData(20, 5); model.startSelection(new Point(0, 10)); model.resizeSelection(new Point(1, 11)); assertSelected(); startSelection(new Point(0, 10)); resizeSelection(new Point(1, 11)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionRightOfItems() { initData(20, 4); model.startSelection(new Point(viewWidth - 1, 10)); model.resizeSelection(new Point(viewWidth - 2, 11)); assertSelected(); startSelection(new Point(viewWidth - 1, 10)); resizeSelection(new Point(viewWidth - 2, 11)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionAboveItems() { initData(20, 4); model.startSelection(new Point(10, 0)); model.resizeSelection(new Point(11, 1)); assertSelected(); startSelection(new Point(10, 0)); resizeSelection(new Point(11, 1)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionBelowItems() { initData(5, 4); model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); assertSelected(); startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testVerticalSelectionBetweenItems() { initData(20, 4); model.startSelection(new Point(106, 0)); model.resizeSelection(new Point(107, 200)); assertSelected(); startSelection(new Point(106, 0)); resizeSelection(new Point(107, 200)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testHorizontalSelectionBetweenItems() { initData(20, 4); model.startSelection(new Point(0, 105)); model.resizeSelection(new Point(200, 106)); assertSelected(); startSelection(new Point(0, 105)); resizeSelection(new Point(200, 106)); assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testGrowingAndShrinkingSelection() { initData(20, 4); model.startSelection(new Point(0, 0)); model.resizeSelection(new Point(5, 5)); assertSelected(0); model.resizeSelection(new Point(109, 109)); assertSelected(0); model.resizeSelection(new Point(110, 109)); assertSelected(0, 1); model.resizeSelection(new Point(110, 110)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(214, 214)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(215, 214)); assertSelected(0, 1, 2, 4, 5, 6); model.resizeSelection(new Point(214, 214)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(110, 110)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(110, 109)); assertSelected(0, 1); model.resizeSelection(new Point(109, 109)); assertSelected(0); model.resizeSelection(new Point(5, 5)); assertSelected(0); model.resizeSelection(new Point(0, 0)); assertSelected(); startSelection(new Point(0, 0)); resizeSelection(new Point(5, 5)); verifySelection(); resizeSelection(new Point(109, 109)); verifySelection(); resizeSelection(new Point(110, 109)); verifySelection(); resizeSelection(new Point(110, 110)); verifySelection(); resizeSelection(new Point(214, 214)); verifySelection(); resizeSelection(new Point(215, 214)); verifySelection(); resizeSelection(new Point(214, 214)); verifySelection(); resizeSelection(new Point(110, 110)); verifySelection(); resizeSelection(new Point(110, 109)); verifySelection(); resizeSelection(new Point(109, 109)); verifySelection(); resizeSelection(new Point(5, 5)); verifySelection(); resizeSelection(new Point(0, 0)); verifySelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionMovingAroundOrigin() { initData(16, 4); model.startSelection(new Point(210, 210)); model.resizeSelection(new Point(viewWidth - 1, 0)); assertSelected(2, 3, 6, 7); model.resizeSelection(new Point(0, 0)); assertSelected(0, 1, 4, 5); model.resizeSelection(new Point(0, 420)); assertSelected(8, 9, 12, 13); model.resizeSelection(new Point(viewWidth - 1, 420)); assertSelected(10, 11, 14, 15); assertEquals(10, model.getPositionNearestOrigin()); startSelection(new Point(210, 210)); resizeSelection(new Point(viewWidth - 1, 0)); verifySelection(); resizeSelection(new Point(0, 0)); verifySelection(); resizeSelection(new Point(0, 420)); verifySelection(); resizeSelection(new Point(viewWidth - 1, 420)); verifySelection(); // This is manually figured and will need to be adjusted if the separator position is // changed. assertEquals(7, model.getPositionNearestOrigin()); } public void testScrollingBandSelect() { initData(40, 4); model.startSelection(new Point(0, 0)); model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); assertSelected(0, 4, 8, 12, 16); startSelection(new Point(0, 0)); resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); verifySelection(); scroll(CHILD_VIEW_EDGE_PX); assertSelected(0, 4, 8, 12, 16, 20); model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21); verifySelection(); resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); verifySelection(); scroll(CHILD_VIEW_EDGE_PX); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25); verifySelection(); scroll(-2 * CHILD_VIEW_EDGE_PX); assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17); model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); assertSelected(0, 4, 8, 12, 16); verifySelection(); resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); verifySelection(); assertEquals(0, model.getPositionNearestOrigin()); } private void assertSelected(int... selectedPositions) { assertEquals(selectedPositions.length, lastSelection.size()); for (int position : selectedPositions) { assertTrue(lastSelection.contains(Integer.toString(position))); /** Returns the current selection area as a Rect. */ private Rect getSelectionArea() { // Construct a rect from the two selection points. Rect selectionArea = new Rect( mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y); selectionArea.union(mSelectionPoint.x, mSelectionPoint.y); // Rect intersection tests are exclusive of bounds, while the MSM's selection code is // inclusive. Expand the rect by 1 pixel in all directions to account for this. selectionArea.inset(-1, -1); return selectionArea; } /** Asserts that the selection is currently empty. */ private void assertNoSelection() { assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(), 0, lastSelection.size()); } /** Verifies the selection using actual bbox checks. */ private void verifySelection() { Rect selectionArea = getSelectionArea(); for (TestEnvironment.Item item: env.items) { if (Rect.intersects(selectionArea, item.rect)) { assertTrue("Expected item " + item + " was not in selection " + selectionArea, lastSelection.contains(item.name)); } else { assertFalse("Unexpected item " + item + " in selection" + selectionArea, lastSelection.contains(item.name)); } } } private void startSelection(Point p) { model.startSelection(p); mSelectionOrigin = env.createAbsolutePoint(p); } private void resizeSelection(Point p) { model.resizeSelection(p); mSelectionPoint = env.createAbsolutePoint(p); } private void scroll(int dy) { assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight()); env.verticalOffset += dy; // Correct the cached selection point as well. mSelectionPoint.y += dy; model.onScrolled(null, 0, dy); } private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment { public int horizontalOffset = 0; public int verticalOffset = 0; private final int mNumColumns; private final int mNumRows; private final int mNumChildren; private final int mSeparatorPosition; public int horizontalOffset = 0; public int verticalOffset = 0; private List<Item> items = new ArrayList<>(); public TestEnvironment(int numChildren, int numColumns) { mNumChildren = numChildren; mNumColumns = numColumns; mNumRows = (int) Math.ceil((double) numChildren / mNumColumns); mSeparatorPosition = mNumColumns + 1; mNumRows = setupGrid(); } private int setupGrid() { // Split the input set into folders and documents. Do this such that there is a // partially-populated row in the middle of the grid, to test corner cases in layout // code. int y = VIEW_PADDING_PX; int i = 0; int numRows = 0; while (i < mNumChildren) { int top = y; int height = CHILD_VIEW_EDGE_PX; int width = CHILD_VIEW_EDGE_PX; for (int j = 0; j < mNumColumns && i < mNumChildren; j++) { int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX)); items.add(new Item( Integer.toString(i), new Rect( left, top, left + width - 1, top + height - 1))); // Create a partially populated row at the separator position. if (++i == mSeparatorPosition) { break; } } y += height + VIEW_PADDING_PX; numRows++; } return numRows; } private int getTotalHeight() { Loading @@ -227,8 +341,16 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private int getNumItemsInRow(int index) { assertTrue(index >= 0 && index < mNumRows); if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) { return mNumChildren % mNumColumns; int mod = mSeparatorPosition % mNumColumns; if (index == (mSeparatorPosition / mNumColumns)) { // The row containing the separator may be incomplete return mod > 0 ? mod : mNumColumns; } // Account for the partial separator row in the final row tally. if (index == mNumRows - 1) { // The last row may be incomplete int finalRowCount = (mNumChildren - mod) % mNumColumns; return finalRowCount > 0 ? finalRowCount : mNumColumns; } return mNumColumns; Loading Loading @@ -257,21 +379,18 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { @Override public int getAdapterPositionAt(int index) { return index + mNumColumns * (getFirstVisibleRowIndex()); // Account for partial rows by actually tallying up the items in hidden rows. int hiddenCount = 0; for (int i = 0; i < getFirstVisibleRowIndex(); i++) { hiddenCount += getNumItemsInRow(i); } return index + hiddenCount; } @Override public Rect getAbsoluteRectForChildViewAt(int index) { int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index; int rowIndex = adapterPosition / mNumColumns; int columnIndex = adapterPosition % mNumColumns; Rect rect = new Rect(); rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1; rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1; return rect; int adapterPosition = getAdapterPositionAt(index); return items.get(adapterPosition).rect; } @Override Loading @@ -284,11 +403,6 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { return mNumColumns; } @Override public int getRowCount() { return mNumRows; } @Override public void showBand(Rect rect) { throw new UnsupportedOperationException(); Loading Loading @@ -328,5 +442,19 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public boolean isLayoutItem(int adapterPosition) { return false; } public static final class Item { public String name; public Rect rect; public Item(String n, Rect r) { name = n; rect = r; } public String toString() { return name + ": " + rect; } } } }
tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java +0 −5 Original line number Diff line number Diff line Loading @@ -86,11 +86,6 @@ public class TestSelectionEnvironment implements SelectionEnvironment { return 0; } @Override public int getRowCount() { return 0; } @Override public int getChildCount() { return 0; Loading