Skip to content

Commit

Permalink
Fix edge case with Grids, *s, and unconstrained layouts (#14114)
Browse files Browse the repository at this point in the history
* Fix edge case with Grids, *s, and unconstrained layouts

* Auto-format source code

---------

Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
  • Loading branch information
hartez and GitHub Actions Autoformatter authored Mar 22, 2023
1 parent fc786dd commit 1e1ca27
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 11 deletions.
10 changes: 8 additions & 2 deletions src/Core/src/Layouts/GridLayoutManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,13 @@ double AvailableHeight(Cell cell)

public void DecompressStars(Size targetSize)
{
if (_grid.VerticalLayoutAlignment == LayoutAlignment.Fill || Dimension.IsExplicitSet(_explicitGridHeight))
bool decompressVertical = Dimension.IsExplicitSet(_explicitGridHeight)
|| _grid.VerticalLayoutAlignment == LayoutAlignment.Fill && targetSize.Height > MeasuredGridHeight();

bool decompressHorizontal = Dimension.IsExplicitSet(_explicitGridWidth)
|| _grid.HorizontalLayoutAlignment == LayoutAlignment.Fill && targetSize.Width > MeasuredGridWidth();

if (decompressVertical)
{
// Reset the size on all star rows
ZeroOutStarSizes(_rows);
Expand All @@ -758,7 +764,7 @@ public void DecompressStars(Size targetSize)
ResolveStarRows(targetSize.Height, true);
}

if (_grid.HorizontalLayoutAlignment == LayoutAlignment.Fill || Dimension.IsExplicitSet(_explicitGridWidth))
if (decompressHorizontal)
{
// Reset the size on all star columns
ZeroOutStarSizes(_columns);
Expand Down
88 changes: 79 additions & 9 deletions src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1936,7 +1936,7 @@ public void StarColumnWidthCorrectWhenFirstChildCollapsed()

[Fact("ArrangeChildren should arranged within measured size")]
[Category(GridStarSizing)]
public void ArrangeChildrenShouldArrangedWithinMeasuredSize()
public void ArrangeChildrenShouldArrangeWithinMeasuredSize()
{
var grid = CreateGridLayout(rows: "*");
grid.Width.Returns(105);
Expand All @@ -1953,7 +1953,7 @@ public void ArrangeChildrenShouldArrangedWithinMeasuredSize()
AssertArranged(view0, 0, 0, measuredSize.Width, measuredSize.Height);
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(LayoutAlignment.Center, true)]
[InlineData(LayoutAlignment.Center, false)]
[InlineData(LayoutAlignment.Start, true)]
Expand All @@ -1980,7 +1980,7 @@ public void GridMeasuresStarColumnToChildWidth(LayoutAlignment alignment, bool i
Assert.Equal(20, measuredSize.Width);
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(true, 100)]
[InlineData(false, 100)]
[InlineData(true, 15)]
Expand All @@ -2002,7 +2002,7 @@ public void FillGridArrangesStarColumnToWidthConstraint(bool implied, double con
AssertArranged(view0, new Rect(0, 0, constraint, 100));
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(LayoutAlignment.Center, true)]
[InlineData(LayoutAlignment.Center, false)]
[InlineData(LayoutAlignment.Start, true)]
Expand All @@ -2029,7 +2029,7 @@ public void NonFillGridArrangesStarColumnToChildWidth(LayoutAlignment alignment,
AssertArranged(view0, new Rect(0, 0, 20, 100));
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(LayoutAlignment.Center, true)]
[InlineData(LayoutAlignment.Center, false)]
[InlineData(LayoutAlignment.Start, true)]
Expand All @@ -2056,7 +2056,7 @@ public void GridMeasuresStarRowToChildHeight(LayoutAlignment alignment, bool imp
Assert.Equal(20, measuredSize.Height);
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(true, 100)]
[InlineData(false, 100)]
[InlineData(true, 15)]
Expand All @@ -2078,7 +2078,7 @@ public void FillGridArrangesStarRowToHeightConstraint(bool implied, double const
AssertArranged(view0, new Rect(0, 0, 100, constraint));
}

[Theory]
[Theory, Category(GridStarSizing)]
[InlineData(LayoutAlignment.Center, true)]
[InlineData(LayoutAlignment.Center, false)]
[InlineData(LayoutAlignment.Start, true)]
Expand All @@ -2104,7 +2104,7 @@ public void NonFillGridArrangesStarRowToChildHeight(LayoutAlignment alignment, b
AssertArranged(view0, new Rect(0, 0, 100, 20));
}

[Fact]
[Fact, Category(GridStarSizing)]
public void StarRowsResizeWhenGridExpandsToFill()
{
var grid = CreateGridLayout(rows: "*");
Expand All @@ -2130,7 +2130,7 @@ public void StarRowsResizeWhenGridExpandsToFill()
AssertArranged(view0, new Rect(0, 0, 20, 100));
}

[Fact]
[Fact, Category(GridStarSizing)]
public void StarColumnsResizeWhenGridExpandsToFill()
{
var grid = CreateGridLayout(columns: "*");
Expand Down Expand Up @@ -2427,5 +2427,75 @@ public void AutoStarRowsRespectUnconstrainedWidth()
// be arranged at the top left corner
AssertArranged(view0, new Rect(0, 0, 20, 20));
}

[Fact, Category(GridStarSizing)]
public void UnconstrainedStarRowsRetainTheirHeightsWhenArrangedAtMeasuredSize()
{
// This test accounts for the situation where a Grid has Rows marked as "*", is measured
// without height constraint, is vertically set to Fill, and is arranged at the measured height.
// Basically, a situation where the Grid is inside a vertically-oriented ScrollView or StackLayout,
// and the concept of vertical "Fill" doesn't mean anything. In that situation, the rows should
// retain their automatic sizing, rather than being evenly distributed as usual.

var grid = CreateGridLayout(rows: "*, *, *");
grid.VerticalLayoutAlignment.Returns(LayoutAlignment.Fill);

var view0 = CreateTestView(new Size(20, 20));
var view1 = CreateTestView(new Size(20, 40));
var view2 = CreateTestView(new Size(20, 60));

SubstituteChildren(grid, view0, view1, view2);

SetLocation(grid, view0, row: 0);
SetLocation(grid, view1, row: 1);
SetLocation(grid, view2, row: 2);

// Measure the Grid with no height constraint, then arrange it using the resulting size
// Unconstrained, we expect the views to total 20 + 40 + 60 = 120 height
// Since we're arranging it at that same height, there's reason for it to expand the items
// so we expect them to be arranged at the same heights
var measure = MeasureAndArrange(grid, widthConstraint: 200, heightConstraint: double.PositiveInfinity);

Assert.Equal(120, measure.Height);

AssertArranged(view0, new Rect(0, 0, 20, 20));
AssertArranged(view1, new Rect(0, 20, 20, 40));
AssertArranged(view2, new Rect(0, 60, 20, 60));
}

[Fact, Category(GridStarSizing)]
public void UnconstrainedStarColumnsRetainTheirWidthsWhenArrangedAtMeasuredSize()
{
// This test accounts for the situation where a Grid has Columns marked as "*", is measured
// without width constraint, is horizontally set to Fill, and is arranged at the measured width.
// Basically, a situation where the Grid is inside a horizontally-oriented ScrollView or StackLayout,
// and the concept of horizontal "Fill" doesn't mean anything. In that situation, the columns should
// retain their automatic sizing, rather than being evenly distributed as usual.

var grid = CreateGridLayout(columns: "*, *, *");
grid.HorizontalLayoutAlignment.Returns(LayoutAlignment.Fill);

var view0 = CreateTestView(new Size(20, 20));
var view1 = CreateTestView(new Size(40, 20));
var view2 = CreateTestView(new Size(60, 20));

SubstituteChildren(grid, view0, view1, view2);

SetLocation(grid, view0, col: 0);
SetLocation(grid, view1, col: 1);
SetLocation(grid, view2, col: 2);

// Measure the Grid with no width constraint, then arrange it using the resulting size
// Unconstrained, we expect the views to total 20 + 40 + 60 = 120 width
// Since we're arranging it at that same width, there's reason for it to expand the items
// so we expect them to be arranged at the same widths
var measure = MeasureAndArrange(grid, widthConstraint: double.PositiveInfinity, heightConstraint: 200);

Assert.Equal(120, measure.Width);

AssertArranged(view0, new Rect(0, 0, 20, 20));
AssertArranged(view1, new Rect(20, 00, 40, 20));
AssertArranged(view2, new Rect(60, 0, 60, 20));
}
}
}

0 comments on commit 1e1ca27

Please sign in to comment.