summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPatrick Dubroy <dubroy@google.com>2010-07-12 14:25:18 -0700
committerPatrick Dubroy <dubroy@google.com>2010-07-12 17:29:35 -0700
commit6569f2c80e179c2f8ed73dae6b01d971ec20f005 (patch)
tree7663e08de41929b01128176660fd1e5271ea5bb7 /src
parent4ab2f860e704b48a721b30095ebbdd353e3c00c4 (diff)
downloadandroid_packages_apps_Trebuchet-6569f2c80e179c2f8ed73dae6b01d971ec20f005.tar.gz
android_packages_apps_Trebuchet-6569f2c80e179c2f8ed73dae6b01d971ec20f005.tar.bz2
android_packages_apps_Trebuchet-6569f2c80e179c2f8ed73dae6b01d971ec20f005.zip
When dragging items on the home screen, visualize where they will drop.
Draw a rectangle around the area where an item will land if it is dropped. If the area is vacant, the rectangle is green; otherwise, it is red. Change-Id: I859b52514566fa55f8c7a04493b8088d12baa476
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/CellLayout.java196
-rw-r--r--src/com/android/launcher2/Launcher.java2
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetInfo.java28
-rw-r--r--src/com/android/launcher2/WidgetChooser.java7
-rw-r--r--src/com/android/launcher2/WidgetListAdapter.java2
-rw-r--r--src/com/android/launcher2/Workspace.java72
6 files changed, 249 insertions, 58 deletions
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 1d45565a0..9cc370f45 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -16,7 +16,7 @@
package com.android.launcher2;
-import java.util.ArrayList;
+import com.android.launcher.R;
import android.app.WallpaperManager;
import android.content.Context;
@@ -25,6 +25,7 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.view.MotionEvent;
@@ -34,7 +35,8 @@ import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.LayoutAnimationController;
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.Arrays;
public class CellLayout extends ViewGroup {
static final String TAG = "CellLayout";
@@ -63,10 +65,25 @@ public class CellLayout extends ViewGroup {
private final Rect mRect = new Rect();
private final CellInfo mCellInfo = new CellInfo();
- int[] mCellXY = new int[2];
+ // This is a temporary variable to prevent having to allocate a new object just to
+ // return an (x, y) value from helper functions. Do NOT use it to maintain other state.
+ private final int[] mTmpCellXY = new int[2];
+
boolean[][] mOccupied;
- private RectF mDragRect = new RectF();
+ private final RectF mDragRect = new RectF();
+
+ // When dragging, used to indicate a vacant drop location
+ private Drawable mVacantDrawable;
+
+ // When dragging, used to indicate an occupied drop location
+ private Drawable mOccupiedDrawable;
+
+ // Updated to point to mVacantDrawable or mOccupiedDrawable, as appropriate
+ private Drawable mDragRectDrawable;
+
+ // When a drag operation is in progress, holds the nearest cell to the touch point
+ private final int[] mDragCell = new int[2];
private boolean mDirtyTag;
private boolean mLastDownOnOccupiedCell = false;
@@ -83,6 +100,13 @@ public class CellLayout extends ViewGroup {
public CellLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+
+ // 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.
+ setWillNotDraw(false);
+ mVacantDrawable = getResources().getDrawable(R.drawable.rounded_rect_green);
+ mOccupiedDrawable = getResources().getDrawable(R.drawable.rounded_rect_red);
+
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10);
@@ -113,6 +137,18 @@ public class CellLayout extends ViewGroup {
}
@Override
+ protected void onDraw(Canvas canvas) {
+ if (!mDragRect.isEmpty()) {
+ mDragRectDrawable.setBounds(
+ (int)mDragRect.left,
+ (int)mDragRect.top,
+ (int)mDragRect.right,
+ (int)mDragRect.bottom);
+ mDragRectDrawable.draw(canvas);
+ }
+ }
+
+ @Override
public void cancelLongPress() {
super.cancelLongPress();
@@ -199,7 +235,7 @@ public class CellLayout extends ViewGroup {
mLastDownOnOccupiedCell = found;
if (!found) {
- int cellXY[] = mCellXY;
+ final int cellXY[] = mTmpCellXY;
pointToCellExact(x, y, cellXY);
final boolean portrait = mPortrait;
@@ -207,7 +243,7 @@ public class CellLayout extends ViewGroup {
final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
final boolean[][] occupied = mOccupied;
- findOccupiedCells(xCount, yCount, occupied, null);
+ findOccupiedCells(xCount, yCount, occupied, null, true);
cellInfo.cell = null;
cellInfo.cellX = cellXY[0];
@@ -258,7 +294,7 @@ public class CellLayout extends ViewGroup {
final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
final boolean[][] occupied = mOccupied;
- findOccupiedCells(xCount, yCount, occupied, null);
+ findOccupiedCells(xCount, yCount, occupied, null, true);
findIntersectingVacantCells(info, info.cellX, info.cellY, xCount, yCount, occupied);
@@ -340,6 +376,9 @@ public class CellLayout extends ViewGroup {
cellInfo.vacantCells.add(cell);
}
+ /**
+ * Check if the column 'x' is empty from rows 'top' to 'bottom', inclusive.
+ */
private static boolean isColumnEmpty(int x, int top, int bottom, boolean[][] occupied) {
for (int y = top; y <= bottom; y++) {
if (occupied[x][y]) {
@@ -349,6 +388,9 @@ public class CellLayout extends ViewGroup {
return true;
}
+ /**
+ * Check if the row 'y' is empty from columns 'left' to 'right', inclusive.
+ */
private static boolean isRowEmpty(int y, int left, int right, boolean[][] occupied) {
for (int x = left; x <= right; x++) {
if (occupied[x][y]) {
@@ -372,7 +414,7 @@ public class CellLayout extends ViewGroup {
}
}
} else {
- findOccupiedCells(xCount, yCount, occupied, ignoreView);
+ findOccupiedCells(xCount, yCount, occupied, ignoreView, true);
}
CellInfo cellInfo = new CellInfo();
@@ -600,7 +642,7 @@ public class CellLayout extends ViewGroup {
if (lp.dropped) {
lp.dropped = false;
- final int[] cellXY = mCellXY;
+ final int[] cellXY = mTmpCellXY;
getLocationOnScreen(cellXY);
mWallpaperManager.sendWallpaperCommand(getWindowToken(), "android.home.drop",
cellXY[0] + childLeft + lp.width / 2,
@@ -626,6 +668,79 @@ public class CellLayout extends ViewGroup {
super.setChildrenDrawnWithCacheEnabled(enabled);
}
+ private boolean isVacant(int originX, int originY, int spanX, int spanY) {
+ for (int i = 0; i < spanY; i++) {
+ if (!isRowEmpty(originY + i, originX, originX + spanX - 1, mOccupied)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Estimate where the top left cell of the dragged item will land if it is dropped.
+ *
+ * @param originX The X value of the top left corner of the item
+ * @param originY The Y value of the top left corner of the item
+ * @param spanX The number of horizontal cells that the item spans
+ * @param spanY The number of vertical cells that the item spans
+ * @param result The estimated drop cell X and Y.
+ */
+ void estimateDropCell(int originX, int originY, int spanX, int spanY, int[] result) {
+ final int countX = getCountX();
+ final int countY = getCountY();
+
+ pointToCellRounded(originX, originY, result);
+
+ // If the item isn't fully on this screen, snap to the edges
+ int rightOverhang = result[0] + spanX - countX;
+ if (rightOverhang > 0) {
+ result[0] -= rightOverhang; // Snap to right
+ }
+ result[0] = Math.max(0, result[0]); // Snap to left
+ int bottomOverhang = result[1] + spanY - countY;
+ if (bottomOverhang > 0) {
+ result[1] -= bottomOverhang; // Snap to bottom
+ }
+ result[1] = Math.max(0, result[1]); // Snap to top
+ }
+
+ void visualizeDropLocation(View view, int originX, int originY, int spanX, int spanY) {
+ final int[] originCell = mDragCell;
+ final int[] cellXY = mTmpCellXY;
+ estimateDropCell(originX, originY, spanX, spanY, cellXY);
+
+ // Only recalculate the bounding rect when necessary
+ if (!Arrays.equals(cellXY, originCell)) {
+ originCell[0] = cellXY[0];
+ originCell[1] = cellXY[1];
+
+ // Find the top left corner of the rect the object will occupy
+ final int[] topLeft = mTmpCellXY;
+ cellToPoint(originCell[0], originCell[1], topLeft);
+ final int left = topLeft[0];
+ final int top = topLeft[1];
+
+ // Now find the bottom right
+ final int[] bottomRight = mTmpCellXY;
+ cellToPoint(originCell[0] + spanX - 1, originCell[1] + spanY - 1, bottomRight);
+ bottomRight[0] += mCellWidth;
+ bottomRight[1] += mCellHeight;
+
+ final int countX = mPortrait ? mShortAxisCells : mLongAxisCells;
+ final int countY = mPortrait ? mLongAxisCells : mShortAxisCells;
+ // TODO: It's not necessary to do this every time, but it's not especially expensive
+ findOccupiedCells(countX, countY, mOccupied, view, false);
+
+ boolean vacant = isVacant(originCell[0], originCell[1], spanX, spanY);
+ mDragRectDrawable = vacant ? mVacantDrawable : mOccupiedDrawable;
+
+ // mDragRect will be rendered in onDraw()
+ mDragRect.set(left, top, bottomRight[0], bottomRight[1]);
+ invalidate();
+ }
+ }
+
/**
* Find a vacant area that will fit the given bounds nearest the requested
* cell location. Uses Euclidean distance to score multiple vacant areas.
@@ -644,7 +759,6 @@ public class CellLayout extends ViewGroup {
// Keep track of best-scoring drop area
final int[] bestXY = recycle != null ? recycle : new int[2];
- final int[] cellXY = mCellXY;
double bestDistance = Double.MAX_VALUE;
// Bail early if vacant cells aren't valid
@@ -662,7 +776,8 @@ public class CellLayout extends ViewGroup {
continue;
}
- // Score is center distance from requested pixel
+ // Score is distance from requested pixel to the top left of each cell
+ final int[] cellXY = mTmpCellXY;
cellToPoint(cell.cellX, cell.cellY, cellXY);
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
@@ -683,6 +798,18 @@ public class CellLayout extends ViewGroup {
}
/**
+ * Called when a drag and drop operation has finished (successfully or not).
+ */
+ void onDragComplete() {
+ // Invalidate the drag data
+ mDragCell[0] = -1;
+ mDragCell[1] = -1;
+
+ mDragRect.setEmpty();
+ invalidate();
+ }
+
+ /**
* Mark a child as having been dropped.
*
* @param child The child that is being dropped
@@ -694,16 +821,15 @@ public class CellLayout extends ViewGroup {
lp.dropped = true;
mDragRect.setEmpty();
child.requestLayout();
- invalidate();
}
+ onDragComplete();
}
void onDropAborted(View child) {
if (child != null) {
((LayoutParams) child.getLayoutParams()).isDragging = false;
- invalidate();
}
- mDragRect.setEmpty();
+ onDragComplete();
}
/**
@@ -718,30 +844,16 @@ public class CellLayout extends ViewGroup {
}
/**
- * Drag a child over the specified position
- *
- * @param child The child that is being dropped
- * @param cellX The child's new x cell location
- * @param cellY The child's new y cell location
- */
- void onDragOverChild(View child, int cellX, int cellY) {
- int[] cellXY = mCellXY;
- pointToCellRounded(cellX, cellY, cellXY);
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- cellToRect(cellXY[0], cellXY[1], lp.cellHSpan, lp.cellVSpan, mDragRect);
- invalidate();
- }
-
- /**
* Computes a bounding rectangle for a range of cells
*
* @param cellX X coordinate of upper left corner expressed as a cell position
* @param cellY Y coordinate of upper left corner expressed as a cell position
* @param cellHSpan Width in cells
* @param cellVSpan Height in cells
- * @param dragRect Rectnagle into which to put the results
+ * @param resultRect Rect into which to put the results
*/
- public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF dragRect) {
+ public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF resultRect) {
+ final boolean portrait = mPortrait;
final int cellWidth = mCellWidth;
final int cellHeight = mCellHeight;
final int widthGap = mWidthGap;
@@ -756,7 +868,7 @@ public class CellLayout extends ViewGroup {
int x = hStartPadding + cellX * (cellWidth + widthGap);
int y = vStartPadding + cellY * (cellHeight + heightGap);
- dragRect.set(x, y, x + width, y + height);
+ resultRect.set(x, y, x + width, y + height);
}
/**
@@ -796,7 +908,7 @@ public class CellLayout extends ViewGroup {
final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
final boolean[][] occupied = mOccupied;
- findOccupiedCells(xCount, yCount, occupied, null);
+ findOccupiedCells(xCount, yCount, occupied, null, true);
return findVacantCell(vacant, spanX, spanY, xCount, yCount, occupied);
}
@@ -825,13 +937,16 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
return false;
}
- boolean[] getOccupiedCells() {
+ /**
+ * Update the array of occupied cells (mOccupied), and return a flattened copy of the array.
+ */
+ boolean[] getOccupiedCellsFlattened() {
final boolean portrait = mPortrait;
final int xCount = portrait ? mShortAxisCells : mLongAxisCells;
final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
final boolean[][] occupied = mOccupied;
- findOccupiedCells(xCount, yCount, occupied, null);
+ findOccupiedCells(xCount, yCount, occupied, null, true);
final boolean[] flat = new boolean[xCount * yCount];
for (int y = 0; y < yCount; y++) {
@@ -843,7 +958,14 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
return flat;
}
- private void findOccupiedCells(int xCount, int yCount, boolean[][] occupied, View ignoreView) {
+ /**
+ * Update the array of occupied cells.
+ * @param ignoreView If non-null, the space occupied by this View is treated as vacant
+ * @param ignoreFolders If true, a cell occupied by a Folder is treated as vacant
+ */
+ private void findOccupiedCells(
+ int xCount, int yCount, boolean[][] occupied, View ignoreView, boolean ignoreFolders) {
+
for (int x = 0; x < xCount; x++) {
for (int y = 0; y < yCount; y++) {
occupied[x][y] = false;
@@ -853,7 +975,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
- if (child instanceof Folder || child.equals(ignoreView)) {
+ if ((ignoreFolders && child instanceof Folder) || child.equals(ignoreView)) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 03066c169..94556be55 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1088,7 +1088,7 @@ public final class Launcher extends Activity
outState.putInt(RUNTIME_STATE_PENDING_ADD_COUNT_X, layout.getCountX());
outState.putInt(RUNTIME_STATE_PENDING_ADD_COUNT_Y, layout.getCountY());
outState.putBooleanArray(RUNTIME_STATE_PENDING_ADD_OCCUPIED_CELLS,
- layout.getOccupiedCells());
+ layout.getOccupiedCellsFlattened());
}
if (mFolderInfo != null && mWaitingForResult) {
diff --git a/src/com/android/launcher2/LauncherAppWidgetInfo.java b/src/com/android/launcher2/LauncherAppWidgetInfo.java
index 3c81bac8e..32c92aabd 100644
--- a/src/com/android/launcher2/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher2/LauncherAppWidgetInfo.java
@@ -21,23 +21,46 @@ import android.content.ComponentName;
import android.content.ContentValues;
/**
- * Represents a widget, which just contains an identifier.
+ * Represents a widget (either instantiated or about to be) in the Launcher.
*/
class LauncherAppWidgetInfo extends ItemInfo {
/**
+ * Indicates that the widget hasn't been instantiated yet.
+ */
+ static final int NO_ID = -1;
+
+ /**
* Identifier for this widget when talking with
* {@link android.appwidget.AppWidgetManager} for updates.
*/
- int appWidgetId;
+ int appWidgetId = NO_ID;
+
ComponentName providerName;
+ // TODO: Are these necessary here?
+ int minWidth = -1;
+ int minHeight = -1;
+
/**
* View that holds this widget after it's been created. This view isn't created
* until Launcher knows it's needed.
*/
AppWidgetHostView hostView = null;
+ /**
+ * Constructor for use with AppWidgets that haven't been instantiated yet.
+ */
+ LauncherAppWidgetInfo(ComponentName providerName) {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+ this.providerName = providerName;
+
+ // Since the widget isn't instantiated yet, we don't know these values. Set them to -1
+ // to indicate that they should be calculated based on the layout and minWidth/minHeight
+ spanX = -1;
+ spanY = -1;
+ }
+
LauncherAppWidgetInfo(int appWidgetId) {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
this.appWidgetId = appWidgetId;
@@ -54,7 +77,6 @@ class LauncherAppWidgetInfo extends ItemInfo {
return "AppWidget(id=" + Integer.toString(appWidgetId) + ")";
}
-
@Override
void unbind() {
super.unbind();
diff --git a/src/com/android/launcher2/WidgetChooser.java b/src/com/android/launcher2/WidgetChooser.java
index 4718c6c22..101b671df 100644
--- a/src/com/android/launcher2/WidgetChooser.java
+++ b/src/com/android/launcher2/WidgetChooser.java
@@ -34,8 +34,11 @@ public class WidgetChooser extends HomeCustomizationItemGallery implements DragS
int screenX = mMotionDownRawX - (w / 2);
int screenY = mMotionDownRawY - h;
- LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(-1);
- dragInfo.providerName = info.provider;
+ AppWidgetProviderInfo appWidgetInfo = (AppWidgetProviderInfo)view.getTag();
+ LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(info.provider);
+ // TODO: Is this really the best place to do this?
+ dragInfo.minWidth = appWidgetInfo.minWidth;
+ dragInfo.minHeight = appWidgetInfo.minHeight;
mDragController.startDrag(bmp, screenX, screenY,
0, 0, w, h, this, dragInfo, DragController.DRAG_ACTION_COPY);
return true;
diff --git a/src/com/android/launcher2/WidgetListAdapter.java b/src/com/android/launcher2/WidgetListAdapter.java
index 5a569ea02..5d5d86a67 100644
--- a/src/com/android/launcher2/WidgetListAdapter.java
+++ b/src/com/android/launcher2/WidgetListAdapter.java
@@ -85,6 +85,8 @@ public class WidgetListAdapter extends BaseAdapter {
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
textView.setCompoundDrawables(null, image, null, null);
textView.setText(info.label);
+ // Store the widget info on the associated view so we can easily fetch it later
+ textView.setTag(info);
return textView;
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 57195ad8f..67b543e87 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -43,9 +44,9 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
import android.view.animation.Interpolator;
import android.view.animation.RotateAnimation;
-import android.view.animation.Animation.AnimationListener;
import android.widget.Scroller;
import android.widget.TextView;
import android.widget.Toast;
@@ -90,6 +91,11 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
*/
private int[] mTargetCell = null;
+ /**
+ * The CellLayout that is currently being dragged over
+ */
+ private CellLayout mDragTargetLayout = null;
+
private float mLastMotionX;
private float mLastMotionY;
@@ -136,6 +142,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private static final float BASELINE_FLING_VELOCITY = 2500.f;
private static final float FLING_VELOCITY_INFLUENCE = 0.4f;
+ private Paint mDropIndicatorPaint;
+
private static class WorkspaceOvershootInterpolator implements Interpolator {
private static final float DEFAULT_TENSION = 1.3f;
private float mTension;
@@ -480,13 +488,12 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
lp.cellVSpan = spanY;
}
- // get the canonical child id to uniquely represent this view in this
- // screen
+ // Get the canonical child id to uniquely represent this view in this screen
int childId = LauncherModel.getCanonicalCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY);
if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
// TODO: This branch occurs when the workspace is adding views
// outside of the defined grid
- // maybe we should be deleting these items from the LauncherMode?
+ // maybe we should be deleting these items from the LauncherModel?
Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
}
@@ -1212,13 +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, DragView dragView, Object dragInfo) {
+ 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) {
+ LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
+
+ if (widgetInfo.spanX == -1) {
+ // Calculate the grid spans needed to fit this widget
+ int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight);
+ item.spanX = spans[0];
+ item.spanY = spans[1];
+ }
+ }
+ if (currentLayout != mDragTargetLayout) {
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.onDragComplete();
+ }
+ mDragTargetLayout = currentLayout;
+ }
+
+ // Find the top left corner of the item
+ int originX = x - xOffset;
+ int originY = y - yOffset;
+
+ final View child = (mDragInfo == null) ? null : mDragInfo.cell;
+ currentLayout.visualizeDropLocation(child, originX, originY, item.spanX, item.spanY);
}
public void onDragExit(DragSource source, int x, int y, int xOffset,
int yOffset, DragView dragView, Object dragInfo) {
clearVacantCache();
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.onDragComplete();
+ mDragTargetLayout = null;
+ }
}
private void onDropExternal(int x, int y, Object dragInfo,
@@ -1257,16 +1296,15 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
+ info.itemType);
}
- // addAppWidgetFromDrop already took care of attaching the widget view to the appropriate cell
- // TODO why aren't we calling addInScreen here?
- if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
- mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout,
- mTargetCell);
+ // If the view is null, it has already been added.
+ if (view == null) {
+ cellLayout.onDragComplete();
+ } else {
+ mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view
- .getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen,
@@ -1344,14 +1382,18 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
*/
private int[] estimateDropCell(int pixelX, int pixelY,
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
+
+ final int[] cellXY = mTempCell;
+ layout.estimateDropCell(pixelX, pixelY, spanX, spanY, cellXY);
+ layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
+
// Create vacant cell cache if none exists
if (mVacantCache == null) {
mVacantCache = layout.findAllVacantCells(null, ignoreView);
}
// Find the best target drop location
- return layout.findNearestVacantArea(pixelX, pixelY,
- spanX, spanY, mVacantCache, recycle);
+ return layout.findNearestVacantArea(mTempEstimate[0], mTempEstimate[1], spanX, spanY, mVacantCache, recycle);
}
void setLauncher(Launcher launcher) {