diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 483309d1cf..2b9c1359b7 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -62,6 +62,7 @@ import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.accessibility.AccessibleDragListenerAdapter; import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper; @@ -161,7 +162,9 @@ public class Workspace extends PagedView protected ShortcutAndWidgetContainer mDragSourceInternal; - @Thunk final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + @Thunk public final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); + @Thunk final IntArray mScreenOrder = new IntArray(); @Thunk boolean mDeferRemoveExtraEmptyScreen = false; diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java index a32ce3c558..469d79f74e 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; +import java.util.stream.Collectors; public class CellLayoutBoard { @@ -140,6 +141,73 @@ public class CellLayoutBoard { return mWidgetsMap.get(c); } + private void removeWidgetFromBoard(WidgetRect widget) { + for (int xi = widget.mBounds.left; xi < widget.mBounds.right; xi++) { + for (int yi = widget.mBounds.top; yi < widget.mBounds.bottom; yi++) { + mWidget[xi][yi] = '-'; + } + } + } + + private void removeOverlappingItems(Rect rect) { + // Remove overlapping widgets and remove them from the board + mWidgetsRects = mWidgetsRects.stream().filter(widget -> { + if (rect.intersect(widget.mBounds)) { + removeWidgetFromBoard(widget); + return false; + } + return true; + }).collect(Collectors.toList()); + // Remove overlapping icons and remove them from the board + mIconPoints = mIconPoints.stream().filter(iconPoint -> { + int x = iconPoint.coord.x; + int y = iconPoint.coord.y; + if (rect.contains(x, y)) { + mWidget[x][y] = '-'; + return false; + } + return true; + }).collect(Collectors.toList()); + } + + private void removeOverlappingItems(Point p) { + // Remove overlapping widgets and remove them from the board + mWidgetsRects = mWidgetsRects.stream().filter(widget -> { + if (widget.mBounds.contains(p.x, p.y)) { + removeWidgetFromBoard(widget); + return false; + } + return true; + }).collect(Collectors.toList()); + // Remove overlapping icons and remove them from the board + mIconPoints = mIconPoints.stream().filter(iconPoint -> { + int x = iconPoint.coord.x; + int y = iconPoint.coord.y; + if (p.x == x && p.y == y) { + mWidget[x][y] = '-'; + return false; + } + return true; + }).collect(Collectors.toList()); + } + + public void addWidget(int x, int y, int spanX, int spanY, char type) { + Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y); + removeOverlappingItems(rect); + WidgetRect widgetRect = new WidgetRect(type, rect); + mWidgetsRects.add(widgetRect); + for (int xi = rect.left; xi < rect.right + 1; xi++) { + for (int yi = rect.bottom; yi < rect.top + 1; yi++) { + mWidget[xi][yi] = type; + } + } + } + + public void addIcon(int x, int y) { + removeOverlappingItems(new Point(x, y)); + mWidget[x][y] = 'i'; + } + public static WidgetRect getWidgetRect(int x, int y, Set used, char[][] board) { char type = board[x][y]; Queue search = new ArrayDeque(); @@ -227,4 +295,17 @@ public class CellLayoutBoard { board.mIconPoints = getIconPoints(board.mWidget); return board; } + + public String toString(int maxX, int maxY) { + StringBuilder s = new StringBuilder(); + maxX = Math.min(maxX, mWidget.length); + maxY = Math.min(maxY, mWidget[0].length); + for (int y = 0; y < maxY; y++) { + for (int x = 0; x < maxX; x++) { + s.append(mWidget[x][y]); + } + s.append('\n'); + } + return s.toString(); + } } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 9da7e0f39b..843f0112ba 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -26,6 +26,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.launcher3.CellLayout; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.celllayout.testcases.FullReorderCase; import com.android.launcher3.celllayout.testcases.MoveOutReorderCase; import com.android.launcher3.celllayout.testcases.PushReorderCase; @@ -46,6 +47,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -108,6 +110,42 @@ public class ReorderWidgets extends AbstractLauncherUiTest { return match; } + private void printCurrentWorkspace() { + InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); + ArrayList boards = workspaceToBoards(); + for (int i = 0; i < boards.size(); i++) { + Log.d(TAG, "Screen number " + i); + Log.d(TAG, ".\n" + boards.get(i).toString(idp.numColumns, idp.numRows)); + } + } + + private ArrayList workspaceToBoards() { + return getFromLauncher(l -> { + ArrayList boards = new ArrayList<>(); + int widgetCount = 0; + for (CellLayout cellLayout : l.getWorkspace().mWorkspaceScreens) { + CellLayoutBoard board = new CellLayoutBoard(); + int count = cellLayout.getShortcutsAndWidgets().getChildCount(); + for (int i = 0; i < count; i++) { + View callView = cellLayout.getShortcutsAndWidgets().getChildAt(i); + CellLayoutLayoutParams params = + (CellLayoutLayoutParams) callView.getLayoutParams(); + // is icon + if (callView instanceof DoubleShadowBubbleTextView) { + board.addIcon(params.cellX, params.cellY); + } else { + // is widget + board.addWidget(params.cellX, params.cellY, params.cellHSpan, + params.cellVSpan, (char) ('A' + widgetCount)); + widgetCount++; + } + } + boards.add(board); + } + return boards; + }); + } + private void runTestCase(ReorderTestCase testCase) throws ExecutionException, InterruptedException { Point mainWidgetCellPos = testCase.mStart.getMain(); @@ -127,6 +165,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest { for (CellLayoutBoard board : testCase.mEnd) { isValid |= validateBoard(board); } + printCurrentWorkspace(); assertTrue("Non of the valid boards match with the current state", isValid); }