Merge branch 'master' into honeycomb-release
diff --git a/res/drawable-hdpi/add_button.png b/res/drawable-hdpi/add_button.png
deleted file mode 100644
index 7e60d81..0000000
--- a/res/drawable-hdpi/add_button.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/pattern_carbon_fiber_dark.png b/res/drawable-hdpi/pattern_carbon_fiber_dark.png
deleted file mode 100644
index 427936f..0000000
--- a/res/drawable-hdpi/pattern_carbon_fiber_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/placeholder_google.png b/res/drawable-hdpi/placeholder_google.png
deleted file mode 100644
index 923c8b8..0000000
--- a/res/drawable-hdpi/placeholder_google.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/rounded_rect_green.9.png b/res/drawable-hdpi/rounded_rect_green.9.png
deleted file mode 100644
index a846cbd..0000000
--- a/res/drawable-hdpi/rounded_rect_green.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/rounded_rect_red.9.png b/res/drawable-hdpi/rounded_rect_red.9.png
deleted file mode 100644
index 21fd62c..0000000
--- a/res/drawable-hdpi/rounded_rect_red.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/add_button.png b/res/drawable-mdpi/add_button.png
deleted file mode 100644
index 2f939d7..0000000
--- a/res/drawable-mdpi/add_button.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/pattern_carbon_fiber_dark.png b/res/drawable-mdpi/pattern_carbon_fiber_dark.png
deleted file mode 100644
index 44e050f..0000000
--- a/res/drawable-mdpi/pattern_carbon_fiber_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/placeholder_google.png b/res/drawable-mdpi/placeholder_google.png
deleted file mode 100644
index 4af30aa..0000000
--- a/res/drawable-mdpi/placeholder_google.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/rounded_rect_green.9.png b/res/drawable-mdpi/rounded_rect_green.9.png
deleted file mode 100644
index 11e2114..0000000
--- a/res/drawable-mdpi/rounded_rect_green.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/rounded_rect_red.9.png b/res/drawable-mdpi/rounded_rect_red.9.png
deleted file mode 100644
index c3ca2f4..0000000
--- a/res/drawable-mdpi/rounded_rect_red.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/glow_wallpaper_small.png b/res/drawable-xlarge-nodpi/glow_wallpaper_small.png
deleted file mode 100644
index f83fc60..0000000
--- a/res/drawable-xlarge-nodpi/glow_wallpaper_small.png
+++ /dev/null
Binary files differ
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index a54528e..fa7af5e 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -1,9 +1,9 @@
 <resources>
     <!--  NOTE: Many of the all apps values here are also used for the customization drawer -->
 
-    <!-- Duration in milliseconds of the all apps zoom-in animation. -->
+    <!-- Duration in milliseconds of the all apps / configuration zoom-in animation. -->
     <!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
-    <integer name="config_allAppsZoomInTime">350</integer>
+    <integer name="config_allAppsZoomInTime">700</integer>
 
     <!-- Duration in milliseconds of the transition between tabs in the all apps/customize
          tray -->
@@ -14,16 +14,14 @@
     <integer name="config_allAppsZoomOutTime">350</integer>
 
     <!-- Scaling factor used in the all apps zooming animations -->
-    <integer name="config_allAppsZoomScaleFactor">5</integer>
-
-    <!-- The extra distance off-screen that all apps appears from -->
-    <integer name="config_allAppsVerticalOffset">200</integer>
+    <integer name="config_allAppsZoomScaleFactor">7</integer>
 
     <!-- Duration in milliseconds of the animations between all apps, customize, & home.
          NOTE: If these are changed, the toolbar animation times below should also be. -->
     <integer name="config_allAppsCameraPanTime">700</integer>
     <integer name="config_workspaceShrinkTime">700</integer>
-    <integer name="config_workspaceUnshrinkTime">700</integer>
+    <integer name="config_workspaceUnshrinkTime">350</integer>
+    <integer name="config_allAppsFadeOutTime">150</integer>
 
     <!-- Duration in milliseconds toolbar fade in and fade out animations.
          NOTE: Fade in and fade out time should together be less the transition
@@ -49,4 +47,8 @@
     <integer name="config_screenOnDropScaleDownDuration">200</integer>
     <integer name="config_screenOnDropAlphaFadeDelay">350</integer>
     <integer name="config_screenOnDropAlphaFadeDuration">50</integer>
+
+    <!-- The slope, in percent, of the drag movement needed to drag an item out of the customization
+         drawer (y / x * 100%)  -->
+    <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
 </resources>
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 6dfa4e5..a7293c8 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -44,6 +44,7 @@
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -52,7 +53,7 @@
 import com.android.launcher.R;
 
 public class CustomizePagedView extends PagedView
