|
|
@@ -25,6 +25,8 @@ namespace Avalonia.Controls
|
|
|
static Grid()
|
|
|
{
|
|
|
ShowGridLinesProperty.Changed.AddClassHandler<Grid>(OnShowGridLinesPropertyChanged);
|
|
|
+ ColumnSpacingProperty.Changed.AddClassHandler<Control>(OnSpacingPropertyChanged);
|
|
|
+ RowSpacingProperty.Changed.AddClassHandler<Control>(OnSpacingPropertyChanged);
|
|
|
|
|
|
IsSharedSizeScopeProperty.Changed.AddClassHandler<Control>(DefinitionBase.OnIsSharedSizeScopePropertyChanged);
|
|
|
ColumnProperty.Changed.AddClassHandler<Control>(OnCellAttachedPropertyChanged);
|
|
|
@@ -32,6 +34,7 @@ namespace Avalonia.Controls
|
|
|
RowProperty.Changed.AddClassHandler<Control>(OnCellAttachedPropertyChanged);
|
|
|
RowSpanProperty.Changed.AddClassHandler<Control>(OnCellAttachedPropertyChanged);
|
|
|
|
|
|
+ AffectsMeasure<Grid>(ColumnSpacingProperty, RowSpacingProperty);
|
|
|
AffectsParentMeasure<Grid>(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty);
|
|
|
}
|
|
|
|
|
|
@@ -161,6 +164,24 @@ namespace Avalonia.Controls
|
|
|
set => SetValue(ShowGridLinesProperty, value);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets the size of the spacing to place between grid rows.
|
|
|
+ /// </summary>
|
|
|
+ public double RowSpacing
|
|
|
+ {
|
|
|
+ get => GetValue(RowSpacingProperty);
|
|
|
+ set => SetValue(RowSpacingProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets the size of the spacing to place between grid columns.
|
|
|
+ /// </summary>
|
|
|
+ public double ColumnSpacing
|
|
|
+ {
|
|
|
+ get => GetValue(ColumnSpacingProperty);
|
|
|
+ set => SetValue(ColumnSpacingProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Returns a ColumnDefinitions of column definitions.
|
|
|
/// </summary>
|
|
|
@@ -299,7 +320,7 @@ namespace Avalonia.Controls
|
|
|
// the cells belonging to them.
|
|
|
//
|
|
|
// However, there are cases when topology of a grid causes cyclical
|
|
|
- // size dependences. For example:
|
|
|
+ // size dependencies. For example:
|
|
|
//
|
|
|
//
|
|
|
// column width="Auto" column width="*"
|
|
|
@@ -425,17 +446,19 @@ 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);
|
|
|
{
|
|
|
// after Group1 is measured, only Group3 may have cells belonging to Auto rows.
|
|
|
bool canResolveStarsV = !HasGroup3CellsInAutoRows;
|
|
|
|
|
|
if (canResolveStarsV)
|
|
|
{
|
|
|
- if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); }
|
|
|
- MeasureCellsGroup(extData.CellGroup2, constraint, false, false);
|
|
|
- if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
|
|
|
- MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
|
|
|
+ if (HasStarCellsV) { ResolveStar(DefinitionsV, innerAvailableSize.Height); }
|
|
|
+ MeasureCellsGroup(extData.CellGroup2, innerAvailableSize, false, false);
|
|
|
+ if (HasStarCellsU) { ResolveStar(DefinitionsU, innerAvailableSize.Width); }
|
|
|
+ MeasureCellsGroup(extData.CellGroup3, innerAvailableSize, false, false);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -444,9 +467,9 @@ namespace Avalonia.Controls
|
|
|
bool canResolveStarsU = extData.CellGroup2 > PrivateCells.Length;
|
|
|
if (canResolveStarsU)
|
|
|
{
|
|
|
- if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
|
|
|
- MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
|
|
|
- if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); }
|
|
|
+ if (HasStarCellsU) { ResolveStar(DefinitionsU, innerAvailableSize.Width); }
|
|
|
+ MeasureCellsGroup(extData.CellGroup3, innerAvailableSize, false, false);
|
|
|
+ if (HasStarCellsV) { ResolveStar(DefinitionsV, innerAvailableSize.Height); }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -462,7 +485,7 @@ namespace Avalonia.Controls
|
|
|
double[] group2MinSizes = CacheMinSizes(extData.CellGroup2, false);
|
|
|
double[] group3MinSizes = CacheMinSizes(extData.CellGroup3, true);
|
|
|
|
|
|
- MeasureCellsGroup(extData.CellGroup2, constraint, false, true);
|
|
|
+ MeasureCellsGroup(extData.CellGroup2, innerAvailableSize, false, true);
|
|
|
|
|
|
do
|
|
|
{
|
|
|
@@ -472,14 +495,14 @@ namespace Avalonia.Controls
|
|
|
ApplyCachedMinSizes(group3MinSizes, true);
|
|
|
}
|
|
|
|
|
|
- if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
|
|
|
- MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
|
|
|
+ if (HasStarCellsU) { ResolveStar(DefinitionsU, innerAvailableSize.Width); }
|
|
|
+ MeasureCellsGroup(extData.CellGroup3, innerAvailableSize, false, false);
|
|
|
|
|
|
// Reset cached Group2Widths
|
|
|
ApplyCachedMinSizes(group2MinSizes, false);
|
|
|
|
|
|
- if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); }
|
|
|
- MeasureCellsGroup(extData.CellGroup2, constraint, cnt == c_layoutLoopMaxCount, false, out hasDesiredSizeUChanged);
|
|
|
+ if (HasStarCellsV) { ResolveStar(DefinitionsV, innerAvailableSize.Height); }
|
|
|
+ MeasureCellsGroup(extData.CellGroup2, innerAvailableSize, cnt == c_layoutLoopMaxCount, false, out hasDesiredSizeUChanged);
|
|
|
}
|
|
|
while (hasDesiredSizeUChanged && ++cnt <= c_layoutLoopMaxCount);
|
|
|
}
|
|
|
@@ -489,8 +512,8 @@ namespace Avalonia.Controls
|
|
|
MeasureCellsGroup(extData.CellGroup4, constraint, false, false);
|
|
|
|
|
|
gridDesiredSize = new Size(
|
|
|
- CalculateDesiredSize(DefinitionsU),
|
|
|
- CalculateDesiredSize(DefinitionsV));
|
|
|
+ CalculateDesiredSize(DefinitionsU) + ColumnSpacing * (DefinitionsU.Count - 1),
|
|
|
+ CalculateDesiredSize(DefinitionsV) + RowSpacing * (DefinitionsU.Count - 1));
|
|
|
}
|
|
|
}
|
|
|
finally
|
|
|
@@ -524,9 +547,12 @@ namespace Avalonia.Controls
|
|
|
else
|
|
|
{
|
|
|
Debug.Assert(DefinitionsU.Count > 0 && DefinitionsV.Count > 0);
|
|
|
-
|
|
|
- SetFinalSize(DefinitionsU, arrangeSize.Width, true);
|
|
|
- SetFinalSize(DefinitionsV, arrangeSize.Height, false);
|
|
|
+ double columnSpacing = ColumnSpacing;
|
|
|
+ double rowSpacing = RowSpacing;
|
|
|
+ double combinedRowSpacing = rowSpacing * (RowDefinitions.Count - 1);
|
|
|
+ double combinedColumnSpacing = columnSpacing * (ColumnDefinitions.Count - 1);
|
|
|
+ SetFinalSize(DefinitionsU, arrangeSize.Width - combinedColumnSpacing, true);
|
|
|
+ SetFinalSize(DefinitionsV, arrangeSize.Height - combinedRowSpacing, false);
|
|
|
|
|
|
var children = Children;
|
|
|
|
|
|
@@ -540,14 +566,13 @@ namespace Avalonia.Controls
|
|
|
int rowSpan = PrivateCells[currentCell].RowSpan;
|
|
|
|
|
|
Rect cellRect = new Rect(
|
|
|
- columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset,
|
|
|
- rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset,
|
|
|
+ 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));
|
|
|
|
|
|
|
|
|
cell.Arrange(cellRect);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
// update render bound on grid lines renderer visual
|
|
|
@@ -2088,7 +2113,7 @@ namespace Avalonia.Controls
|
|
|
// double dpi = columns ? dpiScale.DpiScaleX : dpiScale.DpiScaleY;
|
|
|
var dpi = (VisualRoot as ILayoutRoot)?.LayoutScaling ?? 1.0;
|
|
|
double[] roundingErrors = RoundingErrors;
|
|
|
- double roundedTakenSize = 0.0;
|
|
|
+ double roundedTakenSize = 0;
|
|
|
|
|
|
// round each of the allocated sizes, keeping track of the deltas
|
|
|
for (int i = 0; i < definitions.Count; ++i)
|
|
|
@@ -2363,6 +2388,17 @@ namespace Avalonia.Controls
|
|
|
grid.SetFlags((bool)e.NewValue!, Flags.ShowGridLinesPropertyValue);
|
|
|
}
|
|
|
|
|
|
+ private static void OnSpacingPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
|
|
|
+ {
|
|
|
+ Grid grid = (Grid)d;
|
|
|
+
|
|
|
+ if (grid._extData != null
|
|
|
+ && grid.ListenToNotifications)
|
|
|
+ {
|
|
|
+ grid.CellsStructureDirty = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
|
|
|
{
|
|
|
if (d is Visual child)
|
|
|
@@ -2674,6 +2710,18 @@ namespace Avalonia.Controls
|
|
|
public static readonly StyledProperty<bool> ShowGridLinesProperty =
|
|
|
AvaloniaProperty.Register<Grid, bool>(nameof(ShowGridLines));
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="RowSpacing"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly StyledProperty<double> RowSpacingProperty =
|
|
|
+ AvaloniaProperty.Register<Grid, double>(nameof(RowSpacing));
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="ColumnSpacing"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly StyledProperty<double> ColumnSpacingProperty =
|
|
|
+ AvaloniaProperty.Register<Grid, double>(nameof(ColumnSpacingProperty));
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Column property. This is an attached property.
|
|
|
/// Grid defines Column property, so that it can be set
|
|
|
@@ -3269,6 +3317,14 @@ namespace Avalonia.Controls
|
|
|
drawingContext,
|
|
|
grid.ColumnDefinitions[i].FinalOffset, 0.0,
|
|
|
grid.ColumnDefinitions[i].FinalOffset, _lastArrangeSize.Height);
|
|
|
+
|
|
|
+ if (grid.ColumnSpacing != 0)
|
|
|
+ {
|
|
|
+ DrawGridLine(
|
|
|
+ drawingContext,
|
|
|
+ grid.ColumnDefinitions[i].FinalOffset - grid.ColumnSpacing, 0.0,
|
|
|
+ grid.ColumnDefinitions[i].FinalOffset - grid.ColumnSpacing, _lastArrangeSize.Height);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
for (int i = 1; i < grid.RowDefinitions.Count; ++i)
|
|
|
@@ -3277,6 +3333,14 @@ namespace Avalonia.Controls
|
|
|
drawingContext,
|
|
|
0.0, grid.RowDefinitions[i].FinalOffset,
|
|
|
_lastArrangeSize.Width, grid.RowDefinitions[i].FinalOffset);
|
|
|
+
|
|
|
+ if (grid.RowSpacing != 0)
|
|
|
+ {
|
|
|
+ DrawGridLine(
|
|
|
+ drawingContext,
|
|
|
+ 0.0, grid.RowDefinitions[i].FinalOffset - grid.RowSpacing,
|
|
|
+ _lastArrangeSize.Width, grid.RowDefinitions[i].FinalOffset - grid.RowSpacing);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|