Fixing up PagedView to work in landscape mode

-> separated notion of page spacing and paged view padding
-> always position the current page within the rect
   created by pagedview's viewport + padding
-> space pages by a constant amount

Change-Id: I6bb35f72f04543f83b51ef981f8c9ded051623ac
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 77ea2e9..5874c80 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -37,7 +37,6 @@
             android:layout_height="match_parent"
             android:layout_gravity="center"
             launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
-            launcher:pageSpacing="@dimen/workspace_page_spacing"
             launcher:pageIndicator="@id/page_indicator" />
 
         <include layout="@layout/hotseat"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 6fbf7c7..49e6b6a 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -35,7 +35,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
-            launcher:pageSpacing="@dimen/workspace_page_spacing"
             launcher:pageIndicator="@id/page_indicator">
         </com.android.launcher3.Workspace>
 
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 951e63a..7dac271 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -36,7 +36,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
-            launcher:pageSpacing="@dimen/workspace_page_spacing"
             launcher:pageIndicator="@id/page_indicator">
         </com.android.launcher3.Workspace>
 
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 5961b19..07d9279 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -19,11 +19,6 @@
     <dimen name="toolbar_button_vertical_padding">8dip</dimen>
     <dimen name="toolbar_button_horizontal_padding">0dip</dimen>
 
-<!-- Workspace -->
-    <!-- We really want the page spacing to be the max of either the button bar
-     height or the qsb bar height -->
-    <dimen name="workspace_page_spacing">-1dp</dimen>
-
 <!-- AppsCustomize -->
     <dimen name="apps_customize_tab_bar_height">42dp</dimen>
     <integer name="apps_customize_widget_cell_count_x">3</integer>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 7194a2a..7753ab3 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -15,9 +15,6 @@
 -->
 
 <resources>
-<!-- Workspace -->
-    <dimen name="workspace_page_spacing">-1dp</dimen>
-
 <!-- AppsCustomize -->
     <integer name="apps_customize_cling_focused_x">1</integer>
     <integer name="apps_customize_cling_focused_y">1</integer>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index eb8f83c..433a5d4 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -21,9 +21,6 @@
     <integer name="apps_customize_cling_focused_x">4</integer>
     <integer name="apps_customize_cling_focused_y">2</integer>
 
-<!-- Workspace -->
-    <dimen name="workspace_page_spacing">50dp</dimen>
-
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">100dip</dimen>
diff --git a/res/values-sw720dp-port/dimens.xml b/res/values-sw720dp-port/dimens.xml
index 62bdaaa..9fe312b 100644
--- a/res/values-sw720dp-port/dimens.xml
+++ b/res/values-sw720dp-port/dimens.xml
@@ -19,7 +19,6 @@
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">40dp</dimen>
-    <dimen name="workspace_page_spacing">24dp</dimen>
 
     <integer name="apps_customize_cling_focused_x">2</integer>
     <integer name="apps_customize_cling_focused_y">2</integer>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index a2d3a83..0006a74 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -103,8 +103,7 @@
         <attr name="pageLayoutPaddingBottom" format="dimension" />
         <attr name="pageLayoutPaddingLeft" format="dimension" />
         <attr name="pageLayoutPaddingRight" format="dimension" />
-        <!-- The space between adjacent pages of the PagedView. -->
-        <attr name="pageSpacing" format="dimension" />
+
         <!-- The page indicator for this workspace -->
         <attr name="pageIndicator" format="reference" />
     </declare-styleable>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index dcddc09..d87fb14 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -21,6 +21,7 @@
     <dimen name="dynamic_grid_search_bar_height">48dp</dimen>
     <dimen name="dynamic_grid_page_indicator_height">24dp</dimen>
     <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
+    <dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
 
 <!-- Wallpaper picker -->
     <dimen name="wallpaperThumbnailWidth">106.5dp</dimen>
@@ -41,7 +42,6 @@
 <!-- Workspace -->
     <dimen name="workspace_max_gap">16dp</dimen>
     <dimen name="workspace_overscroll_drawable_padding">0dp</dimen>
-    <dimen name="workspace_spring_loaded_page_spacing">15dp</dimen>
     <dimen name="overview_panel_bottom_padding">50dp</dimen>
     <dimen name="overview_panel_buttonSpacing">60dp</dimen>
     <dimen name="overview_mode_page_offset">130dp</dimen>
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index d90deca..ccbac2c 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -84,6 +84,7 @@
     int heightPx;
     int availableWidthPx;
     int availableHeightPx;
