Merge "Animating the drag view scale up and down when dragging items."
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index f10e07e..2f8d128 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -238,6 +238,7 @@
     static final int WIDGET_INFLATED = 1;
     int mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
     int mWidgetLoadingId = -1;
+    PendingAddWidgetInfo mCreateWidgetInfo = null;
 
     public AppsCustomizePagedView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -578,13 +579,14 @@
     public void onShortPress(View v) {
         // We are anticipating a long press, and we use this time to load bind and instantiate
         // the widget. This will need to be cleaned up if it turns out no long press occurs.
-        PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
-        loadWidgetInBackground(createWidgetInfo);
+        mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag());
+        loadWidgetInBackground(mCreateWidgetInfo);
     }
 
     @Override
     public void cleanUpShortPress(View v) {
-        PendingAddWidgetInfo info = (PendingAddWidgetInfo) v.getTag();
+        PendingAddWidgetInfo info = mCreateWidgetInfo;
+        mCreateWidgetInfo = null;
         if (mWidgetCleanupState >= 0 && mWidgetLoadingId != -1) {
             mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
         }
@@ -611,7 +613,9 @@
         Bitmap preview;
         Bitmap outline;
         if (createItemInfo instanceof PendingAddWidgetInfo) {
-            PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
+            PendingAddWidgetInfo createWidgetInfo = mCreateWidgetInfo;
+            createItemInfo = createWidgetInfo;
+            mCreateWidgetInfo = null;
             int[] spanXY = mLauncher.getSpanForWidget(createWidgetInfo, null);
             int[] size = mLauncher.getWorkspace().estimateItemSize(spanXY[0],
                     spanXY[1], createWidgetInfo, true);
@@ -672,19 +676,23 @@
         postDelayed(new Runnable() {
             @Override
             public void run() {
-                // Dismiss the cling
-                mLauncher.dismissAllAppsCling(null);
+                // We don't enter spring-loaded mode if the drag has been cancelled
+                if (mLauncher.getDragController().isDragging()) {
+                    // Dismiss the cling
+                    mLauncher.dismissAllAppsCling(null);
 
-                // Reset the alpha on the dragged icon before we drag
-                resetDrawableState();
+                    // Reset the alpha on the dragged icon before we drag
+                    resetDrawableState();
 
-                // Go into spring loaded mode (must happen before we startDrag())
-                mLauncher.enterSpringLoadedDragMode();
+                    // Go into spring loaded mode (must happen before we startDrag())
+                    mLauncher.enterSpringLoadedDragMode();
+                }
             }
         },150);
 
         return true;
     }
+
     private void endDragging(View target, boolean success) {
         mLauncher.getWorkspace().onDragStopped(success);
         if (!success || (target != mLauncher.getWorkspace() &&
@@ -694,7 +702,6 @@
             mLauncher.exitSpringLoadedDragMode();
         }
         mLauncher.unlockScreenOrientationOnLargeUI();
-
     }
 
     @Override
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index caababa..023946b 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -347,8 +347,9 @@
 
     /* LauncherTransitionable overrides */
     @Override
-    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+    public void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) {
         mInTransition = true;
+        boolean animated = (animation != null);
 
         mContent.setVisibility(VISIBLE);
 
@@ -371,9 +372,9 @@
     }
 
     @Override
-    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+    public void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace) {
         mInTransition = false;
-        if (animated) {
+        if (animation != null) {
             setLayerType(LAYER_TYPE_NONE, null);
         }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 708d5d6..8850cf8 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -582,6 +582,7 @@
         mWorkspace.animateExternalDrop(mWidgetBeingConfigured, cellLayout,
                 (DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
                 animationType);
+        mWidgetBeingConfigured = null;
     }
 
     @Override
@@ -2212,18 +2213,6 @@
         }
     }
 
-    private void dispatchOnLauncherTransitionStart(View v, boolean animated, boolean toWorkspace) {
-        if (v instanceof LauncherTransitionable) {
-            ((LauncherTransitionable) v).onLauncherTransitionStart(this, animated, toWorkspace);
-        }
-    }
-
-    private void dispatchOnLauncherTransitionEnd(View v, boolean animated, boolean toWorkspace) {
-        if (v instanceof LauncherTransitionable) {
-            ((LauncherTransitionable) v).onLauncherTransitionEnd(this, animated, toWorkspace);
-        }
-    }
-
     /**
      * Things to test when changing the following seven functions.
      *   - Home from workspace
@@ -2269,7 +2258,7 @@
      * Assumes that the view to show is anchored at either the very top or very bottom
      * of the screen.
      */
