Skip to content

Commit

Permalink
Implement Percentage support for gap styles (facebook#44067)
Browse files Browse the repository at this point in the history
Summary:

X-link: facebook/litho#980

X-link: facebook/yoga#1643

Changelog [Internal]:
- Added percentage value for flex layout gap
- Wired up to pass proper available width and height to implement this feature

Reviewed By: NickGerleman

Differential Revision: D56002340
  • Loading branch information
realsoelynn authored and facebook-github-bot committed Apr 15, 2024
1 parent 6dd83cb commit cb74656
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class YogaNative {
static native void jni_YGNodeStyleSetAspectRatioJNI(long nativePointer, float aspectRatio);
static native float jni_YGNodeStyleGetGapJNI(long nativePointer, int gutter);
static native void jni_YGNodeStyleSetGapJNI(long nativePointer, int gutter, float gapLength);
static native void jni_YGNodeStyleSetGapPercentJNI(long nativePointer, int gutter, float gapLength);
static native void jni_YGNodeSetHasMeasureFuncJNI(long nativePointer, boolean hasMeasureFunc);
static native void jni_YGNodeSetHasBaselineFuncJNI(long nativePointer, boolean hasMeasureFunc);
static native void jni_YGNodeSetStyleInputsJNI(long nativePointer, float[] styleInputsArray, int size);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ public interface Inputs {

public abstract void setGap(YogaGutter gutter, float gapLength);

public abstract void setGapPercent(YogaGutter gutter, float gapLength);

public abstract float getLayoutX();

public abstract float getLayoutY();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -721,4 +721,9 @@ public float getGap(YogaGutter gutter) {
public void setGap(YogaGutter gutter, float gapLength) {
YogaNative.jni_YGNodeStyleSetGapJNI(mNativePointer, gutter.intValue(), gapLength);
}

@Override
public void setGapPercent(YogaGutter gutter, float gapLength) {
YogaNative.jni_YGNodeStyleSetGapPercentJNI(mNativePointer, gutter.intValue(), gapLength);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,18 @@ static void jni_YGNodeStyleSetGapJNI(
static_cast<float>(gapLength));
}

static void jni_YGNodeStyleSetGapPercentJNI(
JNIEnv* /*env*/,
jobject /*obj*/,
jlong nativePointer,
jint gutter,
jfloat gapLength) {
YGNodeStyleSetGapPercent(
_jlong2YGNodeRef(nativePointer),
static_cast<YGGutter>(gutter),
static_cast<float>(gapLength));
}

// Yoga specific properties, not compatible with flexbox specification
YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);

Expand Down Expand Up @@ -944,6 +956,9 @@ static JNINativeMethod methods[] = {
(void*)jni_YGNodeSetHasMeasureFuncJNI},
{"jni_YGNodeStyleGetGapJNI", "(JI)F", (void*)jni_YGNodeStyleGetGapJNI},
{"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*)jni_YGNodeStyleSetGapJNI},
{"jni_YGNodeStyleSetGapPercentJNI",
"(JIF)V",
(void*)jni_YGNodeStyleSetGapPercentJNI},
{"jni_YGNodeSetHasBaselineFuncJNI",
"(JZ)V",
(void*)jni_YGNodeSetHasBaselineFuncJNI},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class FakeYogaNode : YogaNode() {
// no-op
}

override fun setGapPercent(gutter: YogaGutter?, gapLength: Float) {
// no-op
}

override fun getLayoutX(): Float = 0f

override fun getLayoutY(): Float = 0f
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 @@ -267,6 +267,11 @@ void YGNodeStyleSetGap(
node, scopedEnum(gutter), value::points(gapLength));
}

void YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float percent) {
updateStyle<&Style::gap, &Style::setGap>(
node, scopedEnum(gutter), value::percent(percent));
}

float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) {
auto gapLength = resolveRef(node)->style().gap(scopedEnum(gutter));
if (gapLength.isUndefined() || gapLength.isAuto()) {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ YG_EXPORT float YGNodeStyleGetBorder(YGNodeConstRef node, YGEdge edge);

YG_EXPORT void
YGNodeStyleSetGap(YGNodeRef node, YGGutter gutter, float gapLength);
YG_EXPORT void
YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float gapLength);
YG_EXPORT float YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter);

YG_EXPORT void YGNodeStyleSetWidth(YGNodeRef node, float width);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,8 @@ static void justifyMainAxis(
node->style().computeFlexEndPaddingAndBorder(
mainAxis, direction, ownerWidth);

const float gap = node->style().computeGapForAxis(mainAxis);
const float gap =
node->style().computeGapForAxis(mainAxis, availableInnerMainDim);
// If we are using "at most" rules in the main axis, make sure that
// remainingFreeSpace is 0 when min main dimension is not given
if (sizingModeMainDim == SizingMode::FitContent &&
Expand Down Expand Up @@ -1380,7 +1381,8 @@ static void calculateLayoutImpl(
generationCount);

if (childCount > 1) {
totalMainDim += node->style().computeGapForAxis(mainAxis) *
totalMainDim +=
node->style().computeGapForAxis(mainAxis, availableInnerMainDim) *
static_cast<float>(childCount - 1);
}

Expand All @@ -1404,7 +1406,8 @@ static void calculateLayoutImpl(
// Accumulated cross dimensions of all lines so far.
float totalLineCrossDim = 0;

const float crossAxisGap = node->style().computeGapForAxis(crossAxis);
const float crossAxisGap =
node->style().computeGapForAxis(crossAxis, availableInnerCrossDim);

// Max main dimension of all the lines.
float maxLineMainDim = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ FlexLine calculateFlexLine(
const FlexDirection mainAxis = resolveDirection(
node->style().flexDirection(), node->resolveDirection(ownerDirection));
const bool isNodeFlexWrap = node->style().flexWrap() != Wrap::NoWrap;
const float gap = node->style().computeGapForAxis(mainAxis);
const float gap =
node->style().computeGapForAxis(mainAxis, availableInnerMainDim);

// Add items to the current line until it's full or we run out of items.
for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) {
Expand Down
6 changes: 2 additions & 4 deletions packages/react-native/ReactCommon/yoga/yoga/style/Style.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,9 @@ class YG_EXPORT Style {
computeInlineEndMargin(axis, Direction::LTR, widthSize);
}

float computeGapForAxis(FlexDirection axis) const {
float computeGapForAxis(FlexDirection axis, float ownerSize) const {
auto gap = isRow(axis) ? computeColumnGap() : computeRowGap();
// TODO: Validate percentage gap, and expose ability to set percentage to
// public API
return maxOrDefined(gap.resolve(0.0f /*ownerSize*/).unwrap(), 0.0f);
return maxOrDefined(gap.resolve(ownerSize).unwrap(), 0.0f);
}

bool flexStartMarginIsAuto(FlexDirection axis, Direction direction) const {
Expand Down

0 comments on commit cb74656

Please sign in to comment.