Fixing widget resize visual / ux ugliness, Bug: 4082591

Change-Id: Ib258e02f52dd83418db0c0249efdc90d2424f059
diff --git a/proguard.flags b/proguard.flags
index 19c8fd5..94dd260 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -20,7 +20,7 @@
   public void setHoverAlpha(float);
 }
 
--keep class com.android.launcher2.CellLayout$LayoutParams {
+-keep class com.android.launcher2.DragLayer$LayoutParams {
   public void setWidth(int);
   public int getWidth();
   public void setHeight(int);
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 2b2662f..d975ed9 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -18,6 +18,8 @@
     private ItemInfo mItemInfo;
     private LauncherAppWidgetHostView mWidgetView;
     private CellLayout mCellLayout;
+    private DragLayer mDragLayer;
+    private Workspace mWorkspace;
     private ImageView mLeftHandle;
     private ImageView mRightHandle;
     private ImageView mTopHandle;
@@ -57,7 +59,7 @@
     public static final int BOTTOM = 3;
 
     public AppWidgetResizeFrame(Context context, ItemInfo itemInfo, 
-            LauncherAppWidgetHostView widgetView, CellLayout cellLayout) {
+            LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
 
         super(context);
         mContext = context;
@@ -65,6 +67,8 @@
         mCellLayout = cellLayout;
         mWidgetView = widgetView;
         mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+        mDragLayer = dragLayer;
+        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
 
         final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
         int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
@@ -150,7 +154,7 @@
             mDeltaX = Math.max(-mBaselineX, deltaX); 
             mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
         } else if (mRightBorderActive) {
-            mDeltaX = Math.min(mCellLayout.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
+            mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
             mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
         }
 
@@ -158,7 +162,7 @@
             mDeltaY = Math.max(-mBaselineY, deltaY);
             mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
         } else if (mBottomBorderActive) {
-            mDeltaY = Math.min(mCellLayout.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
+            mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
             mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
         }
     }
@@ -168,7 +172,8 @@
      */
     public void visualizeResizeForDelta(int deltaX, int deltaY) {
         updateDeltas(deltaX, deltaY);
-        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
         if (mLeftBorderActive) {
             lp.x = mBaselineX + mDeltaX;
             lp.width = mBaselineWidth - mDeltaX;
@@ -261,6 +266,7 @@
 
         // Update the cells occupied by this widget
         mCellLayout.markCellsAsOccupiedForView(mWidgetView);
+        mWidgetView.requestLayout();
     }
 
     /**
@@ -284,20 +290,22 @@
     }
 
     public void snapToWidget(boolean animate) {
-        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+        final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        int xOffset = mCellLayout.getLeft() - mWorkspace.getScrollX();
+        int yOffset = mCellLayout.getTop() - mWorkspace.getScrollY();
 
         int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding;
         int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding;
-        int newX = mWidgetView.getLeft() - mBackgroundPadding;
-        int newY = mWidgetView.getTop() - mBackgroundPadding;
+        int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset;
+        int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset;
 
         // We need to make sure the frame stays within the bounds of the CellLayout
         if (newY < 0) {
             newHeight -= -newY;
             newY = 0;
         }
-        if (newY + newHeight > mCellLayout.getHeight()) {
-            newHeight -= newY + newHeight - mCellLayout.getHeight();
+        if (newY + newHeight > mDragLayer.getHeight()) {
+            newHeight -= newY + newHeight - mDragLayer.getHeight();
         }
 
         if (!animate) {
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index c1c12b5..fa9b6d6 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1551,38 +1551,6 @@
             }
         }
 
-        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;
-        }
-
-        public void setX(int x) {
-            this.x = x;
-        }
-
-        public int getX() {
-            return x;
-        }
-
-        public void setY(int y) {
-            this.y = y;
-        }
-
-        public int getY() {
-            return y;
-        }
-
         public String toString() {
             return "(" + this.cellX + ", " + this.cellY + ")";
         }
diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java
index 04996f3..11b2f9e 100644
--- a/src/com/android/launcher2/CellLayoutChildren.java
+++ b/src/com/android/launcher2/CellLayoutChildren.java
@@ -43,12 +43,6 @@
     private int mWidthGap;
     private int mHeightGap;
 
-    // Variables relating to resizing widgets
-    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
-            new ArrayList<AppWidgetResizeFrame>();
-    private AppWidgetResizeFrame mCurrentResizeFrame;
-    private int mXDown, mYDown;
-
     public CellLayoutChildren(Context context) {
         super(context);
         mWallpaperManager = WallpaperManager.getInstance(context);
@@ -176,95 +170,4 @@
     protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
         super.setChildrenDrawnWithCacheEnabled(enabled);
     }
-
-    public void clearAllResizeFrames() {
-        for (AppWidgetResizeFrame frame: mResizeFrames) {
-            removeView(frame);
-        }
-        mResizeFrames.clear();
-    }
-
-    public boolean hasResizeFrames() {
-        return mResizeFrames.size() > 0;
-    }
-
-    public boolean isWidgetBeingResized() {
-        return mCurrentResizeFrame != null;
-    }
-
-    private boolean handleTouchDown(MotionEvent ev) {
-        Rect hitRect = new Rect();
-
-        int x = (int) ev.getX();
-        int y = (int) ev.getY();
-
-        for (AppWidgetResizeFrame child: mResizeFrames) {
-            child.getHitRect(hitRect);
-            if (hitRect.contains(x, y)) {
-                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
-                    mCurrentResizeFrame = child;
-                    mXDown = x;
-                    mYDown = y;
-                    requestDisallowInterceptTouchEvent(true);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            if (handleTouchDown(ev)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        boolean handled = false;
-        int action = ev.getAction();
-
-        int x = (int) ev.getX();
-        int y = (int) ev.getY();
-
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-                if (handleTouchDown(ev)) {
-                    return true;
-                }
-            }
-        }
-
-        if (mCurrentResizeFrame != null) {
-            handled = true;
-            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);
-                    mCurrentResizeFrame = null;
-            }
-        }
-        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 eb53945..c2b710e 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -16,10 +16,11 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -27,6 +28,8 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import com.android.launcher.R;
+
 /**
  * A ViewGroup that coordinates dragging across its descendants
  */
@@ -34,6 +37,12 @@
     private DragController mDragController;
     private int[] mTmpXY = new int[2];
 
+    // Variables relating to resizing widgets
+    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
+            new ArrayList<AppWidgetResizeFrame>();
+    private AppWidgetResizeFrame mCurrentResizeFrame;
+    private int mXDown, mYDown;
+
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -56,31 +65,66 @@
         return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
     }
 
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        // If the current CellLayoutChildren has a resize frame, we need to detect if any touch
-        // event has occurred which doesn't result in resizing a widget. In this case, we
-        // dismiss any visible resize frames.
-        final Workspace w = (Workspace) findViewById(R.id.workspace);
-        if (w != null) {
-            final CellLayout currentPage = (CellLayout) w.getChildAt(w.getCurrentPage());
-            final CellLayoutChildren childrenLayout = currentPage.getChildrenLayout();
+    private boolean handleTouchDown(MotionEvent ev) {
+        Rect hitRect = new Rect();
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
 
-            if (childrenLayout.hasResizeFrames() && !childrenLayout.isWidgetBeingResized()) {
-                post(new Runnable() {
-                    public void run() {
-                        if (!childrenLayout.isWidgetBeingResized()) {
-                            childrenLayout.clearAllResizeFrames();
-                        }
-                    }
-                });
+        for (AppWidgetResizeFrame child: mResizeFrames) {
+            child.getHitRect(hitRect);
+            if (hitRect.contains(x, y)) {
+                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
+                    mCurrentResizeFrame = child;
+                    mXDown = x;
+                    mYDown = y;
+                    requestDisallowInterceptTouchEvent(true);
+                    return true;
+                }
             }
         }
+        return false;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (handleTouchDown(ev)) {
+                return true;
+            }
+        }
+        clearAllResizeFrames();
         return mDragController.onInterceptTouchEvent(ev);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
+        boolean handled = false;
+        int action = ev.getAction();
+
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                if (handleTouchDown(ev)) {
+                    return true;
+                }
+            }
+        }
+
+        if (mCurrentResizeFrame != null) {
+            handled = true;
+            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);
+                    mCurrentResizeFrame = null;
+            }
+        }
+        if (handled) return true;
         return mDragController.onTouchEvent(ev);
     }
 