-    private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded) {
+    private void showAppsCustomizeHelper(boolean animated, final boolean springLoaded) {
         if (mStateAnimation != null) {
             mStateAnimation.cancel();
             mStateAnimation = null;
@@ -2280,7 +2269,6 @@
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
         final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
         final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
-        final View fromView = mWorkspace;
         final View toView = mAppsCustomizeTabHost;
         final int startDelay =
                 res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
@@ -2327,8 +2315,10 @@
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    dispatchOnLauncherTransitionEnd(fromView, animated, false);
-                    dispatchOnLauncherTransitionEnd(toView, animated, false);
+                    if (toView instanceof LauncherTransitionable) {
+                        ((LauncherTransitionable) toView).onLauncherTransitionEnd(instance,
+                                scaleAnim, false);
+                    }
 
                     if (!springLoaded && !LauncherApplication.isScreenLarge()) {
                         // Hide the workspace scrollbar
@@ -2351,14 +2341,14 @@
             }
 
             boolean delayAnim = false;
+            LauncherTransitionable lt = (LauncherTransitionable) toView;
             final ViewTreeObserver observer;
 
-            dispatchOnLauncherTransitionStart(fromView, animated, false);
-            dispatchOnLauncherTransitionStart(toView, animated, false);
+            lt.onLauncherTransitionStart(instance, mStateAnimation, false);
 
             // If any of the objects being animated haven't been measured/laid out
             // yet, delay the animation until we get a layout pass
-            if ((((LauncherTransitionable) toView).getContent().getMeasuredWidth() == 0) ||
+            if ((lt.getContent().getMeasuredWidth() == 0) ||
                     (mWorkspace.getMeasuredWidth() == 0) ||
                     (toView.getMeasuredWidth() == 0)) {
                 observer = mWorkspace.getViewTreeObserver();
@@ -2397,16 +2387,16 @@
             toView.setScaleY(1.0f);
             toView.setVisibility(View.VISIBLE);
             toView.bringToFront();
+            if (toView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) toView).onLauncherTransitionStart(instance, null, false);
+                ((LauncherTransitionable) toView).onLauncherTransitionEnd(instance, null, false);
 
-            if (!springLoaded && !LauncherApplication.isScreenLarge()) {
-                // Hide the workspace scrollbar
-                mWorkspace.hideScrollingIndicator(true);
-                hideDockDivider();
+                if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                    // Hide the workspace scrollbar
+                    mWorkspace.hideScrollingIndicator(true);
+                    hideDockDivider();
+                }
             }
-            dispatchOnLauncherTransitionStart(fromView, animated, false);
-            dispatchOnLauncherTransitionEnd(fromView, animated, false);
-            dispatchOnLauncherTransitionStart(toView, animated, false);
-            dispatchOnLauncherTransitionEnd(toView, animated, false);
             updateWallpaperVisibility(false);
         }
     }
@@ -2418,12 +2408,12 @@
      */
     private void hideAppsCustomizeHelper(State toState, final boolean animated,
             final boolean springLoaded, final Runnable onCompleteRunnable) {
-
         if (mStateAnimation != null) {
             mStateAnimation.cancel();
             mStateAnimation = null;
         }
         Resources res = getResources();
+        final Launcher instance = this;
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
         final int fadeOutDuration =
@@ -2431,7 +2421,6 @@
         final float scaleFactor = (float)
                 res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
         final View fromView = mAppsCustomizeTabHost;
-        final View toView = mWorkspace;
         Animator workspaceAnim = null;
 
         if (toState == State.WORKSPACE) {
@@ -2462,18 +2451,19 @@
                 .setDuration(fadeOutDuration);
             alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator());
 
-            mStateAnimation = new AnimatorSet();
-
-            dispatchOnLauncherTransitionStart(fromView, animated, true);
-            dispatchOnLauncherTransitionStart(toView, animated, true);
-
-            mStateAnimation.addListener(new AnimatorListenerAdapter() {
+            if (fromView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(instance, alphaAnim,
+                        true);
+            }
+            alphaAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     updateWallpaperVisibility(true);
                     fromView.setVisibility(View.GONE);
-                    dispatchOnLauncherTransitionEnd(fromView, animated, true);
-                    dispatchOnLauncherTransitionEnd(toView, animated, true);
+                    if (fromView instanceof LauncherTransitionable) {
+                        ((LauncherTransitionable) fromView).onLauncherTransitionEnd(instance,
+                                alphaAnim, true);
+                    }
                     mWorkspace.hideScrollingIndicator(false);
                     if (onCompleteRunnable != null) {
                         onCompleteRunnable.run();
@@ -2481,6 +2471,7 @@
                 }
             });
 
+            mStateAnimation = new AnimatorSet();
             mStateAnimation.playTogether(scaleAnim, alphaAnim);
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
@@ -2488,10 +2479,10 @@
             mStateAnimation.start();
         } else {
             fromView.setVisibility(View.GONE);
-            dispatchOnLauncherTransitionStart(fromView, animated, false);
-            dispatchOnLauncherTransitionEnd(fromView, animated, false);
-            dispatchOnLauncherTransitionStart(toView, animated, false);
-            dispatchOnLauncherTransitionEnd(toView, animated, false);
+            if (fromView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(instance, null, true);
+                ((LauncherTransitionable) fromView).onLauncherTransitionEnd(instance, null, true);
+            }
             mWorkspace.hideScrollingIndicator(false);
         }
     }
