diff --git a/gentest/Gemfile b/gentest/Gemfile index 71743c9b4c..6e7555f664 100644 --- a/gentest/Gemfile +++ b/gentest/Gemfile @@ -1,4 +1,4 @@ source "https://rubygems.org" gem 'watir', '~>7.2.0' -gem 'webdrivers', '~> 5.2.0' +gem 'webdrivers', '~> 5.3.0' diff --git a/gentest/Gemfile.lock b/gentest/Gemfile.lock index f05e43b7b2..6f477ff9b4 100644 --- a/gentest/Gemfile.lock +++ b/gentest/Gemfile.lock @@ -1,9 +1,9 @@ GEM remote: https://rubygems.org/ specs: - nokogiri (1.15.2-arm64-darwin) + nokogiri (1.15.4-arm64-darwin) racc (~> 1.4) - racc (1.7.0) + racc (1.7.1) regexp_parser (2.8.1) rexml (3.2.5) rubyzip (2.3.2) @@ -14,10 +14,10 @@ GEM watir (7.2.2) regexp_parser (>= 1.2, < 3) selenium-webdriver (~> 4.2) - webdrivers (5.2.0) + webdrivers (5.3.1) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (~> 4.0) + selenium-webdriver (~> 4.0, < 4.11) websocket (1.2.9) PLATFORMS @@ -25,7 +25,7 @@ PLATFORMS DEPENDENCIES watir (~> 7.2.0) - webdrivers (~> 5.2.0) + webdrivers (~> 5.3.0) BUNDLED WITH 2.4.10 diff --git a/gentest/fixtures/YGJustifyContentTest.html b/gentest/fixtures/YGJustifyContentTest.html index 8f7f383aa7..dc22f73035 100644 --- a/gentest/fixtures/YGJustifyContentTest.html +++ b/gentest/fixtures/YGJustifyContentTest.html @@ -101,3 +101,10 @@ + +
+
+
+
+
+
diff --git a/java/tests/com/facebook/yoga/YGJustifyContentTest.java b/java/tests/com/facebook/yoga/YGJustifyContentTest.java index dd212d3c92..89fde38e44 100644 --- a/java/tests/com/facebook/yoga/YGJustifyContentTest.java +++ b/java/tests/com/facebook/yoga/YGJustifyContentTest.java @@ -1167,6 +1167,77 @@ public void test_justify_content_min_width_with_padding_child_width_lower_than_p assertEquals(100f, root_child0_child0_child0.getLayoutHeight(), 0.0f); } + @Test + public void test_justify_content_space_between_indefinite_container_dim_with_free_space() { + YogaConfig config = YogaConfigFactory.create(); + config.setExperimentalFeatureEnabled(YogaExperimentalFeature.ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE, true); + + final YogaNode root = createNode(config); + root.setAlignItems(YogaAlign.CENTER); + root.setWidth(300f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setJustifyContent(YogaJustify.SPACE_BETWEEN); + root_child0.setMinWidth(200f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(50f); + root_child0_child0.setHeight(50f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(50f); + root_child0_child1.setHeight(50f); + root_child0.addChildAt(root_child0_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(50f, root.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(50f, root.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutHeight(), 0.0f); + } + private YogaNode createNode(YogaConfig config) { return mNodeFactory.create(config); } diff --git a/javascript/tests/generated/YGJustifyContentTest.test.ts b/javascript/tests/generated/YGJustifyContentTest.test.ts index baa6ca0f95..8f7e813f94 100644 --- a/javascript/tests/generated/YGJustifyContentTest.test.ts +++ b/javascript/tests/generated/YGJustifyContentTest.test.ts @@ -1275,3 +1275,80 @@ test('justify_content_min_width_with_padding_child_width_lower_than_parent', () config.free(); } }); +test('justify_content_space_between_indefinite_container_dim_with_free_space', () => { + const config = Yoga.Config.create(); + let root; + + config.setExperimentalFeatureEnabled(ExperimentalFeature.AbsolutePercentageAgainstPaddingEdge, true); + + try { + root = Yoga.Node.create(config); + root.setAlignItems(Align.Center); + root.setWidth(300); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(FlexDirection.Row); + root_child0.setJustifyContent(Justify.SpaceBetween); + root_child0.setMinWidth(200); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(50); + root_child0_child0.setHeight(50); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(50); + root_child0_child1.setHeight(50); + root_child0.insertChild(root_child0_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(50); + + expect(root_child0.getComputedLeft()).toBe(50); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(200); + expect(root_child0.getComputedHeight()).toBe(50); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(50); + + expect(root_child0_child1.getComputedLeft()).toBe(150); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(50); + expect(root_child0_child1.getComputedHeight()).toBe(50); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(50); + + expect(root_child0.getComputedLeft()).toBe(50); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(200); + expect(root_child0.getComputedHeight()).toBe(50); + + expect(root_child0_child0.getComputedLeft()).toBe(150); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(50); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(50); + expect(root_child0_child1.getComputedHeight()).toBe(50); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); diff --git a/tests/generated/YGJustifyContentTest.cpp b/tests/generated/YGJustifyContentTest.cpp index 1ae569f4a0..1e0672c67c 100644 --- a/tests/generated/YGJustifyContentTest.cpp +++ b/tests/generated/YGJustifyContentTest.cpp @@ -1170,3 +1170,75 @@ TEST(YogaTest, justify_content_min_width_with_padding_child_width_lower_than_par YGConfigFree(config); } + +TEST(YogaTest, justify_content_space_between_indefinite_container_dim_with_free_space) { + const YGConfigRef config = YGConfigNew(); + YGConfigSetExperimentalFeatureEnabled(config, YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge, true); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignItems(root, YGAlignCenter); + YGNodeStyleSetWidth(root, 300); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(root_child0, YGJustifySpaceBetween); + YGNodeStyleSetMinWidth(root_child0, 200); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 50); + YGNodeStyleSetHeight(root_child0_child0, 50); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 50); + YGNodeStyleSetHeight(root_child0_child1, 50); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 4288363721..a8cb925f5f 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -1306,11 +1306,6 @@ static void YGJustifyMainAxis( const auto child = node->getChild(i); const Style& childStyle = child->getStyle(); const LayoutResults& childLayout = child->getLayout(); - const bool isLastChild = i == flexLine.endOfLineIndex - 1; - // remove the gap if it is the last element of the line - if (isLastChild) { - betweenMainDim -= gap; - } if (childStyle.display() == YGDisplayNone) { continue; } @@ -1344,6 +1339,10 @@ static void YGJustifyMainAxis( leadingEdge(mainAxis)); } + if (child != flexLine.itemsInFlow.back()) { + flexLine.layout.mainDim += betweenMainDim; + } + if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) { flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / static_cast(numberOfAutoMarginsOnCurrentLine); @@ -1354,14 +1353,14 @@ static void YGJustifyMainAxis( // If we skipped the flex step, then we can't rely on the measuredDims // because they weren't computed. This means we can't call // dimensionWithMargin. - flexLine.layout.mainDim += betweenMainDim + + flexLine.layout.mainDim += child->getMarginForAxis(mainAxis, availableInnerWidth).unwrap() + childLayout.computedFlexBasis.unwrap(); flexLine.layout.crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus // the spacing. - flexLine.layout.mainDim += betweenMainDim + + flexLine.layout.mainDim += dimensionWithMargin(child, mainAxis, availableInnerWidth); if (isNodeBaselineLayout) {