Skip to content

Commit

Permalink
Fix handling 'auto' checks in absolute layout (#46216)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #46216

Regarding [issue](#45817) with incorrect layout when `left` is set to `auto`. This PR introduces handling `auto` whenever inline or flex position is checked to be defined and it fixes above issue.

Changelog:
[General][Fixed] - Fix handling 'auto' checks in absolute layout

## Tests:
 I have run the provided unit tests and everything passes.

X-link: facebook/yoga#1689

Reviewed By: cipolleschi

Differential Revision: D61737876

Pulled By: NickGerleman

fbshipit-source-id: 531199a91c5e122b930b49725ea567cbb1d592ce
  • Loading branch information
coado authored and facebook-github-bot committed Aug 27, 2024
1 parent b96238d commit 3596019
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public class YogaNative {
static native long jni_YGNodeStyleGetPositionJNI(long nativePointer, int edge);
static native void jni_YGNodeStyleSetPositionJNI(long nativePointer, int edge, float position);
static native void jni_YGNodeStyleSetPositionPercentJNI(long nativePointer, int edge, float percent);
static native void jni_YGNodeStyleSetPositionAutoJNI(long nativePointer, int edge);
static native long jni_YGNodeStyleGetWidthJNI(long nativePointer);
static native void jni_YGNodeStyleSetWidthJNI(long nativePointer, float width);
static native void jni_YGNodeStyleSetWidthPercentJNI(long nativePointer, float percent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public interface Inputs {

public abstract void setPositionPercent(YogaEdge edge, float percent);

public abstract void setPositionAuto(YogaEdge edge);

public abstract YogaValue getWidth();

public abstract void setWidth(float width);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ public void setPositionPercent(YogaEdge edge, float percent) {
YogaNative.jni_YGNodeStyleSetPositionPercentJNI(mNativePointer, edge.intValue(), percent);
}

public void setPositionAuto(YogaEdge edge) {
YogaNative.jni_YGNodeStyleSetPositionAutoJNI(mNativePointer, edge.intValue());
}

public YogaValue getWidth() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetWidthJNI(mNativePointer));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,14 @@ static void jni_YGNodeCopyStyleJNI(
static_cast<float>(value)); \
}

#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
static void jni_YGNodeStyleSet##name##AutoJNI( \
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jint edge) { \
YGNodeStyleSet##name##Auto( \
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge)); \
}

YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction);
YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection);
YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent);
Expand All @@ -482,7 +490,7 @@ YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height);
YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight);
YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight);

YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position);
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(Position);

static jlong jni_YGNodeStyleGetMarginJNI(
JNIEnv* /*env*/,
Expand Down Expand Up @@ -891,6 +899,9 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetPositionPercentJNI",
"(JIF)V",
(void*)jni_YGNodeStyleSetPositionPercentJNI},
{"jni_YGNodeStyleSetPositionAutoJNI",
"(JI)V",
(void*)jni_YGNodeStyleSetPositionAutoJNI},
{"jni_YGNodeStyleGetWidthJNI", "(J)J", (void*)jni_YGNodeStyleGetWidthJNI},
{"jni_YGNodeStyleSetWidthJNI", "(JF)V", (void*)jni_YGNodeStyleSetWidthJNI},
{"jni_YGNodeStyleSetWidthPercentJNI",
Expand Down
5 changes: 5 additions & 0 deletions packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) {
node, scopedEnum(edge), value::percent(percent));
}

void YGNodeStyleSetPositionAuto(YGNodeRef node, YGEdge edge) {
updateStyle<&Style::position, &Style::setPosition>(
node, scopedEnum(edge), value::ofAuto());
}

YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) {
return (YGValue)resolveRef(node)->style().position(scopedEnum(edge));
}
Expand Down
4 changes: 3 additions & 1 deletion packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float position);
YG_EXPORT void
YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float position);
YG_EXPORT YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge);
YG_EXPORT void YGNodeStyleSetPositionAuto(YGNodeRef node, YGEdge edge);

YG_EXPORT void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin);
YG_EXPORT
void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin);
YG_EXPORT void
YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float margin);
YG_EXPORT void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ static void positionAbsoluteChildLegacy(
(parent->style().flexWrap() == Wrap::WrapReverse));

