checkpoint 3d all apps entrance / exit animations
diff --git a/res/drawable-land/trash.png b/res/drawable-land/trash.png
new file mode 100644
index 0000000..dccf891
--- /dev/null
+++ b/res/drawable-land/trash.png
Binary files differ
diff --git a/res/raw/rollo.c b/res/raw/rollo.c
index dc1199e..98f1e3e 100644
--- a/res/raw/rollo.c
+++ b/res/raw/rollo.c
@@ -39,6 +39,16 @@
 // Drawing constants, should be parameters ======
 #define VIEW_ANGLE 1.28700222f
 
+int g_lastFrameTime = 0;
+void print_frame_rate()
+{
+    int now = uptimeMillis();
+    if (g_lastFrameTime != 0) {
+        debugI32("frame_rate", 1000/(now-g_lastFrameTime));
+    }
+    g_lastFrameTime = now;
+}
+
 int
 count_pages(int iconCount)
 {
@@ -138,7 +148,7 @@
                     iconLeftX, iconTextureBottom, iconLeftZ,    0.0f, 1.0f);
 
             // label
-            if (scale <= 1.04f) {
+            if (scale <= 0.1f) {
                 float labelLeftX = centerX - farLabelWidth * 0.5f;
                 float labelRightX = centerX + farLabelWidth * 0.5f;
 
@@ -343,6 +353,8 @@
     drawRect(handleLeft, handleTop, handleLeft+handleWidth, handleTop+handleHeight, 0.0f);
     */
 
+    print_frame_rate();
+
     return !done;
 }
 
diff --git a/src/com/android/launcher2/AllAppsGridView.java b/src/com/android/launcher2/AllAppsGridView.java
index 23d4a7a..6606cc9 100644
--- a/src/com/android/launcher2/AllAppsGridView.java
+++ b/src/com/android/launcher2/AllAppsGridView.java
@@ -66,7 +66,7 @@
         app = new ApplicationInfo(app);
 
         mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
-        mLauncher.closeAllAppsDialog(true);
+        mLauncher.closeAllApps(true);
         mDraw = false;
         invalidate();
         return true;
@@ -84,7 +84,7 @@
     }
 
     public void onDropCompleted(View target, boolean success) {
-        mLauncher.closeAllAppsDialog(false);
+        mLauncher.closeAllApps(false);
     }
 
     void setLauncher(Launcher launcher) {
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 5128db3..7bb6c8f 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -64,9 +64,18 @@
         implements View.OnClickListener, View.OnLongClickListener, DragSource {
     private static final String TAG = "Launcher.AllAppsView";
 
+    /** Bit for mLocks for when there are icons being loaded. */
+    private static final int LOCK_ICONS_PENDING = 1;
+
+    /** Bit for mLocks for when the enter/exit is going. */
+    private static final int LOCK_ZOOMING = 2;
+
     private Launcher mLauncher;
     private DragController mDragController;
-    private boolean mLocked = true;
+
+    /** When this is 0, modifications are allowed, when it's not, they're not.
+     * TODO: What about scrolling? */
+    private int mLocks = LOCK_ICONS_PENDING;
 
     private RenderScript mRS;
     private RolloRS mRollo;
@@ -80,7 +89,6 @@
     private int mLastMotionX;
     private int mMotionDownRawX;
     private int mMotionDownRawY;
-    private TouchHandler mTouchHandler;
     private int mScrollHandleTop;
 
     static class Defines {
@@ -168,95 +176,74 @@
             return true;
         }
 
-        if (mLocked) {
+        if (mLocks != 0) {
             return true;
         }
 
         super.onTouchEvent(ev);
 
-        mTouchHandler = mFlingHandler;
-        /*
-        int action = ev.getAction();
-        if (action == MotionEvent.ACTION_DOWN) {
-            if (ev.getY() > mScrollHandleTop) {
-                mTouchHandler = mScrollHandler;
+        int x = (int)ev.getX();
+        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
+                    = mRollo.mState.currentScrollX;
+            if (mRollo.mState.flingVelocityX != 0) {
+                mRollo.clearSelectedIcon();
             } else {
-                mTouchHandler = mFlingHandler;
+                mRollo.selectIcon(x, (int)ev.getY(), mRollo.mState.startScrollX,
+                        (-mRollo.mState.startScrollX / Defines.SCREEN_WIDTH_PX));
             }
+            mRollo.mState.flingVelocityX = 0;
+            mRollo.mState.adjustedDeceleration = 0;
+            mRollo.mState.save();
+            mVelocity = VelocityTracker.obtain();
+            mVelocity.addMovement(ev);
+            mStartedScrolling = false;
+            break;
+        case MotionEvent.ACTION_MOVE:
+        case MotionEvent.ACTION_OUTSIDE:
+            int slop = Math.abs(x - mLastMotionX);
+            if (!mStartedScrolling && slop < mConfig.getScaledTouchSlop()) {
+                // don't update mLastMotionX so slop is right and when we do start scrolling
+                // below, we get the right delta.
+            } else {
+                mStartedScrolling = true;
+                mRollo.clearSelectedIcon();
+                deltaX = x - mLastMotionX;
+                mVelocity.addMovement(ev);
+                mRollo.mState.currentScrollX = mLastScrollX;
+                mLastScrollX += deltaX;
+                mRollo.mState.scrollX = mLastScrollX;
+                mRollo.mState.save();
+                mLastMotionX = x;
+            }
+            break;
+        case MotionEvent.ACTION_UP:
+        case MotionEvent.ACTION_CANCEL:
+            mVelocity.computeCurrentVelocity(1000 /* px/sec */,
+                    mConfig.getScaledMaximumFlingVelocity());
+            mRollo.mState.flingTimeMs = (int)SystemClock.uptimeMillis(); // TODO: use long
+            mRollo.mState.flingVelocityX = (int)mVelocity.getXVelocity();
+            mRollo.clearSelectedIcon();
+            mRollo.mState.save();
+            mLastMotionX = -10000;
+            mVelocity.recycle();
+            mVelocity = null;
+            break;
         }
-        */
-        mTouchHandler.onTouchEvent(ev);
 
         return true;
     }
 
