diff --git a/res/layout/workspace_screen_foldable.xml b/res/layout/workspace_screen_foldable.xml new file mode 100644 index 0000000000..1e0125087b --- /dev/null +++ b/res/layout/workspace_screen_foldable.xml @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index d388ebcb9d..b96e4df8c9 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -99,9 +99,9 @@ public class CellLayout extends ViewGroup { private Point mBorderSpace; @ViewDebug.ExportedProperty(category = "launcher") - private int mCountX; + protected int mCountX; @ViewDebug.ExportedProperty(category = "launcher") - private int mCountY; + protected int mCountY; private boolean mDropPending = false; @@ -111,8 +111,8 @@ public class CellLayout extends ViewGroup { @Thunk final int[] mTempLocation = new int[2]; final PointF mTmpPointF = new PointF(); - private GridOccupancy mOccupied; - private GridOccupancy mTmpOccupied; + protected GridOccupancy mOccupied; + protected GridOccupancy mTmpOccupied; private OnTouchListener mInterceptTouchListener; @@ -121,7 +121,7 @@ public class CellLayout extends ViewGroup { private static final int[] BACKGROUND_STATE_ACTIVE = new int[] { android.R.attr.state_active }; private static final int[] BACKGROUND_STATE_DEFAULT = EMPTY_STATE_SET; - private final Drawable mBackground; + protected final Drawable mBackground; // These values allow a fixed measurement to be set on the CellLayout. private int mFixedWidth = -1; @@ -154,7 +154,7 @@ public class CellLayout extends ViewGroup { private int mGridVisualizationRoundingRadius; private float mGridAlpha = 0f; private int mGridColor = 0; - private float mSpringLoadedProgress = 0f; + protected float mSpringLoadedProgress = 0f; private float mScrollProgress = 0f; // When a drag operation is in progress, holds the nearest cell to the touch point @@ -164,7 +164,7 @@ public class CellLayout extends ViewGroup { private boolean mDragging = false; private final TimeInterpolator mEaseOutInterpolator; - private final ShortcutAndWidgetContainer mShortcutsAndWidgets; + protected final ShortcutAndWidgetContainer mShortcutsAndWidgets; @Retention(RetentionPolicy.SOURCE) @IntDef({WORKSPACE, HOTSEAT, FOLDER}) @@ -565,7 +565,7 @@ public class CellLayout extends ViewGroup { return mSpringLoadedProgress; } - private void updateBgAlpha() { + protected void updateBgAlpha() { mBackground.setAlpha((int) (mSpringLoadedProgress * 255)); } @@ -1662,7 +1662,7 @@ public class CellLayout extends ViewGroup { * @param spanY vertical cell span * @return the configuration that represents the found reorder */ - private ItemConfiguration closestEmptySpaceReorder(int pixelX, int pixelY, int minSpanX, + ItemConfiguration closestEmptySpaceReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY) { ItemConfiguration solution = new ItemConfiguration(); int[] result = new int[2]; @@ -2402,8 +2402,15 @@ public class CellLayout extends ViewGroup { return true; } - private ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY, - int spanX, int spanY, int[] direction, View dragView, boolean decX, + protected ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, + int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX, + ItemConfiguration solution) { + return findReorderSolutionRecursive(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, + direction, dragView, decX, solution); + } + + protected ItemConfiguration findReorderSolutionRecursive(int pixelX, int pixelY, int minSpanX, + int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX, ItemConfiguration solution) { // Copy the current state into the solution. This solution will be manipulated as necessary. copyCurrentStateToSolution(solution, false); @@ -2426,11 +2433,11 @@ public class CellLayout extends ViewGroup { // We try shrinking the widget down to size in an alternating pattern, shrink 1 in // x, then 1 in y etc. if (spanX > minSpanX && (minSpanY == spanY || decX)) { - return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, - direction, dragView, false, solution); + return findReorderSolutionRecursive(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, + spanY, direction, dragView, false, solution); } else if (spanY > minSpanY) { - return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, - direction, dragView, true, solution); + return findReorderSolutionRecursive(pixelX, pixelY, minSpanX, minSpanY, spanX, + spanY - 1, direction, dragView, true, solution); } solution.isSolution = false; } else { @@ -2443,7 +2450,7 @@ public class CellLayout extends ViewGroup { return solution; } - private void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) { + protected void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) { int childCount = mShortcutsAndWidgets.getChildCount(); for (int i = 0; i < childCount; i++) { View child = mShortcutsAndWidgets.getChildAt(i); @@ -2624,7 +2631,7 @@ public class CellLayout extends ViewGroup { return mItemPlacementDirty; } - private static class ItemConfiguration extends CellAndSpan { + static class ItemConfiguration extends CellAndSpan { final ArrayMap map = new ArrayMap<>(); private final ArrayMap savedMap = new ArrayMap<>(); final ArrayList sortedViews = new ArrayList<>(); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2f1f59c2de..d273489bc6 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -44,6 +44,7 @@ import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions; import static com.android.launcher3.anim.Interpolators.EMPHASIZED; +import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE; import static com.android.launcher3.config.FeatureFlags.SHOW_DOT_PAGINATION; import static com.android.launcher3.logging.StatsLogManager.EventEnum; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; @@ -138,6 +139,7 @@ import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.celllayout.CellPosMapper; import com.android.launcher3.celllayout.CellPosMapper.CellPos; +import com.android.launcher3.celllayout.CellPosMapper.TwoPanelCellPosMapper; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dot.DotInfo; @@ -730,7 +732,11 @@ public class Launcher extends StatefulActivity } onDeviceProfileInitiated(); - mCellPosMapper = CellPosMapper.DEFAULT; + if (FOLDABLE_SINGLE_PAGE.get() && mDeviceProfile.isTwoPanels) { + mCellPosMapper = new TwoPanelCellPosMapper(mDeviceProfile.inv.numColumns); + } else { + mCellPosMapper = CellPosMapper.DEFAULT; + } mModelWriter = mModel.getWriter(getDeviceProfile().isVerticalBarLayout(), true, mCellPosMapper, this); return true; diff --git a/src/com/android/launcher3/MultipageCellLayout.java b/src/com/android/launcher3/MultipageCellLayout.java new file mode 100644 index 0000000000..d671c7d165 --- /dev/null +++ b/src/com/android/launcher3/MultipageCellLayout.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2022 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; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +import com.android.launcher3.celllayout.CellLayoutLayoutParams; +import com.android.launcher3.util.CellAndSpan; +import com.android.launcher3.util.GridOccupancy; + +import java.util.function.Supplier; + +/** + * CellLayout that simulates a split in the middle for use in foldable devices. + */ +public class MultipageCellLayout extends CellLayout { + + private final Drawable mLeftBackground; + private final Drawable mRightBackground; + + private View mSeam; + + public MultipageCellLayout(Context context) { + this(context, null); + } + + public MultipageCellLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public MultipageCellLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mLeftBackground = getContext().getDrawable(R.drawable.bg_celllayout); + mLeftBackground.setCallback(this); + mLeftBackground.setAlpha(0); + + mRightBackground = getContext().getDrawable(R.drawable.bg_celllayout); + mRightBackground.setCallback(this); + mRightBackground.setAlpha(0); + + DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + + mCountX = deviceProfile.inv.numColumns * 2; + mCountY = deviceProfile.inv.numRows; + mSeam = new View(getContext()); + setGridSize(mCountX, mCountY); + } + + @Override + ItemConfiguration closestEmptySpaceReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, + int spanX, int spanY) { + return simulateSeam( + () -> super.closestEmptySpaceReorder(pixelX, pixelY, minSpanX, minSpanY, spanX, + spanY)); + } + + @Override + protected ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, + int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX, + ItemConfiguration solution) { + return simulateSeam( + () -> super.findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, + direction, dragView, decX, solution)); + } + + @Override + public ItemConfiguration dropInPlaceSolution(int pixelX, int pixelY, int spanX, int spanY, + View dragView) { + return simulateSeam( + () -> super.dropInPlaceSolution(pixelX, pixelY, spanX, spanY, dragView)); + } + + protected ItemConfiguration simulateSeam(Supplier f) { + CellLayoutLayoutParams lp = new CellLayoutLayoutParams(mCountX / 2, 0, 1, mCountY); + lp.canReorder = false; + mCountX++; + mShortcutsAndWidgets.addViewInLayout(mSeam, lp); + GridOccupancy auxGrid = mOccupied; + mOccupied = createGridOccupancy(); + mTmpOccupied = new GridOccupancy(mCountX, mCountY); + + ItemConfiguration res = removeSeamFromSolution(f.get()); + + mCountX--; + mShortcutsAndWidgets.removeViewInLayout(mSeam); + mOccupied = auxGrid; + mTmpOccupied = new GridOccupancy(mCountX, mCountY); + return res; + } + + private ItemConfiguration removeSeamFromSolution(ItemConfiguration solution) { + solution.map.forEach((view, cell) -> cell.cellX = cell.cellX > mCountX / 2 + ? cell.cellX - 1 : cell.cellX); + solution.cellX = solution.cellX > mCountX / 2 ? solution.cellX - 1 : solution.cellX; + return solution; + } + + GridOccupancy createGridOccupancy() { + GridOccupancy grid = new GridOccupancy(mCountX, mCountY); + for (int i = 0; i < mShortcutsAndWidgets.getChildCount(); i++) { + View view = mShortcutsAndWidgets.getChildAt(i); + CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams(); + int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0; + grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan, + true); + } + return grid; + } + + @Override + protected void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) { + int childCount = mShortcutsAndWidgets.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = mShortcutsAndWidgets.getChildAt(i); + CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams(); + int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0; + CellAndSpan c = new CellAndSpan(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, + lp.cellVSpan); + solution.add(child, c); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mLeftBackground.getAlpha() > 0) { + mLeftBackground.setState(mBackground.getState()); + mLeftBackground.draw(canvas); + } + if (mRightBackground.getAlpha() > 0) { + mRightBackground.setState(mBackground.getState()); + mRightBackground.draw(canvas); + } + + super.onDraw(canvas); + } + + @Override + protected void updateBgAlpha() { + mLeftBackground.setAlpha((int) (mSpringLoadedProgress * 255)); + mRightBackground.setAlpha((int) (mSpringLoadedProgress * 255)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + Rect rect = mBackground.getBounds(); + mLeftBackground.setBounds(rect.left, rect.top, rect.right / 2 - 20, rect.bottom); + mRightBackground.setBounds(rect.right / 2 + 20, rect.top, rect.right, rect.bottom); + } +} diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index 5f39f7e483..55b745ba34 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -107,6 +107,18 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon. } } + /** + * Adds view to Layout a new position and it does not trigger a layout request. + * For more information check documentation for + * {@code ViewGroup#addViewInLayout(View, int, LayoutParams, boolean)} + * + * @param child view to be added + * @return true if the child was added, false otherwise + */ + public boolean addViewInLayout(View child, LayoutParams layoutParams) { + return super.addViewInLayout(child, -1, layoutParams, true); + } + public void setupLp(View child) { CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams(); if (child instanceof NavigableAppWidgetHostView) { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index df829f1f7d..fa54dcfc59 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -135,6 +135,7 @@ import java.util.stream.Collectors; * The workspace is a wide area with a wallpaper and a finite number of pages. * Each page contains a number of icons, folders or widgets the user can * interact with. A workspace is meant to be used with a fixed width only. + * * @param Class that extends View and PageIndicator */ public class Workspace extends PagedView @@ -142,12 +143,16 @@ public class Workspace extends PagedView DragController.DragListener, Insettable, StateHandler, WorkspaceLayoutManager, LauncherBindableItemsContainer, LauncherOverlayCallbacks { - /** The value that {@link #mTransitionProgress} must be greater than for - * {@link #transitionStateShouldAllowDrop()} to return true. */ + /** + * The value that {@link #mTransitionProgress} must be greater than for + * {@link #transitionStateShouldAllowDrop()} to return true. + */ private static final float ALLOW_DROP_TRANSITION_PROGRESS = 0.25f; - /** The value that {@link #mTransitionProgress} must be greater than for - * {@link #isFinishedSwitchingState()} ()} to return true. */ + /** + * The value that {@link #mTransitionProgress} must be greater than for + * {@link #isFinishedSwitchingState()} ()} to return true. + */ private static final float FINISHED_SWITCHING_STATE_TRANSITION_PROGRESS = 0.5f; private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f; @@ -161,16 +166,20 @@ public class Workspace extends PagedView private final int mAllAppsIconSize; private LayoutTransition mLayoutTransition; - @Thunk final WallpaperManager mWallpaperManager; + @Thunk + final WallpaperManager mWallpaperManager; protected ShortcutAndWidgetContainer mDragSourceInternal; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - @Thunk public final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); + @Thunk + public final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); - @Thunk final IntArray mScreenOrder = new IntArray(); + @Thunk + final IntArray mScreenOrder = new IntArray(); - @Thunk boolean mDeferRemoveExtraEmptyScreen = false; + @Thunk + boolean mDeferRemoveExtraEmptyScreen = false; /** * CellInfo for the cell that is currently being dragged @@ -180,14 +189,16 @@ public class Workspace extends PagedView /** * Target drop area calculated during last acceptDrop call. */ - @Thunk int[] mTargetCell = new int[2]; + @Thunk + int[] mTargetCell = new int[2]; private int mDragOverX = -1; private int mDragOverY = -1; /** * The CellLayout that is currently being dragged over */ - @Thunk CellLayout mDragTargetLayout = null; + @Thunk + CellLayout mDragTargetLayout = null; /** * The CellLayout that we will show as highlighted */ @@ -198,13 +209,16 @@ public class Workspace extends PagedView */ private CellLayout mDropToLayout = null; - @Thunk final Launcher mLauncher; - @Thunk DragController mDragController; + @Thunk + final Launcher mLauncher; + @Thunk + DragController mDragController; protected final int[] mTempXY = new int[2]; private final float[] mTempFXY = new float[2]; private final Rect mTempRect = new Rect(); - @Thunk float[] mDragViewVisualCenter = new float[2]; + @Thunk + float[] mDragViewVisualCenter = new float[2]; private SpringLoadedDragController mSpringLoadedDragController; @@ -249,8 +263,10 @@ public class Workspace extends PagedView private static final int DRAG_MODE_ADD_TO_FOLDER = 2; private static final int DRAG_MODE_REORDER = 3; protected int mDragMode = DRAG_MODE_NONE; - @Thunk int mLastReorderX = -1; - @Thunk int mLastReorderY = -1; + @Thunk + int mLastReorderX = -1; + @Thunk + int mLastReorderY = -1; private SparseArray mSavedStates; private final IntArray mRestoredPages = new IntArray(); @@ -275,7 +291,7 @@ public class Workspace extends PagedView * Used to inflate the Workspace from XML. * * @param context The application's context. - * @param attrs The attributes set containing the Workspace's customization values. + * @param attrs The attributes set containing the Workspace's customization values. */ public Workspace(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -284,8 +300,8 @@ public class Workspace extends PagedView /** * Used to inflate the Workspace from XML. * - * @param context The application's context. - * @param attrs The attributes set containing the Workspace's customization values. + * @param context The application's context. + * @param attrs The attributes set containing the Workspace's customization values. * @param defStyle Unused. */ public Workspace(Context context, AttributeSet attrs, int defStyle) { @@ -421,7 +437,9 @@ public class Workspace extends PagedView return mWallpaperOffset.wallpaperOffsetForScroll(pageScroll); } - /** Returns the number of pages used for the wallpaper parallax. */ + /** + * Returns the number of pages used for the wallpaper parallax. + */ public int getNumPagesForWallpaperParallax() { return mWallpaperOffset.getNumPagesForWallpaperParallax(); } @@ -553,6 +571,7 @@ public class Workspace extends PagedView void enableLayoutTransitions() { setLayoutTransition(mLayoutTransition); } + void disableLayoutTransitions() { setLayoutTransition(null); } @@ -644,8 +663,14 @@ public class Workspace extends PagedView // Inflate the cell layout, but do not add it automatically so that we can get the newly // created CellLayout. - CellLayout newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate( + CellLayout newScreen; + if (FOLDABLE_SINGLE_PAGE.get() && isTwoPanelEnabled()) { + newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate( + R.layout.workspace_screen_foldable, this, false /* attachToRoot */); + } else { + newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate( R.layout.workspace_screen, this, false /* attachToRoot */); + } mWorkspaceScreens.put(screenId, newScreen); mScreenOrder.add(insertIndex, screenId); @@ -783,17 +808,17 @@ public class Workspace extends PagedView * Empty page(s) from the end of mWorkspaceScreens will always be removed. The pages with * ID = Workspace.EXTRA_EMPTY_SCREEN_IDS will be removed if there are other non-empty pages. * If there are no more non-empty pages left, extra empty page(s) will either stay or get added. - * + *

* If stripEmptyScreens is true, all empty pages (not just the ones on the end) will be removed * from the Workspace, and if there are no more pages left then extra empty page(s) will be * added. - * + *

* The number of extra empty pages is equal to what getPanelCount() returns. - * + *

* After the method returns the possible pages are: * stripEmptyScreens = true : [non-empty pages, extra empty page(s) alone] * stripEmptyScreens = false : [non-empty pages, empty pages (not in the end), - * extra empty page(s) alone] + * extra empty page(s) alone] */ public void removeExtraEmptyScreenDelayed( int delay, boolean stripEmptyScreens, Runnable onComplete) { @@ -844,11 +869,11 @@ public class Workspace extends PagedView } /** - * Commits the extra empty pages then returns the screen ids of those new screens. - * Usually there's only one extra empty screen, but when two panel home is enabled we commit - * two extra screens. - * - * Returns an empty IntSet in case we cannot commit any new screens. + * Commits the extra empty pages then returns the screen ids of those new screens. + * Usually there's only one extra empty screen, but when two panel home is enabled we commit + * two extra screens. + *

+ * Returns an empty IntSet in case we cannot commit any new screens. */ public IntSet commitExtraEmptyScreens() { if (mLauncher.isWorkspaceLoading()) { @@ -869,7 +894,7 @@ public class Workspace extends PagedView mScreenOrder.removeValue(emptyScreenId); int newScreenId = LauncherSettings.Settings.call(getContext().getContentResolver(), - LauncherSettings.Settings.METHOD_NEW_SCREEN_ID) + LauncherSettings.Settings.METHOD_NEW_SCREEN_ID) .getInt(LauncherSettings.Settings.EXTRA_VALUE); // Launcher database isn't aware of empty pages that are already bound, so we need to // skip those IDs manually. @@ -1058,8 +1083,10 @@ public class Workspace extends PagedView return mIsSwitchingState; } - /** This differs from isSwitchingState in that we take into account how far the transition - * has completed. */ + /** + * This differs from isSwitchingState in that we take into account how far the transition + * has completed. + */ public boolean isFinishedSwitchingState() { return !mIsSwitchingState || (mTransitionProgress > FINISHED_SWITCHING_STATE_TRANSITION_PROGRESS); @@ -1387,7 +1414,9 @@ public class Workspace extends PagedView return mLauncher.isInState(SPRING_LOADED) || !workspaceInModalState(); } - /** Returns whether a drag should be allowed to be started from the current workspace state. */ + /** + * Returns whether a drag should be allowed to be started from the current workspace state. + */ public boolean workspaceIconsCanBeDragged() { return mLauncher.getStateManager().getState().hasFlag(FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED); } @@ -1419,7 +1448,7 @@ public class Workspace extends PagedView // In overview mode, make sure that the two side pages are visible. leftScreen = Utilities.boundToRange(getCurrentPage() - 1, 0, rightScreen); rightScreen = Utilities.boundToRange(getCurrentPage() + 1, - leftScreen, getPageCount() - 1); + leftScreen, getPageCount() - 1); } if (leftScreen == rightScreen) { @@ -1621,7 +1650,7 @@ public class Workspace extends PagedView if (draggableView != null) { draggableView.getSourceVisualDragBounds(dragRect); dragLayerY += dragRect.top; - dragVisualizeOffset = new Point(- halfPadding, halfPadding); + dragVisualizeOffset = new Point(-halfPadding, halfPadding); } @@ -1752,7 +1781,7 @@ public class Workspace extends PagedView } boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell, - float distance, boolean considerTimeout) { + float distance, boolean considerTimeout) { if (distance > target.getFolderCreationRadius(targetCell)) return false; View dropOverView = target.getChildAt(targetCell[0], targetCell[1]); return willCreateUserFolder(info, dropOverView, considerTimeout); @@ -1788,12 +1817,13 @@ public class Workspace extends PagedView } boolean willAddToExistingUserFolder(ItemInfo dragInfo, CellLayout target, int[] targetCell, - float distance) { + float distance) { if (distance > target.getFolderCreationRadius(targetCell)) return false; View dropOverView = target.getChildAt(targetCell[0], targetCell[1]); return willAddToExistingUserFolder(dragInfo, dropOverView); } + boolean willAddToExistingUserFolder(ItemInfo dragInfo, View dropOverView) { if (dropOverView != null) { CellLayoutLayoutParams lp = (CellLayoutLayoutParams) dropOverView.getLayoutParams(); @@ -1894,7 +1924,7 @@ public class Workspace extends PagedView } @Override - public void prepareAccessibilityDrop() { } + public void prepareAccessibilityDrop() {} @Override public void onDrop(final DragObject d, DragOptions options) { @@ -1912,8 +1942,8 @@ public class Workspace extends PagedView boolean resizeOnDrop = false; Runnable onCompleteRunnable = null; if (d.dragSource != this || mDragInfo == null) { - final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1] }; + final int[] touchXY = new int[]{(int) mDragViewVisualCenter[0], + (int) mDragViewVisualCenter[1]}; onDropExternal(touchXY, dropTargetLayout, d); } else { final View cell = mDragInfo.cell; @@ -2311,8 +2341,9 @@ public class Workspace extends PagedView /** * Updates the point in {@param xy} to point to the co-ordinate space of {@param layout} + * * @param layout either hotseat of a page in workspace - * @param xy the point location in workspace co-ordinate space + * @param xy the point location in workspace co-ordinate space */ private void mapPointFromDropLayout(CellLayout layout, float[] xy) { if (mLauncher.isHotseatLayout(layout)) { @@ -2379,7 +2410,7 @@ public class Workspace extends PagedView manageFolderFeedback(targetCellDistance, d); boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int) - mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, + mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, item.spanY, child, mTargetCell); manageReorderOnDragOver(d, targetCellDistance, nearestDropOccupied, minSpanX, minSpanY, @@ -2400,11 +2431,15 @@ public class Workspace extends PagedView ItemInfo item = d.dragInfo; final View child = (mDragInfo == null) ? null : mDragInfo.cell; if (!nearestDropOccupied) { + int[] span = new int[2]; mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY, - child, mTargetCell, new int[2], CellLayout.MODE_SHOW_REORDER_HINT); - mDragTargetLayout.visualizeDropLocation(mTargetCell[0], mTargetCell[1], - item.spanX, item.spanY, d); + child, mTargetCell, span, CellLayout.MODE_SHOW_REORDER_HINT); + mDragTargetLayout.visualizeDropLocation(mTargetCell[0], mTargetCell[1], span[0], + span[1], d); + nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int) + mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, + item.spanY, child, mTargetCell); } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER) && (mLastReorderX != reorderX || mLastReorderY != reorderY) && targetCellDistance < mDragTargetLayout.getReorderRadius(mTargetCell, item.spanX, @@ -2423,6 +2458,7 @@ public class Workspace extends PagedView mReorderAlarm.setAlarm(REORDER_TIMEOUT); } } + /** * Updates {@link #mDragTargetLayout} and {@link #mDragOverlappingLayout} * based on the DragObject's position. @@ -2604,7 +2640,7 @@ public class Workspace extends PagedView final View child; public ReorderAlarmListener(float[] dragViewCenter, int minSpanX, int minSpanY, int spanX, - int spanY, DragObject dragObject, View child) { + int spanY, DragObject dragObject, View child) { this.dragViewCenter = dragViewCenter; this.minSpanX = minSpanX; this.minSpanY = minSpanY; @@ -2621,8 +2657,8 @@ public class Workspace extends PagedView mTargetCell); mTargetCell = mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, - child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER); + (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, + child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER); if (mTargetCell[0] < 0 || mTargetCell[1] < 0) { mDragTargetLayout.revertTempState(); @@ -2646,7 +2682,7 @@ public class Workspace extends PagedView * Drop an item that didn't originate on one of the workspace screens. * It may have come from Launcher (e.g. from all apps or customize), or it may have * come from another app altogether. - * + *

* NOTE: This can also be called when we are outside of a drag event, when we want * to add an item to one of the workspace screens. */ @@ -2688,7 +2724,7 @@ public class Workspace extends PagedView mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); if (willCreateUserFolder(d.dragInfo, cellLayout, mTargetCell, distance, true) || willAddToExistingUserFolder( - d.dragInfo, cellLayout, mTargetCell, distance)) { + d.dragInfo, cellLayout, mTargetCell, distance)) { findNearestVacantCell = false; } } @@ -2923,7 +2959,7 @@ public class Workspace extends PagedView Drawable crossFadeDrawable = createWidgetDrawable(info, finalView); dragView.crossFadeContent(crossFadeDrawable, (int) (duration * 0.8f)); } else if (isWidget && external) { - scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]); + scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]); } DragLayer dragLayer = mLauncher.getDragLayer(); @@ -2962,6 +2998,7 @@ public class Workspace extends PagedView setScaleY(mStateTransitionAnimation.getFinalScale()); } } + public void resetTransitionTransform() { if (isSwitchingState()) { setScaleX(mCurrentScale); @@ -2973,7 +3010,6 @@ public class Workspace extends PagedView * Return the current CellInfo describing our current drag; this method exists * so that Launcher can sync this object with the correct info when the activity is created/ * destroyed - * */ public CellLayout.CellInfo getDragInfo() { return mDragInfo; @@ -2981,11 +3017,12 @@ public class Workspace extends PagedView /** * Calculate the nearest cell where the given object would be dropped. - * + *

* pixelX and pixelY should be in the coordinate system of layout */ - @Thunk int[] findNearestArea(int pixelX, int pixelY, - int spanX, int spanY, CellLayout layout, int[] recycle) { + @Thunk + int[] findNearestArea(int pixelX, int pixelY, + int spanX, int spanY, CellLayout layout, int[] recycle) { return layout.findNearestAreaIgnoreOccupied( pixelX, pixelY, spanX, spanY, recycle); } @@ -3003,7 +3040,7 @@ public class Workspace extends PagedView * Called at the end of a drag which originated on the workspace. */ public void onDropCompleted(final View target, final DragObject d, - final boolean success) { + final boolean success) { if (success) { if (target != this && mDragInfo != null) { removeWorkspaceItem(mDragInfo.cell); @@ -3050,6 +3087,7 @@ public class Workspace extends PagedView /** * Removed widget from workspace by appWidgetId + * * @param appWidgetId */ public void removeWidget(int appWidgetId) { @@ -3256,6 +3294,7 @@ public class Workspace extends PagedView /** * Perform {param operator} over all the items in a given {param layout}. + * * @return The first item that satisfies the operator or null. */ public View mapOverCellLayout(CellLayout layout, ItemOperator operator) { @@ -3310,10 +3349,10 @@ public class Workspace extends PagedView /** * Remove workspace icons & widget information related to items in matcher. * - * @param matcher the matcher generated by the caller. + * @param matcher the matcher generated by the caller. */ public void persistRemoveItemsByMatcher(Predicate matcher, - @Nullable final String reason) { + @Nullable final String reason) { mLauncher.getModelWriter().deleteItemsFromDatabase(matcher, reason); removeItemsByMatcher(matcher); } @@ -3358,7 +3397,9 @@ public class Workspace extends PagedView return mOverlayShown; } - /** Calls {@link #snapToPage(int)} on the {@link #DEFAULT_PAGE}, then requests focus on it. */ + /** + * Calls {@link #snapToPage(int)} on the {@link #DEFAULT_PAGE}, then requests focus on it. + */ public void moveToDefaultScreen() { int page = DEFAULT_PAGE; if (!workspaceInModalState() && getNextPage() != page) { @@ -3458,7 +3499,7 @@ public class Workspace extends PagedView private boolean mRefreshPending; DeferredWidgetRefresh(ArrayList infos, - LauncherWidgetHolder holder) { + LauncherWidgetHolder holder) { mInfos = infos; mWidgetHolder = holder; mHandler = mLauncher.mHandler; diff --git a/src/com/android/launcher3/util/GridOccupancy.java b/src/com/android/launcher3/util/GridOccupancy.java index 13014608c4..43e486c7ab 100644 --- a/src/com/android/launcher3/util/GridOccupancy.java +++ b/src/com/android/launcher3/util/GridOccupancy.java @@ -81,4 +81,16 @@ public class GridOccupancy extends AbsGridOccupancy { public void clear() { markCells(0, 0, mCountX, mCountY, false); } + + @Override + public String toString() { + StringBuilder s = new StringBuilder("Grid: \n"); + for (int y = 0; y < mCountY; y++) { + for (int x = 0; x < mCountX; x++) { + s.append(cells[x][y] ? 1 : 0).append(" "); + } + s.append("\n"); + } + return s.toString(); + } }