summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorAdam Cohen <adamcohen@google.com>2011-02-18 19:25:06 -0800
committerAdam Cohen <adamcohen@google.com>2011-02-25 13:56:06 -0800
commitd4844c3e731b00547a31f23a00f8bd4a271e2b62 (patch)
tree6efae34aca62c6f2ab8ded7fe832fc765155231a /src/com
parente552b8b19ccdfd724c6b5c5f4f265de00bc1ffac (diff)
downloadandroid_packages_apps_Trebuchet-d4844c3e731b00547a31f23a00f8bd4a271e2b62.tar.gz
android_packages_apps_Trebuchet-d4844c3e731b00547a31f23a00f8bd4a271e2b62.tar.bz2
android_packages_apps_Trebuchet-d4844c3e731b00547a31f23a00f8bd4a271e2b62.zip
Implementing resizable widgets in launcher
Change-Id: I18598493dcf34fc6089fa330a4b66803f658b773
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/launcher2/AppWidgetResizeFrame.java298
-rw-r--r--src/com/android/launcher2/CellLayout.java120
-rw-r--r--src/com/android/launcher2/CellLayoutChildren.java110
-rw-r--r--src/com/android/launcher2/DragLayer.java13
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetHostView.java6
-rw-r--r--src/com/android/launcher2/LauncherModel.java27
-rw-r--r--src/com/android/launcher2/Workspace.java20
7 files changed, 573 insertions, 21 deletions
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<AppWidgetResizeFrame> mResizeFrames = new ArrayList<AppWidgetResizeFrame>();
+ 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
@@ -177,6 +177,33 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
+ * Resize an item in the DB to a new <spanX, spanY>
+ */
+ 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;