if (child->style().isFlexEndPositionDefined(axis, direction) &&
!child->style().isFlexStartPositionDefined(axis, direction)) {
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction))) {
child->setLayoutPosition(
containingNode->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis)) -
Expand All @@ -169,15 +170,17 @@ static void positionAbsoluteChildLegacy(
isAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(axis));
} else if (
!child->style().isFlexStartPositionDefined(axis, direction) &&
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction)) &&
shouldCenter) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis))) /
2.0f,
flexStartEdge(axis));
} else if (
!child->style().isFlexStartPositionDefined(axis, direction) &&
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction)) &&
shouldFlexEnd) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
Expand Down Expand Up @@ -223,7 +226,8 @@ static void positionAbsoluteChildImpl(
// to the flex-start edge because this algorithm works by positioning on the
// flex-start edge and then filling in the flex-end direction at the end if
// necessary.
if (child->style().isInlineStartPositionDefined(axis, direction)) {
if (child->style().isInlineStartPositionDefined(axis, direction) &&
!child->style().isInlineStartPositionAuto(axis, direction)) {
const float positionRelativeToInlineStart =
child->style().computeInlineStartPosition(
axis, direction, containingBlockSize) +
Expand All @@ -237,7 +241,9 @@ static void positionAbsoluteChildImpl(
: positionRelativeToInlineStart;

child->setLayoutPosition(positionRelativeToFlexStart, flexStartEdge(axis));
} else if (child->style().isInlineEndPositionDefined(axis, direction)) {
} else if (
child->style().isInlineEndPositionDefined(axis, direction) &&
!child->style().isInlineEndPositionAuto(axis, direction)) {
const float positionRelativeToInlineStart =
containingNode->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis)) -
Expand Down Expand Up @@ -328,7 +334,10 @@ void layoutAbsoluteChild(
if (child->style().isFlexStartPositionDefined(
FlexDirection::Row, direction) &&
child->style().isFlexEndPositionDefined(
FlexDirection::Row, direction)) {
FlexDirection::Row, direction) &&
!child->style().isFlexStartPositionAuto(
FlexDirection::Row, direction) &&
!child->style().isFlexEndPositionAuto(FlexDirection::Row, direction)) {
childWidth =
containingNode->getLayout().measuredDimension(Dimension::Width) -
(containingNode->style().computeFlexStartBorder(
Expand Down Expand Up @@ -360,6 +369,10 @@ void layoutAbsoluteChild(
if (child->style().isFlexStartPositionDefined(
FlexDirection::Column, direction) &&
child->style().isFlexEndPositionDefined(
FlexDirection::Column, direction) &&
!child->style().isFlexStartPositionAuto(
FlexDirection::Column, direction) &&
!child->style().isFlexEndPositionAuto(
FlexDirection::Column, direction)) {
childHeight =
containingNode->getLayout().measuredDimension(Dimension::Height) -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1059,7 +1059,8 @@ static void justifyMainAxis(
continue;
}
if (childStyle.positionType() == PositionType::Absolute &&
child->style().isFlexStartPositionDefined(mainAxis, direction)) {
child->style().isFlexStartPositionDefined(mainAxis, direction) &&
!child->style().isFlexStartPositionAuto(mainAxis, direction)) {
if (performLayout) {
// In case the child is position absolute and has left/top being
// defined, we override the position to whatever the user said (and
Expand Down Expand Up @@ -1629,7 +1630,8 @@ static void calculateLayoutImpl(
// top/left/bottom/right set, override all the previously computed
// positions to set it correctly.
const bool isChildLeadingPosDefined =
child->style().isFlexStartPositionDefined(crossAxis, direction);
child->style().isFlexStartPositionDefined(crossAxis, direction) &&
!child->style().isFlexStartPositionAuto(crossAxis, direction);
if (isChildLeadingPosDefined) {
child->setLayoutPosition(
child->style().computeFlexStartPosition(
Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ float Node::relativePosition(
if (style_.positionType() == PositionType::Static) {
return 0;
}
if (style_.isInlineStartPositionDefined(axis, direction)) {
if (style_.isInlineStartPositionDefined(axis, direction) &&
!style_.isInlineStartPositionAuto(axis, direction)) {
return style_.computeInlineStartPosition(axis, direction, axisSize);
}

Expand Down
18 changes: 18 additions & 0 deletions packages/react-native/ReactCommon/yoga/yoga/style/Style.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,22 +223,40 @@ class YG_EXPORT Style {
return computePosition(flexStartEdge(axis), direction).isDefined();
}

bool isFlexStartPositionAuto(FlexDirection axis, Direction direction) const {
return computePosition(flexStartEdge(axis), direction).isAuto();
}

bool isInlineStartPositionDefined(FlexDirection axis, Direction direction)
const {
return computePosition(inlineStartEdge(axis, direction), direction)
.isDefined();
}

bool isInlineStartPositionAuto(FlexDirection axis, Direction direction)
const {
return computePosition(inlineStartEdge(axis, direction), direction)
.isAuto();
}

bool isFlexEndPositionDefined(FlexDirection axis, Direction direction) const {
return computePosition(flexEndEdge(axis), direction).isDefined();
}

bool isFlexEndPositionAuto(FlexDirection axis, Direction direction) const {
return computePosition(flexEndEdge(axis), direction).isAuto();
}

bool isInlineEndPositionDefined(FlexDirection axis, Direction direction)
const {
return computePosition(inlineEndEdge(axis, direction), direction)
.isDefined();
}

bool isInlineEndPositionAuto(FlexDirection axis, Direction direction) const {
return computePosition(inlineEndEdge(axis, direction), direction).isAuto();
}

float computeFlexStartPosition(
FlexDirection axis,
Direction direction,
Expand Down

0 comments on commit 3596019

Please sign in to comment.