Loading src/com/android/launcher3/Workspace.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -161,7 +162,9 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> protected ShortcutAndWidgetContainer mDragSourceInternal; @Thunk final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>(); @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @Thunk public final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>(); @Thunk final IntArray mScreenOrder = new IntArray(); @Thunk boolean mDeferRemoveExtraEmptyScreen = false; Loading tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +81 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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<Point> used, char[][] board) { char type = board[x][y]; Queue<Point> search = new ArrayDeque<Point>(); Loading Loading @@ -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(); } } tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +39 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -108,6 +110,42 @@ public class ReorderWidgets extends AbstractLauncherUiTest { return match; } private void printCurrentWorkspace() { InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); ArrayList<CellLayoutBoard> 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<CellLayoutBoard> workspaceToBoards() { return getFromLauncher(l -> { ArrayList<CellLayoutBoard> 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(); Loading @@ -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); } Loading Loading
src/com/android/launcher3/Workspace.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -161,7 +162,9 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> protected ShortcutAndWidgetContainer mDragSourceInternal; @Thunk final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>(); @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @Thunk public final IntSparseArrayMap<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>(); @Thunk final IntArray mScreenOrder = new IntArray(); @Thunk boolean mDeferRemoveExtraEmptyScreen = false; Loading
tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +81 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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<Point> used, char[][] board) { char type = board[x][y]; Queue<Point> search = new ArrayDeque<Point>(); Loading Loading @@ -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(); } }
tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +39 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -108,6 +110,42 @@ public class ReorderWidgets extends AbstractLauncherUiTest { return match; } private void printCurrentWorkspace() { InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); ArrayList<CellLayoutBoard> 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<CellLayoutBoard> workspaceToBoards() { return getFromLauncher(l -> { ArrayList<CellLayoutBoard> 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(); Loading @@ -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); } Loading