Bug 701594 - Part 2: Don't duplicate state in the layer controller and pan zoom controller axes. r=kats
authorPatrick Walton <pwalton@mozilla.com>
Wed, 07 Dec 2011 10:44:02 -0800
changeset 83828 953247b411fa6bbb6c5c422d854c16086b247093
parent 83827 ffd93ca68fd798ec54ef43e3ba3698f3afcdb438
child 83829 fe9f200f7d289c39647d46267370304402abf914
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs701594
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 701594 - Part 2: Don't duplicate state in the layer controller and pan zoom controller axes. r=kats
mobile/android/base/ui/PanZoomController.java
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -107,17 +107,20 @@ public class PanZoomController
         0.86069f,   /* 11 */
         0.90651f,   /* 12 */
         0.94471f,   /* 13 */
         0.97401f,   /* 14 */
         0.99309f,   /* 15 */
     };
 
     private Timer mFlingTimer;
-    private Axis mX, mY;
+    /* Information about the X axis. */
+    private AxisX mX;
+    /* Information about the Y axis. */
+    private AxisY mY;
     /* The zoom focus at the first zoom event (in page coordinates). */
     private PointF mLastZoomFocus;
     /* The time the last motion event took place. */
     private long mLastEventTime;
 
     private enum PanZoomState {
         NOTHING,        /* no touch-start events received */
         FLING,          /* all touches removed, but we're still scrolling page */
@@ -134,21 +137,19 @@ public class PanZoomController
     private PanZoomState mState;
 
     private boolean mOverridePanning;
     private boolean mOverrideScrollAck;
     private boolean mOverrideScrollPending;
 
     public PanZoomController(LayerController controller) {
         mController = controller;
-        mX = new Axis(); mY = new Axis();
+        mX = new AxisX(); mY = new AxisY();
         mState = PanZoomState.NOTHING;
 
-        populatePositionAndLength();
-
         GeckoAppShell.registerGeckoEventListener("Browser:ZoomToRect", this);
         GeckoAppShell.registerGeckoEventListener("Browser:ZoomToPageWidth", this);
         GeckoAppShell.registerGeckoEventListener("Panning:Override", this);
         GeckoAppShell.registerGeckoEventListener("Panning:CancelOverride", this);
         GeckoAppShell.registerGeckoEventListener("Gesture:ScrollAck", this);
     }
 
     protected void finalize() throws Throwable {
@@ -221,18 +222,16 @@ public class PanZoomController
         case MotionEvent.ACTION_MOVE:   return onTouchMove(event);
         case MotionEvent.ACTION_UP:     return onTouchEnd(event);
         case MotionEvent.ACTION_CANCEL: return onTouchCancel(event);
         default:                        return false;
         }
     }
 
     public void geometryChanged(boolean aAbortFling) {
-        populatePositionAndLength();
-
         if (aAbortFling) {
             // this happens when gecko changes the viewport on us. if that's the case, abort
             // any fling that's in progress and re-fling so that the page snaps to edges. for
             // other cases (where the user's finger(s) are down) don't do anything special.
             switch (mState) {
             case FLING:
                 mX.velocity = mY.velocity = 0.0f;
                 mState = PanZoomState.NOTHING;
@@ -512,37 +511,21 @@ public class PanZoomController
                 Log.e(LOGTAG, "Error forming Gesture:Scroll message: " + e);
             }
 
             GeckoEvent e = new GeckoEvent("Gesture:Scroll", json.toString());
             GeckoAppShell.sendEventToGecko(e);
             mOverrideScrollAck = false;
         } else {
             mController.scrollBy(new PointF(mX.displacement, mY.displacement));
-            mX.viewportPos += mX.displacement;
-            mY.viewportPos += mY.displacement;
         }
 
         mX.displacement = mY.displacement = 0;
     }
 