-    private abstract class TouchHandler {
-        abstract boolean onTouchEvent(MotionEvent ev);
-    };
-
-    private TouchHandler mFlingHandler = new TouchHandler() {
-        @Override
-        public boolean onTouchEvent(MotionEvent ev)
-        {
-            int x = (int)ev.getX();
-            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
-                            = mRollo.mState.currentScrollX;
-                    if (mRollo.mState.flingVelocityX != 0) {
-                        mRollo.clearSelectedIcon();
-                    } else {
-                        mRollo.selectIcon(x, (int)ev.getY(), mRollo.mState.startScrollX,
-                                (-mRollo.mState.startScrollX / Defines.SCREEN_WIDTH_PX));
-                    }
-                    mRollo.mState.flingVelocityX = 0;
-                    mRollo.mState.adjustedDeceleration = 0;
-                    mRollo.mState.save();
-                    mVelocity = VelocityTracker.obtain();
-                    mVelocity.addMovement(ev);
-                    mStartedScrolling = false;
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                case MotionEvent.ACTION_OUTSIDE:
-                    int slop = Math.abs(x - mLastMotionX);
-                    if (!mStartedScrolling && slop < mConfig.getScaledTouchSlop()) {
-                        // don't update mLastMotionX so slop is right and when we do start scrolling
-                        // below, we get the right delta.
-                    } else {
-                        mStartedScrolling = true;
-                        mRollo.clearSelectedIcon();
-                        deltaX = x - mLastMotionX;
-                        mVelocity.addMovement(ev);
-                        mRollo.mState.currentScrollX = mLastScrollX;
-                        mLastScrollX += deltaX;
-                        mRollo.mState.scrollX = mLastScrollX;
-                        mRollo.mState.save();
-                        mLastMotionX = x;
-                    }
-                    break;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mVelocity.computeCurrentVelocity(1000 /* px/sec */,
-                            mConfig.getScaledMaximumFlingVelocity());
-                    mRollo.mState.flingTimeMs = (int)SystemClock.uptimeMillis(); // TODO: use long
-                    mRollo.mState.flingVelocityX = (int)mVelocity.getXVelocity();
-                    mRollo.clearSelectedIcon();
-                    mRollo.mState.save();
-                    mLastMotionX = -10000;
-                    mVelocity.recycle();
-                    mVelocity = null;
-                    break;
-            }
-            return true;
-        }
-    };
-
     public void onClick(View v) {
+        if (mLocks != 0) {
+            return;
+        }
         int index = mRollo.mState.selectedIconIndex;
         if (mRollo.mState.flingVelocityX == 0 && index >= 0 && index < mAllAppsList.size()) {
             ApplicationInfo app = mAllAppsList.get(index);
@@ -265,6 +252,9 @@
     }
 
     public boolean onLongClick(View v) {
+        if (mLocks != 0) {
+            return true;
+        }
         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()) {
@@ -280,7 +270,7 @@
                     left, top, Defines.ICON_WIDTH_PX, Defines.ICON_HEIGHT_PX,
                     this, app, DragController.DRAG_ACTION_COPY);
 
-            mLauncher.closeAllAppsDialog(true);
+            mLauncher.closeAllApps(true);
         }
         return true;
     }
