Import new C source of truth css-layout
fbshipit-source-id: e866918d6c62fc1cf3a04c269f782b94db9b875a
This commit is contained in:
@@ -1,195 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function __transpileToCSharpCommon(code) {
|
||||
return code
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace(/undefined/g, 'null')
|
||||
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
||||
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
|
||||
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
|
||||
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
||||
.replace(/CSS_POSITION_/g, 'CSSPositionType.')
|
||||
.replace(/CSS_OVERFLOW_/g, 'CSSOverflow.')
|
||||
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
||||
.replace(/css_direction_t/g, 'CSSDirection')
|
||||
.replace(/css_align_t/g, 'CSSAlign')
|
||||
.replace(/css_justify_t/g, 'CSSJustify')
|
||||
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
|
||||
.replace(/css_dim_t/g, 'MeasureOutput')
|
||||
.replace(/bool/g, 'boolean')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[POSITION_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[POSITION_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[POSITION_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[POSITION_BOTTOM')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/(style|layout)\.width/g, '$1.dimensions[DIMENSION_WIDTH]')
|
||||
.replace(/(style|layout)\.height/g, '$1.dimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measuredDimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measuredDimensions[DIMENSION_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measuredDimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1.style.positionType')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent')
|
||||
.replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)')
|
||||
.replace(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '($1.style.dimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '($1.layout.measuredDimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)')
|
||||
.replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.measuredDimensions[dim[$3]] - ($2.style.positionType == CSSPositionType.Absolute ? 0 : $2.layout.measuredDimensions[dim[$3]]) - $2.layout.position[pos[$3]]')
|
||||
.replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex != 0\)')
|
||||
.replace(/isFlexWrap\((.+?)\)/g, '\($1.style.flexWrap == CSSWrap.WRAP\)')
|
||||
.replace(/getPaddingAndBorderAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingPaddingAndBorder($1, $2) + getTrailingPaddingAndBorder($1, $2)\)')
|
||||
.replace(/getMarginAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getLeadingPadding($1, $2) + getLeadingBorder($1, $2)\)')
|
||||
.replace(/getTrailingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getTrailingPadding($1, $2) + getTrailingBorder($1, $2)\)')
|
||||
.replace(/getDimWithMargin\((.+?),\s*(.+?)\)/g, '\($1.layout.measuredDimensions[dim[$2]] + getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/isRowDirection\((.+?)\)/g, '\($1 == CSS_FLEX_DIRECTION_ROW || $1 == CSS_FLEX_DIRECTION_ROW_REVERSE\)')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\)/g, 'Assertions.assertCondition($1, "$2")')
|
||||
.replace(/isUndefined\((.+?)\)/g, 'float.IsNaN\($1\)')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1.style.overflow')
|
||||
.replace(/layoutNodeInternal\((.+?)\)/g, 'layoutNodeInternal(layoutContext, $1)')
|
||||
.replace(/style\.position\[CSS_/g, 'style.position[POSITION_')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '')
|
||||
.replace(/var\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
|
||||
// additional case conversions
|
||||
|
||||
.replace(/(CSSConstants|CSSWrap|CSSJustify|CSSMeasureMode|CSSAlign|CSSPositionType|CSSOverflow)\.([_A-Z]+)/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.' + constantToPascalCase(match2);
|
||||
});
|
||||
}
|
||||
|
||||
function __transpileSingleTestToCSharp(code) {
|
||||
return __transpileToCSharpCommon(code)
|
||||
.replace(/CSS_DIRECTION_/g, 'CSSDirection.')
|
||||
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
||||
.replace(/CSS_WRAP/g, 'CSSWrap.WRAP')
|
||||
.replace(/new_test_css_node/g, 'new TestCSSNode')
|
||||
.replace(// style.position[CSS_TOP] => style.position[CSSLayout.POSITION_TOP]
|
||||
/(style|layout)\.position\[CSS_(LEFT|TOP|RIGHT|BOTTOM)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.position[POSITION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.dimensions[CSS_WIDTH] => style.dimensions[CSSLayout.DIMENSION_WIDTH]
|
||||
/(style|layout)\.dimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.dimensions[DIMENSION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.maxDimensions[CSS_WIDTH] => style.maxWidth
|
||||
/(style|layout)\.maxDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.max' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.minDimensions[CSS_WIDTH] => style.minWidth
|
||||
/(style|layout)\.minDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.min' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] = 12.3 => style.margin[Spacing.TOP].set(12.3)
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]\s+=\s+(-?[\.\d]+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
var propertyCap = match1.charAt(0).toUpperCase() + match1.slice(1);
|
||||
return 'set' + propertyCap + '(Spacing.' + match2 + ', ' + match3 + ')';
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] => style.margin[Spacing.TOP]
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return 'style.' + match1 + '.get(Spacing.' + match2 + ')';
|
||||
})
|
||||
.replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)')
|
||||
.replace(/init_css_node_children/g, 'addChildren')
|
||||
.replace(/css_node_t(\s)\*/g, 'TestCSSNode$1')
|
||||
.replace(/\->/g, '.')
|
||||
.replace(/(\d+\.\d+)/g, '$1f')
|
||||
.replace(// style.flex_direction => style.flexDirection
|
||||
/style\.([^_\[\]\s]+)_(\w)(\w+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
return 'style.' + match1 + match2.toUpperCase() + match3;
|
||||
})
|
||||
.replace(/(\w+)\.measure\s+=\s+.+/g, '$1.setMeasureFunction(sTestMeasureFunction);')
|
||||
|
||||
// additional case conversions
|
||||
|
||||
.replace(/(CSSWrap|CSSFlexDirection)\.([_A-Z]+)/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.' + constantToPascalCase(match2);
|
||||
});
|
||||
}
|
||||
|
||||
function indent(code) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map(function(line) { return ' ' + line; })
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
function constantToPascalCase(str) {
|
||||
return str[0] + str.substr(1)
|
||||
.toLowerCase()
|
||||
.replace(/_(.)/g,
|
||||
function(_, m) { return m.toUpperCase(); });
|
||||
}
|
||||
|
||||
var CSharpTranspiler = {
|
||||
transpileLayoutEngine: function(code) {
|
||||
return indent(
|
||||
__transpileToCSharpCommon(code)
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.getChildCount()')
|
||||
.replace(/node.children\[i\]/g, 'node.getChildAt(i)')
|
||||
.replace(/node.children\[j\]/g, 'node.getChildAt(j)')
|
||||
.replace(/fmaxf/g, 'Math.Max')
|
||||
.replace(/fminf/g, 'Math.Min')
|
||||
.replace(/\/\*\([^\/]+\*\/\n/g, '') // remove comments for other languages
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/css_node_t\*/g, 'CSSNode'));
|
||||
},
|
||||
|
||||
transpileCConstDefs: function(cConstDefs) {
|
||||
return indent(
|
||||
cConstDefs
|
||||
.replace(/#define\s+(\w+)\s+(\"[^\"]+\")/g, 'public static readonly string $1 = $2;')
|
||||
.replace(/#define\s+(\w+)\s+(.+)/g, 'public static readonly float $1 = $2f;'));
|
||||
},
|
||||
|
||||
transpileCTestsArray: function(allTestsInC) {
|
||||
var allTestsInCSharp = [];
|
||||
for (var i = 0; i < allTestsInC.length; i++) {
|
||||
allTestsInCSharp[i] =
|
||||
' [Test]\n' +
|
||||
' public void TestCase' + i + '()\n' +
|
||||
__transpileSingleTestToCSharp(allTestsInC[i]);
|
||||
}
|
||||
return allTestsInCSharp.join('\n\n');
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = CSharpTranspiler;
|
||||
}
|
@@ -1,174 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function __transpileToJavaCommon(code) {
|
||||
return code
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace(/undefined/g, 'null')
|
||||
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
||||
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
|
||||
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
|
||||
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
||||
.replace(/CSS_POSITION_/g, 'CSSPositionType.')
|
||||
.replace(/CSS_OVERFLOW_/g, 'CSSOverflow.')
|
||||
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
||||
.replace(/css_direction_t/g, 'CSSDirection')
|
||||
.replace(/css_align_t/g, 'CSSAlign')
|
||||
.replace(/css_justify_t/g, 'CSSJustify')
|
||||
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
|
||||
.replace(/css_dim_t/g, 'MeasureOutput')
|
||||
.replace(/bool/g, 'boolean')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[POSITION_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[POSITION_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[POSITION_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[POSITION_BOTTOM')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/(style|layout)\.width/g, '$1.dimensions[DIMENSION_WIDTH]')
|
||||
.replace(/(style|layout)\.height/g, '$1.dimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measuredDimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measuredDimensions[DIMENSION_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measuredDimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1.style.positionType')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent')
|
||||
.replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)')
|
||||
.replace(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '($1.style.dimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '($1.layout.measuredDimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)')
|
||||
.replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.measuredDimensions[dim[$3]] - ($2.style.positionType == CSSPositionType.ABSOLUTE ? 0 : $2.layout.measuredDimensions[dim[$3]]) - $2.layout.position[pos[$3]]')
|
||||
.replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex != 0\)')
|
||||
.replace(/isFlexWrap\((.+?)\)/g, '\($1.style.flexWrap == CSSWrap.WRAP\)')
|
||||
.replace(/getPaddingAndBorderAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingPaddingAndBorder($1, $2) + getTrailingPaddingAndBorder($1, $2)\)')
|
||||
.replace(/getMarginAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getLeadingPadding($1, $2) + getLeadingBorder($1, $2)\)')
|
||||
.replace(/getTrailingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getTrailingPadding($1, $2) + getTrailingBorder($1, $2)\)')
|
||||
.replace(/getDimWithMargin\((.+?),\s*(.+?)\)/g, '\($1.layout.measuredDimensions[dim[$2]] + getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/isRowDirection\((.+?)\)/g, '\($1 == CSS_FLEX_DIRECTION_ROW || $1 == CSS_FLEX_DIRECTION_ROW_REVERSE\)')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\)/g, 'Assertions.assertCondition($1, "$2")')
|
||||
.replace(/isUndefined\((.+?)\)/g, 'Float.isNaN\($1\)')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1.style.overflow')
|
||||
.replace(/layoutNodeInternal\((.+?)\)/g, 'layoutNodeInternal(layoutContext, $1)')
|
||||
.replace(/style\.position\[CSS_/g, 'style.position[POSITION_')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '')
|
||||
.replace(/var\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '$1');
|
||||
}
|
||||
|
||||
function __transpileSingleTestToJava(code) {
|
||||
return __transpileToJavaCommon(code)
|
||||
.replace(/CSS_DIRECTION_/g, 'CSSDirection.')
|
||||
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
||||
.replace(/CSS_WRAP/g, 'CSSWrap.WRAP')
|
||||
.replace(/new_test_css_node/g, 'new TestCSSNode')
|
||||
.replace(// style.position[CSS_TOP] => style.position[CSSLayout.POSITION_TOP]
|
||||
/(style|layout)\.position\[CSS_(LEFT|TOP|RIGHT|BOTTOM)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.position[POSITION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.dimensions[CSS_WIDTH] => style.dimensions[CSSLayout.DIMENSION_WIDTH]
|
||||
/(style|layout)\.dimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.dimensions[DIMENSION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.maxDimensions[CSS_WIDTH] => style.maxWidth
|
||||
/(style|layout)\.maxDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.max' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.minDimensions[CSS_WIDTH] => style.minWidth
|
||||
/(style|layout)\.minDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.min' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] = 12.3 => style.margin[Spacing.TOP].set(12.3)
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]\s+=\s+(-?[\.\d]+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
var propertyCap = match1.charAt(0).toUpperCase() + match1.slice(1);
|
||||
return 'set' + propertyCap + '(Spacing.' + match2 + ', ' + match3 + ')';
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] => style.margin[Spacing.TOP]
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return 'style.' + match1 + '.get(Spacing.' + match2 + ')';
|
||||
})
|
||||
.replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)')
|
||||
.replace(/init_css_node_children/g, 'addChildren')
|
||||
.replace(/css_node_t(\s)\*/g, 'TestCSSNode$1')
|
||||
.replace(/\->/g, '.')
|
||||
.replace(/(\d+\.\d+)/g, '$1f')
|
||||
.replace(// style.flex_direction => style.flexDirection
|
||||
/style\.([^_\[\]\s]+)_(\w)(\w+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
return 'style.' + match1 + match2.toUpperCase() + match3;
|
||||
})
|
||||
.replace(/(\w+)\.measure\s+=\s+.+/g, '$1.setMeasureFunction(sTestMeasureFunction);');
|
||||
}
|
||||
|
||||
function indent(code) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map(function(line) { return ' ' + line; })
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
var JavaTranspiler = {
|
||||
transpileLayoutEngine: function(code) {
|
||||
return indent(
|
||||
__transpileToJavaCommon(code)
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.getChildCount()')
|
||||
.replace(/node.children\[i\]/g, 'node.getChildAt(i)')
|
||||
.replace(/node.children\[j\]/g, 'node.getChildAt(j)')
|
||||
.replace(/fmaxf/g, 'Math.max')
|
||||
.replace(/fminf/g, 'Math.min')
|
||||
.replace(/\/\*\([^\/]+\*\/\n/g, '') // remove comments for other languages
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/css_node_t\*/g, 'CSSNode'));
|
||||
},
|
||||
|
||||
transpileCConstDefs: function(cConstDefs) {
|
||||
return indent(
|
||||
cConstDefs
|
||||
.replace(/#define\s+(\w+)\s+(\"[^\"]+\")/g, 'public static final String $1 = $2;')
|
||||
.replace(/#define\s+(\w+)\s+(.+)/g, 'public static final float $1 = $2f;'));
|
||||
},
|
||||
|
||||
transpileCTestsArray: function(allTestsInC) {
|
||||
var allTestsInJava = [];
|
||||
for (var i = 0; i < allTestsInC.length; i++) {
|
||||
allTestsInJava[i] =
|
||||
' @Test\n' +
|
||||
' public void testCase' + i + '()\n' +
|
||||
__transpileSingleTestToJava(allTestsInC[i]);
|
||||
}
|
||||
return allTestsInJava.join('\n\n');
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = JavaTranspiler;
|
||||
}
|
@@ -1,216 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Layout-test-utils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <float.h>
|
||||
#define isnan _isnan
|
||||
|
||||
/* define fmaxf & fminf if < VC12 */
|
||||
#if _MSC_VER < 1800
|
||||
__forceinline const float fmaxf(const float a, const float b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
__forceinline const float fminf(const float a, const float b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** START_GENERATED **/
|
||||
#define SMALL_WIDTH 35
|
||||
#define SMALL_HEIGHT 18
|
||||
#define BIG_WIDTH 172
|
||||
#define BIG_HEIGHT 36
|
||||
#define BIG_MIN_WIDTH 100
|
||||
#define SMALL_TEXT "small"
|
||||
#define LONG_TEXT "loooooooooong with space"
|
||||
#define MEASURE_WITH_RATIO_2 "measureWithRatio2"
|
||||
#define MEASURE_WITH_MATCH_PARENT "measureWithMatchParent"
|
||||
/** END_GENERATED **/
|
||||
|
||||
typedef struct failed_test_t {
|
||||
struct failed_test_t *next;
|
||||
const char *name;
|
||||
css_node_t *style;
|
||||
css_node_t *expected;
|
||||
} failed_test_t;
|
||||
|
||||
static failed_test_t *failed_test_head = NULL;
|
||||
static failed_test_t *failed_test_tail = NULL;
|
||||
static void add_failed_test(const char *name, css_node_t *style, css_node_t *expected) {
|
||||
failed_test_t *failed_test = (failed_test_t *)malloc(sizeof(failed_test_t));
|
||||
failed_test->next = NULL;
|
||||
failed_test->name = name;
|
||||
failed_test->style = style;
|
||||
failed_test->expected = expected;
|
||||
|
||||
if (!failed_test_head) {
|
||||
failed_test_head = failed_test;
|
||||
failed_test_tail = failed_test;
|
||||
} else {
|
||||
failed_test_tail->next = failed_test;
|
||||
failed_test_tail = failed_test;
|
||||
}
|
||||
}
|
||||
|
||||
static bool eq(float a, float b) {
|
||||
return fabs(a - b) < 0.0001;
|
||||
}
|
||||
|
||||
static bool are_layout_equal(css_node_t *a, css_node_t *b) {
|
||||
if (!eq(a->layout.dimensions[CSS_WIDTH], b->layout.dimensions[CSS_WIDTH]) ||
|
||||
!eq(a->layout.dimensions[CSS_HEIGHT], b->layout.dimensions[CSS_HEIGHT]) ||
|
||||
!eq(a->layout.position[CSS_TOP], b->layout.position[CSS_TOP]) ||
|
||||
!eq(a->layout.position[CSS_LEFT], b->layout.position[CSS_LEFT]) ||
|
||||
!eq(a->children_count, b->children_count)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a->children_count; ++i) {
|
||||
if (!are_layout_equal(a->get_child(a->context, i), b->get_child(b->context, i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode) {
|
||||
const char *text = (const char *)context;
|
||||
css_dim_t dim;
|
||||
if (strcmp(text, SMALL_TEXT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 1000000;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
if (strcmp(text, LONG_TEXT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 1000000;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
|
||||
if (strcmp(text, MEASURE_WITH_RATIO_2) == 0) {
|
||||
if (widthMode != CSS_MEASURE_MODE_UNDEFINED) {
|
||||
dim.dimensions[CSS_WIDTH] = width;
|
||||
dim.dimensions[CSS_HEIGHT] = width * 2;
|
||||
} else if (heightMode != CSS_MEASURE_MODE_UNDEFINED) {
|
||||
dim.dimensions[CSS_WIDTH] = height * 2;
|
||||
dim.dimensions[CSS_HEIGHT] = height;
|
||||
} else {
|
||||
dim.dimensions[CSS_WIDTH] = 99999;
|
||||
dim.dimensions[CSS_HEIGHT] = 99999;
|
||||
}
|
||||
return dim;
|
||||
}
|
||||
|
||||
if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 99999;
|
||||
}
|
||||
if (heightMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
height = 99999;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = width;
|
||||
dim.dimensions[CSS_HEIGHT] = height;
|
||||
return dim;
|
||||
}
|
||||
|
||||
// Should not go here
|
||||
dim.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
||||
dim.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
||||
return dim;
|
||||
}
|
||||
|
||||
static int test_ran_count = 0;
|
||||
void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
|
||||
++test_ran_count;
|
||||
layoutNode(style, CSS_UNDEFINED, CSS_UNDEFINED, (css_direction_t)-1);
|
||||
|
||||
if (!are_layout_equal(style, expected_layout)) {
|
||||
printf("%sF%s", "\x1B[31m", "\x1B[0m");
|
||||
add_failed_test(name, style, expected_layout);
|
||||
} else {
|
||||
printf("%s.%s", "\x1B[32m", "\x1B[0m");
|
||||
free_css_node(style);
|
||||
free_css_node(expected_layout);
|
||||
}
|
||||
}
|
||||
|
||||
int tests_finished() {
|
||||
failed_test_t *failed_test = failed_test_head;
|
||||
printf("\n");
|
||||
|
||||
int tests_failed = 0;
|
||||
while (failed_test) {
|
||||
printf("%sFAIL%s %s\n", "\x1B[31m", "\x1B[0m", failed_test->name);
|
||||
|
||||
printf("Input: ");
|
||||
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
|
||||
printf("Output: ");
|
||||
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
||||
|
||||
printf("Expected: ");
|
||||
print_css_node(failed_test->expected, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
||||
|
||||
free_css_node(failed_test->style);
|
||||
free_css_node(failed_test->expected);
|
||||
|
||||
failed_test_t *next_failed_test = failed_test->next;
|
||||
free(failed_test);
|
||||
failed_test = next_failed_test;
|
||||
|
||||
tests_failed++;
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
if (tests_failed > 0) {
|
||||
printf("TESTS FAILED: %d\n", tests_failed);
|
||||
return 1;
|
||||
} else {
|
||||
printf("ALL TESTS PASSED: %d tests ran.\n", test_ran_count);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static css_node_t* get_child(void *context, int i) {
|
||||
css_node_t* children = (css_node_t*)context;
|
||||
return &children[i];
|
||||
}
|
||||
|
||||
static bool is_dirty(void *context) {
|
||||
(void)context; // remove unused warning
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_test_css_node(css_node_t *node) {
|
||||
node->get_child = get_child;
|
||||
node->is_dirty = is_dirty;
|
||||
}
|
||||
|
||||
css_node_t *new_test_css_node(void) {
|
||||
css_node_t *node = new_css_node();
|
||||
init_test_css_node(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void init_css_node_children(css_node_t *node, int children_count) {
|
||||
node->context = calloc((size_t)children_count, sizeof(css_node_t));
|
||||
for (int i = 0; i < children_count; ++i) {
|
||||
init_css_node(node->get_child(node->context, i));
|
||||
init_test_css_node(node->get_child(node->context, i));
|
||||
}
|
||||
node->children_count = children_count;
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Layout.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void test(const char *name, css_node_t *style, css_node_t *expected_layout);
|
||||
int tests_finished(void);
|
||||
css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
|
||||
void init_css_node_children(css_node_t *node, int children_count);
|
||||
css_node_t *new_test_css_node(void);
|
@@ -1,604 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* globals document, computeLayout, navigator */
|
||||
|
||||
var layoutTestUtils = (function() {
|
||||
|
||||
//
|
||||
// Sets the test cases precision, by default set to 1.0, aka pixel precision
|
||||
// (assuming the browser does pixel snapping - and that we're ok with being
|
||||
// 'only' pixel perfect).
|
||||
//
|
||||
// Set it to '10' for .1 precision, etc... in theory the browser is doing
|
||||
// 'pixel' snapping so 1.0 should do, the code is left for clarity...
|
||||
//
|
||||
// Set it to undefined to disable and use full precision.
|
||||
//
|
||||
var testMeasurePrecision = 1.0;
|
||||
|
||||
if (typeof jasmine !== 'undefined') {
|
||||
jasmine.matchersUtil.buildFailureMessage = function() {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
var matcherName = args[0];
|
||||
var isNot = args[1];
|
||||
var actual = args[2];
|
||||
var expected = args.slice(3);
|
||||
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
|
||||
|
||||
var pp = function(node) {
|
||||
return jasmine.pp(node)
|
||||
.replace(/([\{\[]) /g, '$1')
|
||||
.replace(/ ([\}\]:])/g, '$1');
|
||||
};
|
||||
|
||||
var message = 'Expected ' +
|
||||
pp(actual) +
|
||||
(isNot ? ' not ' : ' ') +
|
||||
'\n' +
|
||||
englishyPredicate;
|
||||
|
||||
if (expected.length > 0) {
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
if (i > 0) {
|
||||
message += ',';
|
||||
}
|
||||
message += ' ' + pp(expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return message + '.';
|
||||
};
|
||||
}
|
||||
|
||||
var _cachedIframe;
|
||||
|
||||
function renderIframe() {
|
||||
var iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
return iframe;
|
||||
}
|
||||
|
||||
function getIframe(iframe) {
|
||||
if (_cachedIframe) {
|
||||
return _cachedIframe;
|
||||
}
|
||||
|
||||
var doc = iframe.contentDocument;
|
||||
|
||||
if (doc.readyState === 'complete') {
|
||||
var style = document.createElement('style');
|
||||
style.textContent = (function() {/*
|
||||
body, div {
|
||||
box-sizing: border-box;
|
||||
border: 0 solid black;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
align-items: stretch;
|
||||
-webkit-align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
-webkit-justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
hack to ignore three hundred px width of the body {}
|
||||
body > div {
|
||||
align-self: flex-start;
|
||||
}
|
||||
*/} + '').slice(15, -4);
|
||||
doc.head.appendChild(style);
|
||||
_cachedIframe = iframe;
|
||||
return iframe;
|
||||
} else {
|
||||
setTimeout(getIframe.bind(null, iframe), 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
var iframe = renderIframe();
|
||||
getIframe(iframe);
|
||||
}
|
||||
|
||||
if (typeof computeLayout === 'object') {
|
||||
var fillNodes = computeLayout.fillNodes;
|
||||
var realComputeLayout = computeLayout.computeLayout;
|
||||
var canUseCachedMeasurement = computeLayout.canUseCachedMeasurement;
|
||||
}
|
||||
|
||||
function extractNodes(node) {
|
||||
var keysToCopy = [
|
||||
'width',
|
||||
'height',
|
||||
'left',
|
||||
'top'
|
||||
];
|
||||
var layout = {};
|
||||
keysToCopy.forEach(function(key) {
|
||||
layout[key] = node.layout[key];
|
||||
});
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
layout.children = node.children.map(extractNodes);
|
||||
} else {
|
||||
delete node.children;
|
||||
}
|
||||
|
||||
delete node.layout;
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
function roundLayout(layout) {
|
||||
// Chrome rounds all the numbers with a precision of 1/64
|
||||
// Reproduce the same behavior
|
||||
function round(number) {
|
||||
var floored = Math.floor(number);
|
||||
var decimal = number - floored;
|
||||
if (decimal === 0) {
|
||||
return number;
|
||||
}
|
||||
var minDifference = Infinity;
|
||||
var minDecimal = Infinity;
|
||||
for (var i = 1; i < 64; ++i) {
|
||||
var roundedDecimal = i / 64;
|
||||
var difference = Math.abs(roundedDecimal - decimal);
|
||||
if (difference < minDifference) {
|
||||
minDifference = difference;
|
||||
minDecimal = roundedDecimal;
|
||||
}
|
||||
}
|
||||
return floored + minDecimal;
|
||||
}
|
||||
|
||||
function rec(layout) {
|
||||
layout.top = round(layout.top);
|
||||
layout.left = round(layout.left);
|
||||
layout.width = round(layout.width);
|
||||
layout.height = round(layout.height);
|
||||
if (layout.children) {
|
||||
for (var i = 0; i < layout.children.length; ++i) {
|
||||
rec(layout.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rec(layout);
|
||||
return layout;
|
||||
}
|
||||
|
||||
function capitalizeFirst(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
function computeCSSLayout(rootNode) {
|
||||
fillNodes(rootNode);
|
||||
realComputeLayout(rootNode);
|
||||
return roundLayout(extractNodes(rootNode));
|
||||
}
|
||||
|
||||
function computeDOMLayout(node) {
|
||||
var body = getIframe().contentDocument.body;
|
||||
|
||||
function setStyle(div, name, value) {
|
||||
div.style['-webkit-' + name] = value;
|
||||
div.style['webkit' + capitalizeFirst(name)] = value;
|
||||
div.style[name] = value;
|
||||
}
|
||||
|
||||
function transfer(div, node, name, ext) {
|
||||
if (name in node.style) {
|
||||
var value = node.style[name] + (ext || '');
|
||||
setStyle(div, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
function transferSpacing(div, node, type, suffix) {
|
||||
transfer(div, node, type + suffix, 'px');
|
||||
transfer(div, node, type + 'Left' + suffix, 'px');
|
||||
transfer(div, node, type + 'Top' + suffix, 'px');
|
||||
transfer(div, node, type + 'Bottom' + suffix, 'px');
|
||||
transfer(div, node, type + 'Right' + suffix, 'px');
|
||||
transfer(div, node, type + 'Start' + suffix, 'px');
|
||||
transfer(div, node, type + 'End' + suffix, 'px');
|
||||
}
|
||||
|
||||
function transferFlex(div, node) {
|
||||
if ('flex' in node.style) {
|
||||
var flex = node.style.flex;
|
||||
var resolvedFlex = (
|
||||
flex < 0 ? '0 1 auto' :
|
||||
flex > 0 ? (flex + ' 0 0') :
|
||||
'0 0 auto'
|
||||
);
|
||||
setStyle(div, 'flex', resolvedFlex);
|
||||
}
|
||||
}
|
||||
|
||||
function renderNode(parent, node) {
|
||||
var div = document.createElement('div');
|
||||
transfer(div, node, 'width', 'px');
|
||||
transfer(div, node, 'height', 'px');
|
||||
transfer(div, node, 'minWidth', 'px');
|
||||
transfer(div, node, 'minHeight', 'px');
|
||||
transfer(div, node, 'maxWidth', 'px');
|
||||
transfer(div, node, 'maxHeight', 'px');
|
||||
transfer(div, node, 'top', 'px');
|
||||
transfer(div, node, 'left', 'px');
|
||||
transfer(div, node, 'right', 'px');
|
||||
transfer(div, node, 'bottom', 'px');
|
||||
transferSpacing(div, node, 'margin', '');
|
||||
transferSpacing(div, node, 'padding', '');
|
||||
transferSpacing(div, node, 'border', 'Width');
|
||||
transfer(div, node, 'flexDirection');
|
||||
transfer(div, node, 'direction');
|
||||
transferFlex(div, node);
|
||||
transfer(div, node, 'flexWrap');
|
||||
transfer(div, node, 'justifyContent');
|
||||
transfer(div, node, 'alignSelf');
|
||||
transfer(div, node, 'alignItems');
|
||||
transfer(div, node, 'alignContent');
|
||||
transfer(div, node, 'position');
|
||||
transfer(div, node, 'overflow');
|
||||
parent.appendChild(div);
|
||||
(node.children || []).forEach(function(child) {
|
||||
renderNode(div, child);
|
||||
});
|
||||
if (node.style.measure) {
|
||||
div.innerText = node.style.measure.toString();
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
var div = renderNode(body, node);
|
||||
|
||||
function buildLayout(absoluteRect, div) {
|
||||
var rect = div.getBoundingClientRect();
|
||||
var result = {
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
top: rect.top - absoluteRect.top,
|
||||
left: rect.left - absoluteRect.left
|
||||
};
|
||||
|
||||
var children = [];
|
||||
for (var child = div.firstChild; child; child = child.nextSibling) {
|
||||
if (child.nodeType !== 3 /* textNode */) {
|
||||
children.push(buildLayout(rect, child));
|
||||
}
|
||||
}
|
||||
if (children.length) {
|
||||
result.children = children;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
var layout = buildLayout({left: 0, top: 0}, div);
|
||||
body.removeChild(div);
|
||||
return layout;
|
||||
}
|
||||
|
||||
function inplaceRoundNumbersInObject(obj) {
|
||||
if (!testMeasurePrecision) {
|
||||
// undefined/0, disables rounding
|
||||
return;
|
||||
}
|
||||
|
||||
for (var key in obj) {
|
||||
if (!obj.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var val = obj[key];
|
||||
if (typeof val === 'number') {
|
||||
obj[key] = Math.floor((val * testMeasurePrecision) + 0.5) / testMeasurePrecision;
|
||||
} else if (typeof val === 'object') {
|
||||
inplaceRoundNumbersInObject(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nameLayout(name, layout) {
|
||||
var namedLayout = {name: name};
|
||||
for (var key in layout) {
|
||||
namedLayout[key] = layout[key];
|
||||
}
|
||||
return namedLayout;
|
||||
}
|
||||
|
||||
function testFillNodes(node, filledNode) {
|
||||
expect(fillNodes(node)).toEqual(filledNode);
|
||||
}
|
||||
|
||||
function testExtractNodes(node, extractedNode) {
|
||||
expect(extractNodes(node)).toEqual(extractedNode);
|
||||
}
|
||||
|
||||
function testCanUseCachedMeasurement(canReuse, spec, cacheEntry) {
|
||||
var availableWidth = spec.availableWidth;
|
||||
var availableHeight = spec.availableHeight;
|
||||
var widthMeasureMode = spec.widthMeasureMode;
|
||||
var heightMeasureMode = spec.heightMeasureMode;
|
||||
|
||||
expect(
|
||||
canUseCachedMeasurement(
|
||||
availableWidth, availableHeight,
|
||||
0, 0,
|
||||
widthMeasureMode, heightMeasureMode,
|
||||
cacheEntry
|
||||
)
|
||||
).toEqual(canReuse);
|
||||
}
|
||||
|
||||
function testNamedLayout(name, layoutA, layoutB) {
|
||||
expect(nameLayout(name, layoutA))
|
||||
.toEqual(nameLayout(name, layoutB));
|
||||
}
|
||||
|
||||
function isEqual(a, b) {
|
||||
// computeCSSLayout and computeDOMLayout output a tree with same ordered elements
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
}
|
||||
|
||||
function reduceTest(node) {
|
||||
function isWorking() {
|
||||
return isEqual(
|
||||
computeDOMLayout(node),
|
||||
computeCSSLayout(node)
|
||||
);
|
||||
}
|
||||
if (isWorking()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var isModified = true;
|
||||
|
||||
function rec(node) {
|
||||
var key;
|
||||
var value;
|
||||
|
||||
// Style
|
||||
for (key in node.style) {
|
||||
value = node.style[key];
|
||||
delete node.style[key];
|
||||
if (isWorking()) {
|
||||
node.style[key] = value;
|
||||
} else {
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
// Round values
|
||||
for (key in node.style) {
|
||||
value = node.style[key];
|
||||
if (value > 100) {
|
||||
node.style[key] = Math.round(value / 100) * 100;
|
||||
} else if (value > 10) {
|
||||
node.style[key] = Math.round(value / 10) * 10;
|
||||
} else if (value > 1) {
|
||||
node.style[key] = 5;
|
||||
}
|
||||
if (node.style[key] !== value) {
|
||||
if (isWorking()) {
|
||||
node.style[key] = value;
|
||||
} else {
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Children
|
||||
for (var i = 0; node.children && i < node.children.length; ++i) {
|
||||
value = node.children[i];
|
||||
node.children.splice(i, 1);
|
||||
if (isWorking()) {
|
||||
if (!node.children) {
|
||||
node.children = [];
|
||||
}
|
||||
node.children.splice(i, 0, value);
|
||||
rec(node.children[i]);
|
||||
} else {
|
||||
i--;
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (isModified) {
|
||||
isModified = false;
|
||||
rec(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
var iframeText;
|
||||
function measureTextSizes(text, width) {
|
||||
iframeText = iframeText || document.createElement('iframe');
|
||||
document.body.appendChild(iframeText);
|
||||
|
||||
var body = iframeText.contentDocument.body;
|
||||
if (width === undefined || isNaN(width)) {
|
||||
width = Infinity;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.style.width = (width === Infinity ? 10000000 : width) + 'px';
|
||||
div.style.display = 'flex';
|
||||
div.style.flexDirection = 'column';
|
||||
div.style.alignItems = 'flex-start';
|
||||
div.style.alignContent = 'flex-start';
|
||||
|
||||
var span = document.createElement('span');
|
||||
span.style.display = 'flex';
|
||||
span.style.flexDirection = 'column';
|
||||
span.style.alignItems = 'flex-start';
|
||||
span.style.alignContent = 'flex-start';
|
||||
span.innerText = text;
|
||||
|
||||
div.appendChild(span);
|
||||
body.appendChild(div);
|
||||
var rect = span.getBoundingClientRect();
|
||||
body.removeChild(div);
|
||||
return {
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
};
|
||||
}
|
||||
|
||||
var texts = {
|
||||
small: 'small',
|
||||
big: 'loooooooooong with space'
|
||||
};
|
||||
|
||||
var preDefinedTextSizes = {
|
||||
smallWidth: 34.671875,
|
||||
smallHeight: 18,
|
||||
bigWidth: 172.421875,
|
||||
bigHeight: 36,
|
||||
bigMinWidth: 100.4375
|
||||
};
|
||||
|
||||
// Note(prenaux): Clearly not what I would like, but it seems to be the only
|
||||
// way :( My guess is that since the font on Windows is
|
||||
// different than on OSX it has a different size.
|
||||
if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('Windows NT') > -1) {
|
||||
preDefinedTextSizes.bigHeight = 36;
|
||||
}
|
||||
|
||||
var textSizes;
|
||||
if (typeof require === 'function') {
|
||||
textSizes = preDefinedTextSizes;
|
||||
} else {
|
||||
textSizes = {
|
||||
smallWidth: measureTextSizes(texts.small, 0).width,
|
||||
smallHeight: measureTextSizes(texts.small, 0).height,
|
||||
bigWidth: measureTextSizes(texts.big).width,
|
||||
bigHeight: measureTextSizes(texts.big, 0).height,
|
||||
bigMinWidth: measureTextSizes(texts.big, 0).width
|
||||
};
|
||||
}
|
||||
|
||||
// round the text sizes so that we dont have to update it for every browser
|
||||
// update, assumes we're ok with pixel precision
|
||||
inplaceRoundNumbersInObject(preDefinedTextSizes);
|
||||
inplaceRoundNumbersInObject(textSizes);
|
||||
|
||||
return {
|
||||
texts: texts,
|
||||
textSizes: textSizes,
|
||||
preDefinedTextSizes: preDefinedTextSizes,
|
||||
testLayout: function(node, expectedLayout) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
inplaceRoundNumbersInObject(expectedLayout);
|
||||
testNamedLayout('expected-dom', expectedLayout, domLayout);
|
||||
testNamedLayout('layout-dom', layout, domLayout);
|
||||
},
|
||||
testLayoutAgainstDomOnly: function(node) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
testNamedLayout('layout-dom', layout, domLayout);
|
||||
},
|
||||
testLayoutAgainstExpectedOnly: function(node, expectedLayout) {
|
||||
var layout = computeCSSLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(expectedLayout);
|
||||
testNamedLayout('expected-dom', expectedLayout, layout);
|
||||
},
|
||||
testFillNodes: testFillNodes,
|
||||
testExtractNodes: testExtractNodes,
|
||||
testCanUseCachedMeasurement: testCanUseCachedMeasurement,
|
||||
testRandomLayout: function(node) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
expect({node: node, layout: layout})
|
||||
.toEqual({node: node, layout: domLayout});
|
||||
},
|
||||
testsFinished: function() {
|
||||
console.log('tests finished!');
|
||||
},
|
||||
computeLayout: computeCSSLayout,
|
||||
computeDOMLayout: computeDOMLayout,
|
||||
reduceTest: reduceTest,
|
||||
text: function(text) {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode === 'undefined') {
|
||||
width = Infinity;
|
||||
}
|
||||
|
||||
// Constants for testing purposes between C/JS and other platforms
|
||||
// Comment this block of code if you want to use the browser to
|
||||
// generate proper sizes
|
||||
if (text === texts.small) {
|
||||
return {
|
||||
width: Math.min(textSizes.smallWidth, width),
|
||||
height: textSizes.smallHeight
|
||||
};
|
||||
}
|
||||
if (text === texts.big) {
|
||||
var res = {
|
||||
width: width >= textSizes.bigWidth ? textSizes.bigWidth : Math.max(textSizes.bigMinWidth, width),
|
||||
height: width >= textSizes.bigWidth ? textSizes.smallHeight : textSizes.bigHeight
|
||||
};
|
||||
return res;
|
||||
}
|
||||
};
|
||||
// Name of the function is used in DOM tests as a text in the measured node
|
||||
// and as a way to tell different measure functions apart in transpiled tests
|
||||
fn.toString = function() { return text; };
|
||||
return fn;
|
||||
},
|
||||
measureWithRatio2: function() {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode !== 'undefined') {
|
||||
height = width * 2;
|
||||
} else if (heightMode !== 'undefined') {
|
||||
width = height * 2;
|
||||
} else {
|
||||
// This should be Infinity, but it would be pain to transpile,
|
||||
// so let's just go with big numbers.
|
||||
height = 99999;
|
||||
width = 99999;
|
||||
}
|
||||
return {width: width, height: height};
|
||||
};
|
||||
// This is necessary for transpiled tests, see previous comment
|
||||
fn.toString = function() { return 'measureWithRatio2'; };
|
||||
return fn;
|
||||
},
|
||||
measureWithMatchParent: function() {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode === 'undefined') {
|
||||
width = 99999;
|
||||
}
|
||||
if (heightMode === 'undefined') {
|
||||
height = 99999;
|
||||
}
|
||||
return {width: width, height: height};
|
||||
};
|
||||
// This is necessary for transpiled tests, see previous comment
|
||||
fn.toString = function() { return 'measureWithMatchParent'; };
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = layoutTestUtils;
|
||||
}
|
1817
java/Layout.c
1817
java/Layout.c
File diff suppressed because it is too large
Load Diff
200
java/Layout.h
200
java/Layout.h
@@ -1,200 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LAYOUT_H
|
||||
#define __LAYOUT_H
|
||||
|
||||
#include <math.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
// Not defined in MSVC++
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *)__nan)
|
||||
#endif
|
||||
|
||||
#define CSS_UNDEFINED NAN
|
||||
|
||||
typedef enum {
|
||||
CSS_DIRECTION_INHERIT = 0,
|
||||
CSS_DIRECTION_LTR,
|
||||
CSS_DIRECTION_RTL
|
||||
} css_direction_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_FLEX_DIRECTION_COLUMN = 0,
|
||||
CSS_FLEX_DIRECTION_COLUMN_REVERSE,
|
||||
CSS_FLEX_DIRECTION_ROW,
|
||||
CSS_FLEX_DIRECTION_ROW_REVERSE
|
||||
} css_flex_direction_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_JUSTIFY_FLEX_START = 0,
|
||||
CSS_JUSTIFY_CENTER,
|
||||
CSS_JUSTIFY_FLEX_END,
|
||||
CSS_JUSTIFY_SPACE_BETWEEN,
|
||||
CSS_JUSTIFY_SPACE_AROUND
|
||||
} css_justify_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_OVERFLOW_VISIBLE = 0,
|
||||
CSS_OVERFLOW_HIDDEN
|
||||
} css_overflow_t;
|
||||
|
||||
// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
|
||||
// alignItems.
|
||||
typedef enum {
|
||||
CSS_ALIGN_AUTO = 0,
|
||||
CSS_ALIGN_FLEX_START,
|
||||
CSS_ALIGN_CENTER,
|
||||
CSS_ALIGN_FLEX_END,
|
||||
CSS_ALIGN_STRETCH
|
||||
} css_align_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_POSITION_RELATIVE = 0,
|
||||
CSS_POSITION_ABSOLUTE
|
||||
} css_position_type_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_NOWRAP = 0,
|
||||
CSS_WRAP
|
||||
} css_wrap_type_t;
|
||||
|
||||
// Note: left and top are shared between position[2] and position[4], so
|
||||
// they have to be before right and bottom.
|
||||
typedef enum {
|
||||
CSS_LEFT = 0,
|
||||
CSS_TOP,
|
||||
CSS_RIGHT,
|
||||
CSS_BOTTOM,
|
||||
CSS_START,
|
||||
CSS_END,
|
||||
CSS_POSITION_COUNT
|
||||
} css_position_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_MEASURE_MODE_UNDEFINED = 0,
|
||||
CSS_MEASURE_MODE_EXACTLY,
|
||||
CSS_MEASURE_MODE_AT_MOST,
|
||||
CSS_MEASURE_MODE_COUNT
|
||||
} css_measure_mode_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_WIDTH = 0,
|
||||
CSS_HEIGHT
|
||||
} css_dimension_t;
|
||||
|
||||
typedef struct {
|
||||
float available_width;
|
||||
float available_height;
|
||||
css_measure_mode_t width_measure_mode;
|
||||
css_measure_mode_t height_measure_mode;
|
||||
|
||||
float computed_width;
|
||||
float computed_height;
|
||||
} css_cached_measurement_t;
|
||||
|
||||
enum {
|
||||
// This value was chosen based on empiracle data. Even the most complicated
|
||||
// layouts should not require more than 16 entries to fit within the cache.
|
||||
CSS_MAX_CACHED_RESULT_COUNT = 16
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float position[4];
|
||||
float dimensions[2];
|
||||
css_direction_t direction;
|
||||
|
||||
float flex_basis;
|
||||
|
||||
// Instead of recomputing the entire layout every single time, we
|
||||
// cache some information to break early when nothing changed
|
||||
bool should_update;
|
||||
int generation_count;
|
||||
css_direction_t last_parent_direction;
|
||||
|
||||
int next_cached_measurements_index;
|
||||
css_cached_measurement_t cached_measurements[CSS_MAX_CACHED_RESULT_COUNT];
|
||||
float measured_dimensions[2];
|
||||
|
||||
css_cached_measurement_t cached_layout;
|
||||
} css_layout_t;
|
||||
|
||||
typedef struct {
|
||||
float dimensions[2];
|
||||
} css_dim_t;
|
||||
|
||||
typedef struct {
|
||||
css_direction_t direction;
|
||||
css_flex_direction_t flex_direction;
|
||||
css_justify_t justify_content;
|
||||
css_align_t align_content;
|
||||
css_align_t align_items;
|
||||
css_align_t align_self;
|
||||
css_position_type_t position_type;
|
||||
css_wrap_type_t flex_wrap;
|
||||
css_overflow_t overflow;
|
||||
float flex;
|
||||
float margin[6];
|
||||
float position[4];
|
||||
/**
|
||||
* You should skip all the rules that contain negative values for the
|
||||
* following attributes. For example:
|
||||
* {padding: 10, paddingLeft: -5}
|
||||
* should output:
|
||||
* {left: 10 ...}
|
||||
* the following two are incorrect:
|
||||
* {left: -5 ...}
|
||||
* {left: 0 ...}
|
||||
*/
|
||||
float padding[6];
|
||||
float border[6];
|
||||
float dimensions[2];
|
||||
float minDimensions[2];
|
||||
float maxDimensions[2];
|
||||
} css_style_t;
|
||||
|
||||
typedef struct css_node css_node_t;
|
||||
struct css_node {
|
||||
css_style_t style;
|
||||
css_layout_t layout;
|
||||
int children_count;
|
||||
int line_index;
|
||||
|
||||
css_node_t* next_child;
|
||||
|
||||
css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
|
||||
void (*print)(void *context);
|
||||
struct css_node* (*get_child)(void *context, int i);
|
||||
bool (*is_dirty)(void *context);
|
||||
bool (*is_text_node)(void *context);
|
||||
void *context;
|
||||
};
|
||||
|
||||
// Lifecycle of nodes and children
|
||||
css_node_t *new_css_node(void);
|
||||
void init_css_node(css_node_t *node);
|
||||
void free_css_node(css_node_t *node);
|
||||
|
||||
// Print utilities
|
||||
typedef enum {
|
||||
CSS_PRINT_LAYOUT = 1,
|
||||
CSS_PRINT_STYLE = 2,
|
||||
CSS_PRINT_CHILDREN = 4,
|
||||
} css_print_options_t;
|
||||
void print_css_node(css_node_t *node, css_print_options_t options);
|
||||
|
||||
// Function that computes the layout!
|
||||
void layoutNode(css_node_t *node, float availableWidth, float availableHeight, css_direction_t parentDirection);
|
||||
bool isUndefined(float value);
|
||||
|
||||
#endif
|
1708
java/Layout.js
1708
java/Layout.js
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSAlign {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 class CSSCachedMeasurement {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 class CSSConstants {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSFlexDirection {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSJustify {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
import java.util.Arrays;
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
/**
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSMeasureMode {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
import javax.annotation.Nullable;
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSOverflow {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSPositionType {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
import java.util.Arrays;
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 CSSWrap {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
/**
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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 class FloatUtil {
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
@@ -551,47 +552,46 @@ public class LayoutEngine {
|
||||
CSSMeasureMode widthMeasureMode,
|
||||
CSSMeasureMode heightMeasureMode,
|
||||
boolean performLayout) {
|
||||
/** START_GENERATED **/
|
||||
|
||||
|
||||
Assertions.assertCondition(Float.isNaN(availableWidth) ? widthMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableWidth is indefinite so widthMeasureMode must be CSSMeasureMode.UNDEFINED");
|
||||
Assertions.assertCondition(Float.isNaN(availableHeight) ? heightMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableHeight is indefinite so heightMeasureMode must be CSSMeasureMode.UNDEFINED");
|
||||
|
||||
|
||||
float paddingAndBorderAxisRow = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW])));
|
||||
float paddingAndBorderAxisColumn = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
|
||||
float marginAxisRow = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
float marginAxisColumn = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
|
||||
|
||||
// Set the resolved resolution in the node's layout.
|
||||
CSSDirection direction = resolveDirection(node, parentDirection);
|
||||
node.layout.direction = direction;
|
||||
|
||||
|
||||
// For content (text) nodes, determine the dimensions based on the text contents.
|
||||
if (isMeasureDefined(node)) {
|
||||
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
||||
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
||||
|
||||
|
||||
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
|
||||
|
||||
|
||||
// Don't bother sizing the text if both dimensions are already defined.
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);
|
||||
} else if (innerWidth <= 0 || innerHeight <= 0) {
|
||||
|
||||
|
||||
// Don't bother sizing the text if there's no horizontal or vertical space.
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
} else {
|
||||
|
||||
|
||||
// Measure the text under the current constraints.
|
||||
MeasureOutput measureDim = node.measure(
|
||||
|
||||
|
||||
layoutContext.measureOutput,
|
||||
innerWidth,
|
||||
widthMeasureMode,
|
||||
innerHeight,
|
||||
heightMeasureMode
|
||||
);
|
||||
|
||||
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW,
|
||||
(widthMeasureMode == CSSMeasureMode.UNDEFINED || widthMeasureMode == CSSMeasureMode.AT_MOST) ?
|
||||
measureDim.width + paddingAndBorderAxisRow :
|
||||
@@ -601,10 +601,10 @@ public class LayoutEngine {
|
||||
measureDim.height + paddingAndBorderAxisColumn :
|
||||
availableHeight - marginAxisColumn);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For nodes with no children, use the available values if they were provided, or
|
||||
// the minimum size as indicated by the padding and border sizes.
|
||||
int childCount = node.getChildCount();
|
||||
@@ -619,7 +619,7 @@ public class LayoutEngine {
|
||||
availableHeight - marginAxisColumn);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If we're not being asked to perform a full layout, we can handle a number of common
|
||||
// cases here without incurring the cost of the remaining function.
|
||||
if (!performLayout) {
|
||||
@@ -631,19 +631,19 @@ public class LayoutEngine {
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (widthMeasureMode == CSSMeasureMode.AT_MOST && availableWidth <= 0) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, Float.isNaN(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (heightMeasureMode == CSSMeasureMode.AT_MOST && availableHeight <= 0) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, Float.isNaN(availableWidth) ? 0 : (availableWidth - marginAxisRow));
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If we're being asked to use an exact width/height, there's no need to measure the children.
|
||||
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
@@ -651,32 +651,32 @@ public class LayoutEngine {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM
|
||||
int mainAxis = resolveAxis(getFlexDirection(node), direction);
|
||||
int crossAxis = getCrossFlexDirection(mainAxis, direction);
|
||||
boolean isMainAxisRow = (mainAxis == CSS_FLEX_DIRECTION_ROW || mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE);
|
||||
CSSJustify justifyContent = node.style.justifyContent;
|
||||
boolean isNodeFlexWrap = (node.style.flexWrap == CSSWrap.WRAP);
|
||||
|
||||
|
||||
CSSNode firstAbsoluteChild = null;
|
||||
CSSNode currentAbsoluteChild = null;
|
||||
|
||||
|
||||
float leadingPaddingAndBorderMain = (node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]));
|
||||
float trailingPaddingAndBorderMain = (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
float leadingPaddingAndBorderCross = (node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]));
|
||||
float paddingAndBorderAxisMain = ((node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
|
||||
float paddingAndBorderAxisCross = ((node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (node.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + node.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
|
||||
|
||||
|
||||
CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
|
||||
CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
|
||||
|
||||
|
||||
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
||||
float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
||||
float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
||||
float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
||||
float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
||||
|
||||
|
||||
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
||||
CSSNode child;
|
||||
int i;
|
||||
@@ -686,17 +686,17 @@ public class LayoutEngine {
|
||||
CSSMeasureMode childHeightMeasureMode;
|
||||
for (i = 0; i < childCount; i++) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (performLayout) {
|
||||
// Set the initial position (relative to the parent).
|
||||
CSSDirection childDirection = resolveDirection(child, direction);
|
||||
setPosition(child, childDirection);
|
||||
}
|
||||
|
||||
|
||||
// Absolute-positioned children don't participate in flex layout. Add them
|
||||
// to a list that we can process later.
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE) {
|
||||
|
||||
|
||||
// Store a private linked list of absolutely positioned children
|
||||
// so that we can efficiently traverse them later.
|
||||
if (firstAbsoluteChild == null) {
|
||||
@@ -708,27 +708,27 @@ public class LayoutEngine {
|
||||
currentAbsoluteChild = child;
|
||||
child.nextChild = null;
|
||||
} else {
|
||||
|
||||
|
||||
if (isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
|
||||
|
||||
// The width is definite, so use that as the flex basis.
|
||||
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_WIDTH], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]))));
|
||||
} else if (!isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
|
||||
|
||||
|
||||
// The height is definite, so use that as the flex basis.
|
||||
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]))));
|
||||
} else if (!isFlexBasisAuto(child) && !Float.isNaN(availableInnerMainDim)) {
|
||||
|
||||
|
||||
// If the basis isn't 'auto', it is assumed to be zero.
|
||||
child.layout.flexBasis = Math.max(0, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
} else {
|
||||
|
||||
|
||||
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
|
||||
childWidth = CSSConstants.UNDEFINED;
|
||||
childHeight = CSSConstants.UNDEFINED;
|
||||
childWidthMeasureMode = CSSMeasureMode.UNDEFINED;
|
||||
childHeightMeasureMode = CSSMeasureMode.UNDEFINED;
|
||||
|
||||
|
||||
if ((child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
childWidth = child.style.dimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
@@ -737,7 +737,7 @@ public class LayoutEngine {
|
||||
childHeight = child.style.dimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
|
||||
|
||||
// According to the spec, if the main size is not definite and the
|
||||
// child's inline axis is parallel to the main axis (i.e. it's
|
||||
// horizontal), the child should be sized using "UNDEFINED" in
|
||||
@@ -746,7 +746,7 @@ public class LayoutEngine {
|
||||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
|
||||
// The W3C spec doesn't say anything about the 'overflow' property,
|
||||
// but all major browsers appear to implement the following logic.
|
||||
if (node.style.overflow == CSSOverflow.HIDDEN) {
|
||||
@@ -755,7 +755,7 @@ public class LayoutEngine {
|
||||
childHeightMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If child has no defined size in the cross axis and is set to stretch, set the cross
|
||||
// axis to be measured exactly with the available inner width
|
||||
if (!isMainAxisRow &&
|
||||
@@ -774,76 +774,76 @@ public class LayoutEngine {
|
||||
childHeight = availableInnerHeight;
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
|
||||
|
||||
// Measure the child
|
||||
layoutNodeInternal(layoutContext, child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
|
||||
|
||||
|
||||
child.layout.flexBasis = Math.max(isMainAxisRow ? child.layout.measuredDimensions[DIMENSION_WIDTH] : child.layout.measuredDimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
|
||||
|
||||
|
||||
// Indexes of children that represent the first and last items in the line.
|
||||
int startOfLineIndex = 0;
|
||||
int endOfLineIndex = 0;
|
||||
|
||||
|
||||
// Number of lines.
|
||||
int lineCount = 0;
|
||||
|
||||
|
||||
// Accumulated cross dimensions of all lines so far.
|
||||
float totalLineCrossDim = 0;
|
||||
|
||||
|
||||
// Max main dimension of all the lines.
|
||||
float maxLineMainDim = 0;
|
||||
|
||||
|
||||
while (endOfLineIndex < childCount) {
|
||||
|
||||
|
||||
// Number of items on the currently line. May be different than the difference
|
||||
// between start and end indicates because we skip over absolute-positioned items.
|
||||
int itemsOnLine = 0;
|
||||
|
||||
|
||||
// sizeConsumedOnCurrentLine is accumulation of the dimensions and margin
|
||||
// of all the children on the current line. This will be used in order to
|
||||
// either set the dimensions of the node if none already exist or to compute
|
||||
// the remaining space left for the flexible children.
|
||||
float sizeConsumedOnCurrentLine = 0;
|
||||
|
||||
|
||||
float totalFlexGrowFactors = 0;
|
||||
float totalFlexShrinkScaledFactors = 0;
|
||||
|
||||
|
||||
i = startOfLineIndex;
|
||||
|
||||
|
||||
// Maintain a linked list of the child nodes that can shrink and/or grow.
|
||||
CSSNode firstRelativeChild = null;
|
||||
CSSNode currentRelativeChild = null;
|
||||
|
||||
|
||||
// Add items to the current line until it's full or we run out of items.
|
||||
while (i < childCount) {
|
||||
child = node.getChildAt(i);
|
||||
child.lineIndex = lineCount;
|
||||
|
||||
|
||||
if (child.style.positionType != CSSPositionType.ABSOLUTE) {
|
||||
float outerFlexBasis = child.layout.flexBasis + (child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
|
||||
|
||||
// If this is a multi-line flow and this item pushes us over the available size, we've
|
||||
// hit the end of the current line. Break out of the loop and lay out the current line.
|
||||
if (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sizeConsumedOnCurrentLine += outerFlexBasis;
|
||||
itemsOnLine++;
|
||||
|
||||
|
||||
if ((child.style.positionType == CSSPositionType.RELATIVE && child.style.flex != 0)) {
|
||||
totalFlexGrowFactors += getFlexGrowFactor(child);
|
||||
|
||||
|
||||
// Unlike the grow factor, the shrink factor is scaled relative to the child
|
||||
// dimension.
|
||||
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
|
||||
}
|
||||
|
||||
|
||||
// Store a private linked list of children that need to be layed out.
|
||||
if (firstRelativeChild == null) {
|
||||
firstRelativeChild = child;
|
||||
@@ -854,20 +854,20 @@ public class LayoutEngine {
|
||||
currentRelativeChild = child;
|
||||
child.nextChild = null;
|
||||
}
|
||||
|
||||
|
||||
i++;
|
||||
endOfLineIndex++;
|
||||
}
|
||||
|
||||
|
||||
// If we don't need to measure the cross axis, we can skip the entire flex step.
|
||||
boolean canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
// In order to position the elements in the main axis, we have two
|
||||
// controls. The space between the beginning and the first element
|
||||
// and the space between each two elements.
|
||||
float leadingMainDim = 0;
|
||||
float betweenMainDim = 0;
|
||||
|
||||
|
||||
// STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS
|
||||
// Calculate the remaining available space that needs to be allocated.
|
||||
// If the main dimension size isn't known, it is computed based on
|
||||
@@ -881,17 +881,17 @@ public class LayoutEngine {
|
||||
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
|
||||
remainingFreeSpace = -sizeConsumedOnCurrentLine;
|
||||
}
|
||||
|
||||
|
||||
float originalRemainingFreeSpace = remainingFreeSpace;
|
||||
float deltaFreeSpace = 0;
|
||||
|
||||
|
||||
if (!canSkipFlex) {
|
||||
float childFlexBasis;
|
||||
float flexShrinkScaledFactor;
|
||||
float flexGrowFactor;
|
||||
float baseMainSize;
|
||||
float boundMainSize;
|
||||
|
||||
|
||||
// Do two passes over the flex items to figure out how to distribute the remaining space.
|
||||
// The first pass finds the items whose min/max constraints trigger, freezes them at those
|
||||
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
|
||||
@@ -904,17 +904,17 @@ public class LayoutEngine {
|
||||
// that needs to be repeated a variable number of times. The algorithm implemented here
|
||||
// won't handle all cases but it was simpler to implement and it mitigates performance
|
||||
// concerns because we know exactly how many passes it'll do.
|
||||
|
||||
|
||||
// First pass: detect the flex items whose min/max constraints trigger
|
||||
float deltaFlexShrinkScaledFactors = 0;
|
||||
float deltaFlexGrowFactors = 0;
|
||||
currentRelativeChild = firstRelativeChild;
|
||||
while (currentRelativeChild != null) {
|
||||
childFlexBasis = currentRelativeChild.layout.flexBasis;
|
||||
|
||||
|
||||
if (remainingFreeSpace < 0) {
|
||||
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
|
||||
|
||||
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
@@ -930,7 +930,7 @@ public class LayoutEngine {
|
||||
}
|
||||
} else if (remainingFreeSpace > 0) {
|
||||
flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
|
||||
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
@@ -945,24 +945,24 @@ public class LayoutEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentRelativeChild = currentRelativeChild.nextChild;
|
||||
}
|
||||
|
||||
|
||||
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
|
||||
totalFlexGrowFactors += deltaFlexGrowFactors;
|
||||
remainingFreeSpace += deltaFreeSpace;
|
||||
|
||||
|
||||
// Second pass: resolve the sizes of the flexible items
|
||||
deltaFreeSpace = 0;
|
||||
currentRelativeChild = firstRelativeChild;
|
||||
while (currentRelativeChild != null) {
|
||||
childFlexBasis = currentRelativeChild.layout.flexBasis;
|
||||
float updatedMainSize = childFlexBasis;
|
||||
|
||||
|
||||
if (remainingFreeSpace < 0) {
|
||||
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
|
||||
|
||||
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
|
||||
@@ -970,20 +970,20 @@ public class LayoutEngine {
|
||||
}
|
||||
} else if (remainingFreeSpace > 0) {
|
||||
flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
|
||||
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
|
||||
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
deltaFreeSpace -= updatedMainSize - childFlexBasis;
|
||||
|
||||
|
||||
if (isMainAxisRow) {
|
||||
childWidth = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
if (!Float.isNaN(availableInnerCrossDim) &&
|
||||
!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0) &&
|
||||
heightMeasureMode == CSSMeasureMode.EXACTLY &&
|
||||
@@ -1000,7 +1000,7 @@ public class LayoutEngine {
|
||||
} else {
|
||||
childHeight = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
if (!Float.isNaN(availableInnerCrossDim) &&
|
||||
!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0) &&
|
||||
widthMeasureMode == CSSMeasureMode.EXACTLY &&
|
||||
@@ -1015,32 +1015,32 @@ public class LayoutEngine {
|
||||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean requiresStretchLayout = !(currentRelativeChild.style.dimensions[dim[crossAxis]] >= 0.0) &&
|
||||
getAlignItem(node, currentRelativeChild) == CSSAlign.STRETCH;
|
||||
|
||||
|
||||
// Recursively call the layout algorithm for this child with the updated main size.
|
||||
layoutNodeInternal(layoutContext, currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, "flex");
|
||||
|
||||
|
||||
currentRelativeChild = currentRelativeChild.nextChild;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
|
||||
|
||||
|
||||
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
|
||||
|
||||
|
||||
// At this point, all the children have their dimensions set in the main axis.
|
||||
// Their dimensions are also set in the cross axis with the exception of items
|
||||
// that are aligned "stretch". We need to compute these stretch values and
|
||||
// set the final positions.
|
||||
|
||||
|
||||
// If we are using "at most" rules in the main axis, we won't distribute
|
||||
// any remaining space at this point.
|
||||
if (measureModeMainDim == CSSMeasureMode.AT_MOST) {
|
||||
remainingFreeSpace = 0;
|
||||
}
|
||||
|
||||
|
||||
// Use justifyContent to figure out how to allocate the remaining space
|
||||
// available in the main axis.
|
||||
if (justifyContent != CSSJustify.FLEX_START) {
|
||||
@@ -1061,13 +1061,13 @@ public class LayoutEngine {
|
||||
leadingMainDim = betweenMainDim / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float mainDim = leadingPaddingAndBorderMain + leadingMainDim;
|
||||
float crossDim = 0;
|
||||
|
||||
|
||||
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE &&
|
||||
!Float.isNaN(child.style.position[leading[mainAxis]])) {
|
||||
if (performLayout) {
|
||||
@@ -1084,7 +1084,7 @@ public class LayoutEngine {
|
||||
// we put it at the current accumulated offset.
|
||||
child.layout.position[pos[mainAxis]] += mainDim;
|
||||
}
|
||||
|
||||
|
||||
// Now that we placed the element, we need to update the variables.
|
||||
// We need to do that only for relative elements. Absolute elements
|
||||
// do not take part in that phase.
|
||||
@@ -1098,7 +1098,7 @@ public class LayoutEngine {
|
||||
// The main dimension is the sum of all the elements dimension plus
|
||||
// the spacing.
|
||||
mainDim += betweenMainDim + (child.layout.measuredDimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
|
||||
|
||||
// The cross dimension is the max of the elements dimension since there
|
||||
// can only be one element in that cross dimension.
|
||||
crossDim = Math.max(crossDim, (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
|
||||
@@ -1106,33 +1106,33 @@ public class LayoutEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mainDim += trailingPaddingAndBorderMain;
|
||||
|
||||
|
||||
float containerCrossAxis = availableInnerCrossDim;
|
||||
if (measureModeCrossDim == CSSMeasureMode.UNDEFINED || measureModeCrossDim == CSSMeasureMode.AT_MOST) {
|
||||
// Compute the cross axis from the max cross dimension of the children.
|
||||
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
|
||||
|
||||
|
||||
if (measureModeCrossDim == CSSMeasureMode.AT_MOST) {
|
||||
containerCrossAxis = Math.min(containerCrossAxis, availableInnerCrossDim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If there's no flex wrap, the cross dimension is defined by the container.
|
||||
if (!isNodeFlexWrap && measureModeCrossDim == CSSMeasureMode.EXACTLY) {
|
||||
crossDim = availableInnerCrossDim;
|
||||
}
|
||||
|
||||
|
||||
// Clamp to the min/max size specified on the container.
|
||||
crossDim = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
|
||||
|
||||
|
||||
// STEP 7: CROSS-AXIS ALIGNMENT
|
||||
// We can skip child alignment if we're just measuring the container.
|
||||
if (performLayout) {
|
||||
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE) {
|
||||
// If the child is absolutely positioned and has a top/left/bottom/right
|
||||
// set, override all the previously computed positions to set it correctly.
|
||||
@@ -1146,18 +1146,18 @@ public class LayoutEngine {
|
||||
}
|
||||
} else {
|
||||
float leadingCrossDim = leadingPaddingAndBorderCross;
|
||||
|
||||
|
||||
// For a relative children, we're either using alignItems (parent) or
|
||||
// alignSelf (child) in order to determine the position in the cross axis
|
||||
CSSAlign alignItem = getAlignItem(node, child);
|
||||
|
||||
|
||||
// If the child uses align stretch, we need to lay it out one more time, this time
|
||||
// forcing the cross-axis size to be the computed cross size for the current line.
|
||||
if (alignItem == CSSAlign.STRETCH) {
|
||||
childWidth = child.layout.measuredDimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childHeight = child.layout.measuredDimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
boolean isCrossSizeDefinite = false;
|
||||
|
||||
|
||||
if (isMainAxisRow) {
|
||||
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0);
|
||||
childHeight = crossDim;
|
||||
@@ -1165,7 +1165,7 @@ public class LayoutEngine {
|
||||
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0);
|
||||
childWidth = crossDim;
|
||||
}
|
||||
|
||||
|
||||
// If the child defines a definite size for its cross axis, there's no need to stretch.
|
||||
if (!isCrossSizeDefinite) {
|
||||
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
@@ -1174,36 +1174,36 @@ public class LayoutEngine {
|
||||
}
|
||||
} else if (alignItem != CSSAlign.FLEX_START) {
|
||||
float remainingCrossDim = containerCrossAxis - (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]));
|
||||
|
||||
|
||||
if (alignItem == CSSAlign.CENTER) {
|
||||
leadingCrossDim += remainingCrossDim / 2;
|
||||
} else { // CSSAlign.FLEX_END
|
||||
leadingCrossDim += remainingCrossDim;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// And we apply the position
|
||||
child.layout.position[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
totalLineCrossDim += crossDim;
|
||||
maxLineMainDim = Math.max(maxLineMainDim, mainDim);
|
||||
|
||||
|
||||
// Reset variables for new line.
|
||||
lineCount++;
|
||||
startOfLineIndex = endOfLineIndex;
|
||||
endOfLineIndex = startOfLineIndex;
|
||||
}
|
||||
|
||||
|
||||
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
||||
if (lineCount > 1 && performLayout && !Float.isNaN(availableInnerCrossDim)) {
|
||||
float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
|
||||
|
||||
|
||||
float crossDimLead = 0;
|
||||
float currentLead = leadingPaddingAndBorderCross;
|
||||
|
||||
|
||||
CSSAlign alignContent = node.style.alignContent;
|
||||
if (alignContent == CSSAlign.FLEX_END) {
|
||||
currentLead += remainingAlignContentDim;
|
||||
@@ -1214,12 +1214,12 @@ public class LayoutEngine {
|
||||
crossDimLead = (remainingAlignContentDim / lineCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int endIndex = 0;
|
||||
for (i = 0; i < lineCount; ++i) {
|
||||
int startIndex = endIndex;
|
||||
int j;
|
||||
|
||||
|
||||
// compute the line's height and find the endIndex
|
||||
float lineHeight = 0;
|
||||
for (j = startIndex; j < childCount; ++j) {
|
||||
@@ -1237,14 +1237,14 @@ public class LayoutEngine {
|
||||
}
|
||||
endIndex = j;
|
||||
lineHeight += crossDimLead;
|
||||
|
||||
|
||||
if (performLayout) {
|
||||
for (j = startIndex; j < endIndex; ++j) {
|
||||
child = node.getChildAt(j);
|
||||
if (child.style.positionType != CSSPositionType.RELATIVE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
CSSAlign alignContentAlignItem = getAlignItem(node, child);
|
||||
if (alignContentAlignItem == CSSAlign.FLEX_START) {
|
||||
child.layout.position[pos[crossAxis]] = currentLead + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]);
|
||||
@@ -1260,15 +1260,15 @@ public class LayoutEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentLead += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 9: COMPUTING FINAL DIMENSIONS
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);
|
||||
|
||||
|
||||
// If the user didn't specify a width or height for the node, set the
|
||||
// dimensions based on the children.
|
||||
if (measureModeMainDim == CSSMeasureMode.UNDEFINED) {
|
||||
@@ -1281,7 +1281,7 @@ public class LayoutEngine {
|
||||
boundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)),
|
||||
paddingAndBorderAxisMain);
|
||||
}
|
||||
|
||||
|
||||
if (measureModeCrossDim == CSSMeasureMode.UNDEFINED) {
|
||||
// Clamp the size to the min/max size, if specified, and make sure it
|
||||
// doesn't go below the padding and border amount.
|
||||
@@ -1292,48 +1292,48 @@ public class LayoutEngine {
|
||||
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
|
||||
paddingAndBorderAxisCross);
|
||||
}
|
||||
|
||||
|
||||
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
|
||||
if (performLayout) {
|
||||
boolean needsMainTrailingPos = false;
|
||||
boolean needsCrossTrailingPos = false;
|
||||
|
||||
|
||||
if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
|
||||
mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||
needsMainTrailingPos = true;
|
||||
}
|
||||
|
||||
|
||||
if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
|
||||
crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||
needsCrossTrailingPos = true;
|
||||
}
|
||||
|
||||
|
||||
// Set trailing position if necessary.
|
||||
if (needsMainTrailingPos || needsCrossTrailingPos) {
|
||||
for (i = 0; i < childCount; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (needsMainTrailingPos) {
|
||||
child.layout.position[trailing[mainAxis]] = node.layout.measuredDimensions[dim[mainAxis]] - (child.style.positionType == CSSPositionType.ABSOLUTE ? 0 : child.layout.measuredDimensions[dim[mainAxis]]) - child.layout.position[pos[mainAxis]];
|
||||
}
|
||||
|
||||
|
||||
if (needsCrossTrailingPos) {
|
||||
child.layout.position[trailing[crossAxis]] = node.layout.measuredDimensions[dim[crossAxis]] - (child.style.positionType == CSSPositionType.ABSOLUTE ? 0 : child.layout.measuredDimensions[dim[crossAxis]]) - child.layout.position[pos[crossAxis]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
|
||||
currentAbsoluteChild = firstAbsoluteChild;
|
||||
while (currentAbsoluteChild != null) {
|
||||
// Now that we know the bounds of the container, perform layout again on the
|
||||
// absolutely-positioned children.
|
||||
if (performLayout) {
|
||||
|
||||
|
||||
childWidth = CSSConstants.UNDEFINED;
|
||||
childHeight = CSSConstants.UNDEFINED;
|
||||
|
||||
|
||||
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
childWidth = currentAbsoluteChild.style.dimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
} else {
|
||||
@@ -1345,7 +1345,7 @@ public class LayoutEngine {
|
||||
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
|
||||
childHeight = currentAbsoluteChild.style.dimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
} else {
|
||||
@@ -1357,12 +1357,12 @@ public class LayoutEngine {
|
||||
childHeight = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN, childHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we're still missing one or the other dimension, measure the content.
|
||||
if (Float.isNaN(childWidth) || Float.isNaN(childHeight)) {
|
||||
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
childHeightMeasureMode = Float.isNaN(childHeight) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
// According to the spec, if the main size is not definite and the
|
||||
// child's inline axis is parallel to the main axis (i.e. it's
|
||||
// horizontal), the child should be sized using "UNDEFINED" in
|
||||
@@ -1371,7 +1371,7 @@ public class LayoutEngine {
|
||||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
|
||||
// The W3C spec doesn't say anything about the 'overflow' property,
|
||||
// but all major browsers appear to implement the following logic.
|
||||
if (node.style.overflow == CSSOverflow.HIDDEN) {
|
||||
@@ -1380,14 +1380,14 @@ public class LayoutEngine {
|
||||
childHeightMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "abs-measure");
|
||||
childWidth = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childHeight = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
}
|
||||
|
||||
|
||||
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, CSSMeasureMode.EXACTLY, CSSMeasureMode.EXACTLY, true, "abs-layout");
|
||||
|
||||
|
||||
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) &&
|
||||
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_ROW]])) {
|
||||
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
|
||||
@@ -1395,7 +1395,7 @@ public class LayoutEngine {
|
||||
currentAbsoluteChild.layout.measuredDimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
|
||||
(Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]);
|
||||
}
|
||||
|
||||
|
||||
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) &&
|
||||
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_COLUMN]])) {
|
||||
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
|
||||
@@ -1404,9 +1404,8 @@ public class LayoutEngine {
|
||||
(Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentAbsoluteChild = currentAbsoluteChild.nextChild;
|
||||
}
|
||||
/** END_GENERATED **/
|
||||
}
|
||||
}
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
/**
|
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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;
|
||||
|
||||
import javax.annotation.Nullable;
|
@@ -1,13 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line=LF
|
||||
|
||||
[*.cs]
|
||||
indent_style=space
|
||||
indent_size=4
|
||||
|
||||
[*.js]
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
|
6
java/csharp/.gitignore
vendored
6
java/csharp/.gitignore
vendored
@@ -1,6 +0,0 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
/.vs/
|
||||
*.user
|
||||
*.nupkg
|
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
/**
|
||||
* Tests for {@link CSSNode}.
|
||||
*/
|
||||
public class CSSNodeTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void testAddChildGetParent()
|
||||
{
|
||||
CSSNode parent = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
Assert.IsNull(child.getParent());
|
||||
Assert.AreEqual(0, parent.getChildCount());
|
||||
|
||||
parent.addChildAt(child, 0);
|
||||
|
||||
Assert.AreEqual(1, parent.getChildCount());
|
||||
Assert.AreEqual(child, parent.getChildAt(0));
|
||||
Assert.AreEqual(parent, child.getParent());
|
||||
|
||||
parent.removeChildAt(0);
|
||||
|
||||
Assert.IsNull(child.getParent());
|
||||
Assert.AreEqual(0, parent.getChildCount());
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(InvalidOperationException))]
|
||||
public void testCannotAddChildToMultipleParents()
|
||||
{
|
||||
CSSNode parent1 = new CSSNode();
|
||||
CSSNode parent2 = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
parent1.addChildAt(child, 0);
|
||||
parent2.addChildAt(child, 0);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E687C8FD-0A0D-450F-853D-EC301BE1C038}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Facebook.CSSLayout.Tests</RootNamespace>
|
||||
<AssemblyName>Facebook.CSSLayout.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CSSNodeTest.cs" />
|
||||
<Compile Include="LayoutCachingTest.cs" />
|
||||
<Compile Include="LayoutEngineTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TestConstants.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facebook.CSSLayout\Facebook.CSSLayout.csproj">
|
||||
<Project>{d534fb4b-a7d4-4a29-96d3-f39a91a259bd}</Project>
|
||||
<Name>Facebook.CSSLayout</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -1,240 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests for {@link LayoutEngine} and {@link CSSNode} to make sure layouts are only generated when
|
||||
* needed.
|
||||
*/
|
||||
public class LayoutCachingTest
|
||||
{
|
||||
|
||||
private void assertTreeHasNewLayout(bool expectedHasNewLayout, CSSNode root)
|
||||
{
|
||||
Assert.AreEqual(expectedHasNewLayout, root.HasNewLayout);
|
||||
|
||||
for (int i = 0; i < root.getChildCount(); i++)
|
||||
{
|
||||
assertTreeHasNewLayout(expectedHasNewLayout, root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void markLayoutAppliedForTree(CSSNode root)
|
||||
{
|
||||
root.MarkLayoutSeen();
|
||||
for (int i = 0; i < root.getChildCount(); i++)
|
||||
{
|
||||
markLayoutAppliedForTree(root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testCachesFullTree()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
assertTreeHasNewLayout(true, root);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.calculateLayout();
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenChildAdded()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c0c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
c0c1.Width = 200;
|
||||
c0c1.Height = 200;
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c0c0.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.addChildAt(c0c1, 1);
|
||||
|
||||
root.calculateLayout();
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenEnumPropertyChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.AlignSelf = CSSAlign.Center;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsFalse(c0c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenFloatPropertyChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.SetMargin(CSSSpacingType.Left, 10);
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesFullTreeWhenParentWidthChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.Width = 200;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
Assert.IsTrue(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testDoesNotInvalidateCacheWhenPropertyIsTheSame()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
root.Width = 200;
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.Width = 200;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidateCacheWhenHeightChangesPosition()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.Height = 100;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
Assert.IsFalse(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesOnNewMeasureFunction()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.setMeasureFunction((node, width, widthMode, height, heightMode) => new MeasureOutput(100, 20));
|
||||
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("Facebook.CSSLayout.Tests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Facebook.CSSLayout.Tests")]
|
||||
[assembly: AssemblyCopyright("Copyright © Facebook 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: Guid("c186053a-741f-477d-b031-4d343fb20d1d")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
/**
|
||||
* Generated constants used in {@link LayoutEngineTest}.
|
||||
*/
|
||||
public class TestConstants
|
||||
{
|
||||
|
||||
/** START_GENERATED **/
|
||||
public static readonly float SMALL_WIDTH = 35f;
|
||||
public static readonly float SMALL_HEIGHT = 18f;
|
||||
public static readonly float BIG_WIDTH = 172f;
|
||||
public static readonly float BIG_HEIGHT = 36f;
|
||||
public static readonly float BIG_MIN_WIDTH = 100f;
|
||||
public static readonly string SMALL_TEXT = "small";
|
||||
public static readonly string LONG_TEXT = "loooooooooong with space";
|
||||
public static readonly string MEASURE_WITH_RATIO_2 = "measureWithRatio2";
|
||||
public static readonly string MEASURE_WITH_MATCH_PARENT = "measureWithMatchParent";
|
||||
/** END_GENERATED **/
|
||||
}
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="2.6.4" targetFramework="net45" />
|
||||
</packages>
|
@@ -1,34 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.CSSLayout", "Facebook.CSSLayout\Facebook.CSSLayout.csproj", "{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.CSSLayout.Tests", "Facebook.CSSLayout.Tests\Facebook.CSSLayout.Tests.csproj", "{E687C8FD-0A0D-450F-853D-EC301BE1C038}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{29A6932B-FDDC-4E8A-8895-7FD64CC47B7F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\CSharpTranspiler.js = ..\CSharpTranspiler.js
|
||||
..\JavaTranspiler.js = ..\JavaTranspiler.js
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
static class Assertions
|
||||
{
|
||||
public static T assertNotNull<T>(T v) where T : class
|
||||
{
|
||||
Debug.Assert(v != null);
|
||||
return v;
|
||||
}
|
||||
|
||||
public static void assertCondition(bool condition, string explanation)
|
||||
{
|
||||
Debug.Assert(condition, explanation);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSAlign
|
||||
{
|
||||
Auto,
|
||||
FlexStart,
|
||||
Center,
|
||||
FlexEnd,
|
||||
Stretch,
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
sealed class CSSCachedMeasurement
|
||||
{
|
||||
public float availableWidth;
|
||||
public float availableHeight;
|
||||
public CSSMeasureMode? widthMeasureMode = null;
|
||||
public CSSMeasureMode? heightMeasureMode = null;
|
||||
|
||||
public float computedWidth;
|
||||
public float computedHeight;
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public static class CSSConstants
|
||||
{
|
||||
public const float Undefined = float.NaN;
|
||||
|
||||
public static bool IsUndefined(float value)
|
||||
{
|
||||
return float.IsNaN(value);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSDirection
|
||||
{
|
||||
Inherit,
|
||||
LTR,
|
||||
RTL
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSFlexDirection
|
||||
{
|
||||
Column,
|
||||
ColumnReverse,
|
||||
Row,
|
||||
RowReverse
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSJustify
|
||||
{
|
||||
FlexStart,
|
||||
Center,
|
||||
FlexEnd,
|
||||
SpaceBetween,
|
||||
SpaceAround
|
||||
}
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
|
||||
/**
|
||||
* Where the output of {@link LayoutEngine#layoutNode(CSSNode, float)} will go in the CSSNode.
|
||||
*/
|
||||
|
||||
class CSSLayout
|
||||
{
|
||||
// This value was chosen based on empiracle data. Even the most complicated
|
||||
// layouts should not require more than 16 entries to fit within the cache.
|
||||
public const int MAX_CACHED_RESULT_COUNT = 16;
|
||||
|
||||
public const int POSITION_LEFT = 0;
|
||||
public const int POSITION_TOP = 1;
|
||||
public const int POSITION_RIGHT = 2;
|
||||
public const int POSITION_BOTTOM = 3;
|
||||
|
||||
public const int DIMENSION_WIDTH = 0;
|
||||
public const int DIMENSION_HEIGHT = 1;
|
||||
|
||||
public float[] position = new float[4];
|
||||
public float[] dimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
public CSSDirection direction = CSSDirection.LTR;
|
||||
|
||||
public float flexBasis;
|
||||
|
||||
public int generationCount;
|
||||
public CSSDirection? lastParentDirection;
|
||||
|
||||
public int nextCachedMeasurementsIndex;
|
||||
public CSSCachedMeasurement[] cachedMeasurements = new CSSCachedMeasurement[MAX_CACHED_RESULT_COUNT];
|
||||
public float[] measuredDimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public CSSCachedMeasurement cachedLayout = new CSSCachedMeasurement();
|
||||
|
||||
public void resetResult()
|
||||
{
|
||||
FillArray(position, 0);
|
||||
FillArray(dimensions, CSSConstants.Undefined);
|
||||
|
||||
direction = CSSDirection.LTR;
|
||||
|
||||
flexBasis = 0;
|
||||
|
||||
generationCount = 0;
|
||||
lastParentDirection = null;
|
||||
|
||||
nextCachedMeasurementsIndex = 0;
|
||||
measuredDimensions[DIMENSION_WIDTH] = CSSConstants.Undefined;
|
||||
measuredDimensions[DIMENSION_HEIGHT] = CSSConstants.Undefined;
|
||||
|
||||
cachedLayout.widthMeasureMode = null;
|
||||
cachedLayout.heightMeasureMode = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "layout: {" +
|
||||
"left: " + position[POSITION_LEFT] + ", " +
|
||||
"top: " + position[POSITION_TOP] + ", " +
|
||||
"width: " + dimensions[DIMENSION_WIDTH] + ", " +
|
||||
"height: " + dimensions[DIMENSION_HEIGHT] + ", " +
|
||||
"direction: " + direction +
|
||||
"}";
|
||||
}
|
||||
|
||||
static void FillArray<T>(T[] array, T value)
|
||||
{
|
||||
for (var i = 0; i != array.Length; ++i)
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
|
||||
/**
|
||||
* A context for holding values local to a given instance of layout computation.
|
||||
*
|
||||
* This is necessary for making layout thread-safe. A separate instance should
|
||||
* be used when {@link CSSNode#calculateLayout} is called concurrently on
|
||||
* different node hierarchies.
|
||||
*/
|
||||
|
||||
sealed class CSSLayoutContext
|
||||
{
|
||||
/*package*/
|
||||
public MeasureOutput measureOutput = new MeasureOutput();
|
||||
public int currentGenerationCount;
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSMeasureMode
|
||||
{
|
||||
Undefined,
|
||||
Exactly,
|
||||
AtMost,
|
||||
}
|
||||
}
|
@@ -1,558 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* Should measure the given node and put the result in the given MeasureOutput.
|
||||
*/
|
||||
|
||||
public delegate MeasureOutput MeasureFunction(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
|
||||
|
||||
/**
|
||||
* A CSS Node. It has a style object you can manipulate at {@link #style}. After calling
|
||||
* {@link #calculateLayout()}, {@link #layout} will be filled with the results of the layout.
|
||||
*/
|
||||
|
||||
public class CSSNode
|
||||
{
|
||||
const int POSITION_LEFT = CSSLayout.POSITION_LEFT;
|
||||
const int POSITION_TOP = CSSLayout.POSITION_TOP;
|
||||
const int POSITION_RIGHT = CSSLayout.POSITION_RIGHT;
|
||||
const int POSITION_BOTTOM = CSSLayout.POSITION_BOTTOM;
|
||||
const int DIMENSION_WIDTH = CSSLayout.DIMENSION_WIDTH;
|
||||
const int DIMENSION_HEIGHT = CSSLayout.DIMENSION_HEIGHT;
|
||||
|
||||
enum LayoutState
|
||||
{
|
||||
/**
|
||||
* Some property of this node or its children has changes and the current values in
|
||||
* {@link #layout} are not valid.
|
||||
*/
|
||||
DIRTY,
|
||||
|
||||
/**
|
||||
* This node has a new layout relative to the last time {@link #MarkLayoutSeen()} was called.
|
||||
*/
|
||||
HAS_NEW_LAYOUT,
|
||||
|
||||
/**
|
||||
* {@link #layout} is valid for the node's properties and this layout has been marked as
|
||||
* having been seen.
|
||||
*/
|
||||
UP_TO_DATE,
|
||||
}
|
||||
|
||||
internal readonly CSSStyle style = new CSSStyle();
|
||||
internal readonly CSSLayout layout = new CSSLayout();
|
||||
internal readonly CachedCSSLayout lastLayout = new CachedCSSLayout();
|
||||
|
||||
internal int lineIndex = 0;
|
||||
internal /*package*/ CSSNode nextChild;
|
||||
|
||||
// 4 is kinda arbitrary, but the default of 10 seems really high for an average View.
|
||||
readonly List<CSSNode> mChildren = new List<CSSNode>(4);
|
||||
[Nullable] CSSNode mParent;
|
||||
[Nullable] MeasureFunction mMeasureFunction = null;
|
||||
LayoutState mLayoutState = LayoutState.DIRTY;
|
||||
bool mIsTextNode = false;
|
||||
|
||||
public int ChildCount
|
||||
{
|
||||
get { return mChildren.Count; }
|
||||
}
|
||||
|
||||
public CSSNode this[int i]
|
||||
{
|
||||
get { return mChildren[i]; }
|
||||
}
|
||||
|
||||
public IEnumerable<CSSNode> Children
|
||||
{
|
||||
get { return mChildren; }
|
||||
}
|
||||
|
||||
public void AddChild(CSSNode child)
|
||||
{
|
||||
InsertChild(ChildCount, child);
|
||||
}
|
||||
|
||||
public void InsertChild(int i, CSSNode child)
|
||||
{
|
||||
if (child.mParent != null)
|
||||
{
|
||||
throw new InvalidOperationException("Child already has a parent, it must be removed first.");
|
||||
}
|
||||
|
||||
mChildren.Insert(i, child);
|
||||
child.mParent = this;
|
||||
dirty();
|
||||
}
|
||||
|
||||
public void RemoveChildAt(int i)
|
||||
{
|
||||
mChildren[i].mParent = null;
|
||||
mChildren.RemoveAt(i);
|
||||
dirty();
|
||||
}
|
||||
|
||||
public CSSNode Parent
|
||||
{
|
||||
[return: Nullable]
|
||||
get
|
||||
{ return mParent; }
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index of the given child, or -1 if the child doesn't exist in this node.
|
||||
*/
|
||||
|
||||
public int IndexOf(CSSNode child)
|
||||
{
|
||||
return mChildren.IndexOf(child);
|
||||
}
|
||||
|
||||
public MeasureFunction MeasureFunction
|
||||
{
|
||||
get { return mMeasureFunction; }
|
||||
set
|
||||
{
|
||||
if (!valuesEqual(mMeasureFunction, value))
|
||||
{
|
||||
mMeasureFunction = value;
|
||||
dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTextNode
|
||||
{
|
||||
get { return mIsTextNode; }
|
||||
set { mIsTextNode = value; }
|
||||
}
|
||||
|
||||
public bool IsMeasureDefined
|
||||
{
|
||||
get { return mMeasureFunction != null; }
|
||||
}
|
||||
|
||||
internal MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode)
|
||||
{
|
||||
if (!IsMeasureDefined)
|
||||
{
|
||||
throw new Exception("Measure function isn't defined!");
|
||||
}
|
||||
return Assertions.assertNotNull(mMeasureFunction)(this, width, widthMode, height, heightMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual layout and saves the results in {@link #layout}
|
||||
*/
|
||||
|
||||
public void CalculateLayout()
|
||||
{
|
||||
LayoutEngine.layoutNode(DummyLayoutContext, this, CSSConstants.Undefined, CSSConstants.Undefined, null);
|
||||
}
|
||||
|
||||
static readonly CSSLayoutContext DummyLayoutContext = new CSSLayoutContext();
|
||||
|
||||
/**
|
||||
* See {@link LayoutState#DIRTY}.
|
||||
*/
|
||||
|
||||
public bool IsDirty
|
||||
{
|
||||
get { return mLayoutState == LayoutState.DIRTY; }
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link LayoutState#HAS_NEW_LAYOUT}.
|
||||
*/
|
||||
|
||||
public bool HasNewLayout
|
||||
{
|
||||
get { return mLayoutState == LayoutState.HAS_NEW_LAYOUT; }
|
||||
}
|
||||
|
||||
internal protected virtual void dirty()
|
||||
{
|
||||
if (mLayoutState == LayoutState.DIRTY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (mLayoutState == LayoutState.HAS_NEW_LAYOUT)
|
||||
{
|
||||
throw new InvalidOperationException("Previous layout was ignored! MarkLayoutSeen() never called");
|
||||
}
|
||||
|
||||
mLayoutState = LayoutState.DIRTY;
|
||||
|
||||
if (mParent != null)
|
||||
{
|
||||
mParent.dirty();
|
||||
}
|
||||
}
|
||||
|
||||
internal void markHasNewLayout()
|
||||
{
|
||||
mLayoutState = LayoutState.HAS_NEW_LAYOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the node that the current values in {@link #layout} have been seen. Subsequent calls
|
||||
* to {@link #hasNewLayout()} will return false until this node is laid out with new parameters.
|
||||
* You must call this each time the layout is generated if the node has a new layout.
|
||||
*/
|
||||
|
||||
public void MarkLayoutSeen()
|
||||
{
|
||||
if (!HasNewLayout)
|
||||
{
|
||||
throw new InvalidOperationException("Expected node to have a new layout to be seen!");
|
||||
}
|
||||
|
||||
mLayoutState = LayoutState.UP_TO_DATE;
|
||||
}
|
||||
|
||||
void toStringWithIndentation(StringBuilder result, int level)
|
||||
{
|
||||
// Spaces and tabs are dropped by IntelliJ logcat integration, so rely on __ instead.
|
||||
StringBuilder indentation = new StringBuilder();
|
||||
for (int i = 0; i < level; ++i)
|
||||
{
|
||||
indentation.Append("__");
|
||||
}
|
||||
|
||||
result.Append(indentation.ToString());
|
||||
result.Append(layout.ToString());
|
||||
|
||||
if (ChildCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.Append(", children: [\n");
|
||||
for (var i = 0; i < ChildCount; i++)
|
||||
{
|
||||
this[i].toStringWithIndentation(result, level + 1);
|
||||
result.Append("\n");
|
||||
}
|
||||
result.Append(indentation + "]");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
this.toStringWithIndentation(sb, 0);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
protected bool valuesEqual(float f1, float f2)
|
||||
{
|
||||
return FloatUtil.floatsEqual(f1, f2);
|
||||
}
|
||||
|
||||
protected bool valuesEqual<T>([Nullable] T o1, [Nullable] T o2)
|
||||
{
|
||||
if (o1 == null)
|
||||
{
|
||||
return o2 == null;
|
||||
}
|
||||
return o1.Equals(o2);
|
||||
}
|
||||
|
||||
public CSSDirection Direction
|
||||
{
|
||||
get { return style.direction; }
|
||||
set { updateDiscreteValue(ref style.direction, value); }
|
||||
}
|
||||
|
||||
public CSSFlexDirection FlexDirection
|
||||
{
|
||||
get { return style.flexDirection; }
|
||||
set { updateDiscreteValue(ref style.flexDirection, value); }
|
||||
}
|
||||
|
||||
public CSSJustify JustifyContent
|
||||
{
|
||||
get { return style.justifyContent; }
|
||||
set { updateDiscreteValue(ref style.justifyContent, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignContent
|
||||
{
|
||||
get { return style.alignContent; }
|
||||
set { updateDiscreteValue(ref style.alignContent, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignItems
|
||||
{
|
||||
get { return style.alignItems; }
|
||||
set { updateDiscreteValue(ref style.alignItems, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignSelf
|
||||
{
|
||||
get { return style.alignSelf; }
|
||||
set { updateDiscreteValue(ref style.alignSelf, value); }
|
||||
}
|
||||
|
||||
public CSSPositionType PositionType
|
||||
{
|
||||
get { return style.positionType; }
|
||||
set { updateDiscreteValue(ref style.positionType, value); }
|
||||
}
|
||||
|
||||
public CSSWrap Wrap
|
||||
{
|
||||
get { return style.flexWrap; }
|
||||
set { updateDiscreteValue(ref style.flexWrap, value); }
|
||||
}
|
||||
|
||||
public float Flex
|
||||
{
|
||||
get { return style.flex; }
|
||||
set { updateFloatValue(ref style.flex, value); }
|
||||
}
|
||||
|
||||
public CSSOverflow Overflow
|
||||
{
|
||||
get { return style.overflow; }
|
||||
set { updateDiscreteValue(ref style.overflow, value); }
|
||||
}
|
||||
|
||||
public void SetMargin(CSSSpacingType spacingType, float margin)
|
||||
{
|
||||
if (style.margin.set((int)spacingType, margin))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetMargin(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.margin.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public void SetPadding(CSSSpacingType spacingType, float padding)
|
||||
{
|
||||
if (style.padding.set((int)spacingType, padding))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetPadding(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.padding.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public void SetBorder(CSSSpacingType spacingType, float border)
|
||||
{
|
||||
if (style.border.set((int)spacingType, border))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetBorder(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.border.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public float PositionTop
|
||||
{
|
||||
get { return style.position[POSITION_TOP]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_TOP], value); }
|
||||
}
|
||||
|
||||
public float PositionBottom
|
||||
{
|
||||
get { return style.position[POSITION_BOTTOM]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_BOTTOM], value); }
|
||||
}
|
||||
|
||||
public float PositionLeft
|
||||
{
|
||||
get { return style.position[POSITION_LEFT]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_LEFT], value); }
|
||||
}
|
||||
|
||||
public float PositionRight
|
||||
{
|
||||
get { return style.position[POSITION_RIGHT]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_RIGHT], value); }
|
||||
}
|
||||
|
||||
public float Width
|
||||
{
|
||||
get { return style.dimensions[DIMENSION_WIDTH]; }
|
||||
set { updateFloatValue(ref style.dimensions[DIMENSION_WIDTH], value); }
|
||||
}
|
||||
|
||||
public float Height
|
||||
{
|
||||
get { return style.dimensions[DIMENSION_HEIGHT]; }
|
||||
set { updateFloatValue(ref style.dimensions[DIMENSION_HEIGHT], value); }
|
||||
}
|
||||
|
||||
public float MinWidth
|
||||
{
|
||||
get { return style.minWidth; }
|
||||
set { updateFloatValue(ref style.minWidth, value); }
|
||||
}
|
||||
|
||||
public float MinHeight
|
||||
{
|
||||
get { return style.minHeight; }
|
||||
set { updateFloatValue(ref style.minHeight, value); }
|
||||
}
|
||||
|
||||
public float MaxWidth
|
||||
{
|
||||
get { return style.maxWidth; }
|
||||
set { updateFloatValue(ref style.maxWidth, value); }
|
||||
}
|
||||
|
||||
public float MaxHeight
|
||||
{
|
||||
get { return style.maxHeight; }
|
||||
set { updateFloatValue(ref style.maxHeight, value); }
|
||||
}
|
||||
|
||||
public float LayoutX
|
||||
{
|
||||
get { return layout.position[POSITION_LEFT]; }
|
||||
}
|
||||
|
||||
public float LayoutY
|
||||
{
|
||||
get { return layout.position[POSITION_TOP]; }
|
||||
}
|
||||
|
||||
public float LayoutWidth
|
||||
{
|
||||
get { return layout.dimensions[DIMENSION_WIDTH]; }
|
||||
}
|
||||
|
||||
public float LayoutHeight
|
||||
{
|
||||
get { return layout.dimensions[DIMENSION_HEIGHT]; }
|
||||
}
|
||||
|
||||
public CSSDirection LayoutDirection
|
||||
{
|
||||
get { return layout.direction; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a default padding (left/top/right/bottom) for this node.
|
||||
*/
|
||||
public void SetDefaultPadding(CSSSpacingType spacingType, float padding)
|
||||
{
|
||||
if (style.padding.setDefault((int)spacingType, padding))
|
||||
dirty();
|
||||
}
|
||||
|
||||
void updateDiscreteValue<ValueT>(ref ValueT valueRef, ValueT newValue)
|
||||
{
|
||||
if (valuesEqual(valueRef, newValue))
|
||||
return;
|
||||
|
||||
valueRef = newValue;
|
||||
dirty();
|
||||
}
|
||||
|
||||
void updateFloatValue(ref float valueRef, float newValue)
|
||||
{
|
||||
if (valuesEqual(valueRef, newValue))
|
||||
return;
|
||||
valueRef = newValue;
|
||||
dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CSSNodeExtensions
|
||||
{
|
||||
/*
|
||||
Explicitly mark this node as dirty.
|
||||
|
||||
Calling this function is required when the measure function points to the same instance,
|
||||
but changes its behavior.
|
||||
|
||||
For all other property changes, the node is automatically marked dirty.
|
||||
*/
|
||||
|
||||
public static void MarkDirty(this CSSNode node)
|
||||
{
|
||||
node.dirty();
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CSSNodeExtensionsInternal
|
||||
{
|
||||
public static CSSNode getParent(this CSSNode node)
|
||||
{
|
||||
return node.Parent;
|
||||
}
|
||||
|
||||
public static int getChildCount(this CSSNode node)
|
||||
{
|
||||
return node.ChildCount;
|
||||
}
|
||||
|
||||
public static CSSNode getChildAt(this CSSNode node, int i)
|
||||
{
|
||||
return node[i];
|
||||
}
|
||||
|
||||
public static void addChildAt(this CSSNode node, CSSNode child, int i)
|
||||
{
|
||||
node.InsertChild(i, child);
|
||||
}
|
||||
|
||||
public static void removeChildAt(this CSSNode node, int i)
|
||||
{
|
||||
node.RemoveChildAt(i);
|
||||
}
|
||||
|
||||
public static void setMeasureFunction(this CSSNode node, MeasureFunction measureFunction)
|
||||
{
|
||||
node.MeasureFunction = measureFunction;
|
||||
}
|
||||
|
||||
public static void setIsTextNode(this CSSNode node, bool isTextNode)
|
||||
{
|
||||
node.IsTextNode = isTextNode;
|
||||
}
|
||||
|
||||
public static void calculateLayout(this CSSNode node)
|
||||
{
|
||||
node.CalculateLayout();
|
||||
}
|
||||
|
||||
public static bool isDirty(this CSSNode node)
|
||||
{
|
||||
return node.IsDirty;
|
||||
}
|
||||
|
||||
public static void setMargin(this CSSNode node, int spacingType, float margin)
|
||||
{
|
||||
node.SetMargin((CSSSpacingType)spacingType, margin);
|
||||
}
|
||||
|
||||
public static void setPadding(this CSSNode node, int spacingType, float padding)
|
||||
{
|
||||
node.SetPadding((CSSSpacingType)spacingType, padding);
|
||||
}
|
||||
|
||||
public static void setBorder(this CSSNode node, int spacingType, float border)
|
||||
{
|
||||
node.SetBorder((CSSSpacingType)spacingType, border);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSOverflow
|
||||
{
|
||||
Visible,
|
||||
Hidden
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSPositionType
|
||||
{
|
||||
Relative,
|
||||
Absolute
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSSpacingType
|
||||
{
|
||||
Left = 0,
|
||||
Top = 1,
|
||||
Right = 2,
|
||||
Bottom = 3,
|
||||
Vertical = 4,
|
||||
Horizontal = 5,
|
||||
Start = 6,
|
||||
End = 7,
|
||||
All = 8
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* The CSS style definition for a {@link CSSNode}.
|
||||
*/
|
||||
sealed class CSSStyle
|
||||
{
|
||||
public CSSDirection direction = CSSDirection.Inherit;
|
||||
public CSSFlexDirection flexDirection = CSSFlexDirection.Column;
|
||||
public CSSJustify justifyContent = CSSJustify.FlexStart;
|
||||
public CSSAlign alignContent = CSSAlign.FlexStart;
|
||||
public CSSAlign alignItems = CSSAlign.Stretch;
|
||||
public CSSAlign alignSelf = CSSAlign.Auto;
|
||||
public CSSPositionType positionType = CSSPositionType.Relative;
|
||||
public CSSWrap flexWrap = CSSWrap.NoWrap;
|
||||
public CSSOverflow overflow = CSSOverflow.Visible;
|
||||
public float flex;
|
||||
|
||||
public Spacing margin = new Spacing();
|
||||
public Spacing padding = new Spacing();
|
||||
public Spacing border = new Spacing();
|
||||
|
||||
public float[] position = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public float[] dimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public float minWidth = CSSConstants.Undefined;
|
||||
public float minHeight = CSSConstants.Undefined;
|
||||
|
||||
public float maxWidth = CSSConstants.Undefined;
|
||||
public float maxHeight = CSSConstants.Undefined;
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSWrap
|
||||
{
|
||||
NoWrap,
|
||||
Wrap
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* CSSLayout with additional information about the conditions under which it was generated.
|
||||
* {@link #RequestedWidth} and {@link #RequestedHeight} are the width and height the parent set on
|
||||
* this node before calling layout visited us.
|
||||
*/
|
||||
|
||||
class CachedCSSLayout : CSSLayout
|
||||
{
|
||||
public float requestedWidth = CSSConstants.Undefined;
|
||||
public float requestedHeight = CSSConstants.Undefined;
|
||||
public float parentMaxWidth = CSSConstants.Undefined;
|
||||
public float parentMaxHeight = CSSConstants.Undefined;
|
||||
}
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Facebook.CSSLayout</RootNamespace>
|
||||
<AssemblyName>Facebook.CSSLayout</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assertions.cs" />
|
||||
<Compile Include="CachedCSSLayout.cs" />
|
||||
<Compile Include="CSSAlign.cs" />
|
||||
<Compile Include="CSSCachedMeasurement.cs" />
|
||||
<Compile Include="CSSConstants.cs" />
|
||||
<Compile Include="CSSDirection.cs" />
|
||||
<Compile Include="CSSFlexDirection.cs" />
|
||||
<Compile Include="CSSJustify.cs" />
|
||||
<Compile Include="CSSLayout.cs" />
|
||||
<Compile Include="CSSLayoutContext.cs" />
|
||||
<Compile Include="CSSMeasureMode.cs" />
|
||||
<Compile Include="CSSNode.cs" />
|
||||
<Compile Include="CSSOverflow.cs" />
|
||||
<Compile Include="CSSPositionType.cs" />
|
||||
<Compile Include="CSSStyle.cs" />
|
||||
<Compile Include="CSSWrap.cs" />
|
||||
<Compile Include="FloatUtil.cs" />
|
||||
<Compile Include="LayoutEngine.cs" />
|
||||
<Compile Include="MeasureOutput.cs" />
|
||||
<Compile Include="NullableAttribute.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Spacing.cs" />
|
||||
<Compile Include="CSSSpacingType.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>$id$</id>
|
||||
<version>$version$</version>
|
||||
<title>$title$</title>
|
||||
<authors>$author$</authors>
|
||||
<owners>$author$</owners>
|
||||
<licenseUrl>https://github.com/facebook/css-layout/blob/master/LICENSE</licenseUrl>
|
||||
<projectUrl>https://github.com/facebook/css-layout</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>$description$</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright 2015 Facebook</copyright>
|
||||
<tags>flexbox flex-box css layout css-layout facebook</tags>
|
||||
</metadata>
|
||||
</package>
|
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
static class FloatUtil
|
||||
{
|
||||
const float Epsilon = .00001f;
|
||||
|
||||
public static bool floatsEqual(float f1, float f2)
|
||||
{
|
||||
if (float.IsNaN(f1) || float.IsNaN(f2))
|
||||
{
|
||||
return float.IsNaN(f1) && float.IsNaN(f2);
|
||||
}
|
||||
return Math.Abs(f2 - f1) < Epsilon;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* POJO to hold the output of the measure function.
|
||||
*/
|
||||
public struct MeasureOutput
|
||||
{
|
||||
public MeasureOutput(float width, float height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public readonly float Width;
|
||||
public readonly float Height;
|
||||
|
||||
internal float width
|
||||
{
|
||||
get { return Width; }
|
||||
}
|
||||
|
||||
internal float height
|
||||
{
|
||||
get { return Height; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* This is here to preserve the @nullable attribute of the original Java API.
|
||||
*/
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.Parameter)]
|
||||
sealed class NullableAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyTitle("Facebook.CSSLayout")]
|
||||
[assembly: AssemblyDescription("A subset of CSS's flexbox layout algorithm and box model.")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Facebook")]
|
||||
[assembly: AssemblyProduct("Facebook.CSSLayout")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015 Facebook")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Facebook.CSSLayout.Tests")]
|
@@ -1,234 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to
|
||||
* properly implement interactions and updates for properties like margin, marginLeft, and
|
||||
* marginHorizontal.
|
||||
*/
|
||||
|
||||
sealed class Spacing
|
||||
{
|
||||
/**
|
||||
* Spacing type that represents the left direction. E.g. {@code marginLeft}.
|
||||
*/
|
||||
internal const int LEFT = (int)CSSSpacingType.Left;
|
||||
/**
|
||||
* Spacing type that represents the top direction. E.g. {@code marginTop}.
|
||||
*/
|
||||
internal const int TOP = (int)CSSSpacingType.Top;
|
||||
/**
|
||||
* Spacing type that represents the right direction. E.g. {@code marginRight}.
|
||||
*/
|
||||
internal const int RIGHT = (int)CSSSpacingType.Right;
|
||||
/**
|
||||
* Spacing type that represents the bottom direction. E.g. {@code marginBottom}.
|
||||
*/
|
||||
internal const int BOTTOM = (int)CSSSpacingType.Bottom;
|
||||
/**
|
||||
* Spacing type that represents vertical direction (top and bottom). E.g. {@code marginVertical}.
|
||||
*/
|
||||
internal const int VERTICAL = (int)CSSSpacingType.Vertical;
|
||||
/**
|
||||
* Spacing type that represents horizontal direction (left and right). E.g.
|
||||
* {@code marginHorizontal}.
|
||||
*/
|
||||
internal const int HORIZONTAL = (int)CSSSpacingType.Horizontal;
|
||||
/**
|
||||
* Spacing type that represents start direction e.g. left in left-to-right, right in right-to-left.
|
||||
*/
|
||||
internal const int START = (int)CSSSpacingType.Start;
|
||||
/**
|
||||
* Spacing type that represents end direction e.g. right in left-to-right, left in right-to-left.
|
||||
*/
|
||||
internal const int END = (int)CSSSpacingType.End;
|
||||
/**
|
||||
* Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}.
|
||||
*/
|
||||
internal const int ALL = (int)CSSSpacingType.All;
|
||||
|
||||
static readonly int[] sFlagsMap = {
|
||||
1, /*LEFT*/
|
||||
2, /*TOP*/
|
||||
4, /*RIGHT*/
|
||||
8, /*BOTTOM*/
|
||||
16, /*VERTICAL*/
|
||||
32, /*HORIZONTAL*/
|
||||
64, /*START*/
|
||||
128, /*END*/
|
||||
256 /*ALL*/
|
||||
};
|
||||
|
||||
float[] mSpacing = newFullSpacingArray();
|
||||
[Nullable] float[] mDefaultSpacing = null;
|
||||
int mValueFlags = 0;
|
||||
bool mHasAliasesSet;
|
||||
|
||||
/**
|
||||
* Set a spacing value.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
|
||||
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
|
||||
* @param value the value for this direction
|
||||
* @return {@code true} if the spacing has changed, or {@code false} if the same value was already
|
||||
* set
|
||||
*/
|
||||
|
||||
internal bool set(int spacingType, float value)
|
||||
{
|
||||
if (!FloatUtil.floatsEqual(mSpacing[spacingType], value))
|
||||
{
|
||||
mSpacing[spacingType] = value;
|
||||
|
||||
if (CSSConstants.IsUndefined(value))
|
||||
{
|
||||
mValueFlags &= ~sFlagsMap[spacingType];
|
||||
}
|
||||
else
|
||||
{
|
||||
mValueFlags |= sFlagsMap[spacingType];
|
||||
}
|
||||
|
||||
mHasAliasesSet =
|
||||
(mValueFlags & sFlagsMap[ALL]) != 0 ||
|
||||
(mValueFlags & sFlagsMap[VERTICAL]) != 0 ||
|
||||
(mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a default spacing value. This is used as a fallback when no spacing has been set for a
|
||||
* particular direction.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
|
||||
* @param value the default value for this direction
|
||||
* @return
|
||||
*/
|
||||
|
||||
internal bool setDefault(int spacingType, float value)
|
||||
{
|
||||
if (mDefaultSpacing == null)
|
||||
mDefaultSpacing = newSpacingResultArray();
|
||||
|
||||
if (!FloatUtil.floatsEqual(mDefaultSpacing[spacingType], value))
|
||||
{
|
||||
mDefaultSpacing[spacingType] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spacing for a direction. This takes into account any default values that have been set.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
|
||||
*/
|
||||
|
||||
internal float get(int spacingType)
|
||||
{
|
||||
float defaultValue =
|
||||
(mDefaultSpacing != null)
|
||||
? mDefaultSpacing[spacingType]
|
||||
: (spacingType == START || spacingType == END ? CSSConstants.Undefined : 0);
|
||||
|
||||
if (mValueFlags == 0)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if ((mValueFlags & sFlagsMap[spacingType]) != 0)
|
||||
{
|
||||
return mSpacing[spacingType];
|
||||
}
|
||||
|
||||
if (mHasAliasesSet)
|
||||
{
|
||||
int secondType = spacingType == TOP || spacingType == BOTTOM ? VERTICAL : HORIZONTAL;
|
||||
if ((mValueFlags & sFlagsMap[secondType]) != 0)
|
||||
{
|
||||
return mSpacing[secondType];
|
||||
}
|
||||
else if ((mValueFlags & sFlagsMap[ALL]) != 0)
|
||||
{
|
||||
return mSpacing[ALL];
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw value (that was set using {@link #set(int, float)}), without taking into account
|
||||
* any default values.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
|
||||
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
|
||||
*/
|
||||
|
||||
internal float getRaw(int spacingType)
|
||||
{
|
||||
return mSpacing[spacingType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get start value and fallback to given type if not defined. This is used privately
|
||||
* by the layout engine as a more efficient way to fetch direction-aware values by
|
||||
* avoid extra method invocations.
|
||||
*/
|
||||
internal float getWithFallback(int spacingType, int fallbackType)
|
||||
{
|
||||
return
|
||||
(mValueFlags & sFlagsMap[spacingType]) != 0
|
||||
? mSpacing[spacingType]
|
||||
: get(fallbackType);
|
||||
}
|
||||
|
||||
static float[] newFullSpacingArray()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
}
|
||||
|
||||
static float[] newSpacingResultArray()
|
||||
{
|
||||
return newSpacingResultArray(0);
|
||||
}
|
||||
|
||||
static float[] newSpacingResultArray(float defaultValue)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
defaultValue
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
MSB=msbuild.exe /m /verbosity:m /nologo
|
||||
NUGET=nuget.exe
|
||||
NUNITC=nunit-console.exe
|
||||
|
||||
VER=1.0.0
|
||||
NAME=Facebook.CSSLayout
|
||||
|
||||
.PHONY: all
|
||||
all: test
|
||||
|
||||
.PHONY: distribute
|
||||
distribute: package release-package
|
||||
|
||||
.PHONY: package
|
||||
package: conf=Release
|
||||
package: build
|
||||
cd ${NAME} && ${NUGET} pack ${NAME}.csproj -Version ${VER} -Prop Configuration=${conf}
|
||||
|
||||
.PHONY: release-package
|
||||
release-package:
|
||||
cd ${NAME} && nuget push ${NAME}.${VER}.nupkg
|
||||
|
||||
.PHONY: test
|
||||
test: build-debug
|
||||
cd ${NAME}.Tests/bin/Debug && ${NUNITC} Facebook.CSSLayout.Tests.dll
|
||||
|
||||
.PHONY: build-debug
|
||||
build-debug: conf=Debug
|
||||
build-debug: build
|
||||
|
||||
.PHONY: build-release
|
||||
build-release: conf=Release
|
||||
build-release: build
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
${MSB} ${NAME}.sln /p:Configuration=${conf} /t:"Facebook_CSSLayout:Rebuild;Facebook_CSSLayout_Tests:Rebuild"
|
@@ -1,29 +0,0 @@
|
||||
// UMD (Universal Module Definition)
|
||||
// See https://github.com/umdjs/umd for reference
|
||||
//
|
||||
// This file uses the following specific UMD implementation:
|
||||
// https://github.com/umdjs/umd/blob/master/templates/returnExports.js
|
||||
(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.computeLayout = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
// @@include('./Layout.js')
|
||||
|
||||
return function(node) {
|
||||
/*eslint-disable */
|
||||
// disabling ESLint because this code relies on the above include
|
||||
computeLayout.fillNodes(node);
|
||||
computeLayout.computeLayout(node);
|
||||
/*eslint-enable */
|
||||
};
|
||||
}));
|
1
java/java/.idea/.name
generated
1
java/java/.idea/.name
generated
@@ -1 +0,0 @@
|
||||
css-layout
|
23
java/java/.idea/compiler.xml
generated
23
java/java/.idea/compiler.xml
generated
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
|
5
java/java/.idea/copyright/profiles_settings.xml
generated
5
java/java/.idea/copyright/profiles_settings.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="">
|
||||
<module2copyright />
|
||||
</settings>
|
||||
</component>
|
5
java/java/.idea/encodings.xml
generated
5
java/java/.idea/encodings.xml
generated
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
10
java/java/.idea/misc.xml
generated
10
java/java/.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
9
java/java/.idea/modules.xml
generated
9
java/java/.idea/modules.xml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/java.iml" filepath="$PROJECT_DIR$/java.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
5
java/java/.idea/scopes/scope_settings.xml
generated
5
java/java/.idea/scopes/scope_settings.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
125
java/java/.idea/uiDesigner.xml
generated
125
java/java/.idea/uiDesigner.xml
generated
@@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
|
7
java/java/.idea/vcs.xml
generated
7
java/java/.idea/vcs.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
</component>
|
||||
</project>
|
||||
|
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Tests for {@link CSSNode}.
|
||||
*/
|
||||
public class CSSNodeTest {
|
||||
|
||||
@Test
|
||||
public void testAddChildGetParent() {
|
||||
CSSNode parent = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
assertNull(child.getParent());
|
||||
assertEquals(0, parent.getChildCount());
|
||||
|
||||
parent.addChildAt(child, 0);
|
||||
|
||||
assertEquals(1, parent.getChildCount());
|
||||
assertEquals(child, parent.getChildAt(0));
|
||||
assertEquals(parent, child.getParent());
|
||||
|
||||
parent.removeChildAt(0);
|
||||
|
||||
assertNull(child.getParent());
|
||||
assertEquals(0, parent.getChildCount());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testCannotAddChildToMultipleParents() {
|
||||
CSSNode parent1 = new CSSNode();
|
||||
CSSNode parent2 = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
parent1.addChildAt(child, 0);
|
||||
parent2.addChildAt(child, 0);
|
||||
}
|
||||
}
|
@@ -1,240 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link LayoutEngine} and {@link CSSNode} to make sure layouts are only generated when
|
||||
* needed.
|
||||
*/
|
||||
public class LayoutCachingTest {
|
||||
|
||||
private void assertTreeHasNewLayout(boolean expectedHasNewLayout, CSSNode root) {
|
||||
assertEquals(expectedHasNewLayout, root.hasNewLayout());
|
||||
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
assertTreeHasNewLayout(expectedHasNewLayout, root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void markLayoutAppliedForTree(CSSNode root) {
|
||||
root.markLayoutSeen();
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
markLayoutAppliedForTree(root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachesFullTree() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
assertTreeHasNewLayout(true, root);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatesCacheWhenChildAdded() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c0c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
c0c1.setStyleWidth(200);
|
||||
c0c1.setStyleHeight(200);
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c0c0.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.addChildAt(c0c1, 1);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertTrue(c0c1.hasNewLayout());
|
||||
|
||||
assertTrue(c0c0.hasNewLayout());
|
||||
assertTrue(c1.hasNewLayout());
|
||||
|
||||
assertTrue(c1c0.hasNewLayout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatesCacheWhenEnumPropertyChanges() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.setAlignSelf(CSSAlign.CENTER);
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c1.hasNewLayout());
|
||||
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertFalse(c0c0.hasNewLayout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatesCacheWhenFloatPropertyChanges() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.setMargin(Spacing.LEFT, 10);
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c1.hasNewLayout());
|
||||
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertTrue(c0c0.hasNewLayout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatesFullTreeWhenParentWidthChanges() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.setStyleWidth(200);
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertTrue(c0c0.hasNewLayout());
|
||||
|
||||
assertTrue(c1.hasNewLayout());
|
||||
assertTrue(c1c0.hasNewLayout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotInvalidateCacheWhenPropertyIsTheSame() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
root.setStyleWidth(200);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.setStyleWidth(200);
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidateCacheWhenHeightChangesPosition() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.setStyleHeight(100);
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertTrue(c1.hasNewLayout());
|
||||
assertFalse(c1c0.hasNewLayout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidatesOnNewMeasureFunction() {
|
||||
CSSLayoutContext layoutContext = new CSSLayoutContext();
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.setMeasureFunction(new CSSNode.MeasureFunction() {
|
||||
@Override
|
||||
public void measure(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode, MeasureOutput measureOutput) {
|
||||
measureOutput.width = 100;
|
||||
measureOutput.height = 20;
|
||||
}
|
||||
});
|
||||
|
||||
root.calculateLayout(layoutContext);
|
||||
|
||||
assertTrue(root.hasNewLayout());
|
||||
assertTrue(c1.hasNewLayout());
|
||||
|
||||
assertTrue(c0.hasNewLayout());
|
||||
assertTrue(c0c0.hasNewLayout());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Generated constants used in {@link LayoutEngineTest}.
|
||||
*/
|
||||
public class TestConstants {
|
||||
|
||||
/** START_GENERATED **/
|
||||
public static final float SMALL_WIDTH = 35f;
|
||||
public static final float SMALL_HEIGHT = 18f;
|
||||
public static final float BIG_WIDTH = 172f;
|
||||
public static final float BIG_HEIGHT = 36f;
|
||||
public static final float BIG_MIN_WIDTH = 100f;
|
||||
public static final String SMALL_TEXT = "small";
|
||||
public static final String LONG_TEXT = "loooooooooong with space";
|
||||
public static final String MEASURE_WITH_RATIO_2 = "measureWithRatio2";
|
||||
public static final String MEASURE_WITH_MATCH_PARENT = "measureWithMatchParent";
|
||||
/** END_GENERATED **/
|
||||
}
|
@@ -1,349 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var layoutTestUtils = require('./Layout-test-utils.js');
|
||||
var computeLayout = require('./Layout.js').layoutNodeImpl;
|
||||
var fs = require('fs');
|
||||
var JavaTranspiler = require('./JavaTranspiler.js');
|
||||
var CSharpTranspiler = require('./CSharpTranspiler.js');
|
||||
|
||||
var currentTest = '';
|
||||
var allTests = [];
|
||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
||||
var reduceTest = layoutTestUtils.reduceTest;
|
||||
global.layoutTestUtils = {
|
||||
testLayout: function(node, expectedLayout) {
|
||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||
},
|
||||
testLayoutAgainstDomOnly: function() {
|
||||
},
|
||||
testRandomLayout: function(node, i) {
|
||||
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
||||
},
|
||||
testLayoutAgainstExpectedOnly: function(node, expectedLayout) {
|
||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||
},
|
||||
computeLayout: layoutTestUtils.computeLayout,
|
||||
reduceTest: reduceTest,
|
||||
text: layoutTestUtils.text,
|
||||
texts: layoutTestUtils.texts,
|
||||
textSizes: layoutTestUtils.textSizes,
|
||||
measureWithRatio2: layoutTestUtils.measureWithRatio2,
|
||||
measureWithMatchParent: layoutTestUtils.measureWithMatchParent
|
||||
};
|
||||
|
||||
global.describe = function(name, cb) {
|
||||
if (name.toLowerCase().indexOf('javascript only') === -1) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
global.it = function(name, cb) { currentTest = name; cb(); };
|
||||
global.xit = function() { /* ignore skipped tests */ };
|
||||
|
||||
require('./__tests__/Layout-test.js');
|
||||
|
||||
|
||||
function printLayout(test) {
|
||||
var level = 1;
|
||||
var res = [];
|
||||
|
||||
function indent(level) {
|
||||
var result = '';
|
||||
for (var i = 0; i < level; ++i) {
|
||||
result += ' ';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function add(str) {
|
||||
if (str.length > 0) {
|
||||
str = indent(level) + str;
|
||||
}
|
||||
res.push(str);
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
return !Object.keys(obj).length;
|
||||
}
|
||||
|
||||
add('{');
|
||||
level++;
|
||||
|
||||
// Output the style node
|
||||
add('css_node_t *root_node = new_test_css_node();');
|
||||
add('{');
|
||||
level++;
|
||||
if (!isEmpty(test.node.style) || test.node.children && test.node.children.length) {
|
||||
add('css_node_t *node_0 = root_node;');
|
||||
}
|
||||
function recStyle(node) {
|
||||
|
||||
function addStyle(str) {
|
||||
add('node_' + (level - 3) + '->style.' + str);
|
||||
}
|
||||
|
||||
function addEnum(node, jsKey, cKey, dict) {
|
||||
if (jsKey in node.style) {
|
||||
addStyle(cKey + ' = ' + dict[node.style[jsKey]] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
function addFloat(node, jsKey, cKey) {
|
||||
if (jsKey in node.style) {
|
||||
addStyle(cKey + ' = ' + node.style[jsKey] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
function addSpacing(node, spacing, suffix) {
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_LEFT]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_TOP]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_RIGHT]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_BOTTOM]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_START]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_END]');
|
||||
|
||||
addFloat(node, spacing + 'Left' + suffix, spacing + '[CSS_LEFT]');
|
||||
addFloat(node, spacing + 'Top' + suffix, spacing + '[CSS_TOP]');
|
||||
addFloat(node, spacing + 'Right' + suffix, spacing + '[CSS_RIGHT]');
|
||||
addFloat(node, spacing + 'Bottom' + suffix, spacing + '[CSS_BOTTOM]');
|
||||
addFloat(node, spacing + 'Start' + suffix, spacing + '[CSS_START]');
|
||||
addFloat(node, spacing + 'End' + suffix, spacing + '[CSS_END]');
|
||||
}
|
||||
|
||||
function addMeasure(node) {
|
||||
if ('measure' in node.style) {
|
||||
if (node.children && node.children.length) {
|
||||
throw new Error('Using custom measure function is supported only for leaf nodes.');
|
||||
}
|
||||
add('node_' + (level - 3) + '->measure = measure;');
|
||||
add('node_' + (level - 3) + '->context = "' + node.style.measure.toString() + '";');
|
||||
}
|
||||
}
|
||||
|
||||
addEnum(node, 'direction', 'direction', {
|
||||
'ltr': 'CSS_DIRECTION_LTR',
|
||||
'rtl': 'CSS_DIRECTION_RTL'
|
||||
});
|
||||
addEnum(node, 'flexDirection', 'flex_direction', {
|
||||
'row': 'CSS_FLEX_DIRECTION_ROW',
|
||||
'row-reverse': 'CSS_FLEX_DIRECTION_ROW_REVERSE',
|
||||
'column': 'CSS_FLEX_DIRECTION_COLUMN',
|
||||
'column-reverse': 'CSS_FLEX_DIRECTION_COLUMN_REVERSE'
|
||||
});
|
||||
addEnum(node, 'justifyContent', 'justify_content', {
|
||||
'flex-start': 'CSS_JUSTIFY_FLEX_START',
|
||||
'center': 'CSS_JUSTIFY_CENTER',
|
||||
'flex-end': 'CSS_JUSTIFY_FLEX_END',
|
||||
'space-between': 'CSS_JUSTIFY_SPACE_BETWEEN',
|
||||
'space-around': 'CSS_JUSTIFY_SPACE_AROUND'
|
||||
});
|
||||
addEnum(node, 'alignContent', 'align_content', {
|
||||
'flex-start': 'CSS_ALIGN_FLEX_START',
|
||||
'center': 'CSS_ALIGN_CENTER',
|
||||
'flex-end': 'CSS_ALIGN_FLEX_END',
|
||||
'stretch': 'CSS_ALIGN_STRETCH'
|
||||
});
|
||||
addEnum(node, 'alignItems', 'align_items', {
|
||||
'flex-start': 'CSS_ALIGN_FLEX_START',
|
||||
'center': 'CSS_ALIGN_CENTER',
|
||||
'flex-end': 'CSS_ALIGN_FLEX_END',
|
||||
'stretch': 'CSS_ALIGN_STRETCH'
|
||||
});
|
||||
addEnum(node, 'alignSelf', 'align_self', {
|
||||
'flex-start': 'CSS_ALIGN_FLEX_START',
|
||||
'center': 'CSS_ALIGN_CENTER',
|
||||
'flex-end': 'CSS_ALIGN_FLEX_END',
|
||||
'stretch': 'CSS_ALIGN_STRETCH'
|
||||
});
|
||||
addEnum(node, 'position', 'position_type', {
|
||||
'relative': 'CSS_POSITION_RELATIVE',
|
||||
'absolute': 'CSS_POSITION_ABSOLUTE'
|
||||
});
|
||||
addEnum(node, 'flexWrap', 'flex_wrap', {
|
||||
'nowrap': 'CSS_NOWRAP',
|
||||
'wrap': 'CSS_WRAP'
|
||||
});
|
||||
addEnum(node, 'measureMode', 'measure_mode', {
|
||||
'undefined': 'CSS_MEASURE_MODE_UNDEFINED',
|
||||
'exactly': 'CSS_MEASURE_MODE_EXACTLY',
|
||||
'at-most': 'CSS_MEASURE_MODE_AT_MOST'
|
||||
});
|
||||
addEnum(node, 'overflow', 'overflow', {
|
||||
'visible': 'CSS_OVERFLOW_VISIBLE',
|
||||
'hidden': 'CSS_OVERFLOW_HIDDEN'
|
||||
});
|
||||
addFloat(node, 'flex', 'flex');
|
||||
addFloat(node, 'width', 'dimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'height', 'dimensions[CSS_HEIGHT]');
|
||||
addFloat(node, 'maxWidth', 'maxDimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'maxHeight', 'maxDimensions[CSS_HEIGHT]');
|
||||
addFloat(node, 'minWidth', 'minDimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'minHeight', 'minDimensions[CSS_HEIGHT]');
|
||||
addSpacing(node, 'margin', '');
|
||||
addSpacing(node, 'padding', '');
|
||||
addSpacing(node, 'border', 'Width');
|
||||
addFloat(node, 'left', 'position[CSS_LEFT]');
|
||||
addFloat(node, 'top', 'position[CSS_TOP]');
|
||||
addFloat(node, 'right', 'position[CSS_RIGHT]');
|
||||
addFloat(node, 'bottom', 'position[CSS_BOTTOM]');
|
||||
addMeasure(node);
|
||||
|
||||
if (node.children) {
|
||||
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_' + (level - 3) + ';');
|
||||
|
||||
for (var i = 0; i < node.children.length; ++i) {
|
||||
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
||||
recStyle(node.children[i]);
|
||||
}
|
||||
|
||||
level--;
|
||||
add('}');
|
||||
}
|
||||
}
|
||||
recStyle(test.node);
|
||||
level--;
|
||||
add('}');
|
||||
add('');
|
||||
|
||||
// Output the expected layout node
|
||||
add('css_node_t *root_layout = new_test_css_node();');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_0 = root_layout;');
|
||||
|
||||
function recLayout(node) {
|
||||
function addLayout(str) {
|
||||
add('node_' + (level - 3) + '->layout.' + str);
|
||||
}
|
||||
|
||||
addLayout('position[CSS_TOP] = ' + node.top + ';');
|
||||
addLayout('position[CSS_LEFT] = ' + node.left + ';');
|
||||
addLayout('dimensions[CSS_WIDTH] = ' + node.width + ';');
|
||||
addLayout('dimensions[CSS_HEIGHT] = ' + node.height + ';');
|
||||
|
||||
if (node.children) {
|
||||
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_' + (level - 3) + ';');
|
||||
|
||||
for (var i = 0; i < node.children.length; ++i) {
|
||||
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
||||
recLayout(node.children[i]);
|
||||
}
|
||||
|
||||
level--;
|
||||
add('}');
|
||||
}
|
||||
}
|
||||
recLayout(test.expectedLayout);
|
||||
level--;
|
||||
add('}');
|
||||
add('');
|
||||
|
||||
// Do the test
|
||||
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
||||
level--;
|
||||
add('}');
|
||||
return res.join('\n');
|
||||
}
|
||||
|
||||
function transpileAnnotatedJStoC(jsCode) {
|
||||
return jsCode
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/undefined/g, 'NULL')
|
||||
.replace(/\.children\.length/g, '.children_count')
|
||||
.replace(/\.width/g, '.dimensions[CSS_WIDTH]')
|
||||
.replace(/\.height/g, '.dimensions[CSS_HEIGHT]')
|
||||
.replace(/\.maxWidth/g, '.maxDimensions[CSS_WIDTH]')
|
||||
.replace(/\.maxHeight/g, '.maxDimensions[CSS_HEIGHT]')
|
||||
.replace(/\.minWidth/g, '.minDimensions[CSS_WIDTH]')
|
||||
.replace(/\.minHeight/g, '.minDimensions[CSS_HEIGHT]')
|
||||
.replace(/\.lineIndex/g, '.line_index')
|
||||
.replace(/\.nextChild/g, '.next_child')
|
||||
.replace(/\.flexBasis/g, '.flex_basis')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measured_dimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measured_dimensions[CSS_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measured_dimensions[CSS_HEIGHT]')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[CSS_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[CSS_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[CSS_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[CSS_BOTTOM')
|
||||
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
||||
.replace(/node.children\[j\]/g, 'node->get_child(node->context, j)')
|
||||
.replace(/node\./g, 'node->')
|
||||
.replace(/child\./g, 'child->')
|
||||
.replace(/currentAbsoluteChild\./g, 'currentAbsoluteChild->')
|
||||
.replace(/currentRelativeChild\./g, 'currentRelativeChild->')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1->style.position_type')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1->style.justify_content')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1->style.align_content')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\);/g, 'assert($1); // $2')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1->style.overflow')
|
||||
.replace(/var\/\*\(c\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '');
|
||||
}
|
||||
|
||||
function makeConstDefs() {
|
||||
var lines = [
|
||||
'#define SMALL_WIDTH ' + layoutTestUtils.textSizes.smallWidth,
|
||||
'#define SMALL_HEIGHT ' + layoutTestUtils.textSizes.smallHeight,
|
||||
'#define BIG_WIDTH ' + layoutTestUtils.textSizes.bigWidth,
|
||||
'#define BIG_HEIGHT ' + layoutTestUtils.textSizes.bigHeight,
|
||||
'#define BIG_MIN_WIDTH ' + layoutTestUtils.textSizes.bigMinWidth,
|
||||
'#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"',
|
||||
'#define LONG_TEXT "' + layoutTestUtils.texts.big + '"',
|
||||
'#define MEASURE_WITH_RATIO_2 "' + layoutTestUtils.measureWithRatio2() + '"',
|
||||
'#define MEASURE_WITH_MATCH_PARENT "' + layoutTestUtils.measureWithMatchParent() + '"'
|
||||
];
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function generateFile(fileName, generatedContent) {
|
||||
var content = fs.readFileSync(fileName, 'utf8').toString();
|
||||
content = content.replace(new RegExp(
|
||||
/\/\*\* START_GENERATED \*\*\/[\s\S]*\/\*\* END_GENERATED \*\*\//
|
||||
), '/** START_GENERATED **/\n' + generatedContent + '\n /** END_GENERATED **/');
|
||||
|
||||
fs.writeFileSync(fileName, content);
|
||||
}
|
||||
|
||||
// Extract the function body by trimming the first ('function layoutNode(...) {') and
|
||||
// last ('}') lines. Also, start the function body with a blank line so that regexes
|
||||
// that use \n to match the start of a line will match the actual first line.
|
||||
var computeLayoutCode = [''].concat(computeLayout.toString().split('\n').slice(1, -1)).join('\n');
|
||||
|
||||
var allTestsInC = allTests.map(printLayout);
|
||||
generateFile(__dirname + '/__tests__/Layout-test.c', allTestsInC.join('\n\n'));
|
||||
generateFile(__dirname + '/Layout-test-utils.c', makeConstDefs());
|
||||
generateFile(__dirname + '/Layout.c', transpileAnnotatedJStoC(computeLayoutCode));
|
||||
generateFile(__dirname + '/java/src/com/facebook/csslayout/LayoutEngine.java', JavaTranspiler.transpileLayoutEngine(computeLayoutCode));
|
||||
generateFile(__dirname + '/java/tests/com/facebook/csslayout/TestConstants.java', JavaTranspiler.transpileCConstDefs(makeConstDefs()));
|
||||
generateFile(__dirname + '/java/tests/com/facebook/csslayout/LayoutEngineTest.java', JavaTranspiler.transpileCTestsArray(allTestsInC));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout/LayoutEngine.cs', CSharpTranspiler.transpileLayoutEngine(computeLayoutCode));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout.Tests/TestConstants.cs', CSharpTranspiler.transpileCConstDefs(makeConstDefs()));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs', CSharpTranspiler.transpileCTestsArray(allTestsInC));
|
Reference in New Issue
Block a user