+    int defaultPageSpacingPx;
 
     int iconSizePx;
     int iconTextSizePx;
@@ -132,21 +133,24 @@
                   float minWidth, float minHeight,
                   int wPx, int hPx,
                   int awPx, int ahPx,
-                  Resources resources) {
-        DisplayMetrics dm = resources.getDisplayMetrics();
+                  Resources res) {
+        DisplayMetrics dm = res.getDisplayMetrics();
         ArrayList<DeviceProfileQuery> points =
                 new ArrayList<DeviceProfileQuery>();
         transposeLayoutWithOrientation =
-                resources.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+                res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
         minWidthDps = minWidth;
         minHeightDps = minHeight;
 
         ComponentName cn = new ComponentName(context.getPackageName(),
                 this.getClass().getName());
         defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
-        edgeMarginPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
+        edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
         desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx;
-        pageIndicatorHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
+        pageIndicatorHeightPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
+        defaultPageSpacingPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
 
         // Interpolate the rows
         for (DeviceProfile p : profiles) {
@@ -180,7 +184,8 @@
             points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize));
         }
         iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
-        iconDrawablePaddingOriginalPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
+        iconDrawablePaddingOriginalPx =
+                res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
 
         // Interpolate the hotseat icon size
         points.clear();
@@ -191,7 +196,7 @@
         hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
 
         // Calculate the remaining vars
-        updateFromConfiguration(context, resources, wPx, hPx, awPx, ahPx);
+        updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
         updateAvailableDimensions(context);
     }
 
@@ -382,6 +387,7 @@
     Rect getWorkspacePadding() {
         return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
     }