-    // Populates the viewport info and length in the axes.
-    private void populatePositionAndLength() {
-        FloatSize pageSize = mController.getPageSize();
-        RectF visibleRect = mController.getViewport();
-
-        mX.setPageLength(pageSize.width);
-        mX.viewportPos = visibleRect.left;
-        mX.setViewportLength(visibleRect.width());
-
-        mY.setPageLength(pageSize.height);
-        mY.viewportPos = visibleRect.top;
-        mY.setViewportLength(visibleRect.height());
-    }
-
     // The callback that performs the fling animation.
     private class FlingRunnable implements Runnable {
         public void run() {
             mX.advanceFling(); mY.advanceFling();
 
             if (!mOverridePanning) {
                 // If both X and Y axes are overscrolled, we have to wait until both axes have stopped
                 // to snap back to avoid a jarring effect.
@@ -585,17 +568,17 @@ public class PanZoomController
         }
     }
 
     private float computeElasticity(float excess, float viewportLength) {
         return 1.0f - excess / (viewportLength * SNAP_LIMIT);
     }
 
     // Physics information for one axis (X or Y).
-    private static class Axis {
+    private abstract static class Axis {
         public enum FlingStates {
             STOPPED,
             PANNING,
             FLINGING,
             WAITING_TO_SNAP,
             SNAPPING,
         }
 
@@ -610,69 +593,63 @@ public class PanZoomController
         public float touchPos;                  /* Position of the most recent touch event on the current drag. */
         public float lastTouchPos;              /* Position of the touch event before touchPos. */
         public float velocity;                  /* Velocity in this direction. */
         public boolean locked;                  /* Whether movement on this axis is locked. */
         public boolean disableSnap;             /* Whether overscroll snapping is disabled. */
 
         private FlingStates mFlingState;        /* The fling state we're in on this axis. */
 
-        /* These three need to be kept in sync with the layer controller. */
-        private float viewportPos;
-        private float mViewportLength;
-        private int mScreenLength;
-        private float mPageLength;
+        public abstract float getOrigin();
+        protected abstract float getViewportLength();
+        protected abstract float getPageLength();
 
         public float displacement;
 
         private int mSnapFrame;
         private float mSnapPos, mSnapEndPos;
 
         public Axis() { mSnapFrame = -1; }
 
         public FlingStates getFlingState() { return mFlingState; }
 
         public void setFlingState(FlingStates aFlingState) {
             mFlingState = aFlingState;
         }
 
-        public void setViewportLength(float viewportLength) { mViewportLength = viewportLength; }
-        public void setScreenLength(int screenLength) { mScreenLength = screenLength; }
-        public void setPageLength(float pageLength) { mPageLength = pageLength; }
-
-        private float getViewportEnd() { return viewportPos + mViewportLength; }
+        private float getViewportEnd() { return getOrigin() + getViewportLength(); }
 
         public Overscroll getOverscroll() {
-            boolean minus = (viewportPos < 0.0f);
-            boolean plus = (getViewportEnd() > mPageLength);
+            boolean minus = (getOrigin() < 0.0f);
+            boolean plus = (getViewportEnd() > getPageLength());
             if (minus && plus)
                 return Overscroll.BOTH;
             else if (minus)
                 return Overscroll.MINUS;
             else if (plus)
                 return Overscroll.PLUS;
             else
                 return Overscroll.NONE;
         }
 
         // Returns the amount that the page has been overscrolled. If the page hasn't been
         // overscrolled on this axis, returns 0.
         private float getExcess() {
             switch (getOverscroll()) {
-            case MINUS:     return Math.min(-viewportPos, mPageLength - getViewportEnd());
-            case PLUS:      return Math.min(viewportPos, getViewportEnd() - mPageLength);
+            case MINUS:     return Math.min(-getOrigin(), getPageLength() - getViewportEnd());
+            case PLUS:      return Math.min(getOrigin(), getViewportEnd() - getPageLength());
             default:        return 0.0f;
             }
         }
 
         // Applies resistance along the edges when tracking.
         public void applyEdgeResistance() {
             float excess = getExcess();
             if (excess > 0.0f)
-                velocity *= SNAP_LIMIT - excess / mViewportLength;
+                velocity *= SNAP_LIMIT - excess / getViewportLength();
         }
 
         public void startFling(boolean stopped) {
             if (!stopped) {
                 setFlingState(FlingStates.FLINGING);
                 return;
             }
 
@@ -706,17 +683,17 @@ public class PanZoomController
                 if (Math.abs(velocity) < 0.1f) {
                     velocity = 0.0f;
                     setFlingState(FlingStates.STOPPED);
                 }
                 return;
             }
 
             // Otherwise, decrease the velocity linearly.
-            float elasticity = 1.0f - excess / (mViewportLength * SNAP_LIMIT);
+            float elasticity = 1.0f - excess / (getViewportLength() * SNAP_LIMIT);
             if (getOverscroll() == Overscroll.MINUS)
                 velocity = Math.min((velocity + OVERSCROLL_DECEL_RATE) * elasticity, 0.0f);
             else // must be Overscroll.PLUS
                 velocity = Math.max((velocity - OVERSCROLL_DECEL_RATE) * elasticity, 0.0f);
 
             if (Math.abs(velocity) < 0.3f) {
                 velocity = 0.0f;
                 setFlingState(FlingStates.WAITING_TO_SNAP);
@@ -770,16 +747,34 @@ public class PanZoomController
 
             if (mFlingState == FlingStates.PANNING)
                 displacement += lastTouchPos - touchPos;
             else
                 displacement += velocity;
         }
     }
 
+    private class AxisX extends Axis {
+        @Override
+        public float getOrigin() { return mController.getOrigin().x; }
+        @Override
+        protected float getViewportLength() { return mController.getViewportSize().width; }
+        @Override
+        protected float getPageLength() { return mController.getPageSize().width; }
+    }
+
+    private class AxisY extends Axis {
+        @Override
+        public float getOrigin() { return mController.getOrigin().y; }
+        @Override
+        protected float getViewportLength() { return mController.getViewportSize().height; }
+        @Override
+        protected float getPageLength() { return mController.getPageSize().height; }
+    }
+
     /*
      * Zooming
      */
     @Override
     public boolean onScale(ScaleGestureDetector detector) {
         if (mState == PanZoomState.ANIMATED_ZOOM)
             return false;
 
@@ -957,17 +952,16 @@ public class PanZoomController
                     });
                 } else {
                     mController.post(new Runnable() {
                         public void run() {
                             mController.scaleWithOrigin(finalZoom, finalPoint);
                             mController.setForceRedraw();
                             GeckoApp.mAppContext.showPluginViews();
                             mController.notifyLayerClientOfGeometryChange();
-                            populatePositionAndLength();
                         }
                     });
                     mZoomTimer.cancel();
                     mZoomTimer = null;
                     mState = PanZoomState.NOTHING;
                }
             }
         }, 0, 1000L/60L);