diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java index fbee0802e2..33d8a8430f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java @@ -138,6 +138,8 @@ public class BubbleBarController extends IBubblesListener.Stub { List removedBubbles; List bubbleKeysInOrder; Point expandedViewDropTargetSize; + boolean showOverflow; + boolean showOverflowChanged; // These need to be loaded in the background BubbleBarBubble addedBubble; @@ -156,6 +158,8 @@ public class BubbleBarController extends IBubblesListener.Stub { removedBubbles = update.removedBubbles; bubbleKeysInOrder = update.bubbleKeysInOrder; expandedViewDropTargetSize = update.expandedViewDropTargetSize; + showOverflow = update.showOverflow; + showOverflowChanged = update.showOverflowChanged; } } @@ -271,7 +275,13 @@ public class BubbleBarController extends IBubblesListener.Stub { BubbleBarBubble bubbleToSelect = null; - if (update.addedBubble != null && update.removedBubbles.size() == 1) { + if (Flags.enableOptionalBubbleOverflow() + && update.showOverflowChanged && !update.showOverflow && update.addedBubble != null + && update.removedBubbles.isEmpty()) { + // A bubble was added from the overflow (& now it's empty / not showing) + mBubbles.put(update.addedBubble.getKey(), update.addedBubble); + mBubbleBarViewController.removeOverflowAndAddBubble(update.addedBubble); + } else if (update.addedBubble != null && update.removedBubbles.size() == 1) { // we're adding and removing a bubble at the same time. handle this as a single update. RemovedBubble removedBubble = update.removedBubbles.get(0); BubbleBarBubble bubbleToRemove = mBubbles.remove(removedBubble.getKey()); @@ -285,11 +295,17 @@ public class BubbleBarController extends IBubblesListener.Stub { Log.w(TAG, "trying to remove bubble that doesn't exist: " + removedBubble.getKey()); } } else { + boolean overflowNeedsToBeAdded = Flags.enableOptionalBubbleOverflow() + && update.showOverflowChanged && update.showOverflow; if (!update.removedBubbles.isEmpty()) { for (int i = 0; i < update.removedBubbles.size(); i++) { RemovedBubble removedBubble = update.removedBubbles.get(i); BubbleBarBubble bubble = mBubbles.remove(removedBubble.getKey()); - if (bubble != null) { + if (bubble != null && overflowNeedsToBeAdded) { + // First removal, show the overflow + overflowNeedsToBeAdded = false; + mBubbleBarViewController.addOverflowAndRemoveBubble(bubble); + } else if (bubble != null) { mBubbleBarViewController.removeBubble(bubble); } else { Log.w(TAG, "trying to remove bubble that doesn't exist: " @@ -302,6 +318,11 @@ public class BubbleBarController extends IBubblesListener.Stub { mBubbleBarViewController.addBubble(update.addedBubble, isExpanding, suppressAnimation); } + if (Flags.enableOptionalBubbleOverflow() + && update.showOverflowChanged + && update.showOverflow != mBubbleBarViewController.isOverflowAdded()) { + mBubbleBarViewController.showOverflow(update.showOverflow); + } } // if a bubble was updated upstream, but removed before the update was received, add it back @@ -333,6 +354,9 @@ public class BubbleBarController extends IBubblesListener.Stub { } } } + if (Flags.enableOptionalBubbleOverflow() && update.initialState && update.showOverflow) { + mBubbleBarViewController.showOverflow(true); + } // Adds and removals have happened, update visibility before any other visual changes. mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty()); diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 7d27a90420..32ca9f2f7c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -715,11 +715,13 @@ public class BubbleBarView extends FrameLayout { public void addBubble(BubbleView bubble) { FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) mIconSize, (int) mIconSize, Gravity.LEFT); + final int index = bubble.isOverflow() ? getChildCount() : 0; + if (isExpanded()) { // if we're expanded scale the new bubble in bubble.setScaleX(0f); bubble.setScaleY(0f); - addView(bubble, 0, lp); + addView(bubble, index, lp); bubble.showDotIfNeeded(/* animate= */ false); mBubbleAnimator = new BubbleAnimator(mIconSize, mExpandedBarIconsSpacing, @@ -748,23 +750,33 @@ public class BubbleBarView extends FrameLayout { }; mBubbleAnimator.animateNewBubble(indexOfChild(mSelectedBubbleView), listener); } else { - addView(bubble, 0, lp); + addView(bubble, index, lp); } } /** Add a new bubble and remove an old bubble from the bubble bar. */ - public void addBubbleAndRemoveBubble(View addedBubble, View removedBubble) { + public void addBubbleAndRemoveBubble(BubbleView addedBubble, BubbleView removedBubble) { FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) mIconSize, (int) mIconSize, Gravity.LEFT); + boolean isOverflowSelected = mSelectedBubbleView.isOverflow(); + boolean removingOverflow = removedBubble.isOverflow(); + boolean addingOverflow = addedBubble.isOverflow(); + if (!isExpanded()) { removeView(removedBubble); - addView(addedBubble, 0, lp); + int index = addingOverflow ? getChildCount() : 0; + addView(addedBubble, index, lp); return; } + int index = addingOverflow ? getChildCount() : 0; addedBubble.setScaleX(0f); addedBubble.setScaleY(0f); - addView(addedBubble, 0, lp); + addView(addedBubble, index, lp); + if (isOverflowSelected && removingOverflow) { + // The added bubble will be selected + mSelectedBubbleView = addedBubble; + } int indexOfSelectedBubble = indexOfChild(mSelectedBubbleView); int indexOfBubbleToRemove = indexOfChild(removedBubble); @@ -924,7 +936,7 @@ public class BubbleBarView extends FrameLayout { final float currentWidth = getWidth(); final float expandedWidth = expandedWidth(); final float collapsedWidth = collapsedWidth(); - int bubbleCount = getChildCount(); + int childCount = getChildCount(); float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0); float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight(); // When translating X & Y the scale is ignored, so need to deduct it from the translations @@ -932,7 +944,7 @@ public class BubbleBarView extends FrameLayout { final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); // elevation state is opposite to widthState - when expanded all icons are flat float elevationState = (1 - widthState); - for (int i = 0; i < bubbleCount; i++) { + for (int i = 0; i < childCount; i++) { BubbleView bv = (BubbleView) getChildAt(i); if (bv == mDraggedBubbleView || bv == mDismissedByDragBubbleView) { // Skip the dragged bubble. Its translation is managed by the drag controller. @@ -951,9 +963,9 @@ public class BubbleBarView extends FrameLayout { bv.setTranslationY(ty); // the position of the bubble when the bar is fully expanded - final float expandedX = getExpandedBubbleTranslationX(i, bubbleCount, onLeft); + final float expandedX = getExpandedBubbleTranslationX(i, childCount, onLeft); // the position of the bubble when the bar is fully collapsed - final float collapsedX = getCollapsedBubbleTranslationX(i, bubbleCount, onLeft); + final float collapsedX = getCollapsedBubbleTranslationX(i, childCount, onLeft); // slowly animate elevation while keeping correct Z ordering float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i; @@ -981,13 +993,10 @@ public class BubbleBarView extends FrameLayout { final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth; final float targetX = collapsedX + collapsedBarShift; bv.setTranslationX(widthState * (expandedX - targetX) + targetX); - // If we're fully collapsed, hide all bubbles except for the first 2. If there are - // only 2 bubbles, hide the second bubble as well because it's the overflow. + // If we're fully collapsed, hide all bubbles except for the first 2, excluding + // the overflow. if (widthState == 0) { - if (i > MAX_VISIBLE_BUBBLES_COLLAPSED - 1) { - bv.setAlpha(0); - } else if (i == MAX_VISIBLE_BUBBLES_COLLAPSED - 1 - && bubbleCount == MAX_VISIBLE_BUBBLES_COLLAPSED) { + if (bv.isOverflow() || i > MAX_VISIBLE_BUBBLES_COLLAPSED - 1) { bv.setAlpha(0); } else { bv.setAlpha(1); @@ -1043,22 +1052,26 @@ public class BubbleBarView extends FrameLayout { return translationX - getScaleIconShift(); } - private float getCollapsedBubbleTranslationX(int bubbleIndex, int bubbleCount, boolean onLeft) { - if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) { + private float getCollapsedBubbleTranslationX(int bubbleIndex, int childCount, boolean onLeft) { + if (bubbleIndex < 0 || bubbleIndex >= childCount) { return 0; } float translationX; if (onLeft) { - // Shift the first bubble only if there are more bubbles in addition to overflow - translationX = mBubbleBarPadding + ( - bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED - ? mIconOverlapAmount : 0); + // Shift the first bubble only if there are more bubbles + if (bubbleIndex == 0 && getBubbleChildCount() >= MAX_VISIBLE_BUBBLES_COLLAPSED) { + translationX = mIconOverlapAmount; + } else { + translationX = 0f; + } } else { - translationX = mBubbleBarPadding + ( - bubbleIndex == 0 || bubbleCount <= MAX_VISIBLE_BUBBLES_COLLAPSED - ? 0 : mIconOverlapAmount); + if (bubbleIndex == 1 && getBubbleChildCount() >= MAX_VISIBLE_BUBBLES_COLLAPSED) { + translationX = mIconOverlapAmount; + } else { + translationX = 0f; + } } - return translationX - getScaleIconShift(); + return mBubbleBarPadding + translationX - getScaleIconShift(); } /** @@ -1256,15 +1269,20 @@ public class BubbleBarView extends FrameLayout { } private float collapsedWidth() { - final int childCount = getChildCount(); + final int bubbleChildCount = getBubbleChildCount(); final float horizontalPadding = 2 * mBubbleBarPadding; - // If there are more than 2 bubbles, the first 2 should be visible when collapsed. - // Otherwise just the first bubble should be visible because we don't show the overflow. - return childCount > MAX_VISIBLE_BUBBLES_COLLAPSED + // If there are more than 2 bubbles, the first 2 should be visible when collapsed, + // excluding the overflow. + return bubbleChildCount >= MAX_VISIBLE_BUBBLES_COLLAPSED ? getScaledIconSize() + mIconOverlapAmount + horizontalPadding : getScaledIconSize() + horizontalPadding; } + /** Returns the child count excluding the overflow if it's present. */ + private int getBubbleChildCount() { + return hasOverflow() ? getChildCount() - 1 : getChildCount(); + } + private float getBubbleBarExpandedHeight() { return getBubbleBarCollapsedHeight() + mPointerSize; } @@ -1303,8 +1321,8 @@ public class BubbleBarView extends FrameLayout { return mIsAnimatingNewBubble; } - private boolean hasOverview() { - // Overview is always the last bubble + private boolean hasOverflow() { + // Overflow is always the last bubble View lastChild = getChildAt(getChildCount() - 1); if (lastChild instanceof BubbleView bubbleView) { return bubbleView.getBubble() instanceof BubbleBarOverflow; @@ -1336,7 +1354,7 @@ public class BubbleBarView extends FrameLayout { CharSequence contentDesc = firstChild != null ? firstChild.getContentDescription() : ""; // Don't count overflow if it exists - int bubbleCount = getChildCount() - (hasOverview() ? 1 : 0); + int bubbleCount = getChildCount() - (hasOverflow() ? 1 : 0); if (bubbleCount > 1) { contentDesc = getResources().getString(R.string.bubble_bar_description_multiple_bubbles, contentDesc, bubbleCount - 1); diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index 590916edd0..2cdc0ced86 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -92,6 +92,8 @@ public class BubbleBarViewController { private boolean mHiddenForNoBubbles = true; private boolean mShouldShowEducation; + public boolean mOverflowAdded; + private BubbleBarViewAnimator mBubbleBarViewAnimator; private final TimeSource mTimeSource = System::currentTimeMillis; @@ -123,7 +125,6 @@ public class BubbleBarViewController { mBubbleBarClickListener = v -> expandBubbleBar(); mBubbleDragController.setupBubbleBarView(mBarView); mOverflowBubble = bubbleControllers.bubbleCreator.createOverflow(mBarView); - addOverflow(); mBarView.setOnClickListener(mBubbleBarClickListener); mBarView.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { @@ -494,13 +495,44 @@ public class BubbleBarViewController { } } - /** - * Adds the overflow view to the bubble bar. - */ - public void addOverflow() { - mBarView.addBubble(mOverflowBubble.getView()); + /** Whether the overflow view is added to the bubble bar. */ + public boolean isOverflowAdded() { + return mOverflowAdded; + } + + /** Shows or hides the overflow view. */ + public void showOverflow(boolean showOverflow) { + if (mOverflowAdded == showOverflow) return; + mOverflowAdded = showOverflow; + if (mOverflowAdded) { + mBarView.addBubble(mOverflowBubble.getView()); + mOverflowBubble.getView().setOnClickListener(mBubbleClickListener); + mOverflowBubble.getView().setController(mBubbleViewController); + } else { + mBarView.removeBubble(mOverflowBubble.getView()); + mOverflowBubble.getView().setOnClickListener(null); + mOverflowBubble.getView().setController(null); + } + } + + /** Adds the overflow view to the bubble bar while animating a view away. */ + public void addOverflowAndRemoveBubble(BubbleBarBubble removedBubble) { + if (mOverflowAdded) return; + mOverflowAdded = true; + mBarView.addBubbleAndRemoveBubble(mOverflowBubble.getView(), removedBubble.getView()); mOverflowBubble.getView().setOnClickListener(mBubbleClickListener); mOverflowBubble.getView().setController(mBubbleViewController); + removedBubble.getView().setController(null); + } + + /** Removes the overflow view to the bubble bar while animating a view in. */ + public void removeOverflowAndAddBubble(BubbleBarBubble addedBubble) { + if (!mOverflowAdded) return; + mOverflowAdded = false; + mBarView.addBubbleAndRemoveBubble(addedBubble.getView(), mOverflowBubble.getView()); + addedBubble.getView().setOnClickListener(mBubbleClickListener); + addedBubble.getView().setController(mBubbleViewController); + mOverflowBubble.getView().setController(null); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java index 09da3e0176..f0f28729a6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java @@ -74,6 +74,7 @@ public class BubbleView extends ConstraintLayout { private boolean mOnLeft = false; private BubbleBarItem mBubble; + private boolean mIsOverflow; private Bitmap mIcon; @@ -271,12 +272,18 @@ public class BubbleView extends ConstraintLayout { */ public void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) { mBubble = overflow; + mIsOverflow = true; mIcon = bitmap; updateBubbleIcon(); mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge setContentDescription(getResources().getString(R.string.bubble_bar_overflow_description)); } + /** Whether this view represents the overflow button. */ + public boolean isOverflow() { + return mIsOverflow; + } + /** Returns the bubble being rendered in this view. */ @Nullable public BubbleBarItem getBubble() { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 3c9bd0f3fa..4dc04e757f 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -989,7 +989,6 @@ public abstract class AbsSwipeUpHandler : RecycledViewPool() where T : Context, T : Act fun preInflateAllAppsViewHolders(context: T) { val appsView = context.appsView ?: return val activeRv: RecyclerView = appsView.activeRecyclerView ?: return + val preInflateCount = getPreinflateCount(context) + if (preInflateCount <= 0) { + return + } if (activeRv.layoutManager == null) { if (BuildConfig.IS_STUDIO_BUILD) { @@ -99,7 +103,12 @@ class AllAppsRecyclerViewPool : RecycledViewPool() where T : Context, T : Act override fun getLayoutManager(): RecyclerView.LayoutManager? = null } - preInflateAllAppsViewHolders(adapter, BaseAllAppsAdapter.VIEW_TYPE_ICON, activeRv) { + preInflateAllAppsViewHolders( + adapter, + BaseAllAppsAdapter.VIEW_TYPE_ICON, + activeRv, + preInflateCount + ) { getPreinflateCount(context) } } @@ -109,10 +118,10 @@ class AllAppsRecyclerViewPool : RecycledViewPool() where T : Context, T : Act adapter: RecyclerView.Adapter<*>, viewType: Int, parent: ViewGroup, + preInflationCount: Int, preInflationCountProvider: () -> Int ) { - val preinflationCount = preInflationCountProvider.invoke() - if (preinflationCount <= 0) { + if (preInflationCount <= 0) { return } mCancellableTask?.cancel() @@ -121,7 +130,7 @@ class AllAppsRecyclerViewPool : RecycledViewPool() where T : Context, T : Act CancellableTask( { val list: ArrayList = ArrayList() - for (i in 0 until preinflationCount) { + for (i in 0 until preInflationCount) { if (task?.canceled == true) { break } @@ -132,8 +141,8 @@ class AllAppsRecyclerViewPool : RecycledViewPool() where T : Context, T : Act MAIN_EXECUTOR, { viewHolders -> // Run preInflationCountProvider again as the needed VH might have changed - val newPreinflationCount = preInflationCountProvider.invoke() - for (i in 0 until minOf(viewHolders.size, newPreinflationCount)) { + val newPreInflationCount = preInflationCountProvider.invoke() + for (i in 0 until minOf(viewHolders.size, newPreInflationCount)) { putRecycledView(viewHolders[i]) } } diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt index c32461ea98..a3c7f4fb49 100644 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt @@ -104,7 +104,7 @@ class HotseatReorderUnitTest { val cl = cellLayoutBuilder.createCellLayout(board.width, board.height, false) // The views have to be sorted or the result can vary board.icons - .map(IconPoint::getCoord) + .map(IconPoint::coord) .sortedWith( Comparator.comparing { p: Any -> (p as Point).x } .thenComparing { p: Any -> (p as Point).y } @@ -120,9 +120,7 @@ class HotseatReorderUnitTest { ) } board.widgets - .sortedWith( - Comparator.comparing(WidgetRect::getCellX).thenComparing(WidgetRect::getCellY) - ) + .sortedWith(Comparator.comparing(WidgetRect::cellX).thenComparing(WidgetRect::cellY)) .forEach { widget -> addViewInCellLayout( cl, diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/BoardClasses.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/BoardClasses.kt new file mode 100644 index 0000000000..3cbfc5a252 --- /dev/null +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/BoardClasses.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 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.launcher3.celllayout.board + +import android.graphics.Point +import android.graphics.Rect + +/** Represents a widget in a CellLayoutBoard */ +data class WidgetRect( + val type: Char, + val bounds: Rect, +) { + val spanX: Int = bounds.right - bounds.left + 1 + val spanY: Int = bounds.top - bounds.bottom + 1 + val cellY: Int = bounds.bottom + val cellX: Int = bounds.left + + fun shouldIgnore() = type == CellType.IGNORE + + fun contains(x: Int, y: Int) = bounds.contains(x, y) +} + +/** + * [A-Z]: Represents a folder and number of icons in the folder is represented by the order of + * letter in the alphabet, A=2, B=3, C=4 ... etc. + */ +data class FolderPoint(val coord: Point, val type: Char) { + val numberIconsInside: Int = type.code - 'A'.code + 2 +} + +/** Represents an icon in a CellLayoutBoard */ +data class IconPoint(val coord: Point, val type: Char = CellType.ICON) + +object CellType { + // The cells marked by this will be filled by 1x1 widgets and will be ignored when + // validating + const val IGNORE = 'x' + + // The cells marked by this will be filled by app icons + const val ICON = 'i' + + // The cells marked by FOLDER will be filled by folders with 27 app icons inside + const val FOLDER = 'Z' + + // Empty space + const val EMPTY = '-' + + // Widget that will be saved as "main widget" for easier retrieval + const val MAIN_WIDGET = 'm' // Everything else will be consider a widget +} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java index e5ad888a8c..04bfee97be 100644 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java @@ -88,7 +88,7 @@ public class CellLayoutBoard implements Comparable { public WidgetRect getWidgetOfType(char type) { return mWidgetsRects.stream() - .filter(widgetRect -> widgetRect.mType == type).findFirst().orElse(null); + .filter(widgetRect -> widgetRect.getType() == type).findFirst().orElse(null); } public WidgetRect getWidgetAt(int x, int y) { @@ -117,8 +117,8 @@ public class CellLayoutBoard implements Comparable { } private void removeWidgetFromBoard(WidgetRect widget) { - for (int xi = widget.mBounds.left; xi <= widget.mBounds.right; xi++) { - for (int yi = widget.mBounds.bottom; yi <= widget.mBounds.top; yi++) { + for (int xi = widget.getBounds().left; xi <= widget.getBounds().right; xi++) { + for (int yi = widget.getBounds().bottom; yi <= widget.getBounds().top; yi++) { mWidget[xi][yi] = '-'; } } @@ -127,7 +127,7 @@ public class CellLayoutBoard implements Comparable { private void removeOverlappingItems(Rect rect) { // Remove overlapping widgets and remove them from the board mWidgetsRects = mWidgetsRects.stream().filter(widget -> { - if (rect.intersect(widget.mBounds)) { + if (rect.intersect(widget.getBounds())) { removeWidgetFromBoard(widget); return false; } @@ -135,8 +135,8 @@ public class CellLayoutBoard implements Comparable { }).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; + int x = iconPoint.getCoord().x; + int y = iconPoint.getCoord().y; if (rect.contains(x, y)) { mWidget[x][y] = '-'; return false; @@ -146,8 +146,8 @@ public class CellLayoutBoard implements Comparable { // Remove overlapping folders and remove them from the board mFolderPoints = mFolderPoints.stream().filter(folderPoint -> { - int x = folderPoint.coord.x; - int y = folderPoint.coord.y; + int x = folderPoint.getCoord().x; + int y = folderPoint.getCoord().y; if (rect.contains(x, y)) { mWidget[x][y] = '-'; return false; @@ -159,7 +159,7 @@ public class CellLayoutBoard implements Comparable { private void removeOverlappingItems(Point p) { // Remove overlapping widgets and remove them from the board mWidgetsRects = mWidgetsRects.stream().filter(widget -> { - if (IdenticalBoardComparator.Companion.touchesPoint(widget.mBounds, p)) { + if (IdenticalBoardComparator.Companion.touchesPoint(widget.getBounds(), p)) { removeWidgetFromBoard(widget); return false; } @@ -167,8 +167,8 @@ public class CellLayoutBoard implements Comparable { }).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; + int x = iconPoint.getCoord().x; + int y = iconPoint.getCoord().y; if (p.x == x && p.y == y) { mWidget[x][y] = '-'; return false; @@ -178,8 +178,8 @@ public class CellLayoutBoard implements Comparable { // Remove overlapping folders and remove them from the board mFolderPoints = mFolderPoints.stream().filter(folderPoint -> { - int x = folderPoint.coord.x; - int y = folderPoint.coord.y; + int x = folderPoint.getCoord().x; + int y = folderPoint.getCoord().y; if (p.x == x && p.y == y) { mWidget[x][y] = '-'; return false; @@ -226,7 +226,7 @@ public class CellLayoutBoard implements Comparable { public void removeItem(char type) { mWidgetsRects.stream() - .filter(widgetRect -> widgetRect.mType == type) + .filter(widgetRect -> widgetRect.getType() == type) .forEach(widgetRect -> removeOverlappingItems( new Point(widgetRect.getCellX(), widgetRect.getCellY()))); } @@ -365,10 +365,10 @@ public class CellLayoutBoard implements Comparable { board.mWidth = lines[0].length(); board.mWidgetsRects = getRects(board.mWidget); board.mWidgetsRects.forEach(widgetRect -> { - if (widgetRect.mType == CellType.MAIN_WIDGET) { + if (widgetRect.getType() == CellType.MAIN_WIDGET) { board.mMain = widgetRect; } - board.mWidgetsMap.put(widgetRect.mType, widgetRect); + board.mWidgetsMap.put(widgetRect.getType(), widgetRect); }); board.mIconPoints = getIconPoints(board.mWidget); board.mFolderPoints = getFolderPoints(board.mWidget); diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellType.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellType.java deleted file mode 100644 index 49c146b32a..0000000000 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellType.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2023 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.launcher3.celllayout.board; - -public class CellType { - // The cells marked by this will be filled by 1x1 widgets and will be ignored when - // validating - public static final char IGNORE = 'x'; - // The cells marked by this will be filled by app icons - public static final char ICON = 'i'; - // The cells marked by FOLDER will be filled by folders with 27 app icons inside - public static final char FOLDER = 'Z'; - // Empty space - public static final char EMPTY = '-'; - // Widget that will be saved as "main widget" for easier retrieval - public static final char MAIN_WIDGET = 'm'; - // Everything else will be consider a widget -} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/FolderPoint.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/FolderPoint.java deleted file mode 100644 index 39ba434dc0..0000000000 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/FolderPoint.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2023 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.launcher3.celllayout.board; - -import android.graphics.Point; - -public class FolderPoint { - public Point coord; - public char mType; - - public FolderPoint(Point coord, char type) { - this.coord = coord; - mType = type; - } - - /** - * [A-Z]: Represents a folder and number of icons in the folder is represented by - * the order of letter in the alphabet, A=2, B=3, C=4 ... etc. - */ - public int getNumberIconsInside() { - return (mType - 'A') + 2; - } -} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IconPoint.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IconPoint.java deleted file mode 100644 index d3d297003d..0000000000 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IconPoint.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2023 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.launcher3.celllayout.board; - -import android.graphics.Point; - -public class IconPoint { - public Point coord; - public char mType; - - public IconPoint(Point coord, char type) { - this.coord = coord; - mType = type; - } - - public char getType() { - return mType; - } - - public void setType(char type) { - mType = type; - } - - public Point getCoord() { - return coord; - } - - public void setCoord(Point coord) { - this.coord = coord; - } -} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt index a4a420cf59..aacd940460 100644 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt @@ -26,11 +26,11 @@ class IdenticalBoardComparator : Comparator { /** Converts a list of WidgetRect into a map of the count of different widget.bounds */ private fun widgetsToBoundsMap(widgets: List) = - widgets.groupingBy { it.mBounds }.eachCount() + widgets.groupingBy { it.bounds }.eachCount() /** Converts a list of IconPoint into a map of the count of different icon.coord */ private fun iconsToPosCountMap(widgets: List) = - widgets.groupingBy { it.getCoord() }.eachCount() + widgets.groupingBy { it.coord }.eachCount() override fun compare( cellLayoutBoard: CellLayoutBoard, @@ -47,7 +47,7 @@ class IdenticalBoardComparator : Comparator { widgetsToBoundsMap( otherCellLayoutBoard.widgets .filter { !it.shouldIgnore() } - .filter { !overlapsWithIgnored(ignoredRectangles, it.mBounds) } + .filter { !overlapsWithIgnored(ignoredRectangles, it.bounds) } ) if (widgetsMap != otherWidgetMap) { diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java deleted file mode 100644 index 8a427dd81b..0000000000 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2023 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.launcher3.celllayout.board; - -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider; -import static com.android.launcher3.util.WidgetUtils.createWidgetInfo; - -import android.content.ComponentName; -import android.content.Context; -import android.graphics.Rect; -import android.os.Process; -import android.os.UserHandle; -import android.util.Log; - -import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherSettings; -import com.android.launcher3.celllayout.FavoriteItemsTransaction; -import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.model.data.FolderInfo; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.model.data.LauncherAppWidgetInfo; -import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; - -import java.util.function.Supplier; -import java.util.stream.IntStream; - -public class TestWorkspaceBuilder { - - private static final String TAG = "CellLayoutBoardBuilder"; - private static final String TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests."; - private ComponentName mAppComponentName = new ComponentName( - "com.google.android.calculator", "com.android.calculator2.Calculator"); - private UserHandle mMyUser; - - private Context mContext; - - public TestWorkspaceBuilder(Context context) { - mMyUser = Process.myUserHandle(); - mContext = context; - } - - /** - * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. - */ - private FavoriteItemsTransaction fillWithWidgets(WidgetRect widgetRect, - FavoriteItemsTransaction transaction, int screenId) { - int initX = widgetRect.getCellX(); - int initY = widgetRect.getCellY(); - for (int x = initX; x < initX + widgetRect.getSpanX(); x++) { - for (int y = initY; y < initY + widgetRect.getSpanY(); y++) { - try { - // this widgets are filling, we don't care if we can't place them - transaction.addItem(createWidgetInCell( - new WidgetRect(CellType.IGNORE, - new Rect(x, y, x, y)), screenId)); - } catch (Exception e) { - Log.d(TAG, "Unable to place filling widget at " + x + "," + y); - } - } - } - return transaction; - } - - private AppInfo getApp() { - return new AppInfo(mAppComponentName, "test icon", mMyUser, - AppInfo.makeLaunchIntent(mAppComponentName)); - } - - /** - * Helper to set the app to use for the test workspace, - * using activity-alias from AndroidManifest-common. - * @param testAppName the android:name field of the test app activity-alias to use - */ - public void setTestAppActivityAlias(String testAppName) { - this.mAppComponentName = new ComponentName( - getInstrumentation().getContext().getPackageName(), - TEST_ACTIVITY_PACKAGE_PREFIX + testAppName - ); - } - - private void addCorrespondingWidgetRect(WidgetRect widgetRect, - FavoriteItemsTransaction transaction, int screenId) { - if (widgetRect.mType == 'x') { - fillWithWidgets(widgetRect, transaction, screenId); - } else { - transaction.addItem(createWidgetInCell(widgetRect, screenId)); - } - } - - /** - * Builds the given board into the transaction - */ - public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board, - FavoriteItemsTransaction transaction, final int screenId) { - board.getWidgets().forEach( - (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId)); - board.getIcons().forEach((iconPoint) -> - transaction.addItem(() -> createIconInCell(iconPoint, screenId)) - ); - board.getFolders().forEach((folderPoint) -> - transaction.addItem(() -> createFolderInCell(folderPoint, screenId)) - ); - return transaction; - } - - /** - * Fills the hotseat row with apps instead of suggestions, for this to work the workspace should - * be clean otherwise this doesn't overrides the existing icons. - */ - public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) { - IntStream.range(0, InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons) - .forEach(i -> transaction.addItem(() -> getHotseatValues(i))); - return transaction; - } - - private Supplier createWidgetInCell( - WidgetRect widgetRect, int screenId) { - // Create the widget lazily since the appWidgetId can get lost during setup - return () -> { - LauncherAppWidgetProviderInfo info = findWidgetProvider(false); - LauncherAppWidgetInfo item = createWidgetInfo(info, getApplicationContext(), true); - item.cellX = widgetRect.getCellX(); - item.cellY = widgetRect.getCellY(); - item.spanX = widgetRect.getSpanX(); - item.spanY = widgetRect.getSpanY(); - item.screenId = screenId; - return item; - }; - } - - public FolderInfo createFolderInCell(FolderPoint folderPoint, int screenId) { - FolderInfo folderInfo = new FolderInfo(); - folderInfo.screenId = screenId; - folderInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; - folderInfo.cellX = folderPoint.coord.x; - folderInfo.cellY = folderPoint.coord.y; - folderInfo.minSpanY = folderInfo.minSpanX = folderInfo.spanX = folderInfo.spanY = 1; - folderInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null); - - for (int i = 0; i < folderPoint.getNumberIconsInside(); i++) { - folderInfo.add(getDefaultWorkspaceItem(screenId), false); - } - - return folderInfo; - } - - private WorkspaceItemInfo getDefaultWorkspaceItem(int screenId) { - WorkspaceItemInfo item = new WorkspaceItemInfo(getApp()); - item.screenId = screenId; - item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1; - item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; - return item; - } - - private ItemInfo createIconInCell(IconPoint iconPoint, int screenId) { - WorkspaceItemInfo item = new WorkspaceItemInfo(getApp()); - item.screenId = screenId; - item.cellX = iconPoint.getCoord().x; - item.cellY = iconPoint.getCoord().y; - item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1; - item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; - return item; - } - - private ItemInfo getHotseatValues(int x) { - WorkspaceItemInfo item = new WorkspaceItemInfo(getApp()); - item.cellX = x; - item.cellY = 0; - item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1; - item.rank = x; - item.screenId = x; - item.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT; - return item; - } -} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt new file mode 100644 index 0000000000..8952b8542c --- /dev/null +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2023 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.launcher3.celllayout.board + +import android.content.ComponentName +import android.content.Context +import android.graphics.Rect +import android.os.Process +import android.os.UserHandle +import android.util.Log +import androidx.test.core.app.ApplicationProvider +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.InvariantDeviceProfile +import com.android.launcher3.LauncherSettings +import com.android.launcher3.celllayout.FavoriteItemsTransaction +import com.android.launcher3.model.data.AppInfo +import com.android.launcher3.model.data.FolderInfo +import com.android.launcher3.model.data.ItemInfo +import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.ui.TestViewHelpers +import com.android.launcher3.util.WidgetUtils +import java.util.function.Supplier + +class TestWorkspaceBuilder(private val mContext: Context) { + + private var appComponentName = + ComponentName("com.google.android.calculator", "com.android.calculator2.Calculator") + private val myUser: UserHandle = Process.myUserHandle() + + /** Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. */ + private fun fillWithWidgets( + widgetRect: WidgetRect, + transaction: FavoriteItemsTransaction, + screenId: Int + ): FavoriteItemsTransaction { + val initX = widgetRect.cellX + val initY = widgetRect.cellY + for (x in initX until initX + widgetRect.spanX) { + for (y in initY until initY + widgetRect.spanY) { + try { + // this widgets are filling, we don't care if we can't place them + transaction.addItem( + createWidgetInCell(WidgetRect(CellType.IGNORE, Rect(x, y, x, y)), screenId) + ) + } catch (e: Exception) { + Log.d(TAG, "Unable to place filling widget at $x,$y") + } + } + } + return transaction + } + + private fun app() = + AppInfo(appComponentName, "test icon", myUser, AppInfo.makeLaunchIntent(appComponentName)) + + /** + * Helper to set the app to use for the test workspace, using activity-alias from + * AndroidManifest-common. + * + * @param testAppName the android:name field of the test app activity-alias to use + */ + fun setTestAppActivityAlias(testAppName: String) { + appComponentName = + ComponentName( + InstrumentationRegistry.getInstrumentation().context.packageName, + TEST_ACTIVITY_PACKAGE_PREFIX + testAppName + ) + } + + private fun addCorrespondingWidgetRect( + widgetRect: WidgetRect, + transaction: FavoriteItemsTransaction, + screenId: Int + ) { + if (widgetRect.type == 'x') { + fillWithWidgets(widgetRect, transaction, screenId) + } else { + transaction.addItem(createWidgetInCell(widgetRect, screenId)) + } + } + + /** Builds the given board into the transaction */ + fun buildFromBoard( + board: CellLayoutBoard, + transaction: FavoriteItemsTransaction, + screenId: Int + ): FavoriteItemsTransaction { + board.widgets.forEach { addCorrespondingWidgetRect(it, transaction, screenId) } + board.icons.forEach { transaction.addItem { createIconInCell(it, screenId) } } + board.folders.forEach { transaction.addItem { createFolderInCell(it, screenId) } } + return transaction + } + + /** + * Fills the hotseat row with apps instead of suggestions, for this to work the workspace should + * be clean otherwise this doesn't overrides the existing icons. + */ + fun fillHotseatIcons(transaction: FavoriteItemsTransaction): FavoriteItemsTransaction { + for (i in 0.. { + // Create the widget lazily since the appWidgetId can get lost during setup + return Supplier { + WidgetUtils.createWidgetInfo( + TestViewHelpers.findWidgetProvider(false), + ApplicationProvider.getApplicationContext(), + true + ) + .apply { + cellX = widgetRect.cellX + cellY = widgetRect.cellY + spanX = widgetRect.spanX + spanY = widgetRect.spanY + screenId = paramScreenId + } + } + } + + fun createFolderInCell(folderPoint: FolderPoint, paramScreenId: Int): FolderInfo = + FolderInfo().apply { + screenId = paramScreenId + container = LauncherSettings.Favorites.CONTAINER_DESKTOP + cellX = folderPoint.coord.x + cellY = folderPoint.coord.y + spanY = 1 + spanX = 1 + minSpanX = 1 + minSpanY = 1 + setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null) + for (i in 0 until folderPoint.numberIconsInside) { + add(getDefaultWorkspaceItem(paramScreenId), false) + } + } + + private fun getDefaultWorkspaceItem(paramScreenId: Int): WorkspaceItemInfo = + WorkspaceItemInfo(app()).apply { + screenId = paramScreenId + spanY = 1 + spanX = 1 + minSpanX = 1 + minSpanY = 1 + container = LauncherSettings.Favorites.CONTAINER_DESKTOP + } + + private fun createIconInCell(iconPoint: IconPoint, paramScreenId: Int) = + WorkspaceItemInfo(app()).apply { + screenId = paramScreenId + cellX = iconPoint.coord.x + cellY = iconPoint.coord.y + spanY = 1 + spanX = 1 + minSpanX = 1 + minSpanY = 1 + container = LauncherSettings.Favorites.CONTAINER_DESKTOP + } + + private fun getHotseatValues(x: Int) = + WorkspaceItemInfo(app()).apply { + cellX = x + cellY = 0 + spanY = 1 + spanX = 1 + minSpanX = 1 + minSpanY = 1 + rank = x + screenId = x + container = LauncherSettings.Favorites.CONTAINER_HOTSEAT + } + + companion object { + private const val TAG = "CellLayoutBoardBuilder" + private const val TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests." + } +} diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/WidgetRect.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/WidgetRect.java deleted file mode 100644 index c90ce8504f..0000000000 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/WidgetRect.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2023 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.launcher3.celllayout.board; - -import android.graphics.Rect; - -public class WidgetRect { - public char mType; - public Rect mBounds; - - public WidgetRect(char type, Rect bounds) { - this.mType = type; - this.mBounds = bounds; - } - - public int getSpanX() { - return mBounds.right - mBounds.left + 1; - } - - public int getSpanY() { - return mBounds.top - mBounds.bottom + 1; - } - - public int getCellX() { - return mBounds.left; - } - - public int getCellY() { - return mBounds.bottom; - } - - boolean shouldIgnore() { - return this.mType == CellType.IGNORE; - } - - boolean contains(int x, int y) { - return mBounds.contains(x, y); - } - - @Override - public String toString() { - return "WidgetRect type = " + mType + " x = " + getCellX() + " | y " + getCellY() - + " xs = " + getSpanX() + " ys = " + getSpanY(); - } -} diff --git a/tests/multivalentTests/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPoolTest.kt b/tests/multivalentTests/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPoolTest.kt index 82043130a9..3e6aae2897 100644 --- a/tests/multivalentTests/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPoolTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPoolTest.kt @@ -65,7 +65,7 @@ class AllAppsRecyclerViewPoolTest where T : Context, T : ActivityContext { @Test fun preinflate_success() { - underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 } + underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 } awaitTasksCompleted() assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(10) @@ -73,7 +73,7 @@ class AllAppsRecyclerViewPoolTest where T : Context, T : ActivityContext { @Test fun preinflate_not_triggered() { - underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 0 } + underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 0) { 0 } awaitTasksCompleted() assertThat(underTest.getRecycledViewCount(VIEW_TYPE)).isEqualTo(0) @@ -81,7 +81,7 @@ class AllAppsRecyclerViewPoolTest where T : Context, T : ActivityContext { @Test fun preinflate_cancel_before_runOnMainThread() { - underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 } + underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 } assertThat(underTest.mCancellableTask!!.canceled).isFalse() underTest.clear() @@ -94,7 +94,7 @@ class AllAppsRecyclerViewPoolTest where T : Context, T : ActivityContext { @Test fun preinflate_cancel_after_run() { - underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent) { 10 } + underTest.preInflateAllAppsViewHolders(adapter, VIEW_TYPE, parent, 10) { 10 } assertThat(underTest.mCancellableTask!!.canceled).isFalse() awaitTasksCompleted()