+
     Rect getWorkspacePadding(int orientation) {
         Rect padding = new Rect();
         if (orientation == CellLayout.LANDSCAPE &&
@@ -415,6 +421,19 @@
         return padding;
     }
 
+    int getWorkspacePageSpacing(int orientation) {
+        if (orientation == CellLayout.LANDSCAPE &&
+                transposeLayoutWithOrientation) {
+            // In landscape mode the page spacing is set to the default.
+            return defaultPageSpacingPx;
+        } else {
+            // In portrait, we want the pages spaced such that there is no
+            // overhang of the previous / next page into the current page viewport.
+            // We assume symmetrical padding in portrait mode.
+            return getWorkspacePadding().left;
+        }
+    }
+
     // The rect returned will be extended to below the system ui that covers the workspace
     Rect getHotseatRect() {
         if (isVerticalBarLayout()) {
@@ -447,6 +466,10 @@
         return isLandscape && transposeLayoutWithOrientation;
     }
 
+    boolean shouldFadeAdjacentWorkspaceScreens() {
+        return isVerticalBarLayout() || isLargeTablet();
+    }
+
     public void layout(Launcher launcher) {
         FrameLayout.LayoutParams lp;
         Resources res = launcher.getResources();
@@ -497,15 +520,14 @@
         }
 
         // Layout the workspace
-        View workspace = launcher.findViewById(R.id.workspace);
+        PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
         lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
         lp.gravity = Gravity.CENTER;
-        Rect padding = getWorkspacePadding(isLandscape
-                ? CellLayout.LANDSCAPE
-                : CellLayout.PORTRAIT);
-        workspace.setPadding(padding.left, padding.top,
-                padding.right, padding.bottom);
+        int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT;
+        Rect padding = getWorkspacePadding(orientation);
         workspace.setLayoutParams(lp);
+        workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+        workspace.setPageSpacing(getWorkspacePageSpacing(orientation));
 
         // Layout the hotseat
         View hotseat = launcher.findViewById(R.id.hotseat);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 9b891e4..5146e14 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -124,6 +124,7 @@
     protected int mMaxScrollX;
     protected Scroller mScroller;
     private VelocityTracker mVelocityTracker;
+    private int mPageSpacing = 0;
 
     private float mParentDownMotionX;
     private float mParentDownMotionY;
@@ -785,13 +786,13 @@
         // NOTE: We multiply by 1.5f to account for the fact that depending on the offset of the
         // viewport, we can be at most one and a half screens offset once we scale down
         DisplayMetrics dm = getResources().getDisplayMetrics();
-        int maxSize = Math.max(dm.widthPixels, dm.heightPixels + mInsets.top + mInsets.bottom);
+        int maxSize = Math.max(dm.widthPixels + mInsets.left + mInsets.right,
+                dm.heightPixels + mInsets.top + mInsets.bottom);
 
-        int parentWidthSize, parentHeightSize;
+        int parentWidthSize = (int) (1.5f * maxSize);
+        int parentHeightSize = maxSize;
         int scaledWidthSize, scaledHeightSize;
         if (mUseMinScale) {
-            parentWidthSize = (int) (1.5f * maxSize);
-            parentHeightSize = maxSize;
             scaledWidthSize = (int) (parentWidthSize / mMinScale);
             scaledHeightSize = (int) (parentHeightSize / mMinScale);
         } else {
@@ -851,21 +852,17 @@
                         childHeightMode = MeasureSpec.EXACTLY;
                     }
 
-                    childWidth = widthSize - horizontalPadding;
-                    childHeight = heightSize - verticalPadding - mInsets.top - mInsets.bottom;
+                    childWidth = getViewportWidth() - horizontalPadding
+                            - mInsets.left - mInsets.right;
+                    childHeight = getViewportHeight() - verticalPadding
+                            - mInsets.top - mInsets.bottom;
                     mNormalChildHeight = childHeight;
-
                 } else {
                     childWidthMode = MeasureSpec.EXACTLY;
                     childHeightMode = MeasureSpec.EXACTLY;
 
-                    if (mUseMinScale) {
-                        childWidth = getViewportWidth();
-                        childHeight = getViewportHeight();
-                    } else {
-                        childWidth = widthSize - getPaddingLeft() - getPaddingRight();
-                        childHeight = heightSize - getPaddingTop() - getPaddingBottom();
-                    }
+                    childWidth = getViewportWidth() - mInsets.left - mInsets.right;
+                    childHeight = getViewportHeight();
                 }
 
                 final int childWidthMeasureSpec =
@@ -887,8 +884,6 @@
         if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
         final int childCount = getChildCount();
 
-        int screenWidth = getViewportWidth();
-
         int offsetX = getViewportOffsetX();
         int offsetY = getViewportOffsetY();
 
@@ -903,7 +898,9 @@
 
         int verticalPadding = getPaddingTop() + getPaddingBottom();
 
-        int childLeft = offsetX + (screenWidth - getChildWidth(startIndex)) / 2;
+        LayoutParams lp = (LayoutParams) getChildAt(startIndex).getLayoutParams();
+
+        int childLeft = offsetX + (lp.isFullScreenPage ? 0 : getPaddingLeft());
         if (mPageScrolls == null || getChildCount() != mChildCountOnLastLayout) {
             mPageScrolls = new int[getChildCount()];
         }
@@ -911,7 +908,7 @@
         for (int i = startIndex; i != endIndex; i += delta) {
             final View child = getPageAt(i);
             if (child.getVisibility() != View.GONE) {
-                LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                lp = (LayoutParams) child.getLayoutParams();
                 int childTop;
                 if (lp.isFullScreenPage) {
                     childTop = offsetY;
@@ -929,16 +926,9 @@
                 child.layout(childLeft, childTop,
                         childLeft + child.getMeasuredWidth(), childTop + childHeight);
 
-                // We assume the left and right padding are equal, and hence center the pages
-                // horizontally
-                int scrollOffset = (getViewportWidth() - childWidth) / 2;
-                mPageScrolls[i] = childLeft - scrollOffset - offsetX;
-
-                if (i != endIndex - delta) {
-                    childLeft += childWidth + scrollOffset;
-                    int nextScrollOffset = (getViewportWidth() - getChildWidth(i + delta)) / 2;
-                    childLeft += nextScrollOffset;
-                }
+                int scrollOffsetLeft = lp.isFullScreenPage ? 0 : getPaddingLeft();
+                mPageScrolls[i] = childLeft - scrollOffsetLeft - offsetX;
+                childLeft += childWidth + mPageSpacing;
             }
         }
 
@@ -972,6 +962,11 @@
         }
     }
 
+    public void setPageSpacing(int pageSpacing) {
+        mPageSpacing = pageSpacing;
+        requestLayout();
+    }
+
     protected void screenScrolled(int screenCenter) {
         boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
 
@@ -1278,24 +1273,22 @@
      * Return true if a tap at (x, y) should trigger a flip to the previous page.
      */
     protected boolean hitsPreviousPage(float x, float y) {
-        int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2;
         if (isLayoutRtl()) {
             return (x > (getViewportOffsetX() + getViewportWidth() -
-                    offset));
+                    getPaddingRight() - mPageSpacing));
         }
