Merge "Simulating a split screen CellLayout using one CellLayout" into tm-qpr-dev

This commit is contained in:
Sebastián Franco
2023-02-08 01:04:20 +00:00
committed by Android (Google) Code Review
7 changed files with 347 additions and 78 deletions

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<com.android.launcher3.MultipageCellLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hapticFeedbackEnabled="false"
launcher:containerType="workspace" />

View File

@@ -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<View, CellAndSpan> map = new ArrayMap<>();
private final ArrayMap<View, CellAndSpan> savedMap = new ArrayMap<>();
final ArrayList<View> sortedViews = new ArrayList<>();

View File

@@ -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<LauncherState>
}
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;

View File

@@ -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<ItemConfiguration> 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);
}
}

View File

@@ -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) {

View File

@@ -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 <T> Class that extends View and PageIndicator
*/
public class Workspace<T extends View & PageIndicator> extends PagedView<T>
@@ -142,12 +143,16 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
DragController.DragListener, Insettable, StateHandler<LauncherState>,
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<T extends View & PageIndicator> extends PagedView<T>
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<CellLayout> mWorkspaceScreens = new IntSparseArrayMap<>();
@Thunk
public final IntSparseArrayMap<CellLayout> 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<T extends View & PageIndicator> extends PagedView<T>
/**
* 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<T extends View & PageIndicator> extends PagedView<T>
*/
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<T extends View & PageIndicator> extends PagedView<T>
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<Parcelable> mSavedStates;
private final IntArray mRestoredPages = new IntArray();
@@ -275,7 +291,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
* 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<T extends View & PageIndicator> extends PagedView<T>
/**
* 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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
void enableLayoutTransitions() {
setLayoutTransition(mLayoutTransition);
}
void disableLayoutTransitions() {
setLayoutTransition(null);
}
@@ -644,8 +663,14 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
// 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<T extends View & PageIndicator> extends PagedView<T>
* 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.
*
* <p>
* 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.
*
* <p>
* The number of extra empty pages is equal to what getPanelCount() returns.
*
* <p>
* 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<T extends View & PageIndicator> extends PagedView<T>
}
/**
* 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.
* <p>
* 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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
// 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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
}
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<T extends View & PageIndicator> extends PagedView<T>
}
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<T extends View & PageIndicator> extends PagedView<T>
}
@Override
public void prepareAccessibilityDrop() { }
public void prepareAccessibilityDrop() {}
@Override
public void onDrop(final DragObject d, DragOptions options) {
@@ -1912,8 +1942,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
/**
* 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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
mReorderAlarm.setAlarm(REORDER_TIMEOUT);
}
}
/**
* Updates {@link #mDragTargetLayout} and {@link #mDragOverlappingLayout}
* based on the DragObject's position.
@@ -2604,7 +2640,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
* 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.
*
* <p>
* 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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
setScaleY(mStateTransitionAnimation.getFinalScale());
}
}
public void resetTransitionTransform() {
if (isSwitchingState()) {
setScaleX(mCurrentScale);
@@ -2973,7 +3010,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
* 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<T extends View & PageIndicator> extends PagedView<T>
/**
* Calculate the nearest cell where the given object would be dropped.
*
* <p>
* 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<T extends View & PageIndicator> extends PagedView<T>
* 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<T extends View & PageIndicator> extends PagedView<T>
/**
* Removed widget from workspace by appWidgetId
*
* @param appWidgetId
*/
public void removeWidget(int appWidgetId) {
@@ -3256,6 +3294,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
/**
* 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<T extends View & PageIndicator> extends PagedView<T>
/**
* 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<ItemInfo> matcher,
@Nullable final String reason) {
@Nullable final String reason) {
mLauncher.getModelWriter().deleteItemsFromDatabase(matcher, reason);
removeItemsByMatcher(matcher);
}
@@ -3358,7 +3397,9 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
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<T extends View & PageIndicator> extends PagedView<T>
private boolean mRefreshPending;
DeferredWidgetRefresh(ArrayList<LauncherAppWidgetInfo> infos,
LauncherWidgetHolder holder) {
LauncherWidgetHolder holder) {
mInfos = infos;
mWidgetHolder = holder;
mHandler = mLauncher.mHandler;

View File

@@ -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();
}
}