From d4844c3e731b00547a31f23a00f8bd4a271e2b62 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Fri, 18 Feb 2011 19:25:06 -0800 Subject: Implementing resizable widgets in launcher Change-Id: I18598493dcf34fc6089fa330a4b66803f658b773 --- .../android/launcher2/AppWidgetResizeFrame.java | 298 +++++++++++++++++++++ src/com/android/launcher2/CellLayout.java | 120 ++++++++- src/com/android/launcher2/CellLayoutChildren.java | 110 +++++++- src/com/android/launcher2/DragLayer.java | 13 + .../launcher2/LauncherAppWidgetHostView.java | 6 +- src/com/android/launcher2/LauncherModel.java | 27 ++ src/com/android/launcher2/Workspace.java | 20 +- 7 files changed, 573 insertions(+), 21 deletions(-) create mode 100644 src/com/android/launcher2/AppWidgetResizeFrame.java (limited to 'src/com') diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java new file mode 100644 index 000000000..6ddb5b8c3 --- /dev/null +++ b/src/com/android/launcher2/AppWidgetResizeFrame.java @@ -0,0 +1,298 @@ +package com.android.launcher2; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.appwidget.AppWidgetProviderInfo; +import android.content.Context; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.android.launcher.R; + +public class AppWidgetResizeFrame extends FrameLayout { + + private ItemInfo mItemInfo; + private LauncherAppWidgetHostView mWidgetView; + private CellLayout mCellLayout; + private ImageView mLeftHandle; + private ImageView mRightHandle; + private ImageView mTopHandle; + private ImageView mBottomHandle; + + private boolean mLeftBorderActive; + private boolean mRightBorderActive; + private boolean mTopBorderActive; + private boolean mBottomBorderActive; + + private int mBaselineWidth; + private int mBaselineHeight; + private int mBaselineX; + private int mBaselineY; + private int mResizeMode; + + private int mRunningHInc; + private int mRunningVInc; + private int mMinHSpan; + private int mMinVSpan; + private int mDeltaX; + private int mDeltaY; + + private int mExpandability[] = new int[4]; + + final int BORDER_WIDTH = 50; + final int FRAME_MARGIN = 15; + final int SNAP_DURATION = 150; + + public AppWidgetResizeFrame(Context context, ItemInfo itemInfo, + LauncherAppWidgetHostView widgetView, CellLayout cellLayout) { + + super(context); + mContext = context; + mItemInfo = itemInfo; + mCellLayout = cellLayout; + mWidgetView = widgetView; + mResizeMode = widgetView.getAppWidgetInfo().resizableMode; + + final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo(); + int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null); + mMinHSpan = result[0]; + mMinVSpan = result[1]; + + setBackgroundResource(R.drawable.resize_frame); + setPadding(0, 0, 0, 0); + + LayoutParams lp; + mLeftHandle = new ImageView(context); + mLeftHandle.setImageResource(R.drawable.h_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + Gravity.LEFT | Gravity.CENTER_VERTICAL); + addView(mLeftHandle, lp); + + mRightHandle = new ImageView(context); + mRightHandle.setImageResource(R.drawable.h_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + Gravity.RIGHT | Gravity.CENTER_VERTICAL); + addView(mRightHandle, lp); + + mTopHandle = new ImageView(context); + mTopHandle.setImageResource(R.drawable.v_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + Gravity.CENTER_HORIZONTAL | Gravity.TOP); + addView(mTopHandle, lp); + + mBottomHandle = new ImageView(context); + mBottomHandle.setImageResource(R.drawable.v_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + addView(mBottomHandle, lp); + + if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) { + mTopHandle.setVisibility(GONE); + mBottomHandle.setVisibility(GONE); + } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) { + mLeftHandle.setVisibility(GONE); + mRightHandle.setVisibility(GONE); + } + } + + public boolean beginResizeIfPointInRegion(int x, int y) { + boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0; + boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0; + mLeftBorderActive = (x < BORDER_WIDTH) && horizontalActive; + mRightBorderActive = (x > getWidth() - BORDER_WIDTH) && horizontalActive; + mTopBorderActive = (y < BORDER_WIDTH) && verticalActive; + mBottomBorderActive = (y > getHeight() - BORDER_WIDTH) && verticalActive; + + boolean anyBordersActive = mLeftBorderActive || mRightBorderActive + || mTopBorderActive || mBottomBorderActive; + + mBaselineWidth = getMeasuredWidth(); + mBaselineHeight = getMeasuredHeight(); + mBaselineX = getLeft(); + mBaselineY = getTop(); + mRunningHInc = 0; + mRunningVInc = 0; + + if (anyBordersActive) { + mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : 0.5f); + mRightHandle.setAlpha(mRightBorderActive ? 1.0f : 0.5f); + mTopHandle.setAlpha(mTopBorderActive ? 1.0f : 0.5f); + mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : 0.5f); + } + mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability); + return anyBordersActive; + } + + public void updateDeltas(int deltaX, int deltaY) { + if (mLeftBorderActive) { + mDeltaX = Math.max(-mBaselineX, deltaX); + mDeltaX = Math.min(mBaselineWidth - 2*BORDER_WIDTH, mDeltaX); + } else if (mRightBorderActive) { + mDeltaX = Math.min(mCellLayout.getWidth() - (mBaselineX + mBaselineWidth), deltaX); + mDeltaX = Math.max(-mBaselineWidth + 2*BORDER_WIDTH, mDeltaX); + } + + if (mTopBorderActive) { + mDeltaY = Math.max(-mBaselineY, deltaY); + mDeltaY = Math.min(mBaselineHeight - 2*BORDER_WIDTH, mDeltaY); + } else if (mBottomBorderActive) { + mDeltaY = Math.min(mCellLayout.getHeight() - (mBaselineY + mBaselineHeight), deltaY); + mDeltaY = Math.max(-mBaselineHeight + 2*BORDER_WIDTH, mDeltaY); + } + } + + public void visualizeResizeForDelta(int deltaX, int deltaY) { + updateDeltas(deltaX, deltaY); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + if (mLeftBorderActive) { + lp.x = mBaselineX + mDeltaX; + lp.width = mBaselineWidth - mDeltaX; + } else if (mRightBorderActive) { + lp.width = mBaselineWidth + mDeltaX; + } + + if (mTopBorderActive) { + lp.y = mBaselineY + mDeltaY; + lp.height = mBaselineHeight - mDeltaY; + } else if (mBottomBorderActive) { + lp.height = mBaselineHeight + mDeltaY; + } + + resizeWidgetIfNeeded(); + requestLayout(); + } + + private void resizeWidgetIfNeeded() { + // TODO: these computations probably aren't quite right... think about them + + //System.out.println("runningIncX before: " + mRunningHInc); + //System.out.println("runningIncY before: " + mRunningVInc); + + int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap(); + int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap(); + + int hSpanInc = (int) Math.round(1.0f * mDeltaX / xThreshold) - mRunningHInc; + int vSpanInc = (int) Math.round(1.0f * mDeltaY / yThreshold) - mRunningVInc; + int cellXInc = 0; + int cellYInc = 0; + + if (hSpanInc == 0 && vSpanInc == 0) return; + + // Before we change the widget, we clear the occupied cells associated with it. + // The new set of occupied cells is marked below, once the layout params are updated. + mCellLayout.markCellsAsUnoccupiedForView(mWidgetView); + + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams(); + if (mLeftBorderActive) { + cellXInc = Math.max(-mExpandability[0], hSpanInc); + cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc); + hSpanInc *= -1; + hSpanInc = Math.min(mExpandability[0], hSpanInc); + hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); + mRunningHInc -= hSpanInc; + } else if (mRightBorderActive) { + hSpanInc = Math.min(mExpandability[2], hSpanInc); + hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); + mRunningHInc += hSpanInc; + } + + if (mTopBorderActive) { + cellYInc = Math.max(-mExpandability[1], vSpanInc); + cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc); + vSpanInc *= -1; + vSpanInc = Math.min(mExpandability[1], vSpanInc); + vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); + mRunningVInc -= vSpanInc; + } else if (mBottomBorderActive) { + vSpanInc = Math.min(mExpandability[3], vSpanInc); + vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); + mRunningVInc += vSpanInc; + } + + // Update the widget's dimensions and position according to the deltas computed above + if (mLeftBorderActive || mRightBorderActive) { + lp.cellHSpan += hSpanInc; + lp.cellX += cellXInc; + } + + if (mTopBorderActive || mBottomBorderActive) { + lp.cellVSpan += vSpanInc; + lp.cellY += cellYInc; + } + + try { + mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability); + } catch (Exception e) { + System.out.println("Problem!"); + } + + // Update the cells occupied by this widget + mCellLayout.markCellsAsOccupiedForView(mWidgetView); + } + + public void commitResizeForDelta(int deltaX, int deltaY) { + visualizeResizeForDelta(deltaX, deltaY); + + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams(); + LauncherModel.resizeItemInDatabase(getContext(), mItemInfo, lp.cellX, lp.cellY, + lp.cellHSpan, lp.cellVSpan); + mWidgetView.requestLayout(); + + // Once our widget resizes (hence the post), we want to snap the resize frame to it + post(new Runnable() { + public void run() { + snapToWidget(true); + } + }); + } + + public void snapToWidget(boolean animate) { + final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + + final int newWidth = mWidgetView.getWidth() + 2 * FRAME_MARGIN; + final int newHeight = mWidgetView.getHeight() + 2 * FRAME_MARGIN; + final int newX = mWidgetView.getLeft() - FRAME_MARGIN; + final int newY = mWidgetView.getTop() - FRAME_MARGIN; + if (!animate) { + lp.width = newWidth; + lp.height = newHeight; + lp.x = newX; + lp.y = newY; + mLeftHandle.setAlpha(1.0f); + mRightHandle.setAlpha(1.0f); + mTopHandle.setAlpha(1.0f); + mBottomHandle.setAlpha(1.0f); + requestLayout(); + } else { + PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth); + PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height, newHeight); + PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX); + PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY); + ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y); + ObjectAnimator leftOa = ObjectAnimator.ofFloat(mLeftHandle, "alpha", 1.0f); + ObjectAnimator rightOa = ObjectAnimator.ofFloat(mRightHandle, "alpha", 1.0f); + ObjectAnimator topOa = ObjectAnimator.ofFloat(mTopHandle, "alpha", 1.0f); + ObjectAnimator bottomOa = ObjectAnimator.ofFloat(mBottomHandle, "alpha", 1.0f); + oa.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + requestLayout(); + } + }); + AnimatorSet set = new AnimatorSet(); + if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) { + set.playTogether(oa, topOa, bottomOa); + } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) { + set.playTogether(oa, leftOa, rightOa); + } else { + set.playTogether(oa, leftOa, rightOa, topOa, bottomOa); + } + + set.setDuration(SNAP_DURATION); + set.start(); + } + } +} diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 6691e6447..a2a539e6b 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -587,11 +587,11 @@ public class CellLayout extends ViewGroup { boolean found = false; for (int i = count - 1; i >= 0; i--) { final View child = mChildren.getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) { + if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) && lp.isLockedToGrid) { child.getHitRect(frame); if (frame.contains(x, y)) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); cellInfo.cell = child; cellInfo.cellX = lp.cellX; cellInfo.cellY = lp.cellY; @@ -703,6 +703,14 @@ public class CellLayout extends ViewGroup { return mCellHeight; } + int getWidthGap() { + return mWidthGap; + } + + int getHeightGap() { + return mHeightGap; + } + int getLeftPadding() { return mLeftPadding; } @@ -1332,19 +1340,68 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { } } + public void getExpandabilityArrayForView(View view, int[] expandability) { + final LayoutParams lp = (LayoutParams) view.getLayoutParams(); + boolean flag; + + // Left + expandability[0] = 0; + for (int x = lp.cellX - 1; x >= 0; x--) { + flag = false; + for (int y = lp.cellY; y < lp.cellY + lp.cellVSpan; y++) { + if (mOccupied[x][y]) flag = true; + } + if (flag) break; + expandability[0]++; + } + + // Top + expandability[1] = 0; + for (int y = lp.cellY - 1; y >= 0; y--) { + flag = false; + for (int x = lp.cellX; x < lp.cellX + lp.cellHSpan; x++) { + if (mOccupied[x][y]) flag = true; + } + if (flag) break; + expandability[1]++; + } + + // Right + expandability[2] = 0; + for (int x = lp.cellX + lp.cellHSpan; x < mCountX; x++) { + flag = false; + for (int y = lp.cellY; y < lp.cellY + lp.cellVSpan; y++) { + if (mOccupied[x][y]) flag = true; + } + if (flag) break; + expandability[2]++; + } + + // Bottom + expandability[3] = 0; + for (int y = lp.cellY + lp.cellVSpan; y < mCountY; y++) { + flag = false; + for (int x = lp.cellX; x < lp.cellX + lp.cellHSpan; x++) { + if (mOccupied[x][y]) flag = true; + } + if (flag) break; + expandability[3]++; + } + } + public void onMove(View view, int newCellX, int newCellY) { LayoutParams lp = (LayoutParams) view.getLayoutParams(); markCellsAsUnoccupiedForView(view); markCellsForView(newCellX, newCellY, lp.cellHSpan, lp.cellVSpan, true); } - private void markCellsAsOccupiedForView(View view) { + public void markCellsAsOccupiedForView(View view) { if (view == null || view.getParent() != mChildren) return; LayoutParams lp = (LayoutParams) view.getLayoutParams(); markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true); } - private void markCellsAsUnoccupiedForView(View view) { + public void markCellsAsUnoccupiedForView(View view) { if (view == null || view.getParent() != mChildren) return; LayoutParams lp = (LayoutParams) view.getLayoutParams(); markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false); @@ -1409,6 +1466,8 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { @ViewDebug.ExportedProperty public int cellVSpan; + public boolean isLockedToGrid = true; + /** * Is this item currently being dragged */ @@ -1467,19 +1526,52 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap, int hStartPadding, int vStartPadding) { + if (isLockedToGrid) { + final int myCellHSpan = cellHSpan; + final int myCellVSpan = cellVSpan; + final int myCellX = cellX; + final int myCellY = cellY; + + width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) - + leftMargin - rightMargin; + height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) - + topMargin - bottomMargin; + + x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin; + y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin; + } + } + + public void setWidth(int width) { + this.width = width; + } + + public int getWidth() { + return width; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return height; + } - final int myCellHSpan = cellHSpan; - final int myCellVSpan = cellVSpan; - final int myCellX = cellX; - final int myCellY = cellY; + public void setX(int x) { + this.x = x; + } - width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) - - leftMargin - rightMargin; - height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) - - topMargin - bottomMargin; + public int getX() { + return x; + } + + public void setY(int y) { + this.y = y; + } - x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin; - y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin; + public int getY() { + return y; } public String toString() { diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java index 0d0a33907..2a08fe382 100644 --- a/src/com/android/launcher2/CellLayoutChildren.java +++ b/src/com/android/launcher2/CellLayoutChildren.java @@ -16,12 +16,14 @@ package com.android.launcher2; +import java.util.ArrayList; + import android.app.WallpaperManager; import android.content.Context; import android.graphics.Rect; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.View.MeasureSpec; public class CellLayoutChildren extends ViewGroup { static final String TAG = "CellLayoutChildren"; @@ -32,12 +34,12 @@ public class CellLayoutChildren extends ViewGroup { private final WallpaperManager mWallpaperManager; - private int mCellWidth; - private int mCellHeight; - private int mLeftPadding; private int mTopPadding; + private int mCellWidth; + private int mCellHeight; + private int mWidthGap; private int mHeightGap; @@ -171,4 +173,102 @@ public class CellLayoutChildren extends ViewGroup { protected void setChildrenDrawnWithCacheEnabled(boolean enabled) { super.setChildrenDrawnWithCacheEnabled(enabled); } -} \ No newline at end of file + + private final ArrayList mResizeFrames = new ArrayList(); + private AppWidgetResizeFrame mCurrentResizeFrame; + private int mXDown, mYDown; + private boolean mIsWidgetBeingResized; + + public void clearAllResizeFrames() { + for (AppWidgetResizeFrame frame: mResizeFrames) { + removeView(frame); + } + mResizeFrames.clear(); + } + + public boolean isWidgetBeingResized() { + return mIsWidgetBeingResized; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + Rect hitRect = new Rect(); + + int x = (int) ev.getX(); + int y = (int) ev.getY(); + + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + for (AppWidgetResizeFrame child: mResizeFrames) { + child.getHitRect(hitRect); + if (hitRect.contains(x, y)) { + if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) { + mCurrentResizeFrame = child; + mIsWidgetBeingResized = true; + mXDown = x; + mYDown = y; + requestDisallowInterceptTouchEvent(true); + return true; + } + } + } + mCurrentResizeFrame = null; + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + boolean handled = false; + Rect hitRect = new Rect(); + int action = ev.getAction(); + + int x = (int) ev.getX(); + int y = (int) ev.getY(); + + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + for (AppWidgetResizeFrame child: mResizeFrames) { + child.getHitRect(hitRect); + if (hitRect.contains(x, y)) { + if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) { + mCurrentResizeFrame = child; + mIsWidgetBeingResized = true; + mXDown = x; + mYDown = y; + requestDisallowInterceptTouchEvent(true); + return true; + } + } + } + mCurrentResizeFrame = null; + } + + // TODO: Need to handle ACTION_POINTER_UP / multi-touch + if (mCurrentResizeFrame != null) { + switch (action) { + case MotionEvent.ACTION_MOVE: + mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown); + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown); + mIsWidgetBeingResized = false; + handled = true; + } + } + } + return handled; + } + + public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget, CellLayout cellLayout) { + AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(), + itemInfo, widget, cellLayout); + + CellLayout.LayoutParams lp = new CellLayout.LayoutParams(-1, -1, -1, -1); + lp.isLockedToGrid = false; + + addView(resizeFrame, lp); + mResizeFrames.add(resizeFrame); + + resizeFrame.snapToWidget(false); + } +} diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java index a9dd7e335..1912f81e5 100644 --- a/src/com/android/launcher2/DragLayer.java +++ b/src/com/android/launcher2/DragLayer.java @@ -16,6 +16,8 @@ package com.android.launcher2; +import com.android.launcher.R; + import android.content.Context; import android.graphics.Bitmap; import android.util.AttributeSet; @@ -56,6 +58,17 @@ public class DragLayer extends FrameLayout { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + // Here we need to detect if any touch event has occured which doesn't result + // in resizing a widget. In this case, we dismiss any visible resize frames. + post(new Runnable() { + public void run() { + Workspace w = (Workspace) findViewById(R.id.workspace); + CellLayout currentPage = (CellLayout) w.getChildAt(w.getCurrentPage()); + if (!currentPage.getChildrenLayout().isWidgetBeingResized()) { + currentPage.getChildrenLayout().clearAllResizeFrames(); + } + } + }); return mDragController.onInterceptTouchEvent(ev); } diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java index 85a80f943..7c5de850d 100644 --- a/src/com/android/launcher2/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java @@ -72,7 +72,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView // Otherwise continue letting touch events fall through to children return false; } - + class CheckForLongPress implements Runnable { private int mOriginalWindowAttachCount; @@ -122,4 +122,8 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView } super.onVisibilityChanged(changedView, visibility); } + + public int getResizableMode() { + return getAppWidgetInfo().resizableMode; + } } diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index 23641743f..12f57377e 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -176,6 +176,33 @@ public class LauncherModel extends BroadcastReceiver { }); } + /** + * Resize an item in the DB to a new + */ + static void resizeItemInDatabase(Context context, ItemInfo item, int cellX, int cellY, + int spanX, int spanY) { + item.spanX = spanX; + item.spanY = spanY; + item.cellX = cellX; + item.cellY = cellY; + + final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false); + final ContentValues values = new ContentValues(); + final ContentResolver cr = context.getContentResolver(); + + values.put(LauncherSettings.Favorites.CONTAINER, item.container); + values.put(LauncherSettings.Favorites.SPANX, spanX); + values.put(LauncherSettings.Favorites.SPANY, spanY); + values.put(LauncherSettings.Favorites.CELLX, cellX); + values.put(LauncherSettings.Favorites.CELLY, cellY); + + sWorker.post(new Runnable() { + public void run() { + cr.update(uri, values, null, null); + } + }); + } + /** * Returns true if the shortcuts already exists in the database. * we identify a shortcut by its title and intent. diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index e7735bec9..bd4b5020d 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -2271,6 +2271,24 @@ public class Workspace extends SmoothPagedView cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY)); + if (cell instanceof LauncherAppWidgetHostView) { + final CellLayoutChildren children = dropTargetLayout.getChildrenLayout(); + final CellLayout cellLayout = dropTargetLayout; + // We post this call so that the widget has a chance to be placed + // in its final location + + final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell; + AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo(); + if (pinfo.resizableMode != AppWidgetProviderInfo.RESIZE_NONE) { + post(new Runnable() { + public void run() { + children.addResizeFrame(info, hostView, + cellLayout); + } + }); + } + } + LauncherModel.moveItemInDatabase(mLauncher, info, LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, lp.cellX, lp.cellY); @@ -2309,7 +2327,7 @@ public class Workspace extends SmoothPagedView // 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; + ItemInfo item = (ItemInfo) dragInfo; CellLayout currentLayout = getCurrentDropLayout(); int dragPointX, dragPointY; -- cgit v1.2.3