@@ -294,15 +284,10 @@
 
     private static final int SCALE_SCALE = 100000;
 
-    public void show() {
-        mRollo.mState.read();
-        mRollo.mState.visible = 1;
-        mRollo.mState.zoom = SCALE_SCALE;
-        mRollo.mState.save();
-    }
-
     public void setScale(float amount) {
+        cancelLongPress();
         mRollo.mState.read();
+        mRollo.clearSelectedIcon();
         if (amount > 0.001f) {
             mRollo.mState.visible = 1;
             mRollo.mState.zoom = (int)(SCALE_SCALE*amount);
@@ -310,37 +295,21 @@
             mRollo.mState.visible = 0;
             mRollo.mState.zoom = 0;
         }
-        mRollo.mState.save();
-    }
-
-    public void hide() {
-        mRollo.mState.read();
-        mRollo.mState.visible = 0;
-        mRollo.mState.zoom = 0;
-        mRollo.mState.save();
-    }
-
-    /*
-    private TouchHandler mScrollHandler = new TouchHandler() {
-        @Override
-        public boolean onTouchEvent(MotionEvent ev)
-        {
-            int x = (int)ev.getX();
-            int w = getWidth();
-
-            float percent = x / (float)w;
-
-            mRollo.mState.read();
-
-            mRollo.mState.scrollX = mLastScrollX = -(int)(mPageCount * w * percent);
-            mRollo.mState.flingVelocityX = 0;
-            mRollo.mState.adjustedDeceleration = 0;
-            mRollo.mState.save();
-
-            return true;
+        if (amount > 0.001f && amount < 0.999f) {
+            mLocks |= LOCK_ZOOMING;
+        } else {
+            mLocks &= ~LOCK_ZOOMING;
         }
-    };
-    */
+        mRollo.mState.save();
+    }
+
+    public boolean isZooming() {
+        return (mLocks & LOCK_ZOOMING) != 0;
+    }
+
+    public boolean isVisible() {
+        return mRollo != null && mRollo.mState.visible != 0;
+    }
 
     @Override
     public boolean onTrackballEvent(MotionEvent ev)
@@ -362,7 +331,7 @@
         }
         mPageCount = countPages(list.size());
         Log.d(TAG, "setApps mRollo=" + mRollo + " list=" + list);