@@ -103,4 +147,94 @@
         v.getLocationOnScreen(mTmpXY);
         return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
     }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        public int x, y;
+        public boolean customPosition = false;
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        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;
+        }
+
+        public void setX(int x) {
+            this.x = x;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public void setY(int y) {
+            this.y = y;
+        }
+
+        public int getY() {
+            return y;
+        }
+    }
+
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+            if (flp instanceof LayoutParams) {
+                final LayoutParams lp = (LayoutParams) flp;
+                if (lp.customPosition) {
+                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
+                }
+            }
+        }
+    }
+
+    public void clearAllResizeFrames() {
+        if (mResizeFrames.size() > 0) {
+            for (AppWidgetResizeFrame frame: mResizeFrames) {
+                removeView(frame);
+            }
+            mResizeFrames.clear();
+        }
+    }
+
+    public boolean hasResizeFrames() {
+        return mResizeFrames.size() > 0;
+    }
+
+    public boolean isWidgetBeingResized() {
+        return mCurrentResizeFrame != null;
+    }
+
+    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
+            CellLayout cellLayout) {
+        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
+                itemInfo, widget, cellLayout, this);
+
+        LayoutParams lp = new LayoutParams(-1, -1);
+        lp.customPosition = true;
+
+        addView(resizeFrame, lp);
+        mResizeFrames.add(resizeFrame);
+
+        resizeFrame.snapToWidget(false);
+    }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index e7865d2..b5c1074 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -1800,8 +1800,8 @@
     }
 
     public void exitWidgetResizeMode() {
-        final CellLayout currentLayout = (CellLayout) getChildAt(getCurrentPage());
-        currentLayout.getChildrenLayout().clearAllResizeFrames();
+        DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        dragLayer.clearAllResizeFrames();
     }
 
     void unshrink(boolean animated) {
@@ -2353,7 +2353,6 @@
                             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
@@ -2363,7 +2362,9 @@
                         if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
                             post(new Runnable() {
                                 public void run() {
-                                    children.addResizeFrame(info, hostView, 
+                                    DragLayer dragLayer = (DragLayer)
+                                            mLauncher.findViewById(R.id.drag_layer);
+                                    dragLayer.addResizeFrame(info, hostView,
                                             cellLayout);
                                 }
                             });