From c6cc61d45836e4081920883cc4d448ccb0bb8417 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Wed, 4 Apr 2012 12:47:08 -0700 Subject: Cleanup and refactoring in relation to drag and drop -> folder creation, adding to folders, reordering, switching pages -> ensuring parity of dragEnter and dragExit in cell layouts and workspace (neither were consistently getting an even number of each) -> actually enforced above with exceptions -- probably want to take these out, but maybe we can leave them in as warnings -> fixed bug with mapping points to hotseat -> fixes other bugs with drag and drop Change-Id: I564568f810f2784d122ec6135012b67c2e8e7551 --- .../android/launcher2/AppsCustomizePagedView.java | 1 - src/com/android/launcher2/CellLayout.java | 4 + src/com/android/launcher2/DropTarget.java | 38 ++ src/com/android/launcher2/FolderIcon.java | 5 +- src/com/android/launcher2/Workspace.java | 391 +++++++++++---------- 5 files changed, 247 insertions(+), 192 deletions(-) diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index f1ae2c568..67ae1f112 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -737,7 +737,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen * @param target where the item was dragged to (can be null if the item was flung) */ private void endDragging(View target, boolean isFlingToDelete, boolean success) { - mLauncher.getWorkspace().onDragStopped(success); if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() && !(target instanceof DeleteDropTarget))) { // Exit spring loaded mode if we have not successfully dropped or have not handled the diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 199c41a59..da7c2b0ec 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -161,6 +161,7 @@ public class CellLayout extends ViewGroup { private int[] mDirectionVector = new int[2]; int[] mPreviousReorderDirection = new int[2]; private static final int INVALID_DIRECTION = -100; + private DropTarget.DragEnforcer mDragEnforcer; public CellLayout(Context context) { this(context, null); @@ -172,6 +173,7 @@ public class CellLayout extends ViewGroup { public CellLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mDragEnforcer = new DropTarget.DragEnforcer(mContext); // A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show // the user where a dragged item will land when dropped. @@ -2508,6 +2510,7 @@ public class CellLayout extends ViewGroup { * or it may have begun on another layout. */ void onDragEnter() { + mDragEnforcer.onDragEnter(); if (!mDragging) { // Fade in the drag indicators if (mCrosshairsAnimator != null) { @@ -2521,6 +2524,7 @@ public class CellLayout extends ViewGroup { * Called when drag has left this CellLayout or has been completed (successfully or not) */ void onDragExit() { + mDragEnforcer.onDragExit(); // This can actually be called when we aren't in a drag, e.g. when adding a new // item to this layout via the customize drawer. // Guard against that case. diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java index fb714c60a..397d46245 100644 --- a/src/com/android/launcher2/DropTarget.java +++ b/src/com/android/launcher2/DropTarget.java @@ -16,6 +16,7 @@ package com.android.launcher2; +import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; @@ -63,6 +64,43 @@ public interface DropTarget { } } + public static class DragEnforcer implements DragController.DragListener { + int dragParity = 0; + + public DragEnforcer(Context context) { + Launcher launcher = (Launcher) context; + launcher.getDragController().addDragListener(this); + } + + void onDragEnter() { + dragParity++; + if (dragParity != 1) { + throw new RuntimeException("onDragEnter: Drag contract violated: " + dragParity); + } + } + + void onDragExit() { + dragParity--; + if (dragParity != 0) { + throw new RuntimeException("onDragExit: Drag contract violated: " + dragParity); + } + } + + @Override + public void onDragStart(DragSource source, Object info, int dragAction) { + if (dragParity != 0) { + throw new RuntimeException("onDragEnter: Drag contract violated: " + dragParity); + } + } + + @Override + public void onDragEnd() { + if (dragParity != 0) { + throw new RuntimeException("onDragExit: Drag contract violated: " + dragParity); + } + } + } + /** * Used to temporarily disable certain drop targets * diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java index c005edfcd..513fa6bea 100644 --- a/src/com/android/launcher2/FolderIcon.java +++ b/src/com/android/launcher2/FolderIcon.java @@ -325,7 +325,10 @@ public class FolderIcon extends LinearLayout implements FolderListener { } public void onDragExit(Object dragInfo) { - if (!willAcceptItem((ItemInfo) dragInfo)) return; + onDragExit(); + } + + public void onDragExit() { mFolderRingAnimator.animateToNaturalState(); } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index fd3cc1f8e..8c3b46517 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -35,12 +35,14 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Camera; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.Region.Op; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.IBinder; import android.os.Parcelable; @@ -92,7 +94,7 @@ public class Workspace extends SmoothPagedView private static final int ADJACENT_SCREEN_DROP_DURATION = 300; private static final int FLING_THRESHOLD_VELOCITY = 500; - private float mMaxDistanceForFolderCreation = 50.0f; + private float mMaxDistanceForFolderCreation; // These animators are used to fade the children's outlines private ObjectAnimator mChildrenOutlineFadeInAnimation; @@ -125,11 +127,23 @@ public class Workspace extends SmoothPagedView * Target drop area calculated during last acceptDrop call. */ private int[] mTargetCell = new int[2]; + private int mDragOverX = -1; + private int mDragOverY = -1; /** * The CellLayout that is currently being dragged over */ private CellLayout mDragTargetLayout = null; + /** + * The CellLayout that we will show as glowing + */ + private CellLayout mDragOverlappingLayout = null; + + /** + * The CellLayout which will be dropped to + */ + private CellLayout mDropToLayout = null; + private boolean mDragHasEnteredWorkspace = false; private Launcher mLauncher; @@ -197,9 +211,10 @@ public class Workspace extends SmoothPagedView private final Alarm mFolderCreationAlarm = new Alarm(); private final Alarm mReorderAlarm = new Alarm(); private FolderRingAnimator mDragFolderRingAnimator = null; - private View mLastDragOverView = null; + private FolderIcon mDragOverFolderIcon = null; private boolean mCreateUserFolderOnDrop = false; - private boolean mWillAddToExistingFolder = false; + private boolean mAddToExistingFolderOnDrop = false; + private DropTarget.DragEnforcer mDragEnforcer; // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget) private float mXDown; @@ -224,10 +239,6 @@ public class Workspace extends SmoothPagedView private int mLastReorderX = -1; private int mLastReorderY = -1; - // Relating to workspace drag fade out - private float mDragFadeOutAlpha; - private int mDragFadeOutDuration; - // These variables are used for storing the initial and final values during workspace animations private int mSavedScrollX; private float mSavedRotationY; @@ -276,13 +287,12 @@ public class Workspace extends SmoothPagedView super(context, attrs, defStyle); mContentIsRefreshable = false; + mDragEnforcer = new DropTarget.DragEnforcer(context); // With workspace, data is available straight from the get-go setDataIsReady(); final Resources res = getResources(); mFadeInAdjacentScreens = res.getBoolean(R.bool.config_workspaceFadeAdjacentScreens); - mDragFadeOutAlpha = res.getInteger(R.integer.config_dragFadeOutAlpha) / 100f; - mDragFadeOutDuration = res.getInteger(R.integer.config_dragFadeOutDuration); mWallpaperManager = WallpaperManager.getInstance(context); int cellCountX = DEFAULT_CELL_COUNT_X; @@ -411,7 +421,7 @@ public class Workspace extends SmoothPagedView mWallpaperTravelWidth = (int) (mDisplayWidth * wallpaperTravelToScreenWidthRatio(mDisplayWidth, mDisplayHeight)); - mMaxDistanceForFolderCreation = (0.5f * res.getDimensionPixelSize(R.dimen.app_icon_size)); + mMaxDistanceForFolderCreation = (0.6f * res.getDimensionPixelSize(R.dimen.app_icon_size)); mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity); } @@ -1522,15 +1532,6 @@ public class Workspace extends SmoothPagedView size[1], alphaClipPaint); } - // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was - // never dragged over - public void onDragStopped(boolean success) { - // In the success case, DragController has already called onDragExit() - if (!success) { - doDragExit(null); - } - } - public void exitWidgetResizeMode() { DragLayer dragLayer = mLauncher.getDragLayer(); dragLayer.clearAllResizeFrames(); @@ -1993,9 +1994,10 @@ public class Workspace extends SmoothPagedView */ public boolean acceptDrop(DragObject d) { // If it's an external drop (e.g. from All Apps), check if it should be accepted + CellLayout dropTargetLayout = mDropToLayout; if (d.dragSource != this) { // Don't accept the drop if we're not over a screen at time of drop - if (mDragTargetLayout == null) { + if (dropTargetLayout == null) { return false; } if (!transitionStateShouldAllowDrop()) return false; @@ -2004,10 +2006,10 @@ public class Workspace extends SmoothPagedView d.dragView, mDragViewVisualCenter); // We want the point to be mapped to the dragTarget. - if (mLauncher.isHotseatLayout(mDragTargetLayout)) { + if (mLauncher.isHotseatLayout(dropTargetLayout)) { mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter); } else { - mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null); + mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null); } int spanX = 1; @@ -2030,21 +2032,21 @@ public class Workspace extends SmoothPagedView } mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout, + (int) mDragViewVisualCenter[1], minSpanX, minSpanY, dropTargetLayout, mTargetCell); - float distance = mDragTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0], + float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); - if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, + if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout, mTargetCell, distance, true)) { return true; } - if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, + if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout, mTargetCell, distance)) { return true; } int[] resultSpan = new int[2]; - mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP); boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0; @@ -2053,7 +2055,7 @@ public class Workspace extends SmoothPagedView if (!foundCell) { // Don't show the message if we are dropping on the AllApps button and the hotseat // is full - boolean isHotseat = mLauncher.isHotseatLayout(mDragTargetLayout); + boolean isHotseat = mLauncher.isHotseatLayout(dropTargetLayout); if (mTargetCell != null && isHotseat) { Hotseat hotseat = mLauncher.getHotseat(); if (hotseat.isAllAppsButtonRank( @@ -2177,8 +2179,8 @@ public class Workspace extends SmoothPagedView if (distance > mMaxDistanceForFolderCreation) return false; View dropOverView = target.getChildAt(targetCell[0], targetCell[1]); - if (!mWillAddToExistingFolder) return false; - mWillAddToExistingFolder = false; + if (!mAddToExistingFolderOnDrop) return false; + mAddToExistingFolderOnDrop = false; if (dropOverView instanceof FolderIcon) { FolderIcon fi = (FolderIcon) dropOverView; @@ -2199,17 +2201,17 @@ public class Workspace extends SmoothPagedView mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, mDragViewVisualCenter); + CellLayout dropTargetLayout = mDropToLayout; + // We want the point to be mapped to the dragTarget. - if (mDragTargetLayout != null) { - if (mLauncher.isHotseatLayout(mDragTargetLayout)) { + if (dropTargetLayout != null) { + if (mLauncher.isHotseatLayout(dropTargetLayout)) { mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter); } else { - mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null); + mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null); } } - CellLayout dropTargetLayout = mDragTargetLayout; - int snapScreen = -1; boolean resizeOnDrop = false; if (d.dragSource != this) { @@ -2262,7 +2264,7 @@ public class Workspace extends SmoothPagedView } int[] resultSpan = new int[2]; - mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP); @@ -2406,14 +2408,15 @@ public class Workspace extends SmoothPagedView } public void onDragEnter(DragObject d) { + mDragEnforcer.onDragEnter(); mDragHasEnteredWorkspace = true; - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - mDragTargetLayout.onDragExit(); - } - mDragTargetLayout = getCurrentDropLayout(); - mDragTargetLayout.setIsDragOverlapping(true); - mDragTargetLayout.onDragEnter(); + mCreateUserFolderOnDrop = false; + mAddToExistingFolderOnDrop = false; + + mDropToLayout = null; + CellLayout layout = getCurrentDropLayout(); + setCurrentDropLayout(layout); + setCurrentDragOverlappingLayout(layout); // Because we don't have space in the Phone UI (the CellLayouts run to the edge) we // don't need to show the outlines @@ -2422,26 +2425,29 @@ public class Workspace extends SmoothPagedView } } - private void doDragExit(DragObject d) { - // Clean up folders - cleanupFolderCreation(d); + public void onDragExit(DragObject d) { + mDragEnforcer.onDragExit(); + mDragHasEnteredWorkspace = false; - // Clean up reorder - if (mReorderAlarm != null) { - mReorderAlarm.cancelAlarm(); - mLastReorderX = -1; - mLastReorderY = -1; + // Here we store the final page that will be dropped to, if the workspace in fact + // receives the drop + if (mInScrollArea) { + mDropToLayout = mDragOverlappingLayout; + } else { + mDropToLayout = mDragTargetLayout; + } + + if (mDragMode == DRAG_MODE_CREATE_FOLDER) { + mCreateUserFolderOnDrop = true; + } else if (mDragMode == DRAG_MODE_ADD_TO_FOLDER) { + mAddToExistingFolderOnDrop = true; } // Reset the scroll area and previous drag target onResetScrollArea(); + setCurrentDropLayout(null); + setCurrentDragOverlappingLayout(null); - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - mDragTargetLayout.onDragExit(); - } - mLastDragOverView = null; - mDragMode = DRAG_MODE_NONE; mSpringLoadedDragController.cancel(); if (!mIsPageMoving) { @@ -2449,9 +2455,82 @@ public class Workspace extends SmoothPagedView } } - public void onDragExit(DragObject d) { - mDragHasEnteredWorkspace = false; - doDragExit(d); + void setCurrentDropLayout(CellLayout layout) { + if (mDragTargetLayout != null) { + mDragTargetLayout.revertTempState(); + mDragTargetLayout.onDragExit(); + } + mDragTargetLayout = layout; + if (mDragTargetLayout != null) { + mDragTargetLayout.onDragEnter(); + } + cleanupReorder(true); + cleanupFolderCreation(); + setCurrentDropOverCell(-1, -1); + } + + void setCurrentDragOverlappingLayout(CellLayout layout) { + if (mDragOverlappingLayout != null) { + mDragOverlappingLayout.setIsDragOverlapping(false); + } + mDragOverlappingLayout = layout; + if (mDragOverlappingLayout != null) { + mDragOverlappingLayout.setIsDragOverlapping(true); + } + invalidate(); + } + + void setCurrentDropOverCell(int x, int y) { + if (x != mDragOverX || y != mDragOverY) { + mDragOverX = x; + mDragOverY = y; + setDragMode(DRAG_MODE_NONE); + } + } + + void setDragMode(int dragMode) { + if (dragMode != mDragMode) { + if (dragMode == DRAG_MODE_NONE) { + cleanupAddToFolder(); + // We don't want to cancel the re-order alarm every time the target cell changes + // as this feels to slow / unresponsive. + cleanupReorder(false); + cleanupFolderCreation(); + } else if (dragMode == DRAG_MODE_ADD_TO_FOLDER) { + cleanupReorder(true); + cleanupFolderCreation(); + } else if (dragMode == DRAG_MODE_CREATE_FOLDER) { + cleanupAddToFolder(); + cleanupReorder(true); + } else if (dragMode == DRAG_MODE_REORDER) { + cleanupAddToFolder(); + cleanupFolderCreation(); + } + mDragMode = dragMode; + } + } + + private void cleanupFolderCreation() { + if (mDragFolderRingAnimator != null) { + mDragFolderRingAnimator.animateToNaturalState(); + } + mFolderCreationAlarm.cancelAlarm(); + } + + private void cleanupAddToFolder() { + if (mDragOverFolderIcon != null) { + mDragOverFolderIcon.onDragExit(null); + mDragOverFolderIcon = null; + } + } + + private void cleanupReorder(boolean cancelAlarm) { + // Any pending reorders are canceled + if (cancelAlarm) { + mReorderAlarm.cancelAlarm(); + } + mLastReorderX = -1; + mLastReorderY = -1; } public DropTarget getDropTargetDelegate(DragObject d) { @@ -2525,6 +2604,11 @@ public class Workspace extends SmoothPagedView xy[1] = xy[1] - v.getTop(); } + void mapPointFromSelfToHotseatLayout(Hotseat hotseat, float[] xy) { + xy[0] = xy[0] - hotseat.getLeft() - hotseat.getLayout().getLeft(); + xy[1] = xy[1] - hotseat.getTop() - hotseat.getLayout().getTop(); + } + /* * * Convert the 2D coordinate xy from this CellLayout's coordinate space to @@ -2706,21 +2790,9 @@ public class Workspace extends SmoothPagedView layout = findMatchingPageForDragOver(d.dragView, d.x, d.y, false); } if (layout != mDragTargetLayout) { - // Cancel all intermediate folder states - cleanupFolderCreation(d); - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - mDragTargetLayout.onDragExit(); - } - mDragTargetLayout = layout; - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(true); - mDragTargetLayout.onDragEnter(); - } else { - mLastDragOverView = null; - mDragMode = DRAG_MODE_NONE; - } + setCurrentDropLayout(layout); + setCurrentDragOverlappingLayout(layout); boolean isInSpringLoadedMode = (mState == State.SPRING_LOADED); if (isInSpringLoadedMode) { @@ -2743,13 +2815,8 @@ public class Workspace extends SmoothPagedView layout = getCurrentDropLayout(); } if (layout != mDragTargetLayout) { - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - mDragTargetLayout.onDragExit(); - } - mDragTargetLayout = layout; - mDragTargetLayout.setIsDragOverlapping(true); - mDragTargetLayout.onDragEnter(); + setCurrentDropLayout(layout); + setCurrentDragOverlappingLayout(layout); } } @@ -2757,31 +2824,26 @@ public class Workspace extends SmoothPagedView if (mDragTargetLayout != null) { // We want the point to be mapped to the dragTarget. if (mLauncher.isHotseatLayout(mDragTargetLayout)) { - mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter); + mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter); } else { mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null); } + ItemInfo info = (ItemInfo) d.dragInfo; mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell); + + setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]); + float targetCellDistance = mDragTargetLayout.getDistanceFromCell( mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]); - final View lastDragOverView = mLastDragOverView; - if (mLastDragOverView != dragOverView) { - mDragMode = DRAG_MODE_NONE; - mLastDragOverView = dragOverView; - if (mReorderAlarm != null) { - mReorderAlarm.cancelAlarm(); - } - } - - boolean folder = willCreateOrAddToFolder(info, mDragTargetLayout, mTargetCell, - targetCellDistance, dragOverView, lastDragOverView); + manageFolderFeedback(info, mDragTargetLayout, mTargetCell, + targetCellDistance, dragOverView); int minSpanX = item.spanX; int minSpanY = item.spanY; @@ -2795,96 +2857,70 @@ public class Workspace extends SmoothPagedView (int) mDragViewVisualCenter[1], item.spanX, item.spanY, mDragTargetLayout, reorderPosition); - if (!mDragTargetLayout.isNearestDropLocationOccupied((int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], item.spanX, item.spanY, child, mTargetCell)) { - // If the current hover area isn't occupied (permanently) by any items, then we - // reset all the reordering. - mDragTargetLayout.revertTempState(); - mDragMode = DRAG_MODE_NONE; - mLastDragOverView = dragOverView; - if (mReorderAlarm != null) { - mReorderAlarm.cancelAlarm(); - } - mLastReorderX = -1; - mLastReorderY = -1; + boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int) + mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, + item.spanY, child, mTargetCell); + + if (!nearestDropOccupied) { mDragTargetLayout.visualizeDropLocation(child, mDragOutline, (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false, d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion()); - } else if (!folder && !mReorderAlarm.alarmPending() && - (mLastReorderX != reorderPosition[0] || mLastReorderY != reorderPosition[1])) { + } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER) + && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderPosition[0] || + mLastReorderY != reorderPosition[1])) { // Otherwise, if we aren't adding to or creating a folder and there's no pending // reorder, then we schedule a reorder - cancelFolderCreation(); ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter, minSpanX, minSpanY, item.spanX, item.spanY, d.dragView, child); mReorderAlarm.setOnAlarmListener(listener); mReorderAlarm.setAlarm(REORDER_TIMEOUT); - } else if (folder) { - if (mReorderAlarm != null) { - mReorderAlarm.cancelAlarm(); + } + + if (mDragMode == DRAG_MODE_CREATE_FOLDER || mDragMode == DRAG_MODE_ADD_TO_FOLDER || + !nearestDropOccupied) { + if (mDragTargetLayout != null) { + mDragTargetLayout.revertTempState(); } - mDragTargetLayout.revertTempState(); - mLastReorderX = -1; - mLastReorderY = -1; } } } - private boolean willCreateOrAddToFolder(ItemInfo info, CellLayout targetLayout, - int[] targetCell, float distance, View dragOverView, View lastDragOverView) { + private void manageFolderFeedback(ItemInfo info, CellLayout targetLayout, + int[] targetCell, float distance, View dragOverView) { boolean userFolderPending = willCreateUserFolder(info, targetLayout, targetCell, distance, false); - if (userFolderPending && mDragMode == DRAG_MODE_NONE) { + if (mDragMode == DRAG_MODE_NONE && userFolderPending && + !mFolderCreationAlarm.alarmPending()) { mFolderCreationAlarm.setOnAlarmListener(new FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1])); mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT); + return; } boolean willAddToFolder = willAddToExistingUserFolder(info, targetLayout, targetCell, distance); if (willAddToFolder && mDragMode == DRAG_MODE_NONE) { - FolderIcon fi = ((FolderIcon) dragOverView); - mDragMode = DRAG_MODE_ADD_TO_FOLDER; - mWillAddToExistingFolder = true; - fi.onDragEnter(info); + mDragOverFolderIcon = ((FolderIcon) dragOverView); + mAddToExistingFolderOnDrop = true; + mDragOverFolderIcon.onDragEnter(info); if (targetLayout != null) { targetLayout.clearDragOutlines(); } + setDragMode(DRAG_MODE_ADD_TO_FOLDER); + return; } - if (dragOverView != lastDragOverView || (mCreateUserFolderOnDrop && !userFolderPending) - || (!willAddToFolder && mDragMode == DRAG_MODE_ADD_TO_FOLDER)) { - cancelFolderCreation(); - mWillAddToExistingFolder = false; - if (lastDragOverView != null && lastDragOverView instanceof FolderIcon) { - ((FolderIcon) lastDragOverView).onDragExit(info); - } - } - - return (willAddToFolder || userFolderPending) && mDragMode != DRAG_MODE_REORDER; - } - - private void cleanupFolderCreation(DragObject d) { - if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) { - mDragFolderRingAnimator.animateToNaturalState(); + if (mDragMode == DRAG_MODE_ADD_TO_FOLDER && !willAddToFolder) { + setDragMode(DRAG_MODE_NONE); } - if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) { - if (d != null) { - ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo); - } + if (mDragMode == DRAG_MODE_CREATE_FOLDER && !userFolderPending) { + setDragMode(DRAG_MODE_NONE); } - mFolderCreationAlarm.cancelAlarm(); - } - private void cancelFolderCreation() { - if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) { - mDragFolderRingAnimator.animateToNaturalState(); - } - mCreateUserFolderOnDrop = false; - mFolderCreationAlarm.cancelAlarm(); + return; } class FolderCreationAlarmListener implements OnAlarmListener { @@ -2907,8 +2943,7 @@ public class Workspace extends SmoothPagedView mDragFolderRingAnimator.animateToAcceptState(); layout.showFolderAccept(mDragFolderRingAnimator); layout.clearDragOutlines(); - mCreateUserFolderOnDrop = true; - mDragMode = DRAG_MODE_CREATE_FOLDER; + setDragMode(DRAG_MODE_CREATE_FOLDER); } } @@ -2942,12 +2977,10 @@ public class Workspace extends SmoothPagedView if (mTargetCell[0] < 0 || mTargetCell[1] < 0) { mDragTargetLayout.revertTempState(); + } else { + setDragMode(DRAG_MODE_REORDER); } - if (mDragMode == DRAG_MODE_ADD_TO_FOLDER) { - } - mDragMode = DRAG_MODE_REORDER; - boolean resize = resultSpan[0] != spanX || resultSpan[1] != spanY; mDragTargetLayout.visualizeDropLocation(child, mDragOutline, (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], @@ -3024,9 +3057,9 @@ public class Workspace extends SmoothPagedView cellLayout, mTargetCell); float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); - if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell, + if (willCreateUserFolder((ItemInfo) d.dragInfo, cellLayout, mTargetCell, distance, true) || willAddToExistingUserFolder((ItemInfo) d.dragInfo, - mDragTargetLayout, mTargetCell, distance)) { + cellLayout, mTargetCell, distance)) { findNearestVacantCell = false; } } @@ -3040,7 +3073,7 @@ public class Workspace extends SmoothPagedView minSpanY = item.minSpanY; } int[] resultSpan = new int[2]; - mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, info.spanX, info.spanY, null, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP_EXTERNAL); item.spanX = resultSpan[0]; @@ -3068,7 +3101,6 @@ public class Workspace extends SmoothPagedView throw new IllegalStateException("Unknown item type: " + pendingInfo.itemType); } - cellLayout.onDragExit(); } }; View finalView = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET @@ -3122,7 +3154,7 @@ public class Workspace extends SmoothPagedView if (touchXY != null) { // when dragging and dropping, just find the closest free spot - mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], 1, 1, 1, 1, null, mTargetCell, null, CellLayout.MODE_ON_DROP_EXTERNAL); } else { @@ -3337,10 +3369,6 @@ public class Workspace extends SmoothPagedView } } } else if (mDragInfo != null) { - // NOTE: When 'success' is true, onDragExit is called by the DragController before - // calling onDropCompleted(). We call it ourselves here, but maybe this should be - // moved into DragController.cancelDrag(). - doDragExit(null); CellLayout cellLayout; if (mLauncher.isHotseatLayout(target)) { cellLayout = mLauncher.getHotseat().getLayout(); @@ -3446,17 +3474,13 @@ public class Workspace extends SmoothPagedView final int page = (mNextPage != INVALID_PAGE ? mNextPage : mCurrentPage) + (direction == DragController.SCROLL_LEFT ? -1 : 1); - cancelFolderCreation(); + + // We always want to exit the current layout to ensure parity of enter / exit + setCurrentDropLayout(null); if (0 <= page && page < getChildCount()) { CellLayout layout = (CellLayout) getChildAt(page); - // Exit the current layout and mark the overlapping layout - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - mDragTargetLayout.onDragExit(); - } - mDragTargetLayout = layout; - mDragTargetLayout.setIsDragOverlapping(true); + setCurrentDragOverlappingLayout(layout); // Workspace is responsible for drawing the edge glow on adjacent pages, // so we need to redraw the workspace when this may have changed. @@ -3471,17 +3495,11 @@ public class Workspace extends SmoothPagedView public boolean onExitScrollArea() { boolean result = false; if (mInScrollArea) { - if (mDragTargetLayout != null) { - mDragTargetLayout.setIsDragOverlapping(false); - // Workspace is responsible for drawing the edge glow on adjacent pages, - // so we need to redraw the workspace when this may have changed. - invalidate(); - } - if (mDragTargetLayout != null && mDragHasEnteredWorkspace) { - // Unmark the overlapping layout and re-enter the current layout - mDragTargetLayout = getCurrentDropLayout(); - mDragTargetLayout.onDragEnter(); - } + invalidate(); + CellLayout layout = getCurrentDropLayout(); + setCurrentDropLayout(layout); + setCurrentDragOverlappingLayout(layout); + result = true; mInScrollArea = false; } @@ -3489,14 +3507,7 @@ public class Workspace extends SmoothPagedView } private void onResetScrollArea() { - if (mDragTargetLayout != null) { - // Unmark the overlapping layout - mDragTargetLayout.setIsDragOverlapping(false); - - // Workspace is responsible for drawing the edge glow on adjacent pages, - // so we need to redraw the workspace when this may have changed. - invalidate(); - } + setCurrentDragOverlappingLayout(null); mInScrollArea = false; } -- cgit v1.2.3