From 440c360bc395c43683fa9ca226e59f9e35f9e926 Mon Sep 17 00:00:00 2001 From: Patrick Dubroy Date: Tue, 13 Jul 2010 17:50:32 -0700 Subject: Fix bug with drag visualization and UserFolders. When dragging an app shortcut, it was possible that we'd show a red rectangle around a cell occupied by a UserFolder. This shouldn't be possible -- as soon as that cell becomes the target drop cell, the folder should start handling the drag and drop events. Change-Id: I1b7a8b1aa9aeb7e2f1bd51ce8d947c06455e988f --- src/com/android/launcher2/CellLayout.java | 16 +++++++++++- src/com/android/launcher2/DeleteZone.java | 6 +++++ src/com/android/launcher2/DragController.java | 20 ++++++++++++++- src/com/android/launcher2/DropTarget.java | 20 +++++++++++++++ src/com/android/launcher2/FolderIcon.java | 6 +++++ src/com/android/launcher2/UserFolder.java | 6 +++++ src/com/android/launcher2/Workspace.java | 36 ++++++++++++++++++++++++++- 7 files changed, 107 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 9cc370f45..3f60d5047 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -677,6 +677,20 @@ public class CellLayout extends ViewGroup { return true; } + public View getChildAt(int x, int y) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) && + (lp.cellY <= y) && (y < lp.cellY + lp.cellHSpan)) { + return child; + } + } + return null; + } + /** * Estimate where the top left cell of the dragged item will land if it is dropped. * @@ -690,7 +704,7 @@ public class CellLayout extends ViewGroup { final int countX = getCountX(); final int countY = getCountY(); - pointToCellRounded(originX, originY, result); + pointToCellRounded(originX + (mCellWidth / 2), originY + (mCellHeight / 2), result); // If the item isn't fully on this screen, snap to the edges int rightOverhang = result[0] + spanX - countX; diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java index 3a6c63d8b..b11b1dde6 100644 --- a/src/com/android/launcher2/DeleteZone.java +++ b/src/com/android/launcher2/DeleteZone.java @@ -254,4 +254,10 @@ public class DeleteZone extends ImageView implements DropTarget, DragController. return false; } } + + @Override + public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset, + DragView dragView, Object dragInfo) { + return null; + } } diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java index b4f972bb2..f2fad9a08 100644 --- a/src/com/android/launcher2/DragController.java +++ b/src/com/android/launcher2/DragController.java @@ -394,6 +394,12 @@ public class DragController { // Drop on someone? final int[] coordinates = mCoordinatesTemp; DropTarget dropTarget = findDropTarget(screenX, screenY, coordinates); + DropTarget delegate = dropTarget.getDropTargetDelegate( + mDragSource, coordinates[0], coordinates[1], + (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); + if (delegate != null) { + dropTarget = delegate; + } if (dropTarget != null) { if (mLastDropTarget == dropTarget) { dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1], @@ -482,13 +488,25 @@ public class DragController { final ArrayList dropTargets = mDropTargets; final int count = dropTargets.size(); for (int i=count-1; i>=0; i--) { - final DropTarget target = dropTargets.get(i); + DropTarget target = dropTargets.get(i); target.getHitRect(r); + + // Convert the hit rect to screen coordinates target.getLocationOnScreen(dropCoordinates); r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop()); + if (r.contains(x, y)) { + DropTarget delegate = target.getDropTargetDelegate(mDragSource, + x, y, (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + if (delegate != null) { + target = delegate; + target.getLocationOnScreen(dropCoordinates); + } + + // Make dropCoordinates relative to the DropTarget dropCoordinates[0] = x - dropCoordinates[0]; dropCoordinates[1] = y - dropCoordinates[1]; + return target; } } diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java index 72eb33094..7e542312c 100644 --- a/src/com/android/launcher2/DropTarget.java +++ b/src/com/android/launcher2/DropTarget.java @@ -50,6 +50,26 @@ public interface DropTarget { void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); + /** + * Allows a DropTarget to delegate drag and drop events to another object. + * + * Most subclasses will should just return null from this method. + * + * @param source DragSource where the drag started + * @param x X coordinate of the drop location + * @param y Y coordinate of the drop location + * @param xOffset Horizontal offset with the object being dragged where the original + * touch happened + * @param yOffset Vertical offset with the object being dragged where the original + * touch happened + * @param dragView The DragView that's being dragged around on screen. + * @param dragInfo Data associated with the object being dragged + * + * @return The DropTarget to delegate to, or null to not delegate to another object. + */ + DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset, + DragView dragView, Object dragInfo); + /** * Check if a drop action can occur at, or near, the requested location. * This may be called repeatedly during a drag, so any calls should return diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java index 0013644ab..a09b6e045 100644 --- a/src/com/android/launcher2/FolderIcon.java +++ b/src/com/android/launcher2/FolderIcon.java @@ -102,4 +102,10 @@ public class FolderIcon extends BubbleTextView implements DropTarget { DragView dragView, Object dragInfo) { setCompoundDrawablesWithIntrinsicBounds(null, mCloseIcon, null, null); } + + @Override + public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset, + DragView dragView, Object dragInfo) { + return null; + } } diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java index 255099f3b..b46e92414 100644 --- a/src/com/android/launcher2/UserFolder.java +++ b/src/com/android/launcher2/UserFolder.java @@ -89,4 +89,10 @@ public class UserFolder extends Folder implements DropTarget { super.onOpen(); requestFocus(); } + + @Override + public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset, + DragView dragView, Object dragInfo) { + return null; + } } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 67b543e87..b4986add3 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -1219,11 +1219,45 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag clearVacantCache(); } - public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, + public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { + // We may need to delegate the drag to a child view. If a 1x1 item + // would land in a cell occupied by a DragTarget (e.g. a Folder), + // then drag events should be handled by that child. + ItemInfo item = (ItemInfo)dragInfo; + CellLayout currentLayout = getCurrentDropLayout(); + int dragPointX, dragPointY; + if (item.spanX == 1 && item.spanY == 1) { + // For a 1x1, calculate the drop cell exactly as in onDragOver + dragPointX = x - xOffset; + dragPointY = y - yOffset; + } else { + // Otherwise, use the exact drag coordinates + dragPointX = x; + dragPointY = y; + } + + // If we are dragging over a cell that contains a DropTarget that will + // accept the drop, delegate to that DropTarget. + final int[] cellXY = mTempCell; + currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY); + View child = currentLayout.getChildAt(cellXY[0], cellXY[1]); + if (child instanceof DropTarget) { + DropTarget target = (DropTarget)child; + if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) { + return target; + } + } + return null; + } + + public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, + DragView dragView, Object dragInfo) { + + ItemInfo item = (ItemInfo)dragInfo; CellLayout currentLayout = getCurrentDropLayout(); if (dragInfo instanceof LauncherAppWidgetInfo) { -- cgit v1.2.3