When adding or moving a resizable widget, the widget may resize

-> If a widget is resizable, and there is not enough room to add it
   in its current (or default) size, but can be scaled down to fit
   a certain area, it will be resized to fit the available space
-> The resizing is animated using a crossfade and scale between
   the original dragView and the widget rendered in the final size

Change-Id: I75db9dcabecce11598b3ae55f20b96b2ec6b7e87
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 83ca675..d670463 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -584,9 +584,9 @@
                 }
             };
         }
-        mWorkspace.animateExternalDrop(mWidgetBeingConfigured, cellLayout,
+        mWorkspace.animateWidgetDrop(mWidgetBeingConfigured, cellLayout,
                 (DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
-                animationType);
+                animationType, mWidgetBeingConfigured.boundWidget, true);
         mWidgetBeingConfigured = null;
     }
 
@@ -959,7 +959,7 @@
         return getSpanForWidget(info.provider, info.minWidth, info.minHeight, spanXY);
     }
 
-    int[] getMinResizeSpanForWidget(AppWidgetProviderInfo info, int[] spanXY) {
+    int[] getMinSpanForWidget(AppWidgetProviderInfo info, int[] spanXY) {
         return getSpanForWidget(info.provider, info.minResizeWidth, info.minResizeHeight, spanXY);
     }
 
@@ -967,6 +967,11 @@
         return getSpanForWidget(info.componentName, info.minWidth, info.minHeight, spanXY);
     }
 
+    int[] getMinSpanForWidget(PendingAddWidgetInfo info, int[] spanXY) {
+        return getSpanForWidget(info.componentName, info.minResizeWidth,
+                info.minResizeHeight, spanXY);
+    }
+
     /**
      * Add a widget to the workspace.
      *
@@ -982,6 +987,7 @@
         // Calculate the grid spans needed to fit this widget
         CellLayout layout = getCellLayout(container, screen);
 
+        int[] minSpanXY = getMinSpanForWidget(appWidgetInfo, null);
         int[] spanXY = getSpanForWidget(appWidgetInfo, null);
 
         // Try finding open space on Launcher screen
@@ -989,18 +995,24 @@
         // if we are placing widgets on a "spring-loaded" screen
         int[] cellXY = mTmpAddItemCellCoordinates;
         int[] touchXY = mPendingAddInfo.dropPos;
+        int[] finalSpan = new int[2];
         boolean foundCellSpan = false;
         if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
             cellXY[0] = mPendingAddInfo.cellX;
             cellXY[1] = mPendingAddInfo.cellY;
+            spanXY[0] = mPendingAddInfo.spanX;
+            spanXY[1] = mPendingAddInfo.spanY;
             foundCellSpan = true;
         } else if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
             int[] result = layout.findNearestVacantArea(
-                    touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
+                    touchXY[0], touchXY[1], minSpanXY[0], minSpanXY[1], spanXY[0],
+                    spanXY[1], cellXY, finalSpan);
+            spanXY[0] = finalSpan[0];
+            spanXY[1] = finalSpan[1];
             foundCellSpan = (result != null);
         } else {
-            foundCellSpan = layout.findCellForSpan(cellXY, spanXY[0], spanXY[1]);
+            foundCellSpan = layout.findCellForSpan(cellXY, minSpanXY[0], minSpanXY[1]);
         }
 
         if (!foundCellSpan) {
@@ -1021,6 +1033,8 @@
         LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId);
         launcherInfo.spanX = spanXY[0];
         launcherInfo.spanY = spanXY[1];
+        launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
+        launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
 
         LauncherModel.addItemToDatabase(this, launcherInfo,
                 container, screen, cellXY[0], cellXY[1], false);
@@ -1036,6 +1050,7 @@
             }
 
             launcherInfo.hostView.setTag(launcherInfo);
+            launcherInfo.hostView.setVisibility(View.VISIBLE);
             mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
                     launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
 
@@ -1465,6 +1480,7 @@
         mPendingAddInfo.screen = -1;
         mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
         mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
+        mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = -1;
         mPendingAddInfo.dropPos = null;
     }
 
@@ -1556,15 +1572,22 @@
      * @param position The location on the screen where it was dropped, optional
      */
     void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, int screen,
-            int[] cell, int[] loc) {
+            int[] cell, int[] span, int[] loc) {
         resetAddInfo();
         mPendingAddInfo.container = info.container = container;
         mPendingAddInfo.screen = info.screen = screen;
         mPendingAddInfo.dropPos = loc;
+        mPendingAddInfo.minSpanX = info.minSpanX;
+        mPendingAddInfo.minSpanY = info.minSpanY;
+
         if (cell != null) {
             mPendingAddInfo.cellX = cell[0];
             mPendingAddInfo.cellY = cell[1];
         }
+        if (span != null) {
+            mPendingAddInfo.spanX = span[0];
+            mPendingAddInfo.spanY = span[1];
+        }
 
         AppWidgetHostView hostView = info.boundWidget;
         int appWidgetId;
@@ -1575,7 +1598,6 @@
             AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, info.componentName);
         }
         addAppWidgetImpl(appWidgetId, info);
-
     }
 
     void processShortcut(Intent intent) {