flex-wrap: wrap-reverse support

Summary:
I couldn't resist to do this 😄 #394

This adds ```flex-wrap: wrap-reverse```

I think we hit a edge case here:
https://stackoverflow.com/questions/33891709/when-flexbox-items-wrap-in-column-mode-container-does-not-grow-its-width

as is differs here from chrome, but I think that yoga is here more correct.

So I haven't added this test yet as this would fail against chrome, as chrome outputs a width of 30 for root, whereas yoga gets a width of 60 here, which I think is correct. Strangely the output of ```flex-wrap:wrap``` is in jsfiddle also only with a (visual) width of 30 on chrome, while the tests gets generated with 60.

```html
<div id="wrap_reverse_column" style="height: 100px; flex-wrap: wrap-reverse">
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
  <div style="height: 30px; width: 30px;"></div>
</div>
```

Looking forward what you think here emilsjolander
Closes https://github.com/facebook/yoga/pull/398

Reviewed By: astreet

Differential Revision: D4564711

Pulled By: emilsjolander

fbshipit-source-id: 33dc055abd8444b2aa7796ef90bd7ec99e961bb8
This commit is contained in:
Lukas Wöhrl 2017-02-15 13:35:24 -08:00 committed by Facebook Github Bot
parent d768309367
commit 30f8380095
3 changed files with 24 additions and 9 deletions

View File

@ -14,7 +14,8 @@ import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public enum YogaWrap {
NO_WRAP(0),
WRAP(1);
WRAP(1),
WRAP_REVERSE(2);
private int mIntValue;
@ -30,6 +31,7 @@ public enum YogaWrap {
switch (value) {
case 0: return NO_WRAP;
case 1: return WRAP;
case 2: return WRAP_REVERSE;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}

View File

@ -124,10 +124,11 @@ typedef YG_ENUM_BEGIN(YGUnit) {
YGUnitAuto,
} YG_ENUM_END(YGUnit);
#define YGWrapCount 2
#define YGWrapCount 3
typedef YG_ENUM_BEGIN(YGWrap) {
YGWrapNoWrap,
YGWrapWrap,
YGWrapWrapReverse,
} YG_ENUM_END(YGWrap);
YG_EXTERN_C_END

View File

@ -1072,7 +1072,8 @@ static float YGBaseline(const YGNodeRef node) {
}
YGNodeRef baselineChild = NULL;
for (uint32_t i = 0; i < YGNodeGetChildCount(node); i++) {
const uint32_t childCount = YGNodeGetChildCount(node);
for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef child = YGNodeGetChild(node, i);
if (child->lineIndex > 0) {
break;
@ -1130,7 +1131,8 @@ static bool YGIsBaselineLayout(const YGNodeRef node) {
if (node->style.alignItems == YGAlignBaseline) {
return true;
}
for (uint32_t i = 0; i < YGNodeGetChildCount(node); i++) {
const uint32_t childCount = YGNodeGetChildCount(node);
for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef child = YGNodeGetChild(node, i);
if (child->style.positionType == YGPositionTypeRelative &&
child->style.alignSelf == YGAlignBaseline) {
@ -1735,7 +1737,8 @@ static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
node->layout.position[YGEdgeBottom] = 0;
node->layout.position[YGEdgeLeft] = 0;
node->layout.position[YGEdgeRight] = 0;
for (uint32_t i = 0; i < YGNodeGetChildCount(node); i++) {
const uint32_t childCount = YGNodeGetChildCount(node);
for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef child = YGNodeListGet(node->children, i);
YGZeroOutLayoutRecursivly(child);
}
@ -1759,9 +1762,6 @@ static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
// * The 'visibility' property is always assumed to be 'visible'. Values of
// 'collapse'
// and 'hidden' are not supported.
// * The 'wrap' property supports only 'nowrap' (which is the default) or
// 'wrap'. The
// rarely-used 'wrap-reverse' is not supported.
// * There is no support for forced breaks.
// * It does not support vertical inline directions (top-to-bottom or
// bottom-to-top text).
@ -1911,7 +1911,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);
const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
const YGJustify justifyContent = node->style.justifyContent;
const bool isNodeFlexWrap = node->style.flexWrap == YGWrapWrap;
const bool isNodeFlexWrap = node->style.flexWrap != YGWrapNoWrap;
const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight;
const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth;
@ -2929,6 +2929,18 @@ static void YGNodelayoutImpl(const YGNodeRef node,
paddingAndBorderAxisCross);
}
// As we only wrapped in normal direction yet, we need to reverse the positions on wrap-reverse.
if (performLayout && node->style.flexWrap == YGWrapWrapReverse) {
for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef child = YGNodeGetChild(node, i);
if (child->style.positionType == YGPositionTypeRelative) {
child->layout.position[pos[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] -
child->layout.position[pos[crossAxis]] -
child->layout.measuredDimensions[dim[crossAxis]];
}
}
}
if (performLayout) {
// STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN
for (currentAbsoluteChild = firstAbsoluteChild; currentAbsoluteChild != NULL;