diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 0a55a44ad2..7d30a7e923 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -448,7 +448,7 @@ namespace Avalonia.Controls MeasureCellsGroup(extData.CellGroup1, constraint, false, false); double combinedRowSpacing = RowSpacing * (RowDefinitions.Count - 1); double combinedColumnSpacing = ColumnSpacing * (ColumnDefinitions.Count - 1); - Size innerAvailableSize = new Size(constraint.Width - combinedRowSpacing, constraint.Height - combinedColumnSpacing); + Size innerAvailableSize = new Size(constraint.Width - combinedColumnSpacing, constraint.Height - combinedRowSpacing); { // after Group1 is measured, only Group3 may have cells belonging to Auto rows. bool canResolveStarsV = !HasGroup3CellsInAutoRows; @@ -512,8 +512,8 @@ namespace Avalonia.Controls MeasureCellsGroup(extData.CellGroup4, constraint, false, false); gridDesiredSize = new Size( - CalculateDesiredSize(DefinitionsU) + ColumnSpacing * (DefinitionsU.Count - 1), - CalculateDesiredSize(DefinitionsV) + RowSpacing * (DefinitionsU.Count - 1)); + CalculateDesiredSize(DefinitionsU) + ColumnSpacing * (DefinitionsU.Count - 1), + CalculateDesiredSize(DefinitionsV) + RowSpacing * (DefinitionsU.Count - 1)); } } finally @@ -566,11 +566,10 @@ namespace Avalonia.Controls int rowSpan = PrivateCells[currentCell].RowSpan; Rect cellRect = new Rect( - columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset + (columnSpacing * columnIndex), - rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset + (rowSpacing * rowIndex), - GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan), - GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan)); - + columnIndex == 0 ? 0d : DefinitionsU[columnIndex].FinalOffset, + rowIndex == 0 ? 0d : DefinitionsV[rowIndex].FinalOffset, + GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan, columnSpacing), + GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan, rowSpacing)); cell.Arrange(cellRect); } @@ -1132,9 +1131,10 @@ namespace Avalonia.Controls { // otherwise... cellMeasureWidth = GetMeasureSizeForRange( - DefinitionsU, - PrivateCells[cell].ColumnIndex, - PrivateCells[cell].ColumnSpan); + DefinitionsU, + PrivateCells[cell].ColumnIndex, + PrivateCells[cell].ColumnSpan, + ColumnSpacing); } if (forceInfinityV) @@ -1152,9 +1152,10 @@ namespace Avalonia.Controls else { cellMeasureHeight = GetMeasureSizeForRange( - DefinitionsV, - PrivateCells[cell].RowIndex, - PrivateCells[cell].RowSpan); + DefinitionsV, + PrivateCells[cell].RowIndex, + PrivateCells[cell].RowSpan, + RowSpacing); } @@ -1169,6 +1170,7 @@ namespace Avalonia.Controls /// Source array of definitions to read values from. /// Starting index of the range. /// Number of definitions included in the range. + /// or /// Calculated measure size. /// /// For "Auto" definitions MinWidth is used in place of PreferredSize. @@ -1176,21 +1178,24 @@ namespace Avalonia.Controls private static double GetMeasureSizeForRange( IReadOnlyList definitions, int start, - int count) + int count, + double spacing) { Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Count); - double measureSize = 0; + double measureSize = -spacing; int i = start + count - 1; do { - measureSize += (definitions[i].SizeType == LayoutTimeSizeType.Auto) - ? definitions[i].MinSize - : definitions[i].MeasureSize; + measureSize += + spacing + + (definitions[i].SizeType == LayoutTimeSizeType.Auto ? + definitions[i].MinSize : + definitions[i].MeasureSize); } while (--i >= start); - return (measureSize); + return measureSize; } /// @@ -2216,11 +2221,12 @@ namespace Avalonia.Controls } } + double spacing = columns ? ColumnSpacing : RowSpacing; // Phase 6. Compute final offsets definitions[0].FinalOffset = 0.0; for (int i = 0; i < definitions.Count; ++i) { - definitions[(i + 1) % definitions.Count].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; + definitions[(i + 1) % definitions.Count].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache + spacing; } } @@ -2296,21 +2302,23 @@ namespace Avalonia.Controls /// Array of definitions to process. /// Start of the range. /// Number of items in the range. + /// or /// Final size. private static double GetFinalSizeForRange( IReadOnlyList definitions, int start, - int count) + int count, + double spacing) { - double size = 0; + double size = -spacing; int i = start + count - 1; do { - size += definitions[i].SizeCache; + size += spacing + definitions[i].SizeCache; } while (--i >= start); - return (size); + return size; } /// diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 3eebdde255..8633aeed5c 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1741,6 +1741,48 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Rect(90, 90, 30, 30), target.Children[3].Bounds); } + [Fact] + public void Should_Grid_Controls_With_Spacing_Overflow2() + { + var target = new Grid + { + Height = 100, + ColumnSpacing = 20, + ColumnDefinitions = ColumnDefinitions.Parse("*,Auto"), + Children = + { + new Border { Width = 60 }, + new Border { [Grid.ColumnProperty] = 1, Width = 60 } + }, + }; + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(new Rect(0, 0, 100, 100), target.Bounds); + Assert.Equal(new Rect(-20, 0, 60, 100), target.Children[0].Bounds); + Assert.Equal(new Rect(40, 0, 60, 100), target.Children[1].Bounds); + } + + [Fact] + public void Grid_Controls_With_Spacing_With_Span() + { + var target = new Grid + { + Height = 100, + ColumnSpacing = 20, + ColumnDefinitions = ColumnDefinitions.Parse("20,20"), + Children = + { + new Border { [Grid.ColumnSpanProperty] = 2 } + }, + }; + target.Measure(new Size(100, 100)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(new Rect(0, 0, 60, 100), target.Bounds); + Assert.Equal(new Rect(0, 0, 60, 100), target.Children[0].Bounds); + } + private class TestControl : Control { public Size MeasureSize { get; set; }