Add drag and drop from AllAppsView (to the workspace).

Also had to fix AppInfoCache to load the icon as a drawable, which I had broken
when I made AllAppsView use the icons as power of two textures.
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index b9ec2cf..375fc12 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -61,10 +61,11 @@
 
 
 public class AllAppsView extends RSSurfaceView
-        implements View.OnClickListener, View.OnLongClickListener {
+        implements View.OnClickListener, View.OnLongClickListener, DragSource {
     private static final String TAG = "Launcher.AllAppsView";
 
     private Launcher mLauncher;
+    private DragController mDragController;
 
     private RenderScript mRS;
     private RolloRS mRollo;
@@ -76,6 +77,8 @@
     private VelocityTracker mVelocity;
     private int mLastScrollX;
     private int mLastMotionX;
+    private int mMotionDownRawX;
+    private int mMotionDownRawY;
     private TouchHandler mTouchHandler;
     private int mScrollHandleTop;
 
@@ -190,6 +193,8 @@
             int deltaX;
             switch (ev.getAction()) {
                 case MotionEvent.ACTION_DOWN:
+                    mMotionDownRawX = (int)ev.getRawX();
+                    mMotionDownRawY = (int)ev.getRawY();
                     mLastMotionX = x;
                     mRollo.mState.read();
                     mRollo.mState.startScrollX = mRollo.mState.scrollX = mLastScrollX
@@ -251,11 +256,32 @@
     }
 
     public boolean onLongClick(View v) {
-        Log.d(TAG, "long click! velocity=" + mRollo.mState.flingVelocityX + " index="
-                + mRollo.mState.selectedIconIndex);
+        int index = mRollo.mState.selectedIconIndex;
+        Log.d(TAG, "long click! velocity=" + mRollo.mState.flingVelocityX + " index=" + index);
+        if (mRollo.mState.flingVelocityX == 0 && index >= 0 && index < mAllAppsList.size()) {
+            ApplicationInfo app = mAllAppsList.get(index);
+
+            // We don't really have an accurate location to use.  This will do.
+            int screenX = mMotionDownRawX - (Defines.ICON_WIDTH_PX / 2);
+            int screenY = mMotionDownRawY - Defines.ICON_HEIGHT_PX;
+
+            int left = (Defines.ICON_TEXTURE_WIDTH_PX - Defines.ICON_WIDTH_PX) / 2;
+            int top = (Defines.ICON_TEXTURE_HEIGHT_PX - Defines.ICON_HEIGHT_PX) / 2;
+            mDragController.startDrag(app.iconBitmap, screenX, screenY,
+                    left, top, Defines.ICON_WIDTH_PX, Defines.ICON_HEIGHT_PX,
+                    this, app, DragController.DRAG_ACTION_COPY);
+            // close me!
+        }
         return true;
     }
 
+    public void setDragController(DragController dragger) {
+        mDragController = dragger;
+    }
+
+    public void onDropCompleted(View target, boolean success) {
+    }
+
     /*
     private TouchHandler mScrollHandler = new TouchHandler() {
         @Override
diff --git a/src/com/android/launcher2/AppInfoCache.java b/src/com/android/launcher2/AppInfoCache.java
index 9e87a47..65ae570 100644
--- a/src/com/android/launcher2/AppInfoCache.java
+++ b/src/com/android/launcher2/AppInfoCache.java
@@ -130,12 +130,14 @@
         ApplicationInfo cached;
         synchronized (sCache) {
             cached = sCache.get(componentName);
-        }
-
-        if (cached != null) {
-            return cached.icon;
-        } else {
-            return resolveInfo.activityInfo.loadIcon(packageManager);
+            if (cached != null) {
+                if (cached.icon == null) {
+                    cached.icon = resolveInfo.activityInfo.loadIcon(packageManager);
+                }
+                return cached.icon;
+            } else {
+                return resolveInfo.activityInfo.loadIcon(packageManager);
+            }
         }
     }
 
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 43fb1a6..ed4cba9 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -136,7 +136,7 @@
         dragView.setPaint(null);
     }
 
-    public void onDragStart(View v, DragSource source, Object info, int dragAction) {
+    public void onDragStart(DragSource source, Object info, int dragAction) {
         final ItemInfo item = (ItemInfo) info;
         if (item != null) {
             mTrashMode = true;
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 38bc468..fe79c56 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -80,9 +80,6 @@
     /** Original view that is being dragged.  */
     private View mOriginator;
 
-    /** The contents of mOriginator with no scaling.  */
-    private Bitmap mDragBitmap;
-
     /** X offset from the upper-left corner of the cell to where we touched.  */
     private float mTouchOffsetX;
 
@@ -126,13 +123,12 @@
         /**
          * A drag has begun
          * 
-         * @param v The view that is being dragged
          * @param source An object representing where the drag originated
          * @param info The data associated with the object that is being dragged
          * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
          *        or {@link DragController#DRAG_ACTION_COPY}
          */
-        void onDragStart(View v, DragSource source, Object info, int dragAction);
+        void onDragStart(DragSource source, Object info, int dragAction);
         
         /**
          * The drag has eneded
@@ -152,7 +148,7 @@
     }
 
     /**
-     * Starts a drag
+     * Starts a drag.
      * 
      * @param v The view that is being dragged
      * @param source An object representing where the drag originated
@@ -161,6 +157,44 @@
      *        {@link #DRAG_ACTION_COPY}
      */
     public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) {
+        mOriginator = v;
+
+        Bitmap b = getViewBitmap(v);
+
+        int[] loc = mCoordinatesTemp;
+        v.getLocationOnScreen(loc);
+        int screenX = loc[0];
+        int screenY = loc[1];
+
+        startDrag(b, screenX, screenY, 0, 0, b.getWidth(), b.getHeight(),
+                source, dragInfo, dragAction);
+
+        b.recycle();
+
+        if (dragAction == DRAG_ACTION_MOVE) {
+            v.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * Starts a drag.
+     * 
+     * @param b The bitmap to display as the drag image.  It will be re-scaled to the
+     *          enlarged size.
+     * @param screenX The x position on screen of the left-top of the bitmap.
+     * @param screenY The y position on screen of the left-top of the bitmap.
+     * @param textureLeft The left edge of the region inside b to use.
+     * @param textureTop The top edge of the region inside b to use.
+     * @param textureWidth The width of the region inside b to use.
+     * @param textureHeight The height of the region inside b to use.
+     * @param source An object representing where the drag originated
+     * @param info The data associated with the object that is being dragged
+     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
+     *        {@link #DRAG_ACTION_COPY}
+     */
+    public void startDrag(Bitmap b, int screenX, int screenY,
+            int textureLeft, int textureTop, int textureWidth, int textureHeight,
+            DragSource source, Object dragInfo, int dragAction) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
         }
@@ -173,14 +207,9 @@
         mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
 
         if (mListener != null) {
-            mListener.onDragStart(v, source, dragInfo, dragAction);
+            mListener.onDragStart(source, dragInfo, dragAction);
         }
 
-        int[] loc = mCoordinatesTemp;
-        v.getLocationOnScreen(loc);
-        int screenX = loc[0];
-        int screenY = loc[1];
-
         int registrationX = ((int)mMotionDownX) - screenX;
         int registrationY = ((int)mMotionDownY) - screenY;
 
@@ -188,20 +217,14 @@
         mTouchOffsetY = mMotionDownY - screenY;
 
         mDragging = true;
-        mOriginator = v;
         mDragSource = source;
         mDragInfo = dragInfo;
 
         mVibrator.vibrate(VIBRATE_DURATION);
 
-        mDragBitmap = getViewBitmap(v);
-        DragView dragView = mDragView = new DragView(mContext, mDragBitmap,
-                registrationX, registrationY);
+        DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY,
+                textureLeft, textureTop, textureWidth, textureHeight);
         dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
-
-        if (dragAction == DRAG_ACTION_MOVE) {
-            v.setVisibility(View.GONE);
-        }
     }
 
     /**
@@ -262,10 +285,6 @@
                 mDragView.remove();
                 mDragView = null;
             }
-            if (mDragBitmap != null) {
-                mDragBitmap.recycle();
-                mDragBitmap = null;
-            }
         }
     }
 
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 911a6ce..7128ded 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -62,22 +62,20 @@
      * @param registrationX The x coordinate of the registration point.
      * @param registrationY The y coordinate of the registration point.
      */
-    public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY) {
+    public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY,
+            int left, int top, int width, int height) {
         super(context);
 
         mWindowManager = WindowManagerImpl.getDefault();
         
         mTween = new SymmetricalLinearTween(false, 110 /*ms duration*/, this);
 
-        int width = bitmap.getWidth();
-        int height = bitmap.getHeight();
-
         Matrix scale = new Matrix();
         float scaleFactor = width;
         scaleFactor = mScale = (scaleFactor + DRAG_SCALE) / scaleFactor;
         scale.setScale(scaleFactor, scaleFactor);
 
-        mBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, scale, true);
+        mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
 
         // The point in our scaled bitmap that the touch events are located
         mRegistrationX = registrationX + (DRAG_SCALE / 2);
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index bf08b4e..06f106e 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -519,6 +519,7 @@
 
         mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
         mAllAppsGrid.setLauncher(this);
+        mAllAppsGrid.setDragController(dragController);
 
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
         final Workspace workspace = mWorkspace;
@@ -575,6 +576,9 @@
     View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
         TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
 
+        if (info.icon == null) {
+            info.icon = AppInfoCache.getIconDrawable(getPackageManager(), info);
+        }
         if (!info.filtered) {
             info.icon = Utilities.createIconThumbnail(info.icon, this);
             info.filtered = true;