Browse Source

Fix grid spacing messure issue (#18473)

* fix grid spacing messure issue

* fix grid lines

* fix multi span

* push test
pull/18516/head
Poker 2 years ago
committed by GitHub
parent
commit
beda7a0457
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 58
      src/Avalonia.Controls/Grid.cs
  2. 42
      tests/Avalonia.Controls.UnitTests/GridTests.cs

58
src/Avalonia.Controls/Grid.cs

@ -448,7 +448,7 @@ namespace Avalonia.Controls
MeasureCellsGroup(extData.CellGroup1, constraint, false, false); MeasureCellsGroup(extData.CellGroup1, constraint, false, false);
double combinedRowSpacing = RowSpacing * (RowDefinitions.Count - 1); double combinedRowSpacing = RowSpacing * (RowDefinitions.Count - 1);
double combinedColumnSpacing = ColumnSpacing * (ColumnDefinitions.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. // after Group1 is measured, only Group3 may have cells belonging to Auto rows.
bool canResolveStarsV = !HasGroup3CellsInAutoRows; bool canResolveStarsV = !HasGroup3CellsInAutoRows;
@ -512,8 +512,8 @@ namespace Avalonia.Controls
MeasureCellsGroup(extData.CellGroup4, constraint, false, false); MeasureCellsGroup(extData.CellGroup4, constraint, false, false);
gridDesiredSize = new Size( gridDesiredSize = new Size(
CalculateDesiredSize(DefinitionsU) + ColumnSpacing * (DefinitionsU.Count - 1), CalculateDesiredSize(DefinitionsU) + ColumnSpacing * (DefinitionsU.Count - 1),
CalculateDesiredSize(DefinitionsV) + RowSpacing * (DefinitionsU.Count - 1)); CalculateDesiredSize(DefinitionsV) + RowSpacing * (DefinitionsU.Count - 1));
} }
} }
finally finally
@ -566,11 +566,10 @@ namespace Avalonia.Controls
int rowSpan = PrivateCells[currentCell].RowSpan; int rowSpan = PrivateCells[currentCell].RowSpan;
Rect cellRect = new Rect( Rect cellRect = new Rect(
columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset + (columnSpacing * columnIndex), columnIndex == 0 ? 0d : DefinitionsU[columnIndex].FinalOffset,
rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset + (rowSpacing * rowIndex), rowIndex == 0 ? 0d : DefinitionsV[rowIndex].FinalOffset,
GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan), GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan, columnSpacing),
GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan)); GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan, rowSpacing));
cell.Arrange(cellRect); cell.Arrange(cellRect);
} }
@ -1132,9 +1131,10 @@ namespace Avalonia.Controls
{ {
// otherwise... // otherwise...
cellMeasureWidth = GetMeasureSizeForRange( cellMeasureWidth = GetMeasureSizeForRange(
DefinitionsU, DefinitionsU,
PrivateCells[cell].ColumnIndex, PrivateCells[cell].ColumnIndex,
PrivateCells[cell].ColumnSpan); PrivateCells[cell].ColumnSpan,
ColumnSpacing);
} }
if (forceInfinityV) if (forceInfinityV)
@ -1152,9 +1152,10 @@ namespace Avalonia.Controls
else else
{ {
cellMeasureHeight = GetMeasureSizeForRange( cellMeasureHeight = GetMeasureSizeForRange(
DefinitionsV, DefinitionsV,
PrivateCells[cell].RowIndex, PrivateCells[cell].RowIndex,
PrivateCells[cell].RowSpan); PrivateCells[cell].RowSpan,
RowSpacing);
} }
@ -1169,6 +1170,7 @@ namespace Avalonia.Controls
/// <param name="definitions">Source array of definitions to read values from.</param> /// <param name="definitions">Source array of definitions to read values from.</param>
/// <param name="start">Starting index of the range.</param> /// <param name="start">Starting index of the range.</param>
/// <param name="count">Number of definitions included in the range.</param> /// <param name="count">Number of definitions included in the range.</param>
/// <param name="spacing"><see cref="ColumnSpacing"/> or <see cref="RowSpacing"/></param>
/// <returns>Calculated measure size.</returns> /// <returns>Calculated measure size.</returns>
/// <remarks> /// <remarks>
/// For "Auto" definitions MinWidth is used in place of PreferredSize. /// For "Auto" definitions MinWidth is used in place of PreferredSize.
@ -1176,21 +1178,24 @@ namespace Avalonia.Controls
private static double GetMeasureSizeForRange( private static double GetMeasureSizeForRange(
IReadOnlyList<DefinitionBase> definitions, IReadOnlyList<DefinitionBase> definitions,
int start, int start,
int count) int count,
double spacing)
{ {
Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Count); Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Count);
double measureSize = 0; double measureSize = -spacing;
int i = start + count - 1; int i = start + count - 1;
do do
{ {
measureSize += (definitions[i].SizeType == LayoutTimeSizeType.Auto) measureSize +=
? definitions[i].MinSize spacing +
: definitions[i].MeasureSize; (definitions[i].SizeType == LayoutTimeSizeType.Auto ?
definitions[i].MinSize :
definitions[i].MeasureSize);
} while (--i >= start); } while (--i >= start);
return (measureSize); return measureSize;
} }
/// <summary> /// <summary>
@ -2216,11 +2221,12 @@ namespace Avalonia.Controls
} }
} }
double spacing = columns ? ColumnSpacing : RowSpacing;
// Phase 6. Compute final offsets // Phase 6. Compute final offsets
definitions[0].FinalOffset = 0.0; definitions[0].FinalOffset = 0.0;
for (int i = 0; i < definitions.Count; ++i) 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
/// <param name="definitions">Array of definitions to process.</param> /// <param name="definitions">Array of definitions to process.</param>
/// <param name="start">Start of the range.</param> /// <param name="start">Start of the range.</param>
/// <param name="count">Number of items in the range.</param> /// <param name="count">Number of items in the range.</param>
/// <param name="spacing"><see cref="ColumnSpacing"/> or <see cref="RowSpacing"/></param>
/// <returns>Final size.</returns> /// <returns>Final size.</returns>
private static double GetFinalSizeForRange( private static double GetFinalSizeForRange(
IReadOnlyList<DefinitionBase> definitions, IReadOnlyList<DefinitionBase> definitions,
int start, int start,
int count) int count,
double spacing)
{ {
double size = 0; double size = -spacing;
int i = start + count - 1; int i = start + count - 1;
do do
{ {
size += definitions[i].SizeCache; size += spacing + definitions[i].SizeCache;
} while (--i >= start); } while (--i >= start);
return (size); return size;
} }
/// <summary> /// <summary>

42
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); 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 private class TestControl : Control
{ {
public Size MeasureSize { get; set; } public Size MeasureSize { get; set; }

Loading…
Cancel
Save