-    implements View.OnLongClickListener, View.OnClickListener,
+    implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener,
                 DragSource, ActionMode.Callback {
 
     public enum CustomizationType {
@@ -65,9 +66,12 @@
     private static final String TAG = "CustomizeWorkspace";
     private static final boolean DEBUG = false;
 
+    private View mLastTouchedItem;
     private Launcher mLauncher;
     private DragController mDragController;
     private PackageManager mPackageManager;
+    private boolean mIsDragging;
+    private float mDragSlopeThreshold;
 
     private CustomizationType mCustomizationType;
 
@@ -132,6 +136,10 @@
         mWorkspaceWidgetLayout = new PagedViewCellLayout(context);
         mInflater = LayoutInflater.from(context);
 
+        final Resources r = context.getResources();
+        mDragSlopeThreshold =
+            r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f;
+
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
         setupWorkspaceLayout();
@@ -373,11 +381,98 @@
         if (!v.isInTouchMode()) return false;
         // Return early if we are still animating the pages
         if (mNextPage != INVALID_PAGE) return false;
+        return beginDragging(v);
+    }
 
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        mLastTouchedItem = v;
+        return false;
+    }
+
+    /*
+     * Determines if we should change the touch state to start scrolling after the
+     * user moves their touch point too far.
+     */
+    protected void determineScrollingStart(MotionEvent ev) {
+        if (!mIsDragging) super.determineScrollingStart(ev);
+    }
+
+    /*
+     * Determines if we should change the touch state to start dragging after the
+     * user moves their touch point far enough.
+     */
+    protected void determineDraggingStart(MotionEvent ev) {
+        /*
+         * Locally do absolute value. mLastMotionX is set to the y value
+         * of the down event.
+         */
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        final int xDiff = (int) Math.abs(x - mLastMotionX);
+        final int yDiff = (int) Math.abs(y - mLastMotionY);
+
+        final int touchSlop = mTouchSlop;
+        boolean yMoved = yDiff > touchSlop;
+        boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
+
+        if (isUpwardMotion && yMoved) {
+            // Drag if the user moved far enough along the Y axis
+            beginDragging(mLastTouchedItem);
+
+            // Cancel any pending longpress
+            if (mAllowLongPress) {
+                mAllowLongPress = false;
+                // Try canceling the long press. It could also have been scheduled
+                // by a distant descendant, so use the mAllowLongPress flag to block
+                // everything
+                final View currentPage = getPageAt(mCurrentPage);
+                if (currentPage != null) {
+                    currentPage.cancelLongPress();
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mIsDragging = false;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
+                    determineDraggingStart(ev);
+                }
+                break;
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mIsDragging = false;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
+                    determineDraggingStart(ev);
+                }
+                break;
+        }
+        return super.onTouchEvent(ev);
+    }
+
+    private boolean beginDragging(View v) {
         // End the current choice mode before we start dragging anything
         if (isChoiceMode(CHOICE_MODE_SINGLE)) {
             endChoiceMode();
         }
+        mIsDragging = true;
 
         PendingAddItemInfo createItemInfo;
         switch (mCustomizationType) {
@@ -626,6 +721,7 @@
                     R.layout.customize_paged_view_widget, layout, false);
             l.setTag(createItemInfo);
             l.setOnClickListener(this);
+            l.setOnTouchListener(this);
             l.setOnLongClickListener(this);
 
             final Drawable icon = getWidgetPreview(info);
@@ -729,6 +825,7 @@
                         info.activityInfo.name);
                 icon.setTag(createItemInfo);
                 icon.setOnClickListener(this);
+                icon.setOnTouchListener(this);
                 icon.setOnLongClickListener(this);
                 break;
             default:
@@ -774,6 +871,7 @@
                     R.layout.all_apps_paged_view_application, layout, false);
             icon.applyFromApplicationInfo(info, mPageViewIconCache, true);
             icon.setOnClickListener(this);