@@ -3438,6 +3429,6 @@
 
 interface LauncherTransitionable {
     View getContent();
-    void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace);
-    void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
+    void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace);
+    void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace);
 }
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 7abe6e1..9a140d2 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -1680,7 +1680,6 @@
         if (mHasScrollIndicator && mScrollIndicator == null) {
             ViewGroup parent = (ViewGroup) getParent();
             mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator));
-            mScrollIndicator.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             mHasScrollIndicator = mScrollIndicator != null;
             if (mHasScrollIndicator) {
                 mScrollIndicator.setVisibility(View.VISIBLE);
@@ -1806,6 +1805,7 @@
             indicatorPos += indicatorCenterOffset;
         }
         mScrollIndicator.setTranslationX(indicatorPos);
+        mScrollIndicator.invalidate();
     }
 
     public void showScrollIndicatorTrack() {
diff --git a/src/com/android/launcher2/PendingAddItemInfo.java b/src/com/android/launcher2/PendingAddItemInfo.java
index 851dddb..09a8a9e 100644
--- a/src/com/android/launcher2/PendingAddItemInfo.java
+++ b/src/com/android/launcher2/PendingAddItemInfo.java
@@ -57,4 +57,18 @@
             configurationData = data;
         }
     }
-}
\ No newline at end of file
+
+    // Copy constructor
+    public PendingAddWidgetInfo(PendingAddWidgetInfo copy) {
+        minWidth = copy.minWidth;
+        minHeight = copy.minHeight;
+        previewImage = copy.previewImage;
+        icon = copy.icon;
+        info = copy.info;
+        boundWidget = copy.boundWidget;
+        mimeType = copy.mimeType;
+        configurationData = copy.configurationData;
+        componentName = copy.componentName;
+        itemType = copy.itemType;
+    }
+}
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
index 03ca38f..3a7f24b 100644
--- a/src/com/android/launcher2/SearchDropTargetBar.java
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -129,26 +129,14 @@
             @Override
             public void onAnimationStart(Animator animation) {
                 mQSBSearchBar.setVisibility(View.VISIBLE);
-                mQSBSearchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mQSBSearchBar.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
         mQSBSearchBarFadeOutAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 0f);
         mQSBSearchBarFadeOutAnim.setDuration(sTransitionOutDuration);
         mQSBSearchBarFadeOutAnim.addListener(new AnimatorListenerAdapter() {
             @Override
-            public void onAnimationStart(Animator animation) {
-                mQSBSearchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            }
-
-            @Override
             public void onAnimationEnd(Animator animation) {
                 mQSBSearchBar.setVisibility(View.INVISIBLE);
-                mQSBSearchBar.setLayerType(View.LAYER_TYPE_NONE, null);
             }
         });
     }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index abceb48..704138e 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,6 +17,8 @@
 package com.android.launcher2;
 
 import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
@@ -24,7 +26,6 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.AlertDialog;
 import android.app.WallpaperManager;
