diff --git a/Source/Private/Layout/ASStackUnpositionedLayout.mm b/Source/Private/Layout/ASStackUnpositionedLayout.mm index 8bed958aa..54a17bb08 100644 --- a/Source/Private/Layout/ASStackUnpositionedLayout.mm +++ b/Source/Private/Layout/ASStackUnpositionedLayout.mm @@ -485,7 +485,8 @@ static CGFloat computeItemsStackDimensionSum(const std::vector &l std::vector lines; std::vector lineItems; CGFloat lineStackDimensionSum = 0; + CGFloat interitemSpacing = 0; for(auto it = items.begin(); it != items.end(); ++it) { const auto &item = *it; const CGFloat itemStackDimension = stackDimension(style.direction, item.layout.size); - const CGFloat itemAndSpacingStackDimension = (lineItems.empty() ? 0.0 : style.spacing) + item.child.style.spacingBefore + itemStackDimension + item.child.style.spacingAfter; - const BOOL negativeViolationIfAddItem = (ASStackUnpositionedLayout::computeStackViolation(lineStackDimensionSum + itemAndSpacingStackDimension, style, sizeRange) < 0); + const CGFloat itemAndSpacingStackDimension = item.child.style.spacingBefore + itemStackDimension + item.child.style.spacingAfter; + const BOOL negativeViolationIfAddItem = (ASStackUnpositionedLayout::computeStackViolation(lineStackDimensionSum + interitemSpacing + itemAndSpacingStackDimension, style, sizeRange) < 0); const BOOL breakCurrentLine = negativeViolationIfAddItem && !lineItems.empty(); if (breakCurrentLine) { lines.push_back({.items = std::vector (lineItems)}); lineItems.clear(); lineStackDimensionSum = 0; + interitemSpacing = 0; } lineItems.push_back(std::move(item)); - lineStackDimensionSum += itemAndSpacingStackDimension; + lineStackDimensionSum += interitemSpacing + itemAndSpacingStackDimension; + interitemSpacing = style.spacing; } // Handle last line diff --git a/Tests/ASStackLayoutSpecSnapshotTests.mm b/Tests/ASStackLayoutSpecSnapshotTests.mm index 042203fe1..7f4c3251f 100644 --- a/Tests/ASStackLayoutSpecSnapshotTests.mm +++ b/Tests/ASStackLayoutSpecSnapshotTests.mm @@ -110,6 +110,7 @@ - (void)testStackLayoutSpecWithStyle:(ASStackLayoutSpecStyle)style alignItems:style.alignItems flexWrap:style.flexWrap alignContent:style.alignContent + lineSpacing:style.lineSpacing children:children]; [self testStackLayoutSpec:stackLayoutSpec sizeRange:sizeRange subnodes:subnodes identifier:identifier]; @@ -163,6 +164,7 @@ - (void)testStackLayoutSpec:(ASStackLayoutSpec *)stackLayoutSpec } - (void)testStackLayoutSpecWithAlignContent:(ASStackLayoutAlignContent)alignContent + lineSpacing:(CGFloat)lineSpacing sizeRange:(ASSizeRange)sizeRange identifier:(NSString *)identifier { @@ -170,8 +172,9 @@ - (void)testStackLayoutSpecWithAlignContent:(ASStackLayoutAlignContent)alignCont .direction = ASStackLayoutDirectionHorizontal, .flexWrap = ASStackLayoutFlexWrapWrap, .alignContent = alignContent, + .lineSpacing = lineSpacing, }; - + CGSize subnodeSize = {50, 50}; NSArray *subnodes = @[ ASDisplayNodeWithBackgroundColor([UIColor redColor], subnodeSize), @@ -181,10 +184,17 @@ - (void)testStackLayoutSpecWithAlignContent:(ASStackLayoutAlignContent)alignCont ASDisplayNodeWithBackgroundColor([UIColor greenColor], subnodeSize), ASDisplayNodeWithBackgroundColor([UIColor cyanColor], subnodeSize), ]; - + [self testStackLayoutSpecWithStyle:style sizeRange:sizeRange subnodes:subnodes identifier:identifier]; } +- (void)testStackLayoutSpecWithAlignContent:(ASStackLayoutAlignContent)alignContent + sizeRange:(ASSizeRange)sizeRange + identifier:(NSString *)identifier +{ + [self testStackLayoutSpecWithAlignContent:alignContent lineSpacing:0.0 sizeRange:sizeRange identifier:identifier]; +} + #pragma mark - - (void)testDefaultStackLayoutElementFlexProperties @@ -1209,6 +1219,77 @@ - (void)testBaselineAlignmentWithStretchedItem [self testStackLayoutSpec:stackLayoutSpec sizeRange:kSize subnodes:children identifier:nil]; } +#pragma mark - Flex wrap and item spacings test + +- (void)testFlexWrapWithItemSpacings +{ + ASStackLayoutSpecStyle style = { + .spacing = 50, + .direction = ASStackLayoutDirectionHorizontal, + .flexWrap = ASStackLayoutFlexWrapWrap, + .alignContent = ASStackLayoutAlignContentStart, + .lineSpacing = 5, + }; + + CGSize subnodeSize = {50, 50}; + NSArray *subnodes = @[ + ASDisplayNodeWithBackgroundColor([UIColor redColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor yellowColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor blueColor], subnodeSize), + ]; + + for (ASDisplayNode *subnode in subnodes) { + subnode.style.spacingBefore = 5; + subnode.style.spacingAfter = 5; + } + + // 3 items, each item has a size of {50, 50} + // width is 230px, enough to fit all items without taking all spacings into account + // Test that all spacings are included and therefore the last item is pushed to a second line. + // See: https://github.com/TextureGroup/Texture/pull/472 + static ASSizeRange kSize = {{230, 300}, {230, 300}}; + [self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil]; +} + +- (void)testFlexWrapWithItemSpacingsBeingResetOnNewLines +{ + ASStackLayoutSpecStyle style = { + .spacing = 5, + .direction = ASStackLayoutDirectionHorizontal, + .flexWrap = ASStackLayoutFlexWrapWrap, + .alignContent = ASStackLayoutAlignContentStart, + .lineSpacing = 5, + }; + + CGSize subnodeSize = {50, 50}; + NSArray *subnodes = @[ + // 1st line + ASDisplayNodeWithBackgroundColor([UIColor redColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor yellowColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor blueColor], subnodeSize), + // 2nd line + ASDisplayNodeWithBackgroundColor([UIColor magentaColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor greenColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor cyanColor], subnodeSize), + // 3rd line + ASDisplayNodeWithBackgroundColor([UIColor brownColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor orangeColor], subnodeSize), + ASDisplayNodeWithBackgroundColor([UIColor purpleColor], subnodeSize), + ]; + + for (ASDisplayNode *subnode in subnodes) { + subnode.style.spacingBefore = 5; + subnode.style.spacingAfter = 5; + } + + // 3 lines, each line has 3 items, each item has a size of {50, 50} + // width is 190px, enough to fit 3 items into a line + // Test that interitem spacing is reset on new lines. Otherwise, lines after the 1st line would have only 2 items. + // See: https://github.com/TextureGroup/Texture/pull/472 + static ASSizeRange kSize = {{190, 300}, {190, 300}}; + [self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil]; +} + #pragma mark - Content alignment tests - (void)testAlignContentUnderflow @@ -1282,4 +1363,33 @@ - (void)testAlignContentStretchAndOtherAlignments [self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil]; } +#pragma mark - Line spacing tests + +- (void)testAlignContentAndLineSpacingUnderflow +{ + // 3 lines, each line has 2 items, each item has a size of {50, 50} + // 10px between lines + // width is 110px. It's 10px bigger than the required width of each line (110px vs 100px) to test that items are still correctly collected into lines + static ASSizeRange kSize = {{110, 320}, {110, 320}}; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentStart lineSpacing:10 sizeRange:kSize identifier:@"alignContentStart"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentCenter lineSpacing:10 sizeRange:kSize identifier:@"alignContentCenter"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentEnd lineSpacing:10 sizeRange:kSize identifier:@"alignContentEnd"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentSpaceBetween lineSpacing:10 sizeRange:kSize identifier:@"alignContentSpaceBetween"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentSpaceAround lineSpacing:10 sizeRange:kSize identifier:@"alignContentSpaceAround"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentStretch lineSpacing:10 sizeRange:kSize identifier:@"alignContentStretch"]; +} + +- (void)testAlignContentAndLineSpacingOverflow +{ + // 6 lines, each line has 1 item, each item has a size of {50, 50} + // 10px between lines + // width is 40px. It's 10px smaller than the width of each item (40px vs 50px) to test that items are still correctly collected into lines + static ASSizeRange kSize = {{40, 310}, {40, 310}}; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentStart lineSpacing:10 sizeRange:kSize identifier:@"alignContentStart"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentCenter lineSpacing:10 sizeRange:kSize identifier:@"alignContentCenter"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentEnd lineSpacing:10 sizeRange:kSize identifier:@"alignContentEnd"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentSpaceBetween lineSpacing:10 sizeRange:kSize identifier:@"alignContentSpaceBetween"]; + [self testStackLayoutSpecWithAlignContent:ASStackLayoutAlignContentSpaceAround lineSpacing:10 sizeRange:kSize identifier:@"alignContentSpaceAround"]; +} + @end diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentCenter@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentCenter@2x.png new file mode 100644 index 000000000..188cd6007 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentCenter@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentEnd@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentEnd@2x.png new file mode 100644 index 000000000..18f614cf4 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentEnd@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceAround@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceAround@2x.png new file mode 100644 index 000000000..188cd6007 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceAround@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceBetween@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceBetween@2x.png new file mode 100644 index 000000000..20d303b58 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentSpaceBetween@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentStart@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentStart@2x.png new file mode 100644 index 000000000..20d303b58 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingOverflow_alignContentStart@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentCenter@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentCenter@2x.png new file mode 100644 index 000000000..27b26426d Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentCenter@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentEnd@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentEnd@2x.png new file mode 100644 index 000000000..740100fce Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentEnd@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceAround@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceAround@2x.png new file mode 100644 index 000000000..40bae9ef3 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceAround@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceBetween@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceBetween@2x.png new file mode 100644 index 000000000..a60f63f14 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentSpaceBetween@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStart@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStart@2x.png new file mode 100644 index 000000000..a89a941bf Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStart@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStretch@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStretch@2x.png new file mode 100644 index 000000000..461c78692 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignContentAndLineSpacingUnderflow_alignContentStretch@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacings@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacings@2x.png new file mode 100644 index 000000000..31df2f619 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacings@2x.png differ diff --git a/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacingsBeingResetOnNewLines@2x.png b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacingsBeingResetOnNewLines@2x.png new file mode 100644 index 000000000..1824a2508 Binary files /dev/null and b/Tests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWrapWithItemSpacingsBeingResetOnNewLines@2x.png differ