Add support for marginVertical and marginHorizontal

* implement margin as an array of values
* apply margins with the correct priority (e.g. left, horizontal, all)
* update transpiler & tests
This commit is contained in:
Felix Oghină
2014-11-20 17:28:54 +00:00
parent edf0602ae2
commit 6ee0c5817c
6 changed files with 124 additions and 96 deletions

View File

@@ -54,17 +54,22 @@ function __transpileSingleTestToJava(code) {
return 'layout.' + (match1 == 'TOP' ? 'y' : 'x'); return 'layout.' + (match1 == 'TOP' ? 'y' : 'x');
}) })
.replace( // style.position[CSS_TOP] => style.positionTop .replace( // style.position[CSS_TOP] => style.positionTop
/style\.(position|margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT)\]/g, /style\.(position|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT)\]/g,
function (str, match1, match2) { function (str, match1, match2) {
return 'style.' + match1 + match2[0] + match2.substring(1).toLowerCase(); return 'style.' + match1 + match2[0] + match2.substring(1).toLowerCase();
}) })
.replace( // style.margin[CSS_TOP] => style.margin[CSSStyle.SPACING_TOP]
/style\.(margin)\[CSS_(TOP|BOTTOM|LEFT|RIGHT)\]/g,
function (str, match1, match2) {
return 'style.' + match1 + '[CSSStyle.SPACING_' + match2 + ']';
})
.replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)') .replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)')
.replace(/init_css_node_children/g, 'addChildren') .replace(/init_css_node_children/g, 'addChildren')
.replace(/css_node_t(\s)\*/g, 'TestCSSNode$1') .replace(/css_node_t(\s)\*/g, 'TestCSSNode$1')
.replace(/\->/g, '.') .replace(/\->/g, '.')
.replace(/(\d+\.\d+)/g, '$1f') .replace(/(\d+\.\d+)/g, '$1f')
.replace( // style.flex_direction => style.flexDirection .replace( // style.flex_direction => style.flexDirection
/style\.([^_\s]+)_(\w)(\w+)/g, /style\.([^_\[\]\s]+)_(\w)(\w+)/g,
function (str, match1, match2, match3) { function (str, match1, match2, match3) {
return 'style.' + match1 + match2.toUpperCase() + match3; return 'style.' + match1 + match2.toUpperCase() + match3;
}) })

View File

@@ -35,6 +35,24 @@ public class CSSNode {
UP_TO_DATE, UP_TO_DATE,
} }
public static final int SPACING_ALL = 0;
public static final int SPACING_VERTICAL = 1;
public static final int SPACING_HORIZONTAL = 2;
public static final int SPACING_LEFT = 3;
public static final int SPACING_RIGHT = 4;
public static final int SPACING_TOP = 5;
public static final int SPACING_BOTTOM = 6;
private final float[] mMargin = new float[] {
Float.NaN,
Float.NaN,
Float.NaN,
Float.NaN,
Float.NaN,
Float.NaN,
Float.NaN
};
// Only one copy kept around to keep from allocating a bunch of MeasureOutput objects // Only one copy kept around to keep from allocating a bunch of MeasureOutput objects
// NOT THREAD SAFE! NOT RE-ENTRANT SAFE! // NOT THREAD SAFE! NOT RE-ENTRANT SAFE!
private static final MeasureOutput MEASURE_OUTPUT = new MeasureOutput(); private static final MeasureOutput MEASURE_OUTPUT = new MeasureOutput();
@@ -243,30 +261,33 @@ public class CSSNode {
} }
} }
public void setMarginTop(float marginTop) { public void setMargin(int spacingType, float margin) {
if (!valuesEqual(style.marginTop, marginTop)) { setSpacing(mMargin, spacingType, margin, style.margin);
style.marginTop = marginTop;
dirty();
}
} }
public void setMarginBottom(float marginBottom) { protected void setSpacing(float[] spacingDef, int spacingType, float spacing, float[] cssStyle) {
if (!valuesEqual(style.marginBottom, marginBottom)) { if (!valuesEqual(spacingDef[spacingType], spacing)) {
style.marginBottom = marginBottom; spacingDef[spacingType] = spacing;
dirty(); cssStyle[CSSStyle.SPACING_TOP] =
} !Float.isNaN(spacingDef[SPACING_TOP]) ? spacingDef[SPACING_TOP]
} : !Float.isNaN(spacingDef[SPACING_VERTICAL]) ? spacingDef[SPACING_VERTICAL]
: !Float.isNaN(spacingDef[SPACING_ALL]) ? spacingDef[SPACING_ALL]
public void setMarginLeft(float marginLeft) { : 0;
if (!valuesEqual(style.marginLeft, marginLeft)) { cssStyle[CSSStyle.SPACING_BOTTOM] =
style.marginLeft = marginLeft; !Float.isNaN(spacingDef[SPACING_BOTTOM]) ? spacingDef[SPACING_BOTTOM]
dirty(); : !Float.isNaN(spacingDef[SPACING_VERTICAL]) ? spacingDef[SPACING_VERTICAL]
} : !Float.isNaN(spacingDef[SPACING_ALL]) ? spacingDef[SPACING_ALL]
} : 0;
cssStyle[CSSStyle.SPACING_LEFT] =
public void setMarginRight(float marginRight) { !Float.isNaN(spacingDef[SPACING_LEFT]) ? spacingDef[SPACING_LEFT]
if (!valuesEqual(style.marginRight, marginRight)) { : !Float.isNaN(spacingDef[SPACING_HORIZONTAL]) ? spacingDef[SPACING_HORIZONTAL]
style.marginRight = marginRight; : !Float.isNaN(spacingDef[SPACING_ALL]) ? spacingDef[SPACING_ALL]
: 0;
cssStyle[CSSStyle.SPACING_RIGHT] =
!Float.isNaN(spacingDef[SPACING_RIGHT]) ? spacingDef[SPACING_RIGHT]
: !Float.isNaN(spacingDef[SPACING_HORIZONTAL]) ? spacingDef[SPACING_HORIZONTAL]
: !Float.isNaN(spacingDef[SPACING_ALL]) ? spacingDef[SPACING_ALL]
: 0;
dirty(); dirty();
} }
} }

View File

@@ -13,6 +13,11 @@ package com.facebook.csslayout;
*/ */
public class CSSStyle { public class CSSStyle {
public static final int SPACING_TOP = 0;
public static final int SPACING_RIGHT = 1;
public static final int SPACING_BOTTOM = 2;
public static final int SPACING_LEFT = 3;
public CSSFlexDirection flexDirection = CSSFlexDirection.COLUMN; public CSSFlexDirection flexDirection = CSSFlexDirection.COLUMN;
public CSSJustify justifyContent = CSSJustify.FLEX_START; public CSSJustify justifyContent = CSSJustify.FLEX_START;
public CSSAlign alignItems = CSSAlign.STRETCH; public CSSAlign alignItems = CSSAlign.STRETCH;
@@ -20,10 +25,7 @@ public class CSSStyle {
public CSSPositionType positionType = CSSPositionType.RELATIVE; public CSSPositionType positionType = CSSPositionType.RELATIVE;
public float flex; public float flex;
public float marginTop; public float[] margin = new float[4];
public float marginBottom;
public float marginLeft;
public float marginRight;
public float paddingTop; public float paddingTop;
public float paddingBottom; public float paddingBottom;

View File

@@ -131,13 +131,13 @@ public class LayoutEngine {
private static float getMargin(CSSNode node, PositionIndex position) { private static float getMargin(CSSNode node, PositionIndex position) {
switch (position) { switch (position) {
case TOP: case TOP:
return node.style.marginTop; return node.style.margin[CSSStyle.SPACING_TOP];
case BOTTOM: case BOTTOM:
return node.style.marginBottom; return node.style.margin[CSSStyle.SPACING_BOTTOM];
case LEFT: case LEFT:
return node.style.marginLeft; return node.style.margin[CSSStyle.SPACING_LEFT];
case RIGHT: case RIGHT:
return node.style.marginRight; return node.style.margin[CSSStyle.SPACING_RIGHT];
default: default:
throw new RuntimeException("Someone added a new cardinal direction..."); throw new RuntimeException("Someone added a new cardinal direction...");
} }

View File

@@ -114,7 +114,7 @@ public class LayoutCachingTest {
root.calculateLayout(); root.calculateLayout();
markLayoutAppliedForTree(root); markLayoutAppliedForTree(root);
c1.setMarginLeft(10); c1.setMargin(CSSNode.SPACING_LEFT, 10);
root.calculateLayout(); root.calculateLayout();
assertTrue(root.hasNewLayout()); assertTrue(root.hasNewLayout());

View File

@@ -242,10 +242,10 @@ public class LayoutEngineTest {
TestCSSNode node_0 = root_node; TestCSSNode node_0 = root_node;
node_0.style.width = 100; node_0.style.width = 100;
node_0.style.height = 200; node_0.style.height = 200;
node_0.style.marginLeft = 10; node_0.style.margin[CSSStyle.SPACING_LEFT] = 10;
node_0.style.marginTop = 10; node_0.style.margin[CSSStyle.SPACING_TOP] = 10;
node_0.style.marginRight = 10; node_0.style.margin[CSSStyle.SPACING_RIGHT] = 10;
node_0.style.marginBottom = 10; node_0.style.margin[CSSStyle.SPACING_BOTTOM] = 10;
} }
TestCSSNode root_layout = new TestCSSNode(); TestCSSNode root_layout = new TestCSSNode();
@@ -268,34 +268,34 @@ public class LayoutEngineTest {
TestCSSNode node_0 = root_node; TestCSSNode node_0 = root_node;
node_0.style.width = 1000; node_0.style.width = 1000;
node_0.style.height = 1000; node_0.style.height = 1000;
node_0.style.marginLeft = 10; node_0.style.margin[CSSStyle.SPACING_LEFT] = 10;
node_0.style.marginTop = 10; node_0.style.margin[CSSStyle.SPACING_TOP] = 10;
node_0.style.marginRight = 10; node_0.style.margin[CSSStyle.SPACING_RIGHT] = 10;
node_0.style.marginBottom = 10; node_0.style.margin[CSSStyle.SPACING_BOTTOM] = 10;
addChildren(node_0, 3); addChildren(node_0, 3);
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.width = 100; node_1.style.width = 100;
node_1.style.height = 100; node_1.style.height = 100;
node_1.style.marginLeft = 50; node_1.style.margin[CSSStyle.SPACING_LEFT] = 50;
node_1.style.marginTop = 50; node_1.style.margin[CSSStyle.SPACING_TOP] = 50;
node_1.style.marginRight = 50; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 50;
node_1.style.marginBottom = 50; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 50;
node_1 = node_0.getChildAt(1); node_1 = node_0.getChildAt(1);
node_1.style.width = 100; node_1.style.width = 100;
node_1.style.height = 100; node_1.style.height = 100;
node_1.style.marginLeft = 25; node_1.style.margin[CSSStyle.SPACING_LEFT] = 25;
node_1.style.marginTop = 25; node_1.style.margin[CSSStyle.SPACING_TOP] = 25;
node_1.style.marginRight = 25; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 25;
node_1.style.marginBottom = 25; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 25;
node_1 = node_0.getChildAt(2); node_1 = node_0.getChildAt(2);
node_1.style.width = 100; node_1.style.width = 100;
node_1.style.height = 100; node_1.style.height = 100;
node_1.style.marginLeft = 10; node_1.style.margin[CSSStyle.SPACING_LEFT] = 10;
node_1.style.marginTop = 10; node_1.style.margin[CSSStyle.SPACING_TOP] = 10;
node_1.style.marginRight = 10; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 10;
node_1.style.marginBottom = 10; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 10;
} }
} }
@@ -546,21 +546,21 @@ public class LayoutEngineTest {
TestCSSNode node_0 = root_node; TestCSSNode node_0 = root_node;
node_0.style.width = 1000; node_0.style.width = 1000;
node_0.style.height = 1000; node_0.style.height = 1000;
node_0.style.marginLeft = 5; node_0.style.margin[CSSStyle.SPACING_LEFT] = 5;
node_0.style.marginTop = 10; node_0.style.margin[CSSStyle.SPACING_TOP] = 10;
addChildren(node_0, 2); addChildren(node_0, 2);
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.width = 100; node_1.style.width = 100;
node_1.style.height = 100; node_1.style.height = 100;
node_1.style.marginLeft = 15; node_1.style.margin[CSSStyle.SPACING_LEFT] = 15;
node_1.style.marginTop = 50; node_1.style.margin[CSSStyle.SPACING_TOP] = 50;
node_1.style.marginBottom = 20; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 20;
node_1 = node_0.getChildAt(1); node_1 = node_0.getChildAt(1);
node_1.style.width = 100; node_1.style.width = 100;
node_1.style.height = 100; node_1.style.height = 100;
node_1.style.marginLeft = 30; node_1.style.margin[CSSStyle.SPACING_LEFT] = 30;
} }
} }
@@ -1135,10 +1135,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.marginLeft = 5; node_1.style.margin[CSSStyle.SPACING_LEFT] = 5;
node_1.style.marginTop = 5; node_1.style.margin[CSSStyle.SPACING_TOP] = 5;
node_1.style.marginRight = 5; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 5;
node_1.style.marginBottom = 5; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 5;
} }
} }
@@ -1239,7 +1239,7 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.marginTop = 10; node_1.style.margin[CSSStyle.SPACING_TOP] = 10;
} }
} }
@@ -1279,10 +1279,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_2; TestCSSNode node_2;
node_2 = node_1.getChildAt(0); node_2 = node_1.getChildAt(0);
node_2.style.marginLeft = 10; node_2.style.margin[CSSStyle.SPACING_LEFT] = 10;
node_2.style.marginTop = 10; node_2.style.margin[CSSStyle.SPACING_TOP] = 10;
node_2.style.marginRight = 10; node_2.style.margin[CSSStyle.SPACING_RIGHT] = 10;
node_2.style.marginBottom = 10; node_2.style.margin[CSSStyle.SPACING_BOTTOM] = 10;
node_2 = node_1.getChildAt(1); node_2 = node_1.getChildAt(1);
node_2.style.height = 100; node_2.style.height = 100;
} }
@@ -1370,7 +1370,7 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.marginLeft = 10; node_1.style.margin[CSSStyle.SPACING_LEFT] = 10;
} }
} }
@@ -1471,10 +1471,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.marginLeft = 5; node_1.style.margin[CSSStyle.SPACING_LEFT] = 5;
node_1.style.marginTop = 5; node_1.style.margin[CSSStyle.SPACING_TOP] = 5;
node_1.style.marginRight = 5; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 5;
node_1.style.marginBottom = 5; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 5;
} }
} }
@@ -1596,10 +1596,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_2; TestCSSNode node_2;
node_2 = node_1.getChildAt(0); node_2 = node_1.getChildAt(0);
node_2.style.marginLeft = 16; node_2.style.margin[CSSStyle.SPACING_LEFT] = 16;
node_2.style.marginTop = 16; node_2.style.margin[CSSStyle.SPACING_TOP] = 16;
node_2.style.marginRight = 16; node_2.style.margin[CSSStyle.SPACING_RIGHT] = 16;
node_2.style.marginBottom = 16; node_2.style.margin[CSSStyle.SPACING_BOTTOM] = 16;
} }
} }
} }
@@ -1799,7 +1799,7 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.positionType = CSSPositionType.ABSOLUTE; node_1.style.positionType = CSSPositionType.ABSOLUTE;
node_1.style.marginRight = 15; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 15;
} }
} }
@@ -2096,7 +2096,7 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.positionType = CSSPositionType.ABSOLUTE; node_1.style.positionType = CSSPositionType.ABSOLUTE;
node_1.style.marginTop = 5; node_1.style.margin[CSSStyle.SPACING_TOP] = 5;
node_1.style.positionTop = 5; node_1.style.positionTop = 5;
} }
} }
@@ -2133,7 +2133,7 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.positionType = CSSPositionType.ABSOLUTE; node_1.style.positionType = CSSPositionType.ABSOLUTE;
node_1.style.marginLeft = 5; node_1.style.margin[CSSStyle.SPACING_LEFT] = 5;
node_1.style.positionLeft = 5; node_1.style.positionLeft = 5;
} }
} }
@@ -2215,7 +2215,7 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.flex = 1; node_1.style.flex = 1;
node_1.style.marginLeft = 5; node_1.style.margin[CSSStyle.SPACING_LEFT] = 5;
} }
} }
@@ -2300,7 +2300,7 @@ public class LayoutEngineTest {
node_1.style.flex = 1; node_1.style.flex = 1;
node_1 = node_0.getChildAt(1); node_1 = node_0.getChildAt(1);
node_1.style.flex = 1; node_1.style.flex = 1;
node_1.style.marginLeft = 5; node_1.style.margin[CSSStyle.SPACING_LEFT] = 5;
} }
} }
@@ -2568,7 +2568,7 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.alignSelf = CSSAlign.STRETCH; node_1.style.alignSelf = CSSAlign.STRETCH;
node_1.style.marginLeft = 20; node_1.style.margin[CSSStyle.SPACING_LEFT] = 20;
node_1.style.paddingLeft = 20; node_1.style.paddingLeft = 20;
node_1.style.paddingTop = 20; node_1.style.paddingTop = 20;
node_1.style.paddingRight = 20; node_1.style.paddingRight = 20;
@@ -2644,7 +2644,7 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.marginRight = -8; node_1.style.margin[CSSStyle.SPACING_RIGHT] = -8;
} }
} }
@@ -3003,10 +3003,10 @@ public class LayoutEngineTest {
TestCSSNode node_1; TestCSSNode node_1;
node_1 = node_0.getChildAt(0); node_1 = node_0.getChildAt(0);
node_1.style.alignSelf = CSSAlign.FLEX_START; node_1.style.alignSelf = CSSAlign.FLEX_START;
node_1.style.marginLeft = 10; node_1.style.margin[CSSStyle.SPACING_LEFT] = 10;
node_1.style.marginTop = 10; node_1.style.margin[CSSStyle.SPACING_TOP] = 10;
node_1.style.marginRight = 10; node_1.style.margin[CSSStyle.SPACING_RIGHT] = 10;
node_1.style.marginBottom = 10; node_1.style.margin[CSSStyle.SPACING_BOTTOM] = 10;
addChildren(node_1, 1); addChildren(node_1, 1);
{ {
TestCSSNode node_2; TestCSSNode node_2;
@@ -3144,10 +3144,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_2; TestCSSNode node_2;
node_2 = node_1.getChildAt(0); node_2 = node_1.getChildAt(0);
node_2.style.marginLeft = 20; node_2.style.margin[CSSStyle.SPACING_LEFT] = 20;
node_2.style.marginTop = 20; node_2.style.margin[CSSStyle.SPACING_TOP] = 20;
node_2.style.marginRight = 20; node_2.style.margin[CSSStyle.SPACING_RIGHT] = 20;
node_2.style.marginBottom = 20; node_2.style.margin[CSSStyle.SPACING_BOTTOM] = 20;
node_2.setMeasureFunction(sTestMeasureFunction); node_2.setMeasureFunction(sTestMeasureFunction);
node_2.context = "loooooooooong with space"; node_2.context = "loooooooooong with space";
} }
@@ -3199,10 +3199,10 @@ public class LayoutEngineTest {
{ {
TestCSSNode node_2; TestCSSNode node_2;
node_2 = node_1.getChildAt(0); node_2 = node_1.getChildAt(0);
node_2.style.marginLeft = 20; node_2.style.margin[CSSStyle.SPACING_LEFT] = 20;
node_2.style.marginTop = 20; node_2.style.margin[CSSStyle.SPACING_TOP] = 20;
node_2.style.marginRight = 20; node_2.style.margin[CSSStyle.SPACING_RIGHT] = 20;
node_2.style.marginBottom = 20; node_2.style.margin[CSSStyle.SPACING_BOTTOM] = 20;
node_2.setMeasureFunction(sTestMeasureFunction); node_2.setMeasureFunction(sTestMeasureFunction);
node_2.context = "loooooooooong with space"; node_2.context = "loooooooooong with space";
} }