+            icon.setOnTouchListener(this);
             icon.setOnLongClickListener(this);
 
             final int index = i - startIndex;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 37c2b41..464ea64 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2515,14 +2515,16 @@
      */
     private void setPivotsForZoom(View view, State state, float scaleFactor) {
         final int height = view.getHeight();
+
         view.setPivotX(view.getWidth() / 2.0f);
-        // Set pivotY so that at the starting zoom factor, the view is off-screen by a small margin
-        // Assumes that the view is normally anchored to either the top or bottom of the screen
-        final int margin = getResources().getInteger(R.integer.config_allAppsVerticalOffset);
+        // Set pivotY so that at the starting zoom factor, the view is partially
+        // visible. Modifying initialHeightFactor changes how much of the view is
+        // initially showing, and hence the perceived angle from which the view enters.
+        final float initialHeightFactor = 0.2f;
         if (state == State.ALL_APPS) {
-            view.setPivotY(height + ((view.getTop() + height) / scaleFactor) + margin);
+            view.setPivotY((1 + initialHeightFactor) * height);
         } else {
-            view.setPivotY(0.0f - (view.getTop() / scaleFactor) - margin);
+            view.setPivotY(-initialHeightFactor * height);
         }
     }
 
@@ -2552,7 +2554,8 @@
                     PropertyValuesHolder.ofFloat("scaleX", scale, 1.0f),
                     PropertyValuesHolder.ofFloat("scaleY", scale, 1.0f));
             scaleAnim.setDuration(duration);
-            scaleAnim.setInterpolator(new DecelerateInterpolator());
+
+            scaleAnim.setInterpolator(new Workspace.ZoomOutInterpolator());
             scaleAnim.addListener(new LauncherAnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
@@ -2560,6 +2563,7 @@
                     toView.setTranslationX(0.0f);
                     toView.setTranslationY(0.0f);
                     toView.setVisibility(View.VISIBLE);
+                    toView.setAlpha(1.0f);
                 }
                 @Override
                 public void onAnimationEndOrCancel(Animator animation) {
@@ -2624,8 +2628,12 @@
                     PropertyValuesHolder.ofFloat("scaleX", scaleFactor),
                     PropertyValuesHolder.ofFloat("scaleY", scaleFactor));
             scaleAnim.setDuration(duration);