-        return (x < getViewportOffsetX() + offset);
+        return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing);
     }
 
     /**
      * Return true if a tap at (x, y) should trigger a flip to the next page.
      */
     protected boolean hitsNextPage(float x, float y) {
-        int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2;
         if (isLayoutRtl()) {
-            return (x < getViewportOffsetX() + offset);
+            return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing);
         }
         return  (x > (getViewportOffsetX() + getViewportWidth() -
-                offset));
+                getPaddingRight() - mPageSpacing));
     }
 
     /** Returns whether x and y originated within the buffered viewport */
@@ -1486,9 +1479,21 @@
     protected float getScrollProgress(int screenCenter, View v, int page) {
         final int halfScreenSize = getViewportWidth() / 2;
 
-        int offset = (getViewportWidth() - getChildWidth(page)) / 2;
-        int totalDistance = v.getMeasuredWidth() + offset;
         int delta = screenCenter - (getScrollForPage(page) + halfScreenSize);
+        int count = getChildCount();
+
+        final int totalDistance;
+
+        int adjacentPage = page + 1;
+        if ((delta < 0 && !isLayoutRtl()) || (delta > 0 && isLayoutRtl())) {
+            adjacentPage = page - 1;
+        }
+
+        if (adjacentPage < 0 || adjacentPage > count - 1) {
+            totalDistance = v.getMeasuredWidth() + mPageSpacing;
+        } else {
+            totalDistance = Math.abs(getScrollForPage(adjacentPage) - getScrollForPage(page));
+        }
 
         float scrollProgress = delta / (totalDistance * 1.0f);
         scrollProgress = Math.min(scrollProgress, getMaxScrollProgress());
@@ -1511,7 +1516,13 @@
             return 0;
         } else {
             View child = getChildAt(index);
-            int scrollOffset = (getViewportWidth() - child.getMeasuredWidth()) / 2;
+
+            int scrollOffset = 0;
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (!lp.isFullScreenPage) {
+                scrollOffset = isLayoutRtl() ? getPaddingRight() : getPaddingLeft();
+            }
+
             int baselineX = mPageScrolls[index] + scrollOffset + getViewportOffsetX();
             return (int) (child.getX() - baselineX);
         }
@@ -2575,10 +2586,9 @@
                     int newX = 0;
                     if (slideFromLeft) {
                         if (i == 0) {
-                            int pageSpace = (getViewportWidth() - getChildWidth(i)) / 2;
                             // Simulate the page being offscreen with the page spacing
                             oldX = getViewportOffsetX() + getChildOffset(i) - getChildWidth(i)
-                                    - pageSpace;
+                                    - mPageSpacing;
                         } else {
                             oldX = getViewportOffsetX() + getChildOffset(i - 1);
                         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index d742d42..8e29b40 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -310,7 +310,8 @@
 
         mLauncher = (Launcher) context;
         final Resources res = getResources();
-        mWorkspaceFadeInAdjacentScreens = res.getBoolean(R.bool.config_workspaceFadeAdjacentScreens);
+        mWorkspaceFadeInAdjacentScreens = LauncherAppState.getInstance().getDynamicGrid().
+                getDeviceProfile().shouldFadeAdjacentWorkspaceScreens();
         mFadeInAdjacentScreens = false;
         mWallpaperManager = WallpaperManager.getInstance(context);
 
@@ -1488,12 +1489,6 @@
                     float scrollProgress = getScrollProgress(screenCenter, child, i);
                     float alpha = 1 - Math.abs(scrollProgress);
                     child.getShortcutsAndWidgets().setAlpha(alpha);
-                    if (!mIsDragOccuring) {
-                        child.setBackgroundAlphaMultiplier(
-                                backgroundAlphaInterpolator(Math.abs(scrollProgress)));
-                    } else {
-                        child.setBackgroundAlphaMultiplier(1f);
-                    }
                 }
             }
         }
@@ -2108,7 +2103,14 @@
             final CellLayout cl = (CellLayout) getChildAt(i);
             boolean isCurrentPage = (i == getNextPage());
             float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
-            float finalAlpha = stateIsSmall ? 0f : 1f;
+            float finalAlpha;
+            if (stateIsSmall) {
+                finalAlpha = 0f;
+            } else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
+                finalAlpha = i == getNextPage() ? 1f : 0f;
+            } else {
+                finalAlpha = 1f;
+            }
 
             // If we are animating to/from the small state, then hide the side pages and fade the
             // current page in