-import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ClipData;
@@ -56,7 +57,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.View.MeasureSpec;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -77,7 +77,7 @@
  */
 public class Workspace extends SmoothPagedView
         implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
-        DragController.DragListener, LauncherTransitionable {
+        DragController.DragListener {
     @SuppressWarnings({"UnusedDeclaration"})
     private static final String TAG = "Launcher.Workspace";
 
@@ -159,6 +159,8 @@
     private State mState = State.NORMAL;
     private boolean mIsSwitchingState = false;
 
+    private AnimatorListener mChangeStateAnimationListener;
+
     boolean mAnimatingViewIntoPlace = false;
     boolean mIsDragOccuring = false;
     boolean mChildrenLayersEnabled = true;
@@ -278,9 +280,11 @@
             // landscape
             TypedArray actionBarSizeTypedArray =
                 context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
+            DisplayMetrics displayMetrics = res.getDisplayMetrics();
             final float actionBarHeight = actionBarSizeTypedArray.getDimension(0, 0f);
             final float systemBarHeight = res.getDimension(R.dimen.status_bar_height);
-            final float smallestScreenDim = res.getConfiguration().smallestScreenWidthDp;
+            final float smallestScreenDim = res.getConfiguration().smallestScreenWidthDp *
+                    displayMetrics.density;
 
             cellCountX = 1;
             while (CellLayout.widthInPortrait(res, cellCountX + 1) <= smallestScreenDim) {
@@ -383,6 +387,20 @@
             // In this case, we will skip drawing background protection
         }
 
+        mChangeStateAnimationListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mIsSwitchingState = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mIsSwitchingState = false;
+                mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
+                updateChildrenLayersEnabled();
+            }
+        };
+
         mWallpaperOffset = new WallpaperOffsetInterpolator();
         Display display = mLauncher.getWindowManager().getDefaultDisplay();
         mDisplayWidth = display.getWidth();
@@ -1622,10 +1640,26 @@
                 cl.setBackgroundAlphaMultiplier(finalAlphaMultiplierValue);
                 cl.setAlpha(finalAlpha);
                 cl.setRotationY(rotation);
+                mChangeStateAnimationListener.onAnimationEnd(null);
             }
         }
 
         if (animated) {
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(android.animation.Animator animation) {
+                    // The above code to determine initialAlpha and finalAlpha will ensure that only
+                    // the current page is visible during (and subsequently, after) the transition
+                    // animation.  If fade adjacent pages is disabled, then re-enable the page
+                    // visibility after the transition animation.
+                    if (!mFadeInAdjacentScreens) {
+                        for (int i = 0; i < getChildCount(); i++) {
+                            final CellLayout cl = (CellLayout) getChildAt(i);
+                            cl.setAlpha(1f);
+                        }
+                    }
+                }
+            });
             for (int index = 0; index < getChildCount(); index++) {
                 final int i = index;
                 final CellLayout cl = (CellLayout) getChildAt(i);
@@ -1681,6 +1715,9 @@
                 }
             }
             anim.setStartDelay(delay);
+            // If we call this when we're not animated, onAnimationEnd is never called on
+            // the listener; make sure we only use the listener when we're actually animating
+            anim.addListener(mChangeStateAnimationListener);
         }
 
         if (stateIsSpringLoaded) {
@@ -1696,33 +1733,6 @@
         return anim;
     }
 
-    @Override
-    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
-        mIsSwitchingState = true;
-    }
-
-    @Override
-    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
-        mIsSwitchingState = false;
-        mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
-        updateChildrenLayersEnabled();
-        // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
-        // ensure that only the current page is visible during (and subsequently, after) the
-        // transition animation.  If fade adjacent pages is disabled, then re-enable the page
-        // visibility after the transition animation.
-        if (!mFadeInAdjacentScreens) {
-            for (int i = 0; i < getChildCount(); i++) {
-                final CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setAlpha(1f);
-            }
-        }
-    }
-
-    @Override
-    public View getContent() {
-        return this;
-    }
-
     /**
      * Draw the View v into the given Canvas.
      *
@@ -1947,7 +1957,7 @@
     }
 
     public boolean transitionStateShouldAllowDrop() {
-        return (!isSwitchingState() || mTransitionProgress > 0.5f);
+        return ((!isSwitchingState() || mTransitionProgress > 0.5f) && mState != State.SMALL);
     }
 
     /**