Merge "launcher: use scalable grid in 4x4" into sc-v2-dev
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 65b46cf..720d736 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -180,6 +180,16 @@
         <!-- These min cell values are only used if GridDisplayOption#isScalable is true-->
         <attr name="minCellHeightDps" format="float" />
         <attr name="minCellWidthDps" format="float" />
+        <!-- twoPanelPortraitMinCellWidthDps defaults to minCellHeightDps, if not specified -->
+        <attr name="twoPanelPortraitMinCellHeightDps" format="float" />
+        <!-- twoPanelPortraitMinCellHeightDps defaults to minCellWidthDps, if not specified -->
+        <attr name="twoPanelPortraitMinCellWidthDps" format="float" />
+        <!-- twoPanelLandscapeMinCellHeightDps defaults to twoPanelPortraitMinCellHeightDps,
+        if not specified -->
+        <attr name="twoPanelLandscapeMinCellHeightDps" format="float" />
+        <!-- twoPanelLandscapeMinCellWidthDps defaults to twoPanelPortraitMinCellWidthDps,
+        if not specified -->
+        <attr name="twoPanelLandscapeMinCellWidthDps" format="float" />
 
         <attr name="borderSpacingDps" format="float" />
 
diff --git a/src/com/android/launcher3/DevicePaddings.java b/src/com/android/launcher3/DevicePaddings.java
index 7c387b1..08fb47b 100644
--- a/src/com/android/launcher3/DevicePaddings.java
+++ b/src/com/android/launcher3/DevicePaddings.java
@@ -36,12 +36,12 @@
  * The unused or "extra" height is allocated to three different variable heights:
  * - The space above the workspace
  * - The space between the workspace and hotseat
- * - The espace below the hotseat
+ * - The space below the hotseat
  */
 public class DevicePaddings {
 
-    private static final String DEVICE_PADDING = "device-paddings";
-    private static final String DEVICE_PADDINGS = "device-padding";
+    private static final String DEVICE_PADDINGS = "device-paddings";
+    private static final String DEVICE_PADDING = "device-padding";
 
     private static final String WORKSPACE_TOP_PADDING = "workspaceTopPadding";
     private static final String WORKSPACE_BOTTOM_PADDING = "workspaceBottomPadding";
@@ -58,13 +58,13 @@
             int type;
             while (((type = parser.next()) != XmlPullParser.END_TAG ||
                     parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
-                if ((type == XmlPullParser.START_TAG) && DEVICE_PADDING.equals(parser.getName())) {
+                if ((type == XmlPullParser.START_TAG) && DEVICE_PADDINGS.equals(parser.getName())) {
                     final int displayDepth = parser.getDepth();
                     while (((type = parser.next()) != XmlPullParser.END_TAG ||
                             parser.getDepth() > displayDepth)
                             && type != XmlPullParser.END_DOCUMENT) {
                         if ((type == XmlPullParser.START_TAG)
-                                && DEVICE_PADDINGS.equals(parser.getName())) {
+                                && DEVICE_PADDING.equals(parser.getName())) {
                             TypedArray a = context.obtainStyledAttributes(
                                     Xml.asAttributeSet(parser), R.styleable.DevicePadding);
                             int maxWidthPx = a.getDimensionPixelSize(
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index b7d0481..3121bfc 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -33,6 +33,7 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
+import android.util.Pair;
 import android.view.Surface;
 
 import com.android.launcher3.CellLayout.ContainerType;
@@ -576,8 +577,9 @@
             // We scale to fit the cellWidth and cellHeight in the available space.
             // The benefit of scalable grids is that we can get consistent aspect ratios between
             // devices.
-            float usedWidth = (cellWidthPx * inv.numColumns)
-                    + (cellLayoutBorderSpacingPx * (inv.numColumns - 1))
+            int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+            float usedWidth = (cellWidthPx * numColumns)
+                    + (cellLayoutBorderSpacingPx * (numColumns - 1))
                     + (desiredWorkspaceLeftRightMarginPx * 2);
             // We do not subtract padding here, as we also scale the workspace padding if needed.
             scaleX = availableWidthPx / usedWidth;
@@ -638,8 +640,9 @@
         setCellLayoutBorderSpacing((int) (cellLayoutBorderSpacingOriginalPx * scale));
 
         if (isScalableGrid) {
-            cellWidthPx = pxFromDp(inv.minCellWidth, mMetrics, scale);
-            cellHeightPx = pxFromDp(inv.minCellHeight, mMetrics, scale);
+            PointF minCellHeightAndWidth = getMinCellHeightAndWidth();
+            cellWidthPx = pxFromDp(minCellHeightAndWidth.x, mMetrics, scale);
+            cellHeightPx = pxFromDp(minCellHeightAndWidth.y, mMetrics, scale);
             int cellContentHeight = iconSizePx + iconDrawablePaddingPx
                     + Utilities.calculateTextHeight(iconTextSizePx);
             cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
@@ -698,6 +701,28 @@
         folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
     }
 
+    /**
+     * Returns the minimum cell height and width as a pair.
+     */
+    private PointF getMinCellHeightAndWidth() {
+        PointF result = new PointF();
+
+        if (isTwoPanels) {
+            if (isLandscape) {
+                result.x = inv.twoPanelLandscapeMinCellWidthDps;
+                result.y = inv.twoPanelLandscapeMinCellHeightDps;
+            } else {
+                result.x = inv.twoPanelPortraitMinCellWidthDps;
+                result.y = inv.twoPanelPortraitMinCellHeightDps;
+            }
+        } else {
+            result.x = inv.minCellWidth;
+            result.y = inv.minCellHeight;
+        }
+
+        return result;
+    }
+
     private void updateAvailableFolderCellDimensions(Resources res) {
         updateFolderCellSize(1f, res);
 
@@ -781,17 +806,14 @@
         if (result == null) {
             result = new Point();
         }
+
         // Since we are only concerned with the overall padding, layout direction does
         // not matter.
         Point padding = getTotalWorkspacePadding();
-        // availableWidthPx is the screen width of the device. In 2 panels mode, each panel should
-        // only have half of the screen width. In addition, there is only cellLayoutPadding in the
-        // left side of the left most panel and the right most side of the right panel. There is no
-        // cellLayoutPadding in the middle.
-        int screenWidthPx = isTwoPanels
-                ? availableWidthPx / 2 - padding.x - cellLayoutPaddingLeftRightPx
-                : availableWidthPx - padding.x - cellLayoutPaddingLeftRightPx * 2;
-        result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacingPx, inv.numColumns);
+
+        int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+        int screenWidthPx = availableWidthPx - padding.x;
+        result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacingPx, numColumns);
         result.y = calculateCellHeight(availableHeightPx - padding.y
                 - cellLayoutBottomPaddingPx, cellLayoutBorderSpacingPx, inv.numRows);
         return result;
@@ -1038,6 +1060,14 @@
 
         writer.println(prefix + "\tinv.minCellWidth:" + inv.minCellWidth + "dp");
         writer.println(prefix + "\tinv.minCellHeight:" + inv.minCellHeight + "dp");
+        writer.println(prefix + "\tinv.twoPanelPortraitMinCellHeightDps:"
+                + inv.twoPanelPortraitMinCellHeightDps + "dp");
+        writer.println(prefix + "\tinv.twoPanelPortraitMinCellWidthDps:"
+                + inv.twoPanelPortraitMinCellWidthDps + "dp");
+        writer.println(prefix + "\tinv.twoPanelLandscapeMinCellHeightDps:"
+                + inv.twoPanelLandscapeMinCellHeightDps + "dp");
+        writer.println(prefix + "\tinv.twoPanelLandscapeMinCellWidthDps:"
+                + inv.twoPanelLandscapeMinCellWidthDps + "dp");
 
         writer.println(prefix + "\tinv.numColumns:" + inv.numColumns);
         writer.println(prefix + "\tinv.numRows:" + inv.numRows);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 244cb59..1799f26 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -112,6 +112,10 @@
 
     public float minCellHeight;
     public float minCellWidth;
+    public float twoPanelPortraitMinCellHeightDps;
+    public float twoPanelPortraitMinCellWidthDps;
+    public float twoPanelLandscapeMinCellHeightDps;
+    public float twoPanelLandscapeMinCellWidthDps;
     public float borderSpacing;
 
     private SparseArray<TypedValue> mExtraAttrs;
@@ -274,6 +278,10 @@
 
         minCellHeight = displayOption.minCellHeight;
         minCellWidth = displayOption.minCellWidth;
+        twoPanelPortraitMinCellHeightDps = displayOption.twoPanelPortraitMinCellHeightDps;
+        twoPanelPortraitMinCellWidthDps = displayOption.twoPanelPortraitMinCellWidthDps;
+        twoPanelLandscapeMinCellHeightDps = displayOption.twoPanelLandscapeMinCellHeightDps;
+        twoPanelLandscapeMinCellWidthDps = displayOption.twoPanelLandscapeMinCellWidthDps;
         borderSpacing = displayOption.borderSpacing;
 
         numShownHotseatIcons = closestProfile.numHotseatIcons;
@@ -707,6 +715,10 @@
 
         private float minCellHeight;
         private float minCellWidth;
+        private float twoPanelPortraitMinCellHeightDps;
+        private float twoPanelPortraitMinCellWidthDps;
+        private float twoPanelLandscapeMinCellHeightDps;
+        private float twoPanelLandscapeMinCellWidthDps;
         private float borderSpacing;
 
         private final float[] iconSizes = new float[COUNT_TOTAL];
@@ -726,6 +738,17 @@
 
             minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
             minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
+            twoPanelPortraitMinCellHeightDps = a.getFloat(
+                    R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellHeightDps,
+                    minCellHeight);
+            twoPanelPortraitMinCellWidthDps = a.getFloat(
+                    R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellWidthDps, minCellWidth);
+            twoPanelLandscapeMinCellHeightDps = a.getFloat(
+                    R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellHeightDps,
+                    twoPanelPortraitMinCellHeightDps);
+            twoPanelLandscapeMinCellWidthDps = a.getFloat(
+                    R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
+                    twoPanelPortraitMinCellWidthDps);
             borderSpacing = a.getFloat(R.styleable.ProfileDisplayOption_borderSpacingDps, 0);
 
             iconSizes[INDEX_DEFAULT] =
@@ -782,6 +805,10 @@
             }
             minCellHeight *= w;
             minCellWidth *= w;
+            twoPanelPortraitMinCellHeightDps *= w;
+            twoPanelPortraitMinCellWidthDps *= w;
+            twoPanelLandscapeMinCellHeightDps *= w;
+            twoPanelLandscapeMinCellWidthDps *= w;
             borderSpacing *= w;
             return this;
         }
@@ -793,6 +820,10 @@
             }
             minCellHeight += p.minCellHeight;
             minCellWidth += p.minCellWidth;
+            twoPanelPortraitMinCellHeightDps += p.twoPanelPortraitMinCellHeightDps;
+            twoPanelPortraitMinCellWidthDps += p.twoPanelPortraitMinCellWidthDps;
+            twoPanelLandscapeMinCellHeightDps += p.twoPanelLandscapeMinCellHeightDps;
+            twoPanelLandscapeMinCellWidthDps += p.twoPanelLandscapeMinCellWidthDps;
             borderSpacing += p.borderSpacing;
             return this;
         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 54b2c96..bd2a14f 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -347,13 +347,13 @@
             if (panelCount > 1) {
                 if (i % panelCount == leftPanelModulus) {
                     paddingLeft = paddingLeftRight;
-                    paddingRight = 0;
-                } else if (i % panelCount == rightPanelModulus) {
-                    paddingLeft = 0;
+                    paddingRight = grid.cellLayoutBorderSpacingPx / 2;
+                } else if (i % panelCount == rightPanelModulus) { // right side panel
+                    paddingLeft = grid.cellLayoutBorderSpacingPx / 2;
                     paddingRight = paddingLeftRight;
                 } else { // middle panel
-                    paddingLeft = 0;
-                    paddingRight = 0;
+                    paddingLeft = grid.cellLayoutBorderSpacingPx / 2;
+                    paddingRight = grid.cellLayoutBorderSpacingPx / 2;
                 }
             }
             // SparseArrayMap doesn't keep the order
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 94fc708..b4907e8 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -230,13 +230,13 @@
         CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
         firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
                 mDp.workspacePadding.top,
-                mDp.workspacePadding.right,
+                mDp.workspacePadding.right + mDp.cellLayoutBorderSpacingPx / 2,
                 mDp.workspacePadding.bottom);
         mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
 
         if (mDp.isTwoPanels) {
             CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
-            rightPanel.setPadding(mDp.workspacePadding.left,
+            rightPanel.setPadding(mDp.workspacePadding.left + mDp.cellLayoutBorderSpacingPx / 2,
                     mDp.workspacePadding.top,
                     mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
                     mDp.workspacePadding.bottom);