-            scaleAnim.setInterpolator(new AccelerateInterpolator());
-            mStateAnimation.addListener(new LauncherAnimatorListenerAdapter() {
+            scaleAnim.setInterpolator(new Workspace.ZoomInInterpolator());
+
+            ValueAnimator alphaAnim = ObjectAnimator.ofPropertyValuesHolder(fromView,
+                    PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f));
+            alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
+            alphaAnim.addListener(new LauncherAnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEndOrCancel(Animator animation) {
                     fromView.setVisibility(View.GONE);
@@ -2636,7 +2644,7 @@
             AnimatorSet toolbarShowAnim = new AnimatorSet();
             hideAndShowToolbarButtons(State.WORKSPACE, toolbarShowAnim, toolbarHideAnim);
 
-            mStateAnimation.playTogether(scaleAnim, toolbarHideAnim);
+            mStateAnimation.playTogether(scaleAnim, toolbarHideAnim, alphaAnim);
 
             // Show the new toolbar buttons at the very end of the whole animation
             final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
@@ -2688,6 +2696,7 @@
                 public void onAnimationStart(Animator animation) {
                     toView.setVisibility(View.VISIBLE);
                     toView.setY(toViewStartY);
+                    toView.setAlpha(1.0f);
                 }
                 @Override
                 public void onAnimationEndOrCancel(Animator animation) {
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index caa1e12..d4dffe6 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -74,8 +74,8 @@
     private VelocityTracker mVelocityTracker;
 
     private float mDownMotionX;
-    private float mLastMotionX;
-    private float mLastMotionY;
+    protected float mLastMotionX;
+    protected float mLastMotionY;
     private int mLastScreenCenter = -1;
 
     protected final static int TOUCH_STATE_REST = 0;
@@ -88,9 +88,9 @@
 
     protected OnLongClickListener mLongClickListener;
 
-    private boolean mAllowLongPress = true;
+    protected boolean mAllowLongPress = true;
 
-    private int mTouchSlop;
+    protected int mTouchSlop;
     private int mPagingTouchSlop;
     private int mMaximumVelocity;
     protected int mPageSpacing;
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 82fd362..7e33a2c 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -847,11 +847,6 @@
 
             if (animated) {
                 final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
-                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
-                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
-                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
-                        PropertyValuesHolder.ofFloat("rotationY", rotation));
-                anim.setDuration(duration);
 
                 ObjectAnimator animWithInterpolator = ObjectAnimator.ofPropertyValuesHolder(cl,
                         PropertyValuesHolder.ofFloat("x", newX),
@@ -859,10 +854,14 @@
                         PropertyValuesHolder.ofFloat("scaleX",
                                 SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
                         PropertyValuesHolder.ofFloat("scaleY",
-                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor));
+                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
+                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
+                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
+                        PropertyValuesHolder.ofFloat("rotationY", rotation));
+
                 animWithInterpolator.setDuration(duration);
-                animWithInterpolator.setInterpolator(mZInterpolator);
-                mAnimator.playTogether(anim, animWithInterpolator);
+                animWithInterpolator.setInterpolator(mZoomOutInterpolator);
+                mAnimator.playTogether(animWithInterpolator);
             } else {
                 cl.setX((int)newX);
                 cl.setY((int)newY);
@@ -881,22 +880,64 @@
         setChildrenDrawnWithCacheEnabled(true);
     }
 
-    private class ZInterpolator implements TimeInterpolator {
-        private final float focalLength = 0.2f;
+    /*
+     * This interpolator emulates the rate at which the perceived scale of an object changes
+     * as its distance from a camera increases. When this interpolator is applied to a scale
+     * animation on a view, it evokes the sense that the object is shrinking due to moving away
+     * from the camera. 
+     */
+    static class ZInterpolator implements TimeInterpolator {
+        private float focalLength;
+
+        public ZInterpolator(float foc) {
+            focalLength = foc;
+        }
+
         public float getInterpolation(float input) {
             return (1.0f - focalLength / (focalLength + input)) /
-                    (1.0f - focalLength / (focalLength + 1.0f));
+                (1.0f - focalLength / (focalLength + 1.0f));
         }
     }
 
-    private class InverseZInterpolator implements TimeInterpolator {
+    /*
+     * The exact reverse of ZInterpolator.
+     */
+    static class InverseZInterpolator implements TimeInterpolator {
+        private ZInterpolator zInterpolator;
+        public InverseZInterpolator(float foc) {
+            zInterpolator = new ZInterpolator(foc);
+        }
         public float getInterpolation(float input) {
-            return 1 - mZInterpolator.getInterpolation(1 - input);
+            return 1 - zInterpolator.getInterpolation(1 - input);
         }
     }
 
-    private final ZInterpolator mZInterpolator = new ZInterpolator();
-    private final InverseZInterpolator mInverseZInterpolator = new InverseZInterpolator();
+    /*
+     * ZInterpolator compounded with an ease-out.
+     */
+    static class ZoomOutInterpolator implements TimeInterpolator {
+        private final ZInterpolator zInterpolator = new ZInterpolator(0.2f);
+        private final DecelerateInterpolator decelerate = new DecelerateInterpolator(1.5f);
+
+        public float getInterpolation(float input) {
+            return decelerate.getInterpolation(zInterpolator.getInterpolation(input));
+        }
+    }
+
+    /*
+     * InvereZInterpolator compounded with an ease-out.
+     */
+    static class ZoomInInterpolator implements TimeInterpolator {
+        private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
+        private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
+
+        public float getInterpolation(float input) {
+            return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
+        }
+    }
+
+    private final ZoomOutInterpolator mZoomOutInterpolator = new ZoomOutInterpolator();
+    private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
 
     private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
         updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
@@ -1026,20 +1067,18 @@
                 }
 
                 if (animated) {
-                    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
-                            PropertyValuesHolder.ofFloat("backgroundAlpha", 0.0f),
-                            PropertyValuesHolder.ofFloat("alpha", finalAlphaValue),
-                            PropertyValuesHolder.ofFloat("rotationY", rotation));
-                    anim.setDuration(duration);
 
                     ObjectAnimator animWithInterpolator = ObjectAnimator.ofPropertyValuesHolder(cl,
                             PropertyValuesHolder.ofFloat("translationX", 0.0f),
                             PropertyValuesHolder.ofFloat("translationY", 0.0f),
                             PropertyValuesHolder.ofFloat("scaleX", 1.0f),
-                            PropertyValuesHolder.ofFloat("scaleY", 1.0f));
+                            PropertyValuesHolder.ofFloat("scaleY", 1.0f),
+                            PropertyValuesHolder.ofFloat("backgroundAlpha", 0.0f),
+                            PropertyValuesHolder.ofFloat("alpha", finalAlphaValue),
+                            PropertyValuesHolder.ofFloat("rotationY", rotation));
                     animWithInterpolator.setDuration(duration);
-                    animWithInterpolator.setInterpolator(mInverseZInterpolator);
-                    mAnimator.playTogether(anim, animWithInterpolator);
+                    animWithInterpolator.setInterpolator(mZoomInInterpolator);
+                    mAnimator.playTogether(animWithInterpolator);
                 } else {
                     cl.setTranslationX(0.0f);
                     cl.setTranslationY(0.0f);