-        mLocked = false;
+        mLocks &= ~LOCK_ICONS_PENDING;
     }
 
     private void invokeIcon(int index) {
diff --git a/src/com/android/launcher2/HandleView.java b/src/com/android/launcher2/HandleView.java
index 98b3a37..7d2269a 100644
--- a/src/com/android/launcher2/HandleView.java
+++ b/src/com/android/launcher2/HandleView.java
@@ -49,7 +49,7 @@
     @Override
     public View focusSearch(int direction) {
         View newFocus = super.focusSearch(direction);
-        if (newFocus == null && mLauncher.isDrawerDown()) {
+        if (newFocus == null && mLauncher.isAllAppsVisible()) {
             final Workspace workspace = mLauncher.getWorkspace();
             workspace.dispatchUnhandledMove(null, direction);
             return (mOrientation == ORIENTATION_HORIZONTAL && direction == FOCUS_DOWN) ?
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index ec3622c..7be2a1b 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -177,7 +177,6 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
-    private boolean mAllAppsVisible; // if it's visible at all
     private int mMode = MODE_WORKSPACE;
 
     private Bundle mSavedState;
@@ -424,7 +423,7 @@
     @Override
     protected void onPause() {
         super.onPause();
-        closeAllAppsDialog(false);
+        closeAllApps(false);
     }
 
     @Override
@@ -812,7 +811,7 @@
                     mWorkspace.moveToDefaultScreen();
                 }
 
-                closeAllAppsDialog(true);
+                closeAllApps(true);
 
                 final View v = getWindow().peekDecorView();
                 if (v != null && v.getWindowToken() != null) {
@@ -821,7 +820,7 @@
                     imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                 }
             } else {
-                closeAllAppsDialog(false);
+                closeAllApps(false);
             }
         }
     }
@@ -853,7 +852,8 @@
 
         // When the drawer is opened and we are saving the state because of a
         // configuration change
-        if (mAllAppsVisible && isConfigurationChange) {
+        // TODO should not do this if the drawer is currently closing.
+        if (isAllAppsVisible() && isConfigurationChange) {
             outState.putBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, true);
         }
 
@@ -906,7 +906,7 @@
     public void startSearch(String initialQuery, boolean selectInitialQuery,
             Bundle appSearchData, boolean globalSearch) {
 
-        closeAllAppsDialog(false);
+        closeAllApps(false);
 
         // Slide the search widget to the top, if it's on the current screen,
         // otherwise show the search dialog immediately.
@@ -1282,8 +1282,8 @@
                 case KeyEvent.KEYCODE_BACK:
                     if (!event.isCanceled()) {
                         mWorkspace.dispatchKeyEvent(event);
-                        if (mAllAppsVisible) {
-                            closeAllAppsDialog(true);
+                        if (isAllAppsVisible()) {
+                            closeAllApps(true);
                         } else {
                             closeFolder();
                         }
@@ -1341,10 +1341,11 @@
         } else if (tag instanceof FolderInfo) {
             handleFolderClick((FolderInfo) tag);
         } else if (v == mHandleView) {
-            if (mAllAppsVisible) {
-                // TODO how can we be here?
+            Log.d(TAG, "onClick");
+            if (isAllAppsVisible()) {
+                closeAllApps(true);
             } else {
-                showAllAppsDialog();
+                showAllApps(true);
             }
         }
     }
@@ -1453,10 +1454,6 @@
         return mHandleView;
     }
 
-    boolean isDrawerDown() { // TODO rename to isAllAppsVisible()
-        return /* TODO !mDrawer.isMoving() && */ !mAllAppsVisible;
-    }
-
     Workspace getWorkspace() {
         return mWorkspace;
     }
@@ -1605,26 +1602,44 @@
         }
     }
 
-    void showAllAppsDialog() {
-        mAllAppsVisible = true;
-        mAllAppsGrid.show();
+    boolean isAllAppsVisible() {
+        return mAllAppsGrid.isZooming() || mAllAppsGrid.isVisible();
+    }
+
+    void showAllApps(boolean animated) {
+        if (mMode == MODE_ALL_APPS) {
+            return;
+        }
+
+        mSwipeController.setRange(-1, 0);
+        if (animated) {
+            mSwipeController.animate(-1);
+        } else {
+            mSwipeController.setImmediate(-1);
+        }
+
         mWorkspace.hide();
         
         // TODO: fade these two too
         mDeleteZone.setVisibility(View.GONE);
-        mHandleView.setVisibility(View.GONE);
+        //mHandleView.setVisibility(View.GONE);
     }
 
-    void closeAllAppsDialog(boolean animated) {
-        if (mAllAppsVisible) {
-            mAllAppsGrid.hide();
-            mAllAppsVisible = false;
+    void closeAllApps(boolean animated) {
+        if (mAllAppsGrid.isVisible()) {
+            mSwipeController.setRange(0, 1);
+            if (animated) {
+                mSwipeController.animate(1);
+            } else {
+                mSwipeController.setImmediate(1);
+            }
             mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
-            mWorkspace.show();
 
             // TODO: fade these two too
+            /*
             mDeleteZone.setVisibility(View.VISIBLE);
             mHandleView.setVisibility(View.VISIBLE);
+            */
         }
     }
 
@@ -1777,6 +1792,7 @@
         switch (mMode) {
         case MODE_WORKSPACE:
             if (amount == -1) {
+                setWorkspaceAndAllAppsScale(-amount);
                 mWorkspace.clearChildrenCache();
                 mMode = MODE_ALL_APPS;
                 mSwipeController.setRange(0, 1);
@@ -1784,6 +1800,7 @@
             break;
         case MODE_ALL_APPS:
             if (amount == 1) {
+                setWorkspaceAndAllAppsScale(1-amount);
                 mWorkspace.clearChildrenCache();
                 mMode = MODE_WORKSPACE;
                 mSwipeController.setRange(-1, 0);
@@ -1983,7 +2000,7 @@
 
             final boolean allApps = mSavedState.getBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, false);
             if (allApps) {
-                showAllAppsDialog();
+                showAllApps(false);
             }
 
             mSavedState = null;
diff --git a/src/com/android/launcher2/SwipeController.java b/src/com/android/launcher2/SwipeController.java
index 7443b3b..41a02f0 100644
--- a/src/com/android/launcher2/SwipeController.java
+++ b/src/com/android/launcher2/SwipeController.java
@@ -143,6 +143,41 @@
         return mTracking || mCanceled;
     }
 
+    /**
+     * Set the value, performing an animation.  Make sure that you have set the
+     * range properly first, otherwise the value may be clamped.
+     */
+    public void animate(float dest) {
+        go(dest, 0);
+    }
+
+    /**
+     * Set the value, but don't perform an animation.  Make sure that you have set the
+     * range properly first, otherwise the value may be clamped.
+     */
+    public void setImmediate(float dest) {
+        go(dest, dest);
+    }
+
+    /**
+     * Externally start a swipe.  If dest == amount, this will end up just immediately
+     * setting the value, but it will perform the proper start and finish callbacks.
+     */
+    private void go(float dest, float amount) {
+        mListener.onStartSwipe();
+
+        dest = clamp(dest);
+        mDirection = dest > amount ? 1 : -1; // if they're equal it doesn't matter
+        mVelocity = mDirection * 0.002f; // TODO: density.
+        mAmount = amount;
+        mDest = dest;
+
+        mFlingTime = SystemClock.uptimeMillis();
+        mLastTime = 0;
+
+        scheduleAnim();
+    }
+
     private float clamp(float v) {
         if (v < mMinDest) {
             return mMinDest;
@@ -165,6 +200,7 @@
         mVelocityTracker.computeCurrentVelocity(1);
 
         mVelocity = mVelocityTracker.getYVelocity() / mSwipeDistance;
+        Log.d(TAG, "mVelocity=" + mVelocity);
         mDirection = mVelocity >= 0.0f ? 1 : -1;
         mAmount = clamp((screenY-mDownY)/mSwipeDistance);
         if (mAmount < 0) {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 01985e9..2fe4113 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -600,7 +600,7 @@
 
     @Override
     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        if (mLauncher.isDrawerDown()) {
+        if (mLauncher.isAllAppsVisible()) {
             final Folder openFolder = getOpenFolder();
             if (openFolder != null) {
                 return openFolder.requestFocus(direction, previouslyFocusedRect);
@@ -635,7 +635,7 @@
 
     @Override
     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if (mLauncher.isDrawerDown()) {
+        if (mLauncher.isAllAppsVisible()) {
             final Folder openFolder = getOpenFolder();
             if (openFolder == null) {
                 getChildAt(mCurrentScreen).addFocusables(views, direction);
@@ -656,7 +656,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
+        if (mLauncher.isWorkspaceLocked() || !mLauncher.isAllAppsVisible()) {
             return false; // We don't want the events.  Let them fall through to the all apps view.
         }
 
@@ -766,7 +766,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
 
-        if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
+        if (mLauncher.isWorkspaceLocked() || !mLauncher.isAllAppsVisible()) {
             return false; // We don't want the events.  Let them fall through to the all apps view.
         }