Support ROW_REVERSE, COLUMN_REVERSE and RTL direction
This commit is contained in:
@@ -11,6 +11,8 @@ function __transpileToJavaCommon(code) {
|
|||||||
return code
|
return code
|
||||||
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
||||||
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
||||||
|
.replace(/css_direction_t/g, 'CSSDirection')
|
||||||
|
.replace(/CSS_DIRECTION_/g, 'CSSDirection.')
|
||||||
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
||||||
.replace(/css_align_t/g, 'CSSAlign')
|
.replace(/css_align_t/g, 'CSSAlign')
|
||||||
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
||||||
@@ -33,7 +35,11 @@ function __transpileToJavaCommon(code) {
|
|||||||
.replace(
|
.replace(
|
||||||
/(\w+)\.layout\[((?:getLeading|getPos)\([^\)]+\))\]\s+=\s+([^;]+);/gm,
|
/(\w+)\.layout\[((?:getLeading|getPos)\([^\)]+\))\]\s+=\s+([^;]+);/gm,
|
||||||
'setLayoutPosition($1, $2, $3);')
|
'setLayoutPosition($1, $2, $3);')
|
||||||
|
.replace(
|
||||||
|
/(\w+)\.layout\[((?:getTrailing|getPos)\([^\)]+\))\]\s+=\s+([^;]+);/gm,
|
||||||
|
'setLayoutPosition($1, $2, $3);')
|
||||||
.replace(/(\w+)\.layout\[((?:getLeading|getPos)\([^\]]+\))\]/g, 'getLayoutPosition($1, $2)')
|
.replace(/(\w+)\.layout\[((?:getLeading|getPos)\([^\]]+\))\]/g, 'getLayoutPosition($1, $2)')
|
||||||
|
.replace(/(\w+)\.layout\[((?:getTrailing|getPos)\([^\]]+\))\]/g, 'getLayoutPosition($1, $2)')
|
||||||
.replace(
|
.replace(
|
||||||
/(\w+)\.layout\[(getDim\([^\)]+\))\]\s+=\s+([^;]+);/gm,
|
/(\w+)\.layout\[(getDim\([^\)]+\))\]\s+=\s+([^;]+);/gm,
|
||||||
'setLayoutDimension($1, $2, $3);')
|
'setLayoutDimension($1, $2, $3);')
|
||||||
@@ -63,7 +69,7 @@ function __transpileSingleTestToJava(code) {
|
|||||||
.replace( // layout.position[CSS_TOP] => layout.y
|
.replace( // layout.position[CSS_TOP] => layout.y
|
||||||
/layout\.position\[CSS_(TOP|LEFT)\]/g,
|
/layout\.position\[CSS_(TOP|LEFT)\]/g,
|
||||||
function (str, match1) {
|
function (str, match1) {
|
||||||
return 'layout.' + (match1 === 'TOP' ? 'y' : 'x');
|
return 'layout.' + (match1 === 'TOP' ? 'top' : 'left');
|
||||||
})
|
})
|
||||||
.replace( // style.position[CSS_TOP] => style.positionTop
|
.replace( // style.position[CSS_TOP] => style.positionTop
|
||||||
/style\.(position)\[CSS_(TOP|BOTTOM|LEFT|RIGHT)\]/g,
|
/style\.(position)\[CSS_(TOP|BOTTOM|LEFT|RIGHT)\]/g,
|
||||||
|
@@ -88,7 +88,7 @@ css_dim_t measure(void *context, float width) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
|
void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
|
||||||
layoutNode(style, CSS_UNDEFINED);
|
layoutNode(style, CSS_UNDEFINED, -1);
|
||||||
|
|
||||||
if (!are_layout_equal(style, expected_layout)) {
|
if (!are_layout_equal(style, expected_layout)) {
|
||||||
printf("%sF%s", "\x1B[31m", "\x1B[0m");
|
printf("%sF%s", "\x1B[31m", "\x1B[0m");
|
||||||
|
@@ -184,6 +184,7 @@ var layoutTestUtils = (function() {
|
|||||||
transferSpacing(div, node, 'padding', '');
|
transferSpacing(div, node, 'padding', '');
|
||||||
transferSpacing(div, node, 'border', 'Width');
|
transferSpacing(div, node, 'border', 'Width');
|
||||||
transfer(div, node, 'flexDirection');
|
transfer(div, node, 'flexDirection');
|
||||||
|
transfer(div, node, 'direction');
|
||||||
transfer(div, node, 'flex');
|
transfer(div, node, 'flex');
|
||||||
transfer(div, node, 'flexWrap');
|
transfer(div, node, 'flexWrap');
|
||||||
transfer(div, node, 'justifyContent');
|
transfer(div, node, 'justifyContent');
|
||||||
|
163
src/Layout.c
163
src/Layout.c
@@ -36,6 +36,9 @@ static bool eq(float a, float b) {
|
|||||||
void init_css_node(css_node_t *node) {
|
void init_css_node(css_node_t *node) {
|
||||||
node->style.align_items = CSS_ALIGN_STRETCH;
|
node->style.align_items = CSS_ALIGN_STRETCH;
|
||||||
|
|
||||||
|
node->style.direction = CSS_DIRECTION_INHERIT;
|
||||||
|
node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
|
||||||
|
|
||||||
// Some of the fields default to undefined and not 0
|
// Some of the fields default to undefined and not 0
|
||||||
node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
||||||
node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
||||||
@@ -58,6 +61,7 @@ void init_css_node(css_node_t *node) {
|
|||||||
node->layout.last_requested_dimensions[CSS_WIDTH] = -1;
|
node->layout.last_requested_dimensions[CSS_WIDTH] = -1;
|
||||||
node->layout.last_requested_dimensions[CSS_HEIGHT] = -1;
|
node->layout.last_requested_dimensions[CSS_HEIGHT] = -1;
|
||||||
node->layout.last_parent_max_width = -1;
|
node->layout.last_parent_max_width = -1;
|
||||||
|
node->layout.last_direction = -1;
|
||||||
node->layout.should_update = true;
|
node->layout.should_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +123,14 @@ static void print_css_node_rec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options & CSS_PRINT_STYLE) {
|
if (options & CSS_PRINT_STYLE) {
|
||||||
if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) {
|
if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN) {
|
||||||
|
printf("flexDirection: 'column', ");
|
||||||
|
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||||
|
printf("flexDirection: 'columnReverse', ");
|
||||||
|
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) {
|
||||||
printf("flexDirection: 'row', ");
|
printf("flexDirection: 'row', ");
|
||||||
|
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
|
||||||
|
printf("flexDirection: 'rowReverse', ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->style.justify_content == CSS_JUSTIFY_CENTER) {
|
if (node->style.justify_content == CSS_JUSTIFY_CENTER) {
|
||||||
@@ -210,25 +220,32 @@ void print_css_node(css_node_t *node, css_print_options_t options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static css_position_t leading[2] = {
|
static css_position_t leading[4] = {
|
||||||
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
|
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
|
||||||
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT
|
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
|
||||||
};
|
};
|
||||||
static css_position_t trailing[2] = {
|
static css_position_t trailing[4] = {
|
||||||
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM,
|
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM,
|
||||||
/* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT
|
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_TOP,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_LEFT
|
||||||
};
|
};
|
||||||
static css_position_t pos[2] = {
|
static css_position_t pos[4] = {
|
||||||
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
|
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
|
||||||
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT
|
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
|
||||||
};
|
};
|
||||||
static css_dimension_t dim[2] = {
|
static css_dimension_t dim[4] = {
|
||||||
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT,
|
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT,
|
||||||
/* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH
|
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_HEIGHT,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH,
|
||||||
|
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_WIDTH
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static float getMargin(css_node_t *node, int location) {
|
static float getMargin(css_node_t *node, int location) {
|
||||||
return node->style.margin[location];
|
return node->style.margin[location];
|
||||||
}
|
}
|
||||||
@@ -278,10 +295,50 @@ static css_align_t getAlignItem(css_node_t *node, css_node_t *child) {
|
|||||||
return node->style.align_items;
|
return node->style.align_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isRowDirection(css_flex_direction_t flex_direction) {
|
||||||
|
return flex_direction == CSS_FLEX_DIRECTION_ROW ||
|
||||||
|
flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isColumnDirection(css_flex_direction_t flex_direction) {
|
||||||
|
return flex_direction == CSS_FLEX_DIRECTION_COLUMN ||
|
||||||
|
flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static css_direction_t resolveDirection(css_node_t *node, css_direction_t parentDirection) {
|
||||||
|
css_direction_t direction = node->style.direction;
|
||||||
|
|
||||||
|
if (direction == CSS_DIRECTION_INHERIT) {
|
||||||
|
direction = parentDirection > CSS_DIRECTION_INHERIT ? parentDirection : CSS_DIRECTION_LTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
static css_flex_direction_t getFlexDirection(css_node_t *node) {
|
static css_flex_direction_t getFlexDirection(css_node_t *node) {
|
||||||
return node->style.flex_direction;
|
return node->style.flex_direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static css_flex_direction_t resolveAxis(css_flex_direction_t flex_direction, css_direction_t direction) {
|
||||||
|
if (direction == CSS_DIRECTION_RTL) {
|
||||||
|
if (flex_direction == CSS_FLEX_DIRECTION_ROW) {
|
||||||
|
return CSS_FLEX_DIRECTION_ROW_REVERSE;
|
||||||
|
} else if (flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
|
||||||
|
return CSS_FLEX_DIRECTION_ROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flex_direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
static css_flex_direction_t getCrossFlexDirection(css_flex_direction_t flex_direction, css_direction_t direction) {
|
||||||
|
if (isColumnDirection(flex_direction)) {
|
||||||
|
return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
|
||||||
|
} else {
|
||||||
|
return CSS_FLEX_DIRECTION_COLUMN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static float getFlex(css_node_t *node) {
|
static float getFlex(css_node_t *node) {
|
||||||
return node->style.flex;
|
return node->style.flex;
|
||||||
}
|
}
|
||||||
@@ -328,10 +385,10 @@ static float boundAxis(css_node_t *node, css_flex_direction_t axis, float value)
|
|||||||
float min = CSS_UNDEFINED;
|
float min = CSS_UNDEFINED;
|
||||||
float max = CSS_UNDEFINED;
|
float max = CSS_UNDEFINED;
|
||||||
|
|
||||||
if (axis == CSS_FLEX_DIRECTION_COLUMN) {
|
if (isColumnDirection(axis)) {
|
||||||
min = node->style.minDimensions[CSS_HEIGHT];
|
min = node->style.minDimensions[CSS_HEIGHT];
|
||||||
max = node->style.maxDimensions[CSS_HEIGHT];
|
max = node->style.maxDimensions[CSS_HEIGHT];
|
||||||
} else if (axis == CSS_FLEX_DIRECTION_ROW) {
|
} else if (isRowDirection(axis)) {
|
||||||
min = node->style.minDimensions[CSS_WIDTH];
|
min = node->style.minDimensions[CSS_WIDTH];
|
||||||
max = node->style.maxDimensions[CSS_WIDTH];
|
max = node->style.maxDimensions[CSS_WIDTH];
|
||||||
}
|
}
|
||||||
@@ -366,6 +423,11 @@ static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setTrailingPosition(css_node_t *node, css_node_t *child, css_flex_direction_t axis) {
|
||||||
|
child->layout.position[trailing[axis]] = node->layout.dimensions[dim[axis]] -
|
||||||
|
child->layout.dimensions[dim[axis]] - child->layout.position[pos[axis]];
|
||||||
|
}
|
||||||
|
|
||||||
// If both left and right are defined, then use left. Otherwise return
|
// If both left and right are defined, then use left. Otherwise return
|
||||||
// +left or -right depending on which is defined.
|
// +left or -right depending on which is defined.
|
||||||
static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
|
static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
|
||||||
@@ -376,13 +438,12 @@ static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
|
|||||||
return -getPosition(node, trailing[axis]);
|
return -getPosition(node, trailing[axis]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, css_direction_t parentDirection) {
|
||||||
/** START_GENERATED **/
|
/** START_GENERATED **/
|
||||||
|
css_direction_t direction = resolveDirection(node, parentDirection);
|
||||||
css_flex_direction_t mainAxis = getFlexDirection(node);
|
css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
|
||||||
css_flex_direction_t crossAxis = mainAxis == CSS_FLEX_DIRECTION_ROW ?
|
css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
|
||||||
CSS_FLEX_DIRECTION_COLUMN :
|
css_flex_direction_t resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
|
||||||
CSS_FLEX_DIRECTION_ROW;
|
|
||||||
|
|
||||||
// Handle width and height style attributes
|
// Handle width and height style attributes
|
||||||
setDimensionFromStyle(node, mainAxis);
|
setDimensionFromStyle(node, mainAxis);
|
||||||
@@ -392,26 +453,30 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
// delta composed of the margin and left/top/right/bottom
|
// delta composed of the margin and left/top/right/bottom
|
||||||
node->layout.position[leading[mainAxis]] += getMargin(node, leading[mainAxis]) +
|
node->layout.position[leading[mainAxis]] += getMargin(node, leading[mainAxis]) +
|
||||||
getRelativePosition(node, mainAxis);
|
getRelativePosition(node, mainAxis);
|
||||||
|
node->layout.position[trailing[mainAxis]] += getMargin(node, trailing[mainAxis]) +
|
||||||
|
getRelativePosition(node, mainAxis);
|
||||||
node->layout.position[leading[crossAxis]] += getMargin(node, leading[crossAxis]) +
|
node->layout.position[leading[crossAxis]] += getMargin(node, leading[crossAxis]) +
|
||||||
getRelativePosition(node, crossAxis);
|
getRelativePosition(node, crossAxis);
|
||||||
|
node->layout.position[trailing[crossAxis]] += getMargin(node, trailing[crossAxis]) +
|
||||||
|
getRelativePosition(node, crossAxis);
|
||||||
|
|
||||||
if (isMeasureDefined(node)) {
|
if (isMeasureDefined(node)) {
|
||||||
float width = CSS_UNDEFINED;
|
float width = CSS_UNDEFINED;
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
width = node->style.dimensions[CSS_WIDTH];
|
width = node->style.dimensions[CSS_WIDTH];
|
||||||
} else if (!isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]])) {
|
} else if (!isUndefined(node->layout.dimensions[dim[resolvedRowAxis]])) {
|
||||||
width = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]];
|
width = node->layout.dimensions[dim[resolvedRowAxis]];
|
||||||
} else {
|
} else {
|
||||||
width = parentMaxWidth -
|
width = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getMarginAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
width -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
width -= getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
// We only need to give a dimension for the text if we haven't got any
|
// We only need to give a dimension for the text if we haven't got any
|
||||||
// for it computed yet. It can either be from the style attribute or because
|
// for it computed yet. It can either be from the style attribute or because
|
||||||
// the element is flexible.
|
// the element is flexible.
|
||||||
bool isRowUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_ROW) &&
|
bool isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&
|
||||||
isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]]);
|
isUndefined(node->layout.dimensions[dim[resolvedRowAxis]]);
|
||||||
bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
|
bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
|
||||||
isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
|
isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
|
||||||
|
|
||||||
@@ -424,7 +489,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
);
|
);
|
||||||
if (isRowUndefined) {
|
if (isRowUndefined) {
|
||||||
node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
|
node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
if (isColumnUndefined) {
|
if (isColumnUndefined) {
|
||||||
node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
|
node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
|
||||||
@@ -527,20 +592,20 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
maxWidth = CSS_UNDEFINED;
|
maxWidth = CSS_UNDEFINED;
|
||||||
if (mainAxis != CSS_FLEX_DIRECTION_ROW) {
|
if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
|
maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the main recursive call. We layout non flexible children.
|
// This is the main recursive call. We layout non flexible children.
|
||||||
if (alreadyComputedNextLayout == 0) {
|
if (alreadyComputedNextLayout == 0) {
|
||||||
layoutNode(child, maxWidth);
|
layoutNode(child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute positioned elements do not take part of the layout, so we
|
// Absolute positioned elements do not take part of the layout, so we
|
||||||
@@ -626,17 +691,17 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
maxWidth = CSS_UNDEFINED;
|
maxWidth = CSS_UNDEFINED;
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
|
maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
} else if (mainAxis != CSS_FLEX_DIRECTION_ROW) {
|
} else if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And we recursively call the layout algorithm for this child
|
// And we recursively call the layout algorithm for this child
|
||||||
layoutNode(child, maxWidth);
|
layoutNode(child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,6 +754,11 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
// If the child is position absolute (without top/left) or relative,
|
// If the child is position absolute (without top/left) or relative,
|
||||||
// we put it at the current accumulated offset.
|
// we put it at the current accumulated offset.
|
||||||
child->layout.position[pos[mainAxis]] += mainDim;
|
child->layout.position[pos[mainAxis]] += mainDim;
|
||||||
|
|
||||||
|
// Define the trailing position accordingly.
|
||||||
|
if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
|
||||||
|
setTrailingPosition(node, child, mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we placed the element, we need to update the variables
|
// Now that we placed the element, we need to update the variables
|
||||||
@@ -783,6 +853,12 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
// We can never assign a width smaller than the padding and borders
|
// We can never assign a width smaller than the padding and borders
|
||||||
getPaddingAndBorderAxis(node, mainAxis)
|
getPaddingAndBorderAxis(node, mainAxis)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Now that the width is defined, we should update the trailing
|
||||||
|
// positions for the children.
|
||||||
|
for (i = 0; i < node->children_count; ++i) {
|
||||||
|
setTrailingPosition(node, node->get_child(node->context, i), mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
|
if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
|
||||||
@@ -835,8 +911,9 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
|||||||
/** END_GENERATED **/
|
/** END_GENERATED **/
|
||||||
}
|
}
|
||||||
|
|
||||||
void layoutNode(css_node_t *node, float parentMaxWidth) {
|
void layoutNode(css_node_t *node, float parentMaxWidth, css_direction_t parentDirection) {
|
||||||
css_layout_t *layout = &node->layout;
|
css_layout_t *layout = &node->layout;
|
||||||
|
css_direction_t direction = node->style.direction;
|
||||||
layout->should_update = true;
|
layout->should_update = true;
|
||||||
|
|
||||||
bool skipLayout =
|
bool skipLayout =
|
||||||
@@ -844,6 +921,7 @@ void layoutNode(css_node_t *node, float parentMaxWidth) {
|
|||||||
eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
|
eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
|
||||||
eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
|
eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
|
||||||
eq(layout->last_parent_max_width, parentMaxWidth);
|
eq(layout->last_parent_max_width, parentMaxWidth);
|
||||||
|
eq(layout->last_direction, direction);
|
||||||
|
|
||||||
if (skipLayout) {
|
if (skipLayout) {
|
||||||
layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH];
|
layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH];
|
||||||
@@ -854,8 +932,9 @@ void layoutNode(css_node_t *node, float parentMaxWidth) {
|
|||||||
layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
|
layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
|
||||||
layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
|
layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
|
||||||
layout->last_parent_max_width = parentMaxWidth;
|
layout->last_parent_max_width = parentMaxWidth;
|
||||||
|
layout->last_direction = direction;
|
||||||
|
|
||||||
layoutNodeImpl(node, parentMaxWidth);
|
layoutNodeImpl(node, parentMaxWidth, parentDirection);
|
||||||
|
|
||||||
layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
|
layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
|
||||||
layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
|
layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
|
||||||
|
16
src/Layout.h
16
src/Layout.h
@@ -23,9 +23,17 @@ static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
|||||||
|
|
||||||
#define CSS_UNDEFINED NAN
|
#define CSS_UNDEFINED NAN
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CSS_DIRECTION_INHERIT = 0,
|
||||||
|
CSS_DIRECTION_LTR,
|
||||||
|
CSS_DIRECTION_RTL
|
||||||
|
} css_direction_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CSS_FLEX_DIRECTION_COLUMN = 0,
|
CSS_FLEX_DIRECTION_COLUMN = 0,
|
||||||
CSS_FLEX_DIRECTION_ROW
|
CSS_FLEX_DIRECTION_COLUMN_REVERSE,
|
||||||
|
CSS_FLEX_DIRECTION_ROW,
|
||||||
|
CSS_FLEX_DIRECTION_ROW_REVERSE
|
||||||
} css_flex_direction_t;
|
} css_flex_direction_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -72,7 +80,7 @@ typedef enum {
|
|||||||
} css_dimension_t;
|
} css_dimension_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float position[2];
|
float position[4];
|
||||||
float dimensions[2];
|
float dimensions[2];
|
||||||
|
|
||||||
// Instead of recomputing the entire layout every single time, we
|
// Instead of recomputing the entire layout every single time, we
|
||||||
@@ -82,6 +90,7 @@ typedef struct {
|
|||||||
float last_parent_max_width;
|
float last_parent_max_width;
|
||||||
float last_dimensions[2];
|
float last_dimensions[2];
|
||||||
float last_position[2];
|
float last_position[2];
|
||||||
|
css_direction_t last_direction;
|
||||||
} css_layout_t;
|
} css_layout_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -89,6 +98,7 @@ typedef struct {
|
|||||||
} css_dim_t;
|
} css_dim_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
css_direction_t direction;
|
||||||
css_flex_direction_t flex_direction;
|
css_flex_direction_t flex_direction;
|
||||||
css_justify_t justify_content;
|
css_justify_t justify_content;
|
||||||
css_align_t align_items;
|
css_align_t align_items;
|
||||||
@@ -142,7 +152,7 @@ typedef enum {
|
|||||||
void print_css_node(css_node_t *node, css_print_options_t options);
|
void print_css_node(css_node_t *node, css_print_options_t options);
|
||||||
|
|
||||||
// Function that computes the layout!
|
// Function that computes the layout!
|
||||||
void layoutNode(css_node_t *node, float maxWidth);
|
void layoutNode(css_node_t *node, float maxWidth, css_direction_t parentDirection);
|
||||||
bool isUndefined(float value);
|
bool isUndefined(float value);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
172
src/Layout.js
172
src/Layout.js
@@ -11,8 +11,14 @@ var computeLayout = (function() {
|
|||||||
|
|
||||||
var CSS_UNDEFINED;
|
var CSS_UNDEFINED;
|
||||||
|
|
||||||
|
var CSS_DIRECTION_INHERIT = 'inherit';
|
||||||
|
var CSS_DIRECTION_LTR = 'ltr';
|
||||||
|
var CSS_DIRECTION_RTL = 'rtl';
|
||||||
|
|
||||||
var CSS_FLEX_DIRECTION_ROW = 'row';
|
var CSS_FLEX_DIRECTION_ROW = 'row';
|
||||||
|
var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';
|
||||||
var CSS_FLEX_DIRECTION_COLUMN = 'column';
|
var CSS_FLEX_DIRECTION_COLUMN = 'column';
|
||||||
|
var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';
|
||||||
|
|
||||||
// var CSS_JUSTIFY_FLEX_START = 'flex-start';
|
// var CSS_JUSTIFY_FLEX_START = 'flex-start';
|
||||||
var CSS_JUSTIFY_CENTER = 'center';
|
var CSS_JUSTIFY_CENTER = 'center';
|
||||||
@@ -29,20 +35,28 @@ var computeLayout = (function() {
|
|||||||
var CSS_POSITION_ABSOLUTE = 'absolute';
|
var CSS_POSITION_ABSOLUTE = 'absolute';
|
||||||
|
|
||||||
var leading = {
|
var leading = {
|
||||||
row: 'left',
|
'row': 'left',
|
||||||
column: 'top'
|
'row-reverse': 'right',
|
||||||
|
'column': 'top',
|
||||||
|
'column-reverse': 'bottom'
|
||||||
};
|
};
|
||||||
var trailing = {
|
var trailing = {
|
||||||
row: 'right',
|
'row': 'right',
|
||||||
column: 'bottom'
|
'row-reverse': 'left',
|
||||||
|
'column': 'bottom',
|
||||||
|
'column-reverse': 'top'
|
||||||
};
|
};
|
||||||
var pos = {
|
var pos = {
|
||||||
row: 'left',
|
'row': 'left',
|
||||||
column: 'top'
|
'row-reverse': 'right',
|
||||||
|
'column': 'top',
|
||||||
|
'column-reverse': 'bottom'
|
||||||
};
|
};
|
||||||
var dim = {
|
var dim = {
|
||||||
row: 'width',
|
'row': 'width',
|
||||||
column: 'height'
|
'row-reverse': 'width',
|
||||||
|
'column': 'height',
|
||||||
|
'column-reverse': 'height'
|
||||||
};
|
};
|
||||||
|
|
||||||
function capitalizeFirst(str) {
|
function capitalizeFirst(str) {
|
||||||
@@ -67,7 +81,9 @@ var computeLayout = (function() {
|
|||||||
width: undefined,
|
width: undefined,
|
||||||
height: undefined,
|
height: undefined,
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0
|
||||||
};
|
};
|
||||||
if (!node.style) {
|
if (!node.style) {
|
||||||
node.style = {};
|
node.style = {};
|
||||||
@@ -88,6 +104,10 @@ var computeLayout = (function() {
|
|||||||
} else {
|
} else {
|
||||||
delete node.children;
|
delete node.children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete layout.right;
|
||||||
|
delete layout.bottom;
|
||||||
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,11 +174,56 @@ var computeLayout = (function() {
|
|||||||
return 'stretch';
|
return 'stretch';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRowDirection(flexDirection) {
|
||||||
|
return flexDirection === CSS_FLEX_DIRECTION_ROW ||
|
||||||
|
flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isColumnDirection(flexDirection) {
|
||||||
|
return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||
|
||||||
|
flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAxis(axis, direction) {
|
||||||
|
if (direction === CSS_DIRECTION_RTL) {
|
||||||
|
if (axis === CSS_FLEX_DIRECTION_ROW) {
|
||||||
|
return CSS_FLEX_DIRECTION_ROW_REVERSE;
|
||||||
|
} else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {
|
||||||
|
return CSS_FLEX_DIRECTION_ROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveDirection(node, parentDirection) {
|
||||||
|
var direction;
|
||||||
|
if ('direction' in node.style) {
|
||||||
|
direction = node.style.direction;
|
||||||
|
} else {
|
||||||
|
direction = CSS_DIRECTION_INHERIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction === CSS_DIRECTION_INHERIT) {
|
||||||
|
direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
function getFlexDirection(node) {
|
function getFlexDirection(node) {
|
||||||
if ('flexDirection' in node.style) {
|
if ('flexDirection' in node.style) {
|
||||||
return node.style.flexDirection;
|
return node.style.flexDirection;
|
||||||
}
|
}
|
||||||
return 'column';
|
return CSS_FLEX_DIRECTION_COLUMN;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCrossFlexDirection(flexDirection, direction) {
|
||||||
|
if (isColumnDirection(flexDirection)) {
|
||||||
|
return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
|
||||||
|
} else {
|
||||||
|
return CSS_FLEX_DIRECTION_COLUMN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPositionType(node) {
|
function getPositionType(node) {
|
||||||
@@ -208,13 +273,17 @@ var computeLayout = (function() {
|
|||||||
|
|
||||||
function boundAxis(node, axis, value) {
|
function boundAxis(node, axis, value) {
|
||||||
var min = {
|
var min = {
|
||||||
row: node.style.minWidth,
|
'row': node.style.minWidth,
|
||||||
column: node.style.minHeight
|
'row-reverse': node.style.minWidth,
|
||||||
|
'column': node.style.minHeight,
|
||||||
|
'column-reverse': node.style.minHeight
|
||||||
}[axis];
|
}[axis];
|
||||||
|
|
||||||
var max = {
|
var max = {
|
||||||
row: node.style.maxWidth,
|
'row': node.style.maxWidth,
|
||||||
column: node.style.maxHeight
|
'row-reverse': node.style.maxWidth,
|
||||||
|
'column': node.style.maxHeight,
|
||||||
|
'column-reverse': node.style.maxHeight
|
||||||
}[axis];
|
}[axis];
|
||||||
|
|
||||||
var boundValue = value;
|
var boundValue = value;
|
||||||
@@ -252,6 +321,11 @@ var computeLayout = (function() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTrailingPosition(node, child, axis) {
|
||||||
|
child.layout[trailing[axis]] = node.layout[dim[axis]] -
|
||||||
|
child.layout[dim[axis]] - child.layout[pos[axis]];
|
||||||
|
}
|
||||||
|
|
||||||
// If both left and right are defined, then use left. Otherwise return
|
// If both left and right are defined, then use left. Otherwise return
|
||||||
// +left or -right depending on which is defined.
|
// +left or -right depending on which is defined.
|
||||||
function getRelativePosition(node, axis) {
|
function getRelativePosition(node, axis) {
|
||||||
@@ -261,12 +335,11 @@ var computeLayout = (function() {
|
|||||||
return -getPosition(node, trailing[axis]);
|
return -getPosition(node, trailing[axis]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function layoutNode(node, parentMaxWidth) {
|
function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) {
|
||||||
|
var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);
|
||||||
var/*css_flex_direction_t*/ mainAxis = getFlexDirection(node);
|
var/*css_flex_direction_t*/ mainAxis = resolveAxis(getFlexDirection(node), direction);
|
||||||
var/*css_flex_direction_t*/ crossAxis = mainAxis === CSS_FLEX_DIRECTION_ROW ?
|
var/*css_flex_direction_t*/ crossAxis = getCrossFlexDirection(mainAxis, direction);
|
||||||
CSS_FLEX_DIRECTION_COLUMN :
|
var/*css_flex_direction_t*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
|
||||||
CSS_FLEX_DIRECTION_ROW;
|
|
||||||
|
|
||||||
// Handle width and height style attributes
|
// Handle width and height style attributes
|
||||||
setDimensionFromStyle(node, mainAxis);
|
setDimensionFromStyle(node, mainAxis);
|
||||||
@@ -276,26 +349,30 @@ var computeLayout = (function() {
|
|||||||
// delta composed of the margin and left/top/right/bottom
|
// delta composed of the margin and left/top/right/bottom
|
||||||
node.layout[leading[mainAxis]] += getMargin(node, leading[mainAxis]) +
|
node.layout[leading[mainAxis]] += getMargin(node, leading[mainAxis]) +
|
||||||
getRelativePosition(node, mainAxis);
|
getRelativePosition(node, mainAxis);
|
||||||
|
node.layout[trailing[mainAxis]] += getMargin(node, trailing[mainAxis]) +
|
||||||
|
getRelativePosition(node, mainAxis);
|
||||||
node.layout[leading[crossAxis]] += getMargin(node, leading[crossAxis]) +
|
node.layout[leading[crossAxis]] += getMargin(node, leading[crossAxis]) +
|
||||||
getRelativePosition(node, crossAxis);
|
getRelativePosition(node, crossAxis);
|
||||||
|
node.layout[trailing[crossAxis]] += getMargin(node, trailing[crossAxis]) +
|
||||||
|
getRelativePosition(node, crossAxis);
|
||||||
|
|
||||||
if (isMeasureDefined(node)) {
|
if (isMeasureDefined(node)) {
|
||||||
var/*float*/ width = CSS_UNDEFINED;
|
var/*float*/ width = CSS_UNDEFINED;
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
width = node.style.width;
|
width = node.style.width;
|
||||||
} else if (!isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_ROW]])) {
|
} else if (!isUndefined(node.layout[dim[resolvedRowAxis]])) {
|
||||||
width = node.layout[dim[CSS_FLEX_DIRECTION_ROW]];
|
width = node.layout[dim[resolvedRowAxis]];
|
||||||
} else {
|
} else {
|
||||||
width = parentMaxWidth -
|
width = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getMarginAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
width -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
width -= getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
// We only need to give a dimension for the text if we haven't got any
|
// We only need to give a dimension for the text if we haven't got any
|
||||||
// for it computed yet. It can either be from the style attribute or because
|
// for it computed yet. It can either be from the style attribute or because
|
||||||
// the element is flexible.
|
// the element is flexible.
|
||||||
var/*bool*/ isRowUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_ROW) &&
|
var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&
|
||||||
isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_ROW]]);
|
isUndefined(node.layout[dim[resolvedRowAxis]]);
|
||||||
var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
|
var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
|
||||||
isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);
|
isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);
|
||||||
|
|
||||||
@@ -308,7 +385,7 @@ var computeLayout = (function() {
|
|||||||
);
|
);
|
||||||
if (isRowUndefined) {
|
if (isRowUndefined) {
|
||||||
node.layout.width = measureDim.width +
|
node.layout.width = measureDim.width +
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
if (isColumnUndefined) {
|
if (isColumnUndefined) {
|
||||||
node.layout.height = measureDim.height +
|
node.layout.height = measureDim.height +
|
||||||
@@ -411,20 +488,20 @@ var computeLayout = (function() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
maxWidth = CSS_UNDEFINED;
|
maxWidth = CSS_UNDEFINED;
|
||||||
if (mainAxis !== CSS_FLEX_DIRECTION_ROW) {
|
if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = node.layout[dim[CSS_FLEX_DIRECTION_ROW]] -
|
maxWidth = node.layout[dim[resolvedRowAxis]] -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the main recursive call. We layout non flexible children.
|
// This is the main recursive call. We layout non flexible children.
|
||||||
if (alreadyComputedNextLayout === 0) {
|
if (alreadyComputedNextLayout === 0) {
|
||||||
layoutNode(/*(java)!layoutContext, */child, maxWidth);
|
layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute positioned elements do not take part of the layout, so we
|
// Absolute positioned elements do not take part of the layout, so we
|
||||||
@@ -510,17 +587,17 @@ var computeLayout = (function() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
maxWidth = CSS_UNDEFINED;
|
maxWidth = CSS_UNDEFINED;
|
||||||
if (isDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = node.layout[dim[CSS_FLEX_DIRECTION_ROW]] -
|
maxWidth = node.layout[dim[resolvedRowAxis]] -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
} else if (mainAxis !== CSS_FLEX_DIRECTION_ROW) {
|
} else if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSS_FLEX_DIRECTION_ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And we recursively call the layout algorithm for this child
|
// And we recursively call the layout algorithm for this child
|
||||||
layoutNode(/*(java)!layoutContext, */child, maxWidth);
|
layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,6 +650,11 @@ var computeLayout = (function() {
|
|||||||
// If the child is position absolute (without top/left) or relative,
|
// If the child is position absolute (without top/left) or relative,
|
||||||
// we put it at the current accumulated offset.
|
// we put it at the current accumulated offset.
|
||||||
child.layout[pos[mainAxis]] += mainDim;
|
child.layout[pos[mainAxis]] += mainDim;
|
||||||
|
|
||||||
|
// Define the trailing position accordingly.
|
||||||
|
if (!isUndefined(node.layout[dim[mainAxis]])) {
|
||||||
|
setTrailingPosition(node, child, mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we placed the element, we need to update the variables
|
// Now that we placed the element, we need to update the variables
|
||||||
@@ -667,6 +749,12 @@ var computeLayout = (function() {
|
|||||||
// We can never assign a width smaller than the padding and borders
|
// We can never assign a width smaller than the padding and borders
|
||||||
getPaddingAndBorderAxis(node, mainAxis)
|
getPaddingAndBorderAxis(node, mainAxis)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Now that the width is defined, we should update the trailing
|
||||||
|
// positions for the children.
|
||||||
|
for (i = 0; i < node.children.length; ++i) {
|
||||||
|
setTrailingPosition(node, node.children[i], mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUndefined(node.layout[dim[crossAxis]])) {
|
if (isUndefined(node.layout[dim[crossAxis]])) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -19,14 +19,14 @@ describe('Javascript Only', function() {
|
|||||||
it('should fill root node with layout, style, and children', function() {
|
it('should fill root node with layout, style, and children', function() {
|
||||||
testFillNodes(
|
testFillNodes(
|
||||||
{},
|
{},
|
||||||
{layout: {width: undefined, height: undefined, top: 0, left: 0}, style: {}, children: []}
|
{layout: {width: undefined, height: undefined, top: 0, left: 0, right: 0, bottom: 0}, style: {}, children: []}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should fill root and child node with layout, style, and children', function() {
|
it('should fill root and child node with layout, style, and children', function() {
|
||||||
testFillNodes(
|
testFillNodes(
|
||||||
{children: [{}]},
|
{children: [{}]},
|
||||||
{layout: {width: undefined, height: undefined, top: 0, left: 0}, style: {}, children: [
|
{layout: {width: undefined, height: undefined, top: 0, left: 0, right: 0, bottom: 0}, style: {}, children: [
|
||||||
{layout: {width: undefined, height: undefined, top: 0, left: 0}, style: {}, children: []}
|
{layout: {width: undefined, height: undefined, top: 0, left: 0, right: 0, bottom: 0}, style: {}, children: []}
|
||||||
]}
|
]}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -46,9 +46,9 @@ describe('Javascript Only', function() {
|
|||||||
]}
|
]}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('Layout', function() {
|
describe('Layout', function() {
|
||||||
it('should layout a single node with width and height', function() {
|
it('should layout a single node with width and height', function() {
|
||||||
testLayout({
|
testLayout({
|
||||||
@@ -73,6 +73,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with children in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 500, height: 500}},
|
||||||
|
{style: {width: 250, height: 250}},
|
||||||
|
{style: {width: 125, height: 125}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 500, height: 500, top: 500, left: 0},
|
||||||
|
{width: 250, height: 250, top: 250, left: 0},
|
||||||
|
{width: 125, height: 125, top: 125, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with nested children', function() {
|
it('should layout node with nested children', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000}, children: [
|
{style: {width: 1000, height: 1000}, children: [
|
||||||
@@ -92,6 +107,25 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with nested children in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 500, height: 500}},
|
||||||
|
{style: {width: 500, height: 500, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 250, height: 250}},
|
||||||
|
{style: {width: 250, height: 250}}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 500, height: 500, top: 500, left: 0},
|
||||||
|
{width: 500, height: 500, top: 0, left: 0, children: [
|
||||||
|
{width: 250, height: 250, top: 250, left: 0},
|
||||||
|
{width: 250, height: 250, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with margin', function() {
|
it('should layout node with margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 100, height: 200, margin: 10}},
|
{style: {width: 100, height: 200, margin: 10}},
|
||||||
@@ -114,6 +148,34 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with several children in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', margin: 10}, children: [
|
||||||
|
{style: {width: 100, height: 100, margin: 50}},
|
||||||
|
{style: {width: 100, height: 100, margin: 25}},
|
||||||
|
{style: {width: 100, height: 100, margin: 10}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 10, left: 10, children: [
|
||||||
|
{width: 100, height: 100, top: 850, left: 50},
|
||||||
|
{width: 100, height: 100, top: 675, left: 25},
|
||||||
|
{width: 100, height: 100, top: 540, left: 10}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should layout rtl with reverse correctly', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, direction: 'rtl', flexDirection: 'row-reverse'}, children: [
|
||||||
|
{style: {width: 100, height: 200}},
|
||||||
|
{style: {width: 300, height: 150}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 200, top: 0, left: 0},
|
||||||
|
{width: 300, height: 150, top: 0, left: 100}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with row flex direction', function() {
|
it('should layout node with row flex direction', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, flexDirection: 'row'}, children: [
|
{style: {width: 1000, height: 1000, flexDirection: 'row'}, children: [
|
||||||
@@ -127,6 +189,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with row flex direction in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {width: 100, height: 200}},
|
||||||
|
{style: {width: 300, height: 150}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 200, top: 0, left: 900},
|
||||||
|
{width: 300, height: 150, top: 0, left: 600}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node based on children main dimensions', function() {
|
it('should layout node based on children main dimensions', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300}, children: [
|
{style: {width: 300}, children: [
|
||||||
@@ -140,6 +215,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node based on children main dimensions in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 100, height: 200}},
|
||||||
|
{style: {width: 300, height: 150}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 350, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 200, top: 150, left: 0},
|
||||||
|
{width: 300, height: 150, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with just flex', function() {
|
it('should layout node with just flex', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000}, children: [
|
{style: {width: 1000, height: 1000}, children: [
|
||||||
@@ -153,6 +241,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with just flex in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 100, height: 200}},
|
||||||
|
{style: {width: 100, flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 200, top: 800, left: 0},
|
||||||
|
{width: 100, height: 800, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with flex recursively', function() {
|
it('should layout node with flex recursively', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000}, children: [
|
{style: {width: 1000, height: 1000}, children: [
|
||||||
@@ -172,6 +273,25 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with flex recursively in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 1000, flex: 1, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 1000, flex: 1, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {width: 1000, flex: 1, flexDirection: 'column-reverse'}}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with targeted margin', function() {
|
it('should layout node with targeted margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, marginTop: 10, marginLeft: 5}, children: [
|
{style: {width: 1000, height: 1000, marginTop: 10, marginLeft: 5}, children: [
|
||||||
@@ -185,6 +305,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with targeted margin in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', marginTop: 10, marginLeft: 5}, children: [
|
||||||
|
{style: {width: 100, height: 100, marginTop: 50, marginLeft: 15, marginBottom: 20}},
|
||||||
|
{style: {width: 100, height: 100, marginLeft: 30}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 10, left: 5, children: [
|
||||||
|
{width: 100, height: 100, top: 880, left: 15},
|
||||||
|
{width: 100, height: 100, top: 730, left: 30}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with justifyContent: flex-start', function() {
|
it('should layout node with justifyContent: flex-start', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, justifyContent: 'flex-start'}, children: [
|
{style: {width: 1000, height: 1000, justifyContent: 'flex-start'}, children: [
|
||||||
@@ -198,6 +331,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with justifyContent: flex-start in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', justifyContent: 'flex-start'}, children: [
|
||||||
|
{style: {width: 100, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 100, top: 900, left: 0},
|
||||||
|
{width: 100, height: 100, top: 800, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with justifyContent: flex-end', function() {
|
it('should layout node with justifyContent: flex-end', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, justifyContent: 'flex-end'}, children: [
|
{style: {width: 1000, height: 1000, justifyContent: 'flex-end'}, children: [
|
||||||
@@ -211,6 +357,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with justifyContent: flex-end in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', justifyContent: 'flex-end'}, children: [
|
||||||
|
{style: {width: 100, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 100, top: 100, left: 0},
|
||||||
|
{width: 100, height: 100, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with justifyContent: space-between', function() {
|
it('should layout node with justifyContent: space-between', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, justifyContent: 'space-between'}, children: [
|
{style: {width: 1000, height: 1000, justifyContent: 'space-between'}, children: [
|
||||||
@@ -224,6 +383,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with justifyContent: space-between in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', justifyContent: 'space-between'}, children: [
|
||||||
|
{style: {width: 100, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 100, top: 900, left: 0},
|
||||||
|
{width: 100, height: 100, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with justifyContent: space-around', function() {
|
it('should layout node with justifyContent: space-around', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, justifyContent: 'space-around'}, children: [
|
{style: {width: 1000, height: 1000, justifyContent: 'space-around'}, children: [
|
||||||
@@ -237,6 +409,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with justifyContent: space-around in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', justifyContent: 'space-around'}, children: [
|
||||||
|
{style: {width: 100, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 100, top: 700, left: 0},
|
||||||
|
{width: 100, height: 100, top: 200, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with justifyContent: center', function() {
|
it('should layout node with justifyContent: center', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, justifyContent: 'center'}, children: [
|
{style: {width: 1000, height: 1000, justifyContent: 'center'}, children: [
|
||||||
@@ -250,6 +435,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with justifyContent: center in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', justifyContent: 'center'}, children: [
|
||||||
|
{style: {width: 100, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 100, top: 500, left: 0},
|
||||||
|
{width: 100, height: 100, top: 400, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with flex override height', function() {
|
it('should layout node with flex override height', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000}, children: [
|
{style: {width: 1000, height: 1000}, children: [
|
||||||
@@ -274,6 +472,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with alignItems: flex-start in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', alignItems: 'flex-start'}, children: [
|
||||||
|
{style: {width: 200, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: 100, top: 900, left: 0},
|
||||||
|
{width: 100, height: 100, top: 800, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with alignItems: center', function() {
|
it('should layout node with alignItems: center', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, alignItems: 'center'}, children: [
|
{style: {width: 1000, height: 1000, alignItems: 'center'}, children: [
|
||||||
@@ -287,6 +498,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with alignItems: center in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', alignItems: 'center'}, children: [
|
||||||
|
{style: {width: 200, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: 100, top: 900, left: 400},
|
||||||
|
{width: 100, height: 100, top: 800, left: 450}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with alignItems: flex-end', function() {
|
it('should layout node with alignItems: flex-end', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, alignItems: 'flex-end'}, children: [
|
{style: {width: 1000, height: 1000, alignItems: 'flex-end'}, children: [
|
||||||
@@ -300,6 +524,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with alignItems: flex-end in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', alignItems: 'flex-end'}, children: [
|
||||||
|
{style: {width: 200, height: 100}},
|
||||||
|
{style: {width: 100, height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: 100, top: 900, left: 800},
|
||||||
|
{width: 100, height: 100, top: 800, left: 900}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with alignSelf overrides alignItems', function() {
|
it('should layout node with alignSelf overrides alignItems', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, alignItems: 'flex-end'}, children: [
|
{style: {width: 1000, height: 1000, alignItems: 'flex-end'}, children: [
|
||||||
@@ -313,6 +550,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with alignSelf overrides alignItems in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', alignItems: 'flex-end'}, children: [
|
||||||
|
{style: {width: 200, height: 100}},
|
||||||
|
{style: {width: 100, height: 100, alignSelf: 'center'}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: 100, top: 900, left: 800},
|
||||||
|
{width: 100, height: 100, top: 800, left: 450}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with alignItem: stretch', function() {
|
it('should layout node with alignItem: stretch', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000, alignItems: 'stretch'}, children: [
|
{style: {width: 1000, height: 1000, alignItems: 'stretch'}, children: [
|
||||||
@@ -324,6 +574,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with alignItem: stretch in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, height: 1000, flexDirection: 'column-reverse', alignItems: 'stretch'}, children: [
|
||||||
|
{style: {height: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 1000, top: 0, left: 0, children: [
|
||||||
|
{width: 1000, height: 100, top: 900, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout empty node', function() {
|
it('should layout empty node', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -335,6 +596,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout empty node in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {}}
|
||||||
|
]},
|
||||||
|
{width: 0, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout child with margin', function() {
|
it('should layout child with margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -346,6 +618,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout child with margin in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {margin: 5}}
|
||||||
|
]},
|
||||||
|
{width: 10, height: 10, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 5, left: 5}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not shrink children if not enough space', function() {
|
it('should not shrink children if not enough space', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {height: 100}, children: [
|
{style: {height: 100}, children: [
|
||||||
@@ -359,6 +642,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not shrink children if not enough space in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {height: 100, flexDirection: 'column-reverse'}, children: [
|
||||||
|
{style: {height: 100}},
|
||||||
|
{style: {height: 200}}
|
||||||
|
]},
|
||||||
|
{width: 0, height: 100, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 100, top: 0, left: 0},
|
||||||
|
{width: 0, height: 200, top: -200, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout for center', function() {
|
it('should layout for center', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {justifyContent: 'center'}},
|
{style: {justifyContent: 'center'}},
|
||||||
@@ -377,6 +673,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout flex-end taking into account margin in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {height: 100, flexDirection: 'column-reverse', justifyContent: 'flex-end'}, children: [
|
||||||
|
{style: {marginTop: 10}}
|
||||||
|
]},
|
||||||
|
{width: 0, height: 100, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 10, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout alignItems with margin', function() {
|
it('should layout alignItems with margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -394,6 +701,23 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout alignItems with margin in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {}, children: [
|
||||||
|
{style: {flexDirection: 'column-reverse', alignItems: 'flex-end'}, children: [
|
||||||
|
{style: {margin: 10}},
|
||||||
|
{style: {height: 100}}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 20, height: 120, top: 0, left: 0, children: [
|
||||||
|
{width: 20, height: 120, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 110, left: 10},
|
||||||
|
{width: 0, height: 100, top: 0, left: 20}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout flex inside of an empty element', function() {
|
it('should layout flex inside of an empty element', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -416,6 +740,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout alignItems stretch and margin in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {flexDirection: 'column-reverse', alignItems: 'stretch'}, children: [
|
||||||
|
{style: {marginLeft: 10}}
|
||||||
|
]},
|
||||||
|
{width: 10, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 0, left: 10}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with padding', function() {
|
it('should layout node with padding', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {padding: 5}},
|
{style: {padding: 5}},
|
||||||
@@ -652,6 +987,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with space-around and child position absolute in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {height: 200, flexDirection: 'column-reverse', justifyContent: 'space-around'}, children: [
|
||||||
|
{style: {position: 'absolute'}},
|
||||||
|
{style: {}}
|
||||||
|
]},
|
||||||
|
{width: 0, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 100, left: 0},
|
||||||
|
{width: 0, height: 0, top: 100, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with flex and main margin', function() {
|
it('should layout node with flex and main margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 700, flexDirection: 'row'}, children: [
|
{style: {width: 700, flexDirection: 'row'}, children: [
|
||||||
@@ -663,6 +1011,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with flex and main margin in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 700, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {marginRight: 5, flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 700, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 695, height: 0, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with multiple flex and padding', function() {
|
it('should layout node with multiple flex and padding', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 700, flexDirection: 'row'}, children: [
|
{style: {width: 700, flexDirection: 'row'}, children: [
|
||||||
@@ -676,6 +1035,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with multiple flex and padding in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 700, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1}},
|
||||||
|
{style: {paddingLeft: 5, flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 700, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 347.5, height: 0, top: 0, left: 352.5},
|
||||||
|
{width: 352.5, height: 0, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with multiple flex and margin', function() {
|
it('should layout node with multiple flex and margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 700, flexDirection: 'row'}, children: [
|
{style: {width: 700, flexDirection: 'row'}, children: [
|
||||||
@@ -689,6 +1061,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with multiple flex and margin in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 700, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1}},
|
||||||
|
{style: {marginRight: 5, flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 700, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 347.5, height: 0, top: 0, left: 352.5},
|
||||||
|
{width: 347.5, height: 0, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with flex and overflow', function() {
|
it('should layout node with flex and overflow', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {height: 300}, children: [
|
{style: {height: 300}, children: [
|
||||||
@@ -713,6 +1098,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with flex and position absolute in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 600, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1, position: 'absolute'}}
|
||||||
|
]},
|
||||||
|
{width: 600, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 0, left: 600}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with double flex and position absolute', function() {
|
it('should layout node with double flex and position absolute', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {height: 500}, children: [
|
{style: {height: 500}, children: [
|
||||||
@@ -788,6 +1184,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle negative margin and min padding correctly in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {borderLeftWidth: 1, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {marginLeft: -8}}
|
||||||
|
]},
|
||||||
|
{width: 1, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 0, top: 0, left: 1}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with just text', function() {
|
it('should layout node with just text', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {measure: text(texts.small)}},
|
{style: {measure: text(texts.small)}},
|
||||||
@@ -839,6 +1246,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout node with text and flex in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {}, children: [
|
||||||
|
{style: {width: 500, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1, measure: text(texts.big)}}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 500, height: textSizes.smallHeight, top: 0, left: 0, children: [
|
||||||
|
{width: 500, height: textSizes.smallHeight, top: 0, left: 0, children: [
|
||||||
|
{width: 500, height: textSizes.smallHeight, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with text and stretch', function() {
|
it('should layout node with text and stretch', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 130}, children: [
|
{style: {width: 130}, children: [
|
||||||
@@ -908,6 +1330,19 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout space-between when remaining space is negative in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {height: 100, flexDirection: 'column-reverse', justifyContent: 'space-between'}, children: [
|
||||||
|
{style: {height: 900}},
|
||||||
|
{style: {}}
|
||||||
|
]},
|
||||||
|
{width: 0, height: 100, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 900, top: -800, left: 0},
|
||||||
|
{width: 0, height: 0, top: -800, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout flex-end when remaining space is negative', function() {
|
it('should layout flex-end when remaining space is negative', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 200, flexDirection: 'row', justifyContent: 'flex-end'}, children: [
|
{style: {width: 200, flexDirection: 'row', justifyContent: 'flex-end'}, children: [
|
||||||
@@ -919,6 +1354,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout flex-end when remaining space is negative in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 200, direction: 'rtl', flexDirection: 'row', justifyContent: 'flex-end'}, children: [
|
||||||
|
{style: {width: 900}}
|
||||||
|
]},
|
||||||
|
{width: 200, height: 0, top: 0, left: 0, children: [
|
||||||
|
{width: 900, height: 0, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout text with flexDirection row', function() {
|
it('should layout text with flexDirection row', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -934,6 +1380,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout text with flexDirection row in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: { direction: 'rtl' }, children: [
|
||||||
|
{style: {width: 200, flexDirection: 'row'}, children: [
|
||||||
|
{style: {margin: 20, measure: text(texts.big)}}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 200, height: textSizes.smallHeight + 40, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: textSizes.smallHeight + 40, top: 0, left: 0, children: [
|
||||||
|
{width: textSizes.bigWidth, height: textSizes.smallHeight, top: 20, left: 7.578125}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout with text and margin', function() {
|
it('should layout with text and margin', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {}, children: [
|
{style: {}, children: [
|
||||||
@@ -973,15 +1434,28 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should layout with negative flex', function() {
|
it('should layout with arbitrary flex in reverse', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 100, height: 100, alignSelf: 'flex-start'}, children: [
|
{style: {width: 100, height: 100, flexDirection: 'column-reverse', alignSelf: 'flex-start'}, children: [
|
||||||
|
{style: {flex: 2.5, alignSelf: 'flex-start'}},
|
||||||
|
{style: {flex: 7.5, alignSelf: 'flex-start'}}
|
||||||
|
]},
|
||||||
|
{width: 100, height: 100, top: 0, left: 0, children: [
|
||||||
|
{width: 0, height: 25, top: 75, left: 0},
|
||||||
|
{width: 0, height: 75, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should layout with negative flex in reverse', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 100, height: 100, flexDirection: 'column-reverse', alignSelf: 'flex-start'}, children: [
|
||||||
{style: {flex: -2.5, alignSelf: 'flex-start'}},
|
{style: {flex: -2.5, alignSelf: 'flex-start'}},
|
||||||
{style: {flex: 0, alignSelf: 'flex-start'}}
|
{style: {flex: 0, alignSelf: 'flex-start'}}
|
||||||
]},
|
]},
|
||||||
{width: 100, height: 100, top: 0, left: 0, children: [
|
{width: 100, height: 100, top: 0, left: 0, children: [
|
||||||
{width: 0, height: 0, top: 0, left: 0},
|
{width: 0, height: 0, top: 100, left: 0},
|
||||||
{width: 0, height: 0, top: 0, left: 0}
|
{width: 0, height: 0, top: 100, left: 0}
|
||||||
]}
|
]}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1196,6 +1670,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout flex-wrap in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {flexWrap: 'wrap', direction: 'rtl', flexDirection: 'row', width: 100}, children: [
|
||||||
|
{style: {width: 40, height: 10}},
|
||||||
|
{style: {width: 40, height: 10}},
|
||||||
|
{style: {width: 40, height: 10}}
|
||||||
|
]},
|
||||||
|
{width: 100, height: 20, top: 0, left: 0, children: [
|
||||||
|
{width: 40, height: 10, top: 0, left: 60},
|
||||||
|
{width: 40, height: 10, top: 0, left: 20},
|
||||||
|
{width: 40, height: 10, top: 10, left: 60}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout flex wrap with a line bigger than container', function() {
|
it('should layout flex wrap with a line bigger than container', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {height: 100, flexWrap: 'wrap'}, children: [
|
{style: {height: 100, flexWrap: 'wrap'}, children: [
|
||||||
@@ -1315,6 +1804,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should override flex direction size with min bounds in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, height: 200, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1}},
|
||||||
|
{style: {flex: 1, minWidth: 200}},
|
||||||
|
{style: {flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 50, height: 200, top: 0, left: 250},
|
||||||
|
{width: 200, height: 200, top: 0, left: 50},
|
||||||
|
{width: 50, height: 200, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not override flex direction size within bounds', function() {
|
it('should not override flex direction size within bounds', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
||||||
@@ -1330,6 +1834,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not override flex direction size within bounds in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, height: 200, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1}},
|
||||||
|
{style: {flex: 1, minWidth: 90, maxWidth: 110}},
|
||||||
|
{style: {flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 200, top: 0, left: 200},
|
||||||
|
{width: 100, height: 200, top: 0, left: 100},
|
||||||
|
{width: 100, height: 200, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should override flex direction size with max bounds', function() {
|
it('should override flex direction size with max bounds', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
||||||
@@ -1345,6 +1864,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should override flex direction size with max bounds in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, height: 200, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1}},
|
||||||
|
{style: {flex: 1, maxWidth: 60}},
|
||||||
|
{style: {flex: 1}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 120, height: 200, top: 0, left: 180},
|
||||||
|
{width: 60, height: 200, top: 0, left: 120},
|
||||||
|
{width: 120, height: 200, top: 0, left: 0}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should ignore flex size if fully max bound', function() {
|
it('should ignore flex size if fully max bound', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
||||||
@@ -1360,6 +1894,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore flex size if fully max bound in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, height: 200, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1, maxWidth: 60}},
|
||||||
|
{style: {flex: 1, maxWidth: 60}},
|
||||||
|
{style: {flex: 1, maxWidth: 60}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 60, height: 200, top: 0, left: 240},
|
||||||
|
{width: 60, height: 200, top: 0, left: 180},
|
||||||
|
{width: 60, height: 200, top: 0, left: 120}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should ignore flex size if fully min bound', function() {
|
it('should ignore flex size if fully min bound', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
{style: {width: 300, height: 200, flexDirection: 'row'}, children: [
|
||||||
@@ -1375,6 +1924,21 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore flex size if fully min bound in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 300, height: 200, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {flex: 1, minWidth: 120}},
|
||||||
|
{style: {flex: 1, minWidth: 120}},
|
||||||
|
{style: {flex: 1, minWidth: 120}}
|
||||||
|
]},
|
||||||
|
{width: 300, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 120, height: 200, top: 0, left: 180},
|
||||||
|
{width: 120, height: 200, top: 0, left: 60},
|
||||||
|
{width: 120, height: 200, top: 0, left: -60}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should pre-fill child size within bounds', function() {
|
it('should pre-fill child size within bounds', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 300, height: 200}, children: [
|
{style: {width: 300, height: 200}, children: [
|
||||||
@@ -1491,6 +2055,17 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should keep cross axis size within min bounds in rtl', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 1000, direction: 'rtl', flexDirection: 'row'}, children: [
|
||||||
|
{style: {height: 100, minHeight: 110, minWidth: 100}}
|
||||||
|
]},
|
||||||
|
{width: 1000, height: 110, top: 0, left: 0, children: [
|
||||||
|
{width: 100, height: 110, top: 0, left: 900}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should layout node with position absolute, top and left and max bounds', function() {
|
it('should layout node with position absolute, top and left and max bounds', function() {
|
||||||
testLayout(
|
testLayout(
|
||||||
{style: {width: 1000, height: 1000}, children: [
|
{style: {width: 1000, height: 1000}, children: [
|
||||||
@@ -1586,5 +2161,28 @@ describe('Layout', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should layout nested nodes with mixed directions', function() {
|
||||||
|
testLayout(
|
||||||
|
{style: {width: 200, height: 200, direction: 'rtl'}, children: [
|
||||||
|
{style: {flexDirection: 'row'}, children: [
|
||||||
|
{style: {width: 50, height: 50}},
|
||||||
|
{style: {width: 50, height: 50}}
|
||||||
|
]},
|
||||||
|
{style: {direction: 'ltr', flexDirection: 'row'}, children: [
|
||||||
|
{style: {width: 50, height: 50}},
|
||||||
|
{style: {width: 50, height: 50}}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{width: 200, height: 200, top: 0, left: 0, children: [
|
||||||
|
{width: 200, height: 50, top: 0, left: 0, children: [
|
||||||
|
{width: 50, height: 50, top: 0, left: 150},
|
||||||
|
{width: 50, height: 50, top: 0, left: 100}
|
||||||
|
]},
|
||||||
|
{width: 200, height: 50, top: 50, left: 0, children: [
|
||||||
|
{width: 50, height: 50, top: 0, left: 0},
|
||||||
|
{width: 50, height: 50, top: 0, left: 50}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
15
src/java/src/com/facebook/csslayout/CSSDirection.java
Normal file
15
src/java/src/com/facebook/csslayout/CSSDirection.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
package com.facebook.csslayout;
|
||||||
|
|
||||||
|
public enum CSSDirection {
|
||||||
|
INHERIT,
|
||||||
|
LTR,
|
||||||
|
RTL,
|
||||||
|
}
|
@@ -10,5 +10,7 @@ package com.facebook.csslayout;
|
|||||||
|
|
||||||
public enum CSSFlexDirection {
|
public enum CSSFlexDirection {
|
||||||
COLUMN,
|
COLUMN,
|
||||||
|
COLUMN_REVERSE,
|
||||||
ROW,
|
ROW,
|
||||||
|
ROW_REVERSE
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,10 @@ package com.facebook.csslayout;
|
|||||||
*/
|
*/
|
||||||
public class CSSLayout {
|
public class CSSLayout {
|
||||||
|
|
||||||
public float x;
|
public float top;
|
||||||
public float y;
|
public float left;
|
||||||
|
public float right;
|
||||||
|
public float bottom;
|
||||||
public float width = CSSConstants.UNDEFINED;
|
public float width = CSSConstants.UNDEFINED;
|
||||||
public float height = CSSConstants.UNDEFINED;
|
public float height = CSSConstants.UNDEFINED;
|
||||||
|
|
||||||
@@ -22,15 +24,19 @@ public class CSSLayout {
|
|||||||
* This should always get called before calling {@link LayoutEngine#layoutNode(CSSNode, float)}
|
* This should always get called before calling {@link LayoutEngine#layoutNode(CSSNode, float)}
|
||||||
*/
|
*/
|
||||||
public void resetResult() {
|
public void resetResult() {
|
||||||
x = 0;
|
left = 0;
|
||||||
y = 0;
|
top = 0;
|
||||||
|
right = 0;
|
||||||
|
bottom = 0;
|
||||||
width = CSSConstants.UNDEFINED;
|
width = CSSConstants.UNDEFINED;
|
||||||
height = CSSConstants.UNDEFINED;
|
height = CSSConstants.UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copy(CSSLayout layout) {
|
public void copy(CSSLayout layout) {
|
||||||
x = layout.x;
|
left = layout.left;
|
||||||
y = layout.y;
|
top = layout.top;
|
||||||
|
right = layout.right;
|
||||||
|
bottom = layout.bottom;
|
||||||
width = layout.width;
|
width = layout.width;
|
||||||
height = layout.height;
|
height = layout.height;
|
||||||
}
|
}
|
||||||
@@ -38,8 +44,8 @@ public class CSSLayout {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "layout: {" +
|
return "layout: {" +
|
||||||
"x: " + x + ", " +
|
"left: " + left + ", " +
|
||||||
"y: " + y + ", " +
|
"top: " + top + ", " +
|
||||||
"width: " + width + ", " +
|
"width: " + width + ", " +
|
||||||
"height: " + height +
|
"height: " + height +
|
||||||
"}";
|
"}";
|
||||||
|
@@ -125,7 +125,7 @@ public class CSSNode {
|
|||||||
*/
|
*/
|
||||||
public void calculateLayout(CSSLayoutContext layoutContext) {
|
public void calculateLayout(CSSLayoutContext layoutContext) {
|
||||||
layout.resetResult();
|
layout.resetResult();
|
||||||
LayoutEngine.layoutNode(layoutContext, this, CSSConstants.UNDEFINED);
|
LayoutEngine.layoutNode(layoutContext, this, CSSConstants.UNDEFINED, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -328,11 +328,11 @@ public class CSSNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float getLayoutX() {
|
public float getLayoutX() {
|
||||||
return layout.x;
|
return layout.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getLayoutY() {
|
public float getLayoutY() {
|
||||||
return layout.y;
|
return layout.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getLayoutWidth() {
|
public float getLayoutWidth() {
|
||||||
|
@@ -13,6 +13,7 @@ package com.facebook.csslayout;
|
|||||||
*/
|
*/
|
||||||
public class CSSStyle {
|
public class CSSStyle {
|
||||||
|
|
||||||
|
public CSSDirection direction = CSSDirection.INHERIT;
|
||||||
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;
|
||||||
|
@@ -28,24 +28,34 @@ public class LayoutEngine {
|
|||||||
private static void setLayoutPosition(CSSNode node, PositionIndex position, float value) {
|
private static void setLayoutPosition(CSSNode node, PositionIndex position, float value) {
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case TOP:
|
case TOP:
|
||||||
node.layout.y = value;
|
node.layout.top = value;
|
||||||
break;
|
break;
|
||||||
case LEFT:
|
case LEFT:
|
||||||
node.layout.x = value;
|
node.layout.left = value;
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
node.layout.right = value;
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
node.layout.bottom = value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Didn't get TOP or LEFT!");
|
throw new RuntimeException("Didn't get TOP, LEFT, RIGHT, or BOTTOM!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float getLayoutPosition(CSSNode node, PositionIndex position) {
|
private static float getLayoutPosition(CSSNode node, PositionIndex position) {
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case TOP:
|
case TOP:
|
||||||
return node.layout.y;
|
return node.layout.top;
|
||||||
case LEFT:
|
case LEFT:
|
||||||
return node.layout.x;
|
return node.layout.left;
|
||||||
|
case RIGHT:
|
||||||
|
return node.layout.right;
|
||||||
|
case BOTTOM:
|
||||||
|
return node.layout.bottom;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Didn't get TOP or LEFT!");
|
throw new RuntimeException("Didn't get TOP, LEFT, RIGHT, or BOTTOM!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,19 +110,61 @@ public class LayoutEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PositionIndex getLeading(CSSFlexDirection axis) {
|
private static PositionIndex getLeading(CSSFlexDirection axis) {
|
||||||
return axis == CSSFlexDirection.COLUMN ? PositionIndex.TOP : PositionIndex.LEFT;
|
switch (axis) {
|
||||||
|
case COLUMN:
|
||||||
|
return PositionIndex.TOP;
|
||||||
|
case COLUMN_REVERSE:
|
||||||
|
return PositionIndex.BOTTOM;
|
||||||
|
case ROW:
|
||||||
|
return PositionIndex.LEFT;
|
||||||
|
case ROW_REVERSE:
|
||||||
|
return PositionIndex.RIGHT;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Didn't get TOP, LEFT, RIGHT, or BOTTOM!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PositionIndex getTrailing(CSSFlexDirection axis) {
|
private static PositionIndex getTrailing(CSSFlexDirection axis) {
|
||||||
return axis == CSSFlexDirection.COLUMN ? PositionIndex.BOTTOM : PositionIndex.RIGHT;
|
switch (axis) {
|
||||||
|
case COLUMN:
|
||||||
|
return PositionIndex.BOTTOM;
|
||||||
|
case COLUMN_REVERSE:
|
||||||
|
return PositionIndex.TOP;
|
||||||
|
case ROW:
|
||||||
|
return PositionIndex.RIGHT;
|
||||||
|
case ROW_REVERSE:
|
||||||
|
return PositionIndex.LEFT;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Didn't get COLUMN, COLUMN_REVERSE, ROW, or ROW_REVERSE!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PositionIndex getPos(CSSFlexDirection axis) {
|
private static PositionIndex getPos(CSSFlexDirection axis) {
|
||||||
return axis == CSSFlexDirection.COLUMN ? PositionIndex.TOP : PositionIndex.LEFT;
|
switch (axis) {
|
||||||
|
case COLUMN:
|
||||||
|
return PositionIndex.TOP;
|
||||||
|
case COLUMN_REVERSE:
|
||||||
|
return PositionIndex.BOTTOM;
|
||||||
|
case ROW:
|
||||||
|
return PositionIndex.LEFT;
|
||||||
|
case ROW_REVERSE:
|
||||||
|
return PositionIndex.RIGHT;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Didn't get COLUMN, COLUMN_REVERSE, ROW, or ROW_REVERSE!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DimensionIndex getDim(CSSFlexDirection axis) {
|
private static DimensionIndex getDim(CSSFlexDirection axis) {
|
||||||
return axis == CSSFlexDirection.COLUMN ? DimensionIndex.HEIGHT : DimensionIndex.WIDTH;
|
switch (axis) {
|
||||||
|
case COLUMN:
|
||||||
|
case COLUMN_REVERSE:
|
||||||
|
return DimensionIndex.HEIGHT;
|
||||||
|
case ROW:
|
||||||
|
case ROW_REVERSE:
|
||||||
|
return DimensionIndex.WIDTH;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Didn't get COLUMN, COLUMN_REVERSE, ROW, or ROW_REVERSE!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDimDefined(CSSNode node, CSSFlexDirection axis) {
|
private static boolean isDimDefined(CSSNode node, CSSFlexDirection axis) {
|
||||||
@@ -196,10 +248,10 @@ public class LayoutEngine {
|
|||||||
float min = CSSConstants.UNDEFINED;
|
float min = CSSConstants.UNDEFINED;
|
||||||
float max = CSSConstants.UNDEFINED;
|
float max = CSSConstants.UNDEFINED;
|
||||||
|
|
||||||
if (axis == CSSFlexDirection.COLUMN) {
|
if (isColumnDirection(axis)) {
|
||||||
min = node.style.minHeight;
|
min = node.style.minHeight;
|
||||||
max = node.style.maxHeight;
|
max = node.style.maxHeight;
|
||||||
} else if (axis == CSSFlexDirection.ROW) {
|
} else if (isRowDirection(axis)) {
|
||||||
min = node.style.minWidth;
|
min = node.style.minWidth;
|
||||||
max = node.style.maxWidth;
|
max = node.style.maxWidth;
|
||||||
}
|
}
|
||||||
@@ -233,6 +285,18 @@ public class LayoutEngine {
|
|||||||
setLayoutDimension(node, getDim(axis), maxLayoutDimension);
|
setLayoutDimension(node, getDim(axis), maxLayoutDimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setTrailingPosition(
|
||||||
|
CSSNode node,
|
||||||
|
CSSNode child,
|
||||||
|
CSSFlexDirection axis) {
|
||||||
|
setLayoutPosition(
|
||||||
|
child,
|
||||||
|
getTrailing(axis),
|
||||||
|
getLayoutDimension(node, getDim(axis)) -
|
||||||
|
getLayoutDimension(child, getDim(axis)) -
|
||||||
|
getLayoutPosition(child, getPos(axis)));
|
||||||
|
}
|
||||||
|
|
||||||
private static float getRelativePosition(CSSNode node, CSSFlexDirection axis) {
|
private static float getRelativePosition(CSSNode node, CSSFlexDirection axis) {
|
||||||
float lead = getStylePosition(node, getLeading(axis));
|
float lead = getStylePosition(node, getLeading(axis));
|
||||||
if (!CSSConstants.isUndefined(lead)) {
|
if (!CSSConstants.isUndefined(lead)) {
|
||||||
@@ -245,10 +309,53 @@ public class LayoutEngine {
|
|||||||
return node.style.flex;
|
return node.style.flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isRowDirection(CSSFlexDirection flexDirection) {
|
||||||
|
return flexDirection == CSSFlexDirection.ROW ||
|
||||||
|
flexDirection == CSSFlexDirection.ROW_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isColumnDirection(CSSFlexDirection flexDirection) {
|
||||||
|
return flexDirection == CSSFlexDirection.COLUMN ||
|
||||||
|
flexDirection == CSSFlexDirection.COLUMN_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CSSFlexDirection resolveAxis(
|
||||||
|
CSSFlexDirection axis,
|
||||||
|
CSSDirection direction) {
|
||||||
|
if (direction == CSSDirection.RTL) {
|
||||||
|
if (axis == CSSFlexDirection.ROW) {
|
||||||
|
return CSSFlexDirection.ROW_REVERSE;
|
||||||
|
} else if (axis == CSSFlexDirection.ROW_REVERSE) {
|
||||||
|
return CSSFlexDirection.ROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CSSDirection resolveDirection(CSSNode node, CSSDirection parentDirection) {
|
||||||
|
CSSDirection direction = node.style.direction;
|
||||||
|
if (direction == CSSDirection.INHERIT) {
|
||||||
|
direction = (parentDirection == null ? CSSDirection.LTR : parentDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
private static CSSFlexDirection getFlexDirection(CSSNode node) {
|
private static CSSFlexDirection getFlexDirection(CSSNode node) {
|
||||||
return node.style.flexDirection;
|
return node.style.flexDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static CSSFlexDirection getCrossFlexDirection(
|
||||||
|
CSSFlexDirection flexDirection,
|
||||||
|
CSSDirection direction) {
|
||||||
|
if (isColumnDirection(flexDirection)) {
|
||||||
|
return resolveAxis(CSSFlexDirection.ROW, direction);
|
||||||
|
} else {
|
||||||
|
return CSSFlexDirection.COLUMN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static CSSPositionType getPositionType(CSSNode node) {
|
private static CSSPositionType getPositionType(CSSNode node) {
|
||||||
return node.style.positionType;
|
return node.style.positionType;
|
||||||
}
|
}
|
||||||
@@ -292,13 +399,14 @@ public class LayoutEngine {
|
|||||||
/*package*/ static void layoutNode(
|
/*package*/ static void layoutNode(
|
||||||
CSSLayoutContext layoutContext,
|
CSSLayoutContext layoutContext,
|
||||||
CSSNode node,
|
CSSNode node,
|
||||||
float parentMaxWidth) {
|
float parentMaxWidth,
|
||||||
|
CSSDirection parentDirection) {
|
||||||
if (needsRelayout(node, parentMaxWidth)) {
|
if (needsRelayout(node, parentMaxWidth)) {
|
||||||
node.lastLayout.requestedWidth = node.layout.width;
|
node.lastLayout.requestedWidth = node.layout.width;
|
||||||
node.lastLayout.requestedHeight = node.layout.height;
|
node.lastLayout.requestedHeight = node.layout.height;
|
||||||
node.lastLayout.parentMaxWidth = parentMaxWidth;
|
node.lastLayout.parentMaxWidth = parentMaxWidth;
|
||||||
|
|
||||||
layoutNodeImpl(layoutContext, node, parentMaxWidth);
|
layoutNodeImpl(layoutContext, node, parentMaxWidth, parentDirection);
|
||||||
node.lastLayout.copy(node.layout);
|
node.lastLayout.copy(node.layout);
|
||||||
} else {
|
} else {
|
||||||
node.layout.copy(node.lastLayout);
|
node.layout.copy(node.lastLayout);
|
||||||
@@ -310,18 +418,18 @@ public class LayoutEngine {
|
|||||||
private static void layoutNodeImpl(
|
private static void layoutNodeImpl(
|
||||||
CSSLayoutContext layoutContext,
|
CSSLayoutContext layoutContext,
|
||||||
CSSNode node,
|
CSSNode node,
|
||||||
float parentMaxWidth) {
|
float parentMaxWidth,
|
||||||
|
CSSDirection parentDirection) {
|
||||||
for (int i = 0; i < node.getChildCount(); i++) {
|
for (int i = 0; i < node.getChildCount(); i++) {
|
||||||
node.getChildAt(i).layout.resetResult();
|
node.getChildAt(i).layout.resetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** START_GENERATED **/
|
/** START_GENERATED **/
|
||||||
|
|
||||||
|
CSSDirection direction = resolveDirection(node, parentDirection);
|
||||||
CSSFlexDirection mainAxis = getFlexDirection(node);
|
CSSFlexDirection mainAxis = resolveAxis(getFlexDirection(node), direction);
|
||||||
CSSFlexDirection crossAxis = mainAxis == CSSFlexDirection.ROW ?
|
CSSFlexDirection crossAxis = getCrossFlexDirection(mainAxis, direction);
|
||||||
CSSFlexDirection.COLUMN :
|
CSSFlexDirection resolvedRowAxis = resolveAxis(CSSFlexDirection.ROW, direction);
|
||||||
CSSFlexDirection.ROW;
|
|
||||||
|
|
||||||
// Handle width and height style attributes
|
// Handle width and height style attributes
|
||||||
setDimensionFromStyle(node, mainAxis);
|
setDimensionFromStyle(node, mainAxis);
|
||||||
@@ -331,26 +439,30 @@ public class LayoutEngine {
|
|||||||
// delta composed of the margin and left/top/right/bottom
|
// delta composed of the margin and left/top/right/bottom
|
||||||
setLayoutPosition(node, getLeading(mainAxis), getLayoutPosition(node, getLeading(mainAxis)) + getMargin(node, getLeading(mainAxis)) +
|
setLayoutPosition(node, getLeading(mainAxis), getLayoutPosition(node, getLeading(mainAxis)) + getMargin(node, getLeading(mainAxis)) +
|
||||||
getRelativePosition(node, mainAxis));
|
getRelativePosition(node, mainAxis));
|
||||||
|
setLayoutPosition(node, getTrailing(mainAxis), getLayoutPosition(node, getTrailing(mainAxis)) + getMargin(node, getTrailing(mainAxis)) +
|
||||||
|
getRelativePosition(node, mainAxis));
|
||||||
setLayoutPosition(node, getLeading(crossAxis), getLayoutPosition(node, getLeading(crossAxis)) + getMargin(node, getLeading(crossAxis)) +
|
setLayoutPosition(node, getLeading(crossAxis), getLayoutPosition(node, getLeading(crossAxis)) + getMargin(node, getLeading(crossAxis)) +
|
||||||
getRelativePosition(node, crossAxis));
|
getRelativePosition(node, crossAxis));
|
||||||
|
setLayoutPosition(node, getTrailing(crossAxis), getLayoutPosition(node, getTrailing(crossAxis)) + getMargin(node, getTrailing(crossAxis)) +
|
||||||
|
getRelativePosition(node, crossAxis));
|
||||||
|
|
||||||
if (isMeasureDefined(node)) {
|
if (isMeasureDefined(node)) {
|
||||||
float width = CSSConstants.UNDEFINED;
|
float width = CSSConstants.UNDEFINED;
|
||||||
if (isDimDefined(node, CSSFlexDirection.ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
width = node.style.width;
|
width = node.style.width;
|
||||||
} else if (!CSSConstants.isUndefined(getLayoutDimension(node, getDim(CSSFlexDirection.ROW)))) {
|
} else if (!CSSConstants.isUndefined(getLayoutDimension(node, getDim(resolvedRowAxis)))) {
|
||||||
width = getLayoutDimension(node, getDim(CSSFlexDirection.ROW));
|
width = getLayoutDimension(node, getDim(resolvedRowAxis));
|
||||||
} else {
|
} else {
|
||||||
width = parentMaxWidth -
|
width = parentMaxWidth -
|
||||||
getMarginAxis(node, CSSFlexDirection.ROW);
|
getMarginAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
width -= getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
width -= getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
// We only need to give a dimension for the text if we haven't got any
|
// We only need to give a dimension for the text if we haven't got any
|
||||||
// for it computed yet. It can either be from the style attribute or because
|
// for it computed yet. It can either be from the style attribute or because
|
||||||
// the element is flexible.
|
// the element is flexible.
|
||||||
boolean isRowUndefined = !isDimDefined(node, CSSFlexDirection.ROW) &&
|
boolean isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&
|
||||||
CSSConstants.isUndefined(getLayoutDimension(node, getDim(CSSFlexDirection.ROW)));
|
CSSConstants.isUndefined(getLayoutDimension(node, getDim(resolvedRowAxis)));
|
||||||
boolean isColumnUndefined = !isDimDefined(node, CSSFlexDirection.COLUMN) &&
|
boolean isColumnUndefined = !isDimDefined(node, CSSFlexDirection.COLUMN) &&
|
||||||
CSSConstants.isUndefined(getLayoutDimension(node, getDim(CSSFlexDirection.COLUMN)));
|
CSSConstants.isUndefined(getLayoutDimension(node, getDim(CSSFlexDirection.COLUMN)));
|
||||||
|
|
||||||
@@ -362,7 +474,7 @@ public class LayoutEngine {
|
|||||||
);
|
);
|
||||||
if (isRowUndefined) {
|
if (isRowUndefined) {
|
||||||
node.layout.width = measureDim.width +
|
node.layout.width = measureDim.width +
|
||||||
getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
if (isColumnUndefined) {
|
if (isColumnUndefined) {
|
||||||
node.layout.height = measureDim.height +
|
node.layout.height = measureDim.height +
|
||||||
@@ -465,20 +577,20 @@ public class LayoutEngine {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
maxWidth = CSSConstants.UNDEFINED;
|
maxWidth = CSSConstants.UNDEFINED;
|
||||||
if (mainAxis != CSSFlexDirection.ROW) {
|
if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSSFlexDirection.ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
|
|
||||||
if (isDimDefined(node, CSSFlexDirection.ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = getLayoutDimension(node, getDim(CSSFlexDirection.ROW)) -
|
maxWidth = getLayoutDimension(node, getDim(resolvedRowAxis)) -
|
||||||
getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the main recursive call. We layout non flexible children.
|
// This is the main recursive call. We layout non flexible children.
|
||||||
if (alreadyComputedNextLayout == 0) {
|
if (alreadyComputedNextLayout == 0) {
|
||||||
layoutNode(layoutContext, child, maxWidth);
|
layoutNode(layoutContext, child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute positioned elements do not take part of the layout, so we
|
// Absolute positioned elements do not take part of the layout, so we
|
||||||
@@ -564,17 +676,17 @@ public class LayoutEngine {
|
|||||||
));
|
));
|
||||||
|
|
||||||
maxWidth = CSSConstants.UNDEFINED;
|
maxWidth = CSSConstants.UNDEFINED;
|
||||||
if (isDimDefined(node, CSSFlexDirection.ROW)) {
|
if (isDimDefined(node, resolvedRowAxis)) {
|
||||||
maxWidth = getLayoutDimension(node, getDim(CSSFlexDirection.ROW)) -
|
maxWidth = getLayoutDimension(node, getDim(resolvedRowAxis)) -
|
||||||
getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
} else if (mainAxis != CSSFlexDirection.ROW) {
|
} else if (!isRowDirection(mainAxis)) {
|
||||||
maxWidth = parentMaxWidth -
|
maxWidth = parentMaxWidth -
|
||||||
getMarginAxis(node, CSSFlexDirection.ROW) -
|
getMarginAxis(node, resolvedRowAxis) -
|
||||||
getPaddingAndBorderAxis(node, CSSFlexDirection.ROW);
|
getPaddingAndBorderAxis(node, resolvedRowAxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And we recursively call the layout algorithm for this child
|
// And we recursively call the layout algorithm for this child
|
||||||
layoutNode(layoutContext, child, maxWidth);
|
layoutNode(layoutContext, child, maxWidth, direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,6 +739,11 @@ public class LayoutEngine {
|
|||||||
// If the child is position absolute (without top/left) or relative,
|
// If the child is position absolute (without top/left) or relative,
|
||||||
// we put it at the current accumulated offset.
|
// we put it at the current accumulated offset.
|
||||||
setLayoutPosition(child, getPos(mainAxis), getLayoutPosition(child, getPos(mainAxis)) + mainDim);
|
setLayoutPosition(child, getPos(mainAxis), getLayoutPosition(child, getPos(mainAxis)) + mainDim);
|
||||||
|
|
||||||
|
// Define the trailing position accordingly.
|
||||||
|
if (!CSSConstants.isUndefined(getLayoutDimension(node, getDim(mainAxis)))) {
|
||||||
|
setTrailingPosition(node, child, mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we placed the element, we need to update the variables
|
// Now that we placed the element, we need to update the variables
|
||||||
@@ -721,6 +838,12 @@ public class LayoutEngine {
|
|||||||
// We can never assign a width smaller than the padding and borders
|
// We can never assign a width smaller than the padding and borders
|
||||||
getPaddingAndBorderAxis(node, mainAxis)
|
getPaddingAndBorderAxis(node, mainAxis)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Now that the width is defined, we should update the trailing
|
||||||
|
// positions for the children.
|
||||||
|
for (i = 0; i < node.getChildCount(); ++i) {
|
||||||
|
setTrailingPosition(node, node.getChildAt(i), mainAxis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CSSConstants.isUndefined(getLayoutDimension(node, getDim(crossAxis)))) {
|
if (CSSConstants.isUndefined(getLayoutDimension(node, getDim(crossAxis)))) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -111,9 +111,15 @@ function printLayout(test) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addEnum(node, 'direction', 'direction', {
|
||||||
|
'ltr': 'CSS_DIRECTION_LTR',
|
||||||
|
'rtl': 'CSS_DIRECTION_RTL'
|
||||||
|
});
|
||||||
addEnum(node, 'flexDirection', 'flex_direction', {
|
addEnum(node, 'flexDirection', 'flex_direction', {
|
||||||
'row': 'CSS_FLEX_DIRECTION_ROW',
|
'row': 'CSS_FLEX_DIRECTION_ROW',
|
||||||
'column': 'CSS_FLEX_DIRECTION_COLUMN'
|
'row-reverse': 'CSS_FLEX_DIRECTION_ROW_REVERSE',
|
||||||
|
'column': 'CSS_FLEX_DIRECTION_COLUMN',
|
||||||
|
'column-reverse': 'CSS_FLEX_DIRECTION_COLUMN_REVERSE'
|
||||||
});
|
});
|
||||||
addEnum(node, 'justifyContent', 'justify_content', {
|
addEnum(node, 'justifyContent', 'justify_content', {
|
||||||
'flex-start': 'CSS_JUSTIFY_FLEX_START',
|
'flex-start': 'CSS_JUSTIFY_FLEX_START',
|
||||||
@@ -234,6 +240,7 @@ function transpileAnnotatedJStoC(jsCode) {
|
|||||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||||
|
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||||
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
||||||
.replace(/node\./g, 'node->')
|
.replace(/node\./g, 'node->')
|
||||||
|
Reference in New Issue
Block a user