@ -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 dependenci es. 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 , _l astArrangeSize . Height ) ;
if ( grid . ColumnSpacing ! = 0 )
{
DrawGridLine (
drawingContext ,
grid . ColumnDefinitions [ i ] . FinalOffset - grid . ColumnSpacing , 0.0 ,
grid . ColumnDefinitions [ i ] . FinalOffset - grid . ColumnSpacing , _l astArrangeSize . Height ) ;
}
}
for ( int i = 1 ; i < grid . RowDefinitions . Count ; + + i )
@ -3277,6 +3333,14 @@ namespace Avalonia.Controls
drawingContext ,
0.0 , grid . RowDefinitions [ i ] . FinalOffset ,
_l astArrangeSize . Width , grid . RowDefinitions [ i ] . FinalOffset ) ;
if ( grid . RowSpacing ! = 0 )
{
DrawGridLine (
drawingContext ,
0.0 , grid . RowDefinitions [ i ] . FinalOffset - grid . RowSpacing ,
_l astArrangeSize . Width , grid . RowDefinitions [ i ] . FinalOffset - grid . RowSpacing ) ;
}
}
}