| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.documentsui.dirlist; |
| |
| import static com.android.documentsui.dirlist.MultiSelectManager.GridModel.NOT_SET; |
| |
| import android.graphics.Point; |
| import android.graphics.Rect; |
| import android.support.v7.widget.RecyclerView.OnScrollListener; |
| import android.test.AndroidTestCase; |
| import android.test.suitebuilder.annotation.SmallTest; |
| import android.view.View; |
| |
| import com.android.documentsui.dirlist.MultiSelectManager.GridModel; |
| |
| import java.util.ArrayList; |
| import java.util.Set; |
| |
| @SmallTest |
| public class MultiSelectManager_GridModelTest extends AndroidTestCase { |
| |
| private static final int VIEW_PADDING_PX = 5; |
| private static final int CHILD_VIEW_EDGE_PX = 100; |
| private static final int VIEWPORT_HEIGHT = 500; |
| |
| private GridModel model; |
| private TestEnvironment env; |
| private TestDocumentsAdapter adapter; |
| private Set<String> lastSelection; |
| private int viewWidth; |
| |
| private void initData(final int numChildren, int numColumns) { |
| env = new TestEnvironment(numChildren, numColumns); |
| adapter = new TestDocumentsAdapter(new ArrayList<String>()) { |
| @Override |
| public String getModelId(int position) { |
| return Integer.toString(position); |
| } |
| |
| @Override |
| public int getItemCount() { |
| return numChildren; |
| } |
| }; |
| |
| viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX); |
| model = new GridModel(env, adapter); |
| model.addOnSelectionChangedListener( |
| new GridModel.OnSelectionChangedListener() { |
| @Override |
| public void onSelectionChanged(Set<String> updatedSelection) { |
| lastSelection = updatedSelection; |
| } |
| }); |
| } |
| |
| @Override |
| public void tearDown() { |
| model = null; |
| env = null; |
| lastSelection = null; |
| } |
| |
| public void testSelectionLeftOfItems() { |
| initData(20, 5); |
| model.startSelection(new Point(0, 10)); |
| model.resizeSelection(new Point(1, 11)); |
| assertSelected(); |
| 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(); |
| assertEquals(NOT_SET, model.getPositionNearestOrigin()); |
| } |
| |
| public void testSelectionAboveItems() { |
| initData(20, 4); |
| model.startSelection(new Point(10, 0)); |
| model.resizeSelection(new Point(11, 1)); |
| assertSelected(); |
| 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(); |
| assertEquals(NOT_SET, model.getPositionNearestOrigin()); |
| } |
| |
| public void testVerticalSelectionBetweenItems() { |
| initData(20, 4); |
| model.startSelection(new Point(106, 0)); |
| model.resizeSelection(new Point(107, 200)); |
| assertSelected(); |
| assertEquals(NOT_SET, model.getPositionNearestOrigin()); |
| } |
| |
| public void testHorizontalSelectionBetweenItems() { |
| initData(20, 4); |
| model.startSelection(new Point(0, 105)); |
| model.resizeSelection(new Point(200, 106)); |
| assertSelected(); |
| 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(); |
| 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()); |
| } |
| |
| 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); |
| 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); |
| scroll(CHILD_VIEW_EDGE_PX); |
| assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25); |
| 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); |
| assertEquals(0, model.getPositionNearestOrigin()); |
| } |
| |
| private void assertSelected(int... selectedPositions) { |
| assertEquals(selectedPositions.length, lastSelection.size()); |
| for (int position : selectedPositions) { |
| assertTrue(lastSelection.contains(Integer.toString(position))); |
| } |
| } |
| |
| private void scroll(int dy) { |
| assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight()); |
| env.verticalOffset += 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; |
| |
| public TestEnvironment(int numChildren, int numColumns) { |
| mNumChildren = numChildren; |
| mNumColumns = numColumns; |
| mNumRows = (int) Math.ceil((double) numChildren / mNumColumns); |
| } |
| |
| private int getTotalHeight() { |
| return CHILD_VIEW_EDGE_PX * mNumRows + VIEW_PADDING_PX * (mNumRows + 1); |
| } |
| |
| private int getFirstVisibleRowIndex() { |
| return verticalOffset / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); |
| } |
| |
| private int getLastVisibleRowIndex() { |
| int lastVisibleRowUncapped = |
| (VIEWPORT_HEIGHT + verticalOffset - 1) / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); |
| return Math.min(lastVisibleRowUncapped, mNumRows - 1); |
| } |
| |
| private int getNumItemsInRow(int index) { |
| assertTrue(index >= 0 && index < mNumRows); |
| if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) { |
| return mNumChildren % mNumColumns; |
| } |
| |
| return mNumColumns; |
| } |
| |
| @Override |
| public void addOnScrollListener(OnScrollListener listener) {} |
| |
| @Override |
| public void removeOnScrollListener(OnScrollListener listener) {} |
| |
| @Override |
| public Point createAbsolutePoint(Point relativePoint) { |
| return new Point( |
| relativePoint.x + horizontalOffset, relativePoint.y + verticalOffset); |
| } |
| |
| @Override |
| public int getVisibleChildCount() { |
| int childCount = 0; |
| for (int i = getFirstVisibleRowIndex(); i <= getLastVisibleRowIndex(); i++) { |
| childCount += getNumItemsInRow(i); |
| } |
| return childCount; |
| } |
| |
| @Override |
| public int getAdapterPositionAt(int index) { |
| return index + mNumColumns * (getFirstVisibleRowIndex()); |
| } |
| |
| @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; |
| } |
| |
| @Override |
| public int getChildCount() { |
| return mNumChildren; |
| } |
| |
| @Override |
| public int getColumnCount() { |
| return mNumColumns; |
| } |
| |
| @Override |
| public int getRowCount() { |
| return mNumRows; |
| } |
| |
| @Override |
| public void showBand(Rect rect) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void hideBand() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void scrollBy(int dy) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int getHeight() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void invalidateView() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void runAtNextFrame(Runnable r) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void removeCallback(Runnable r) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int getAdapterPositionForChildView(View view) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void focusItem(int i) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean isLayoutItem(int adapterPosition) { |
| return false; |
| } |
| } |
| } |