From ea9a2724284d85295c4b569abd6225ec6736b9c0 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 10:12:43 +0800 Subject: [PATCH 01/26] make row/col definitions styleable --- src/Avalonia.Controls/Grid.cs | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 6357ec98a8f..85f2611a835 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -32,6 +32,7 @@ static Grid() RowSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty); + } /// @@ -160,44 +161,54 @@ public bool ShowGridLines set { SetValue(ShowGridLinesProperty, value); } } - /// - /// Returns a ColumnDefinitions of column definitions. - /// + public static readonly StyledProperty ColumnDefinitionsProperty = + AvaloniaProperty.Register(nameof(ColumnDefinitions)); + public ColumnDefinitions ColumnDefinitions { get { if (_data == null) { _data = new ExtendedData(); } - if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; } + if (_data.ColumnDefinitions == null) + { + _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; + SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); + } - return (_data.ColumnDefinitions); + return GetValue(ColumnDefinitionsProperty); } set { if (_data == null) { _data = new ExtendedData(); } _data.ColumnDefinitions = value; _data.ColumnDefinitions.Parent = this; + SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); InvalidateMeasure(); } } - /// - /// Returns a RowDefinitions of row definitions. - /// + public static readonly StyledProperty RowDefinitionsProperty = + AvaloniaProperty.Register(nameof(RowDefinitions)); + public RowDefinitions RowDefinitions { get { if (_data == null) { _data = new ExtendedData(); } - if (_data.RowDefinitions == null) { _data.RowDefinitions = new RowDefinitions() { Parent = this }; } + if (_data.RowDefinitions == null) + { + _data.RowDefinitions = new RowDefinitions() { Parent = this }; + SetValue(RowDefinitionsProperty, _data.RowDefinitions); + } - return (_data.RowDefinitions); + return GetValue(RowDefinitionsProperty); } set { if (_data == null) { _data = new ExtendedData(); } _data.RowDefinitions = value; _data.RowDefinitions.Parent = this; + SetValue(RowDefinitionsProperty, _data.RowDefinitions); InvalidateMeasure(); } } @@ -2314,7 +2325,7 @@ private void SetValid() } } } - + /// /// Synchronized ShowGridLines property with the state of the grid's visual collection /// by adding / removing GridLinesRenderer visual. From ba3cc0fa42ac9b7a981c1470a82de1808145c75a Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 11:18:50 +0800 Subject: [PATCH 02/26] make the magic happen --- src/Avalonia.Controls/Grid.cs | 60 ++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 85f2611a835..e111541e84e 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -23,18 +23,54 @@ public class Grid : Panel { static Grid() { - ShowGridLinesProperty.Changed.AddClassHandler(OnShowGridLinesPropertyChanged); + ShowGridLinesProperty.Changed.AddClassHandler((Action)OnShowGridLinesPropertyChanged); - IsSharedSizeScopeProperty.Changed.AddClassHandler(DefinitionBase.OnIsSharedSizeScopePropertyChanged); - ColumnProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); - ColumnSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); - RowProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); - RowSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); + IsSharedSizeScopeProperty.Changed.AddClassHandler((Action)DefinitionBase.OnIsSharedSizeScopePropertyChanged); + ColumnProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); + ColumnSpanProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); + RowProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); + RowSpanProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); - AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty); + AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty, ColumnDefinitionsProperty, RowDefinitionsProperty); + AffectsMeasure(ColumnDefinitionsProperty, RowDefinitionsProperty); + RowDefinitionsProperty.Changed.AddClassHandler(RowDefinitionsPropertyChanged); + ColumnDefinitionsProperty.Changed.AddClassHandler(ColumnDefinitionsPropertyChanged); } + private static void ColumnDefinitionsPropertyChanged(Grid arg1, AvaloniaPropertyChangedEventArgs arg2) + { + var val = arg2.NewValue as ColumnDefinitions; + ColumnDefinitionsPropertyChangedCore(arg1, val); + } + + private static void ColumnDefinitionsPropertyChangedCore(Grid arg1, ColumnDefinitions arg2) + { + if (arg1._data is null) + arg1._data = new ExtendedData(); + + arg1._data!.ColumnDefinitions = arg2; + arg1._data!.ColumnDefinitions.IsDirty = true; + arg1._data!.ColumnDefinitions.Parent = arg1; + } + + private static void RowDefinitionsPropertyChanged(Grid arg1, AvaloniaPropertyChangedEventArgs arg2) + { + var val = arg2.NewValue as RowDefinitions; + RowDefinitionsPropertyChangedCore(arg1, val); + } + + private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg2) + { + if (arg1._data is null) + arg1._data = new ExtendedData(); + + arg1._data!.RowDefinitions = arg2; + arg1._data!.RowDefinitions.IsDirty = true; + arg1._data!.RowDefinitions.Parent = arg1; + } +/// + /// /// Default constructor. /// @@ -179,11 +215,8 @@ public ColumnDefinitions ColumnDefinitions } set { - if (_data == null) { _data = new ExtendedData(); } - _data.ColumnDefinitions = value; - _data.ColumnDefinitions.Parent = this; + ColumnDefinitionsPropertyChangedCore(this, value); SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); - InvalidateMeasure(); } } @@ -205,11 +238,8 @@ public RowDefinitions RowDefinitions } set { - if (_data == null) { _data = new ExtendedData(); } - _data.RowDefinitions = value; - _data.RowDefinitions.Parent = this; + RowDefinitionsPropertyChangedCore(this, value); SetValue(RowDefinitionsProperty, _data.RowDefinitions); - InvalidateMeasure(); } } From a7f5cd5a414e48943cb8118e0fbc2e7fcbd53a6a Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 11:26:57 +0800 Subject: [PATCH 03/26] add null check --- src/Avalonia.Controls/Grid.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index e111541e84e..88a84bf90bb 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -46,6 +46,8 @@ private static void ColumnDefinitionsPropertyChanged(Grid arg1, AvaloniaProperty private static void ColumnDefinitionsPropertyChangedCore(Grid arg1, ColumnDefinitions arg2) { + if (arg2 is null) return; + if (arg1._data is null) arg1._data = new ExtendedData(); @@ -62,6 +64,8 @@ private static void RowDefinitionsPropertyChanged(Grid arg1, AvaloniaPropertyCha private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg2) { + if (arg2 is null) return; + if (arg1._data is null) arg1._data = new ExtendedData(); @@ -69,7 +73,6 @@ private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg1._data!.RowDefinitions.IsDirty = true; arg1._data!.RowDefinitions.Parent = arg1; } -/// /// /// Default constructor. From ee3e5cea144347b94f8e72d20f0836ec97f9861e Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 12:55:18 +0800 Subject: [PATCH 04/26] nit fixes --- src/Avalonia.Controls/Grid.cs | 122 ++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 88a84bf90bb..e3ed8762077 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -38,42 +38,6 @@ static Grid() ColumnDefinitionsProperty.Changed.AddClassHandler(ColumnDefinitionsPropertyChanged); } - private static void ColumnDefinitionsPropertyChanged(Grid arg1, AvaloniaPropertyChangedEventArgs arg2) - { - var val = arg2.NewValue as ColumnDefinitions; - ColumnDefinitionsPropertyChangedCore(arg1, val); - } - - private static void ColumnDefinitionsPropertyChangedCore(Grid arg1, ColumnDefinitions arg2) - { - if (arg2 is null) return; - - if (arg1._data is null) - arg1._data = new ExtendedData(); - - arg1._data!.ColumnDefinitions = arg2; - arg1._data!.ColumnDefinitions.IsDirty = true; - arg1._data!.ColumnDefinitions.Parent = arg1; - } - - private static void RowDefinitionsPropertyChanged(Grid arg1, AvaloniaPropertyChangedEventArgs arg2) - { - var val = arg2.NewValue as RowDefinitions; - RowDefinitionsPropertyChangedCore(arg1, val); - } - - private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg2) - { - if (arg2 is null) return; - - if (arg1._data is null) - arg1._data = new ExtendedData(); - - arg1._data!.RowDefinitions = arg2; - arg1._data!.RowDefinitions.IsDirty = true; - arg1._data!.RowDefinitions.Parent = arg1; - } - /// /// Default constructor. /// @@ -192,7 +156,9 @@ public static bool GetIsSharedSizeScope(Control element) } /// - /// ShowGridLines property. + /// This property is used mostly for simplification of visual debugging. + /// When it is set to true, grid lines are drawn + /// to visualize location of grid lines. /// public bool ShowGridLines { @@ -200,15 +166,17 @@ public bool ShowGridLines set { SetValue(ShowGridLinesProperty, value); } } - public static readonly StyledProperty ColumnDefinitionsProperty = - AvaloniaProperty.Register(nameof(ColumnDefinitions)); - + /// + /// A list of objects defined on this instance of . + /// public ColumnDefinitions ColumnDefinitions { get { - if (_data == null) { _data = new ExtendedData(); } - if (_data.ColumnDefinitions == null) + if (_data is null) + _data = new ExtendedData(); + + if (_data.ColumnDefinitions is null) { _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); @@ -223,9 +191,9 @@ public ColumnDefinitions ColumnDefinitions } } - public static readonly StyledProperty RowDefinitionsProperty = - AvaloniaProperty.Register(nameof(RowDefinitions)); - + /// + /// A list of objects defined on this instance of . + /// public RowDefinitions RowDefinitions { get @@ -2444,6 +2412,52 @@ private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaProp } } + private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) + { + var val = e.NewValue as ColumnDefinitions; + ColumnDefinitionsPropertyChangedCore(target, val); + } + + /// + /// Reflects the changes on the ColumnDefinition StyledProperty + /// to the backing ExtendedData class. + /// + private static void ColumnDefinitionsPropertyChangedCore(Grid target, ColumnDefinitions colDef) + { + if (colDef is null) + return; + + if (target._data is null) + target._data = new ExtendedData(); + + target._data.ColumnDefinitions = colDef; + target._data.ColumnDefinitions.IsDirty = true; + target._data.ColumnDefinitions.Parent = target; + } + + private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs rowDef) + { + var val = rowDef.NewValue as RowDefinitions; + RowDefinitionsPropertyChangedCore(target, val); + } + + /// + /// Reflects the changes on the RowDefinition StyledProperty + /// to the backing ExtendedData class. + /// + private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg2) + { + if (arg2 is null) + return; + + if (arg1._data is null) + arg1._data = new ExtendedData(); + + arg1._data.RowDefinitions = arg2; + arg1._data.RowDefinitions.IsDirty = true; + arg1._data.RowDefinitions.Parent = arg1; + } + /// /// Helper for Comparer methods. /// @@ -2739,10 +2753,20 @@ private enum Flags } /// - /// ShowGridLines property. This property is used mostly - /// for simplification of visual debuggig. When it is set - /// to true grid lines are drawn to visualize location - /// of grid lines. + /// Defines the property. + /// + public static readonly StyledProperty ColumnDefinitionsProperty = + AvaloniaProperty.Register(nameof(ColumnDefinitions)); + + /// + /// Defines the property. + /// + public static readonly StyledProperty RowDefinitionsProperty = + AvaloniaProperty.Register(nameof(RowDefinitions)); + + + /// + /// Defines the property. /// public static readonly StyledProperty ShowGridLinesProperty = AvaloniaProperty.Register(nameof(ShowGridLines)); From 0a3c39cae711f43b1553a104300a4a7cba193527 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 12:59:45 +0800 Subject: [PATCH 05/26] whatever happened there --- src/Avalonia.Controls/Grid.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index e3ed8762077..d0d52468815 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -23,15 +23,15 @@ public class Grid : Panel { static Grid() { - ShowGridLinesProperty.Changed.AddClassHandler((Action)OnShowGridLinesPropertyChanged); + ShowGridLinesProperty.Changed.AddClassHandler(OnShowGridLinesPropertyChanged); - IsSharedSizeScopeProperty.Changed.AddClassHandler((Action)DefinitionBase.OnIsSharedSizeScopePropertyChanged); - ColumnProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); - ColumnSpanProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); - RowProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); - RowSpanProperty.Changed.AddClassHandler((Action)OnCellAttachedPropertyChanged); + IsSharedSizeScopeProperty.Changed.AddClassHandler(DefinitionBase.OnIsSharedSizeScopePropertyChanged); + ColumnProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); + ColumnSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); + RowProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); + RowSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); - AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty, ColumnDefinitionsProperty, RowDefinitionsProperty); + AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty); AffectsMeasure(ColumnDefinitionsProperty, RowDefinitionsProperty); RowDefinitionsProperty.Changed.AddClassHandler(RowDefinitionsPropertyChanged); @@ -2440,7 +2440,7 @@ private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyC var val = rowDef.NewValue as RowDefinitions; RowDefinitionsPropertyChangedCore(target, val); } - + /// /// Reflects the changes on the RowDefinition StyledProperty /// to the backing ExtendedData class. From f8df56fe8f75cacbc464b70b2d142a066525c049 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 13:02:17 +0800 Subject: [PATCH 06/26] rename --- src/Avalonia.Controls/Grid.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index d0d52468815..1709602c705 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -186,7 +186,7 @@ public ColumnDefinitions ColumnDefinitions } set { - ColumnDefinitionsPropertyChangedCore(this, value); + SynchronizeColumnDefinitions(this, value); SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); } } @@ -209,7 +209,7 @@ public RowDefinitions RowDefinitions } set { - RowDefinitionsPropertyChangedCore(this, value); + SynchronizeRowDefinitions(this, value); SetValue(RowDefinitionsProperty, _data.RowDefinitions); } } @@ -2415,14 +2415,14 @@ private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaProp private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) { var val = e.NewValue as ColumnDefinitions; - ColumnDefinitionsPropertyChangedCore(target, val); + SynchronizeColumnDefinitions(target, val); } /// /// Reflects the changes on the ColumnDefinition StyledProperty /// to the backing ExtendedData class. /// - private static void ColumnDefinitionsPropertyChangedCore(Grid target, ColumnDefinitions colDef) + private static void SynchronizeColumnDefinitions(Grid target, ColumnDefinitions colDef) { if (colDef is null) return; @@ -2438,14 +2438,14 @@ private static void ColumnDefinitionsPropertyChangedCore(Grid target, ColumnDefi private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs rowDef) { var val = rowDef.NewValue as RowDefinitions; - RowDefinitionsPropertyChangedCore(target, val); + SynchronizeRowDefinitions(target, val); } /// /// Reflects the changes on the RowDefinition StyledProperty /// to the backing ExtendedData class. /// - private static void RowDefinitionsPropertyChangedCore(Grid arg1, RowDefinitions arg2) + private static void SynchronizeRowDefinitions(Grid arg1, RowDefinitions arg2) { if (arg2 is null) return; From db6d99cf23619f55a165137d3b220d47f8236f67 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 13:56:06 +0800 Subject: [PATCH 07/26] nit --- src/Avalonia.Controls/Grid.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 1709602c705..36022e1f8e6 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -2445,17 +2445,17 @@ private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyC /// Reflects the changes on the RowDefinition StyledProperty /// to the backing ExtendedData class. /// - private static void SynchronizeRowDefinitions(Grid arg1, RowDefinitions arg2) + private static void SynchronizeRowDefinitions(Grid target, RowDefinitions rowDef) { - if (arg2 is null) + if (rowDef is null) return; - if (arg1._data is null) - arg1._data = new ExtendedData(); + if (target._data is null) + target._data = new ExtendedData(); - arg1._data.RowDefinitions = arg2; - arg1._data.RowDefinitions.IsDirty = true; - arg1._data.RowDefinitions.Parent = arg1; + target._data.RowDefinitions = rowDef; + target._data.RowDefinitions.IsDirty = true; + target._data.RowDefinitions.Parent = target; } /// From c0a04694616570ff50f048be51028b3625473545 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 13:57:34 +0800 Subject: [PATCH 08/26] simplify --- src/Avalonia.Controls/Grid.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 36022e1f8e6..76aa0a33354 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -2430,9 +2430,9 @@ private static void SynchronizeColumnDefinitions(Grid target, ColumnDefinitions if (target._data is null) target._data = new ExtendedData(); + colDef.IsDirty = true; + colDef.Parent = target; target._data.ColumnDefinitions = colDef; - target._data.ColumnDefinitions.IsDirty = true; - target._data.ColumnDefinitions.Parent = target; } private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs rowDef) @@ -2453,9 +2453,9 @@ private static void SynchronizeRowDefinitions(Grid target, RowDefinitions rowDef if (target._data is null) target._data = new ExtendedData(); + rowDef.IsDirty = true; + rowDef.Parent = target; target._data.RowDefinitions = rowDef; - target._data.RowDefinitions.IsDirty = true; - target._data.RowDefinitions.Parent = target; } /// From af197facaebb1a0355418cd3eb4717d07576c457 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 14:35:39 +0800 Subject: [PATCH 09/26] handle non-matching row/col changes --- src/Avalonia.Controls/Grid.cs | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 76aa0a33354..ab69c52c1db 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -276,7 +276,13 @@ protected override Size MeasureOverride(Size constraint) ValidateDefinitionsVStructure(); ValidateDefinitionsLayout(DefinitionsV, sizeToContentV); - CellsStructureDirty |= (SizeToContentU != sizeToContentU) || (SizeToContentV != sizeToContentV); + CellsStructureDirty = (SizeToContentU != sizeToContentU) || + (SizeToContentV != sizeToContentV) || + _data.OldColumnCount != DefinitionsU.Count || + _data.OldRowCount != DefinitionsV.Count; + + _data.OldColumnCount = DefinitionsU.Count; + _data.OldRowCount = DefinitionsV.Count; SizeToContentU = sizeToContentU; SizeToContentV = sizeToContentV; @@ -2705,17 +2711,19 @@ static double StarWeight(DefinitionBase def, double scale) /// private class ExtendedData { - internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support) - internal RowDefinitions RowDefinitions; // collection of row definitions (logical tree support) - internal IReadOnlyList DefinitionsU; // collection of column definitions used during calc - internal IReadOnlyList DefinitionsV; // collection of row definitions used during calc - internal CellCache[] CellCachesCollection; // backing store for logical children - internal int CellGroup1; // index of the first cell in first cell group - internal int CellGroup2; // index of the first cell in second cell group - internal int CellGroup3; // index of the first cell in third cell group - internal int CellGroup4; // index of the first cell in forth cell group - internal DefinitionBase[] TempDefinitions; // temporary array used during layout for various purposes - // TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length) + internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support) + internal RowDefinitions RowDefinitions; // Collection of row definitions (logical tree support) + internal IReadOnlyList DefinitionsU; // Collection of column definitions used during calc + internal IReadOnlyList DefinitionsV; // Collection of row definitions used during calc + internal CellCache[] CellCachesCollection; // Backing store for logical children + internal int CellGroup1; // Index of the first cell in first cell group + internal int CellGroup2; // Index of the first cell in second cell group + internal int CellGroup3; // Index of the first cell in third cell group + internal int CellGroup4; // Index of the first cell in forth cell group + internal DefinitionBase[] TempDefinitions; // Temporary array used during layout for various purposes + // TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length) + internal int OldColumnCount; // Count of the previous column definition list. Invalidates the cells when it doesn't match up. + internal int OldRowCount; // Count of the previous row definition list. Invalidates the cells when it doesn't match up. } /// From d68323c82165ac840dbd4d887fd1a6e7e6177e87 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 15:59:40 +0800 Subject: [PATCH 10/26] handle row/col change in definition count --- src/Avalonia.Controls/Grid.cs | 42 ++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index ab69c52c1db..7e98fdf071f 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -36,6 +36,7 @@ static Grid() RowDefinitionsProperty.Changed.AddClassHandler(RowDefinitionsPropertyChanged); ColumnDefinitionsProperty.Changed.AddClassHandler(ColumnDefinitionsPropertyChanged); + } /// @@ -554,23 +555,25 @@ protected override Size ArrangeOverride(Size arrangeSize) for (int currentCell = 0; currentCell < PrivateCells.Length; ++currentCell) { var cell = children[currentCell]; - if (cell == null) + var privCell = PrivateCells[currentCell]; + + if (cell is null || privCell.Skip) { + cell.Arrange(new Rect(arrangeSize)); continue; } - int columnIndex = PrivateCells[currentCell].ColumnIndex; - int rowIndex = PrivateCells[currentCell].RowIndex; - int columnSpan = PrivateCells[currentCell].ColumnSpan; - int rowSpan = PrivateCells[currentCell].RowSpan; + int columnIndex = privCell.ColumnIndex; + int rowIndex = privCell.RowIndex; + int columnSpan = privCell.ColumnSpan; + int rowSpan = privCell.RowSpan; - Rect cellRect = new Rect( + var cellRect = new Rect( columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset, rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset, GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan), GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan)); - cell.Arrange(cellRect); } @@ -724,28 +727,35 @@ private void ValidateCellsCore() continue; } - CellCache cell = new CellCache(); - + var cell = new CellCache(); + var control = (Control)child; // Read indices from the corresponding properties: // clamp to value < number_of_columns // column >= 0 is guaranteed by property value validation callback - cell.ColumnIndex = Math.Min(GetColumn((Control)child), DefinitionsU.Count - 1); + cell.ColumnIndex = GetColumn(control); // clamp to value < number_of_rows // row >= 0 is guaranteed by property value validation callback - cell.RowIndex = Math.Min(GetRow((Control)child), DefinitionsV.Count - 1); + cell.RowIndex = GetRow(control); // Read span properties: // clamp to not exceed beyond right side of the grid // column_span > 0 is guaranteed by property value validation callback - cell.ColumnSpan = Math.Min(GetColumnSpan((Control)child), DefinitionsU.Count - cell.ColumnIndex); + cell.ColumnSpan = Math.Min(GetColumnSpan(control), DefinitionsU.Count - cell.ColumnIndex); // clamp to not exceed beyond bottom side of the grid // row_span > 0 is guaranteed by property value validation callback - cell.RowSpan = Math.Min(GetRowSpan((Control)child), DefinitionsV.Count - cell.RowIndex); + cell.RowSpan = Math.Min(GetRowSpan(control), DefinitionsV.Count - cell.RowIndex); - Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < DefinitionsU.Count); - Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Count); + var isOverCol = cell.ColumnIndex < 0 || cell.ColumnIndex > (DefinitionsU.Count - 1); + var isOverRow = cell.RowIndex < 0 || cell.RowIndex > (DefinitionsV.Count - 1); + + if (isOverCol || isOverRow) + { + cell.Skip = true; + PrivateCells[i] = cell; + continue; + } // Calculate and cache length types for the child. @@ -1017,6 +1027,7 @@ private void MeasureCellsGroup( int i = cellsHead; do { + double oldWidth = children[i].DesiredSize.Width; MeasureCell(i, forceInfinityV); @@ -2872,6 +2883,7 @@ internal enum LayoutTimeSizeType : byte /// private struct CellCache { + internal bool Skip; internal int ColumnIndex; internal int RowIndex; internal int ColumnSpan; From 7ea79cc2786da10372278b1bca8899aeac004636 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 16:09:45 +0800 Subject: [PATCH 11/26] Fix test --- src/Avalonia.Controls/Grid.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 7e98fdf071f..9ac63b7bd92 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -277,7 +277,10 @@ protected override Size MeasureOverride(Size constraint) ValidateDefinitionsVStructure(); ValidateDefinitionsLayout(DefinitionsV, sizeToContentV); - CellsStructureDirty = (SizeToContentU != sizeToContentU) || + // Include the prior value just in case it was explicitly + // is done set before Measure + CellsStructureDirty = CellsStructureDirty || + (SizeToContentU != sizeToContentU) || (SizeToContentV != sizeToContentV) || _data.OldColumnCount != DefinitionsU.Count || _data.OldRowCount != DefinitionsV.Count; @@ -2613,7 +2616,7 @@ private bool CellsStructureDirty get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } set { SetFlags(!value, Flags.ValidCellsStructure); } } - + /// /// Convenience accessor to ListenToNotifications bit flag. /// From 6eaea94ecc09d23e8311b9ef83cf7c0d13194ed1 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 29 Jul 2020 16:11:41 +0800 Subject: [PATCH 12/26] nits --- src/Avalonia.Controls/Grid.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 9ac63b7bd92..fc787d98896 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -278,10 +278,11 @@ protected override Size MeasureOverride(Size constraint) ValidateDefinitionsLayout(DefinitionsV, sizeToContentV); // Include the prior value just in case it was explicitly - // is done set before Measure + // set before Measure was called. + CellsStructureDirty = CellsStructureDirty || - (SizeToContentU != sizeToContentU) || - (SizeToContentV != sizeToContentV) || + SizeToContentU != sizeToContentU || + SizeToContentV != sizeToContentV || _data.OldColumnCount != DefinitionsU.Count || _data.OldRowCount != DefinitionsV.Count; From 5753ff5c9554985ad01169e010e3883a90012e13 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Thu, 6 Aug 2020 16:52:47 +0800 Subject: [PATCH 13/26] add unit test --- .../Avalonia.Controls.UnitTests/GridTests.cs | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 4ffa526b855..db4ca01cbf9 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -211,6 +211,86 @@ public void Layout_StarRowColumnWithMaxLength_BoundsCorrect() GridAssert.ChildrenWidth(columnGrid, 200, 300, 300); } + [Fact] + public void Row_Definition_Cardinality_Change_Triggers_Measure_In_Child() + { + var target = new Grid + { + Height = 100, + RowDefinitions = new RowDefinitions("*,*"), + Children = + { + new Panel + { + [Grid.RowProperty] = 0, + [Grid.RowSpanProperty] = 1, + }, + new Panel + { + [Grid.RowProperty] = 1, + [Grid.RowSpanProperty] = 1, + }, + } + }; + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.True(target.IsMeasureValid); + + Assert.Equal(50, target.Children[0].Bounds.Height); + Assert.Equal(50, target.Children[1].Bounds.Height); + + target.RowDefinitions = new RowDefinitions("*"); + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + Assert.True(target.IsMeasureValid); + + Assert.Equal(100, target.Children[0].Bounds.Height); + Assert.Equal(100, target.Children[1].Bounds.Height); + } + + + [Fact] + public void Column_Definition_Cardinality_Change_Triggers_Measure_In_Child() + { + var target = new Grid + { + Width = 100, + ColumnDefinitions = new ColumnDefinitions("*,*"), + Children = + { + new Panel + { + [Grid.ColumnProperty] = 0, + [Grid.ColumnSpanProperty] = 1, + }, + new Panel + { + [Grid.ColumnProperty] = 1, + [Grid.ColumnSpanProperty] = 1, + }, + } + }; + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + Assert.True(target.IsMeasureValid); + + Assert.Equal(50, target.Children[0].Bounds.Width); + Assert.Equal(50, target.Children[1].Bounds.Width); + + target.ColumnDefinitions = new ColumnDefinitions("*"); + + target.Measure(Size.Infinity); + target.Arrange(new Rect(target.DesiredSize)); + Assert.True(target.IsMeasureValid); + + Assert.Equal(100, target.Children[0].Bounds.Width); + Assert.Equal(100, target.Children[1].Bounds.Width); + } + [Fact] public void Changing_Child_Column_Invalidates_Measure() { From 9d14e0b71882caca81329596ecdead250cc753fc Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 7 Aug 2020 19:35:46 +0800 Subject: [PATCH 14/26] ugly fix --- src/Avalonia.Controls/Grid.cs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index fc787d98896..630f5ed0548 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -44,6 +44,13 @@ static Grid() /// public Grid() { + _data = new ExtendedData(); + + _data.RowDefinitions = new RowDefinitions() { Parent = this }; + RowDefinitions = _data.RowDefinitions; + + _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; + ColumnDefinitions = _data.ColumnDefinitions; } /// @@ -174,15 +181,6 @@ public ColumnDefinitions ColumnDefinitions { get { - if (_data is null) - _data = new ExtendedData(); - - if (_data.ColumnDefinitions is null) - { - _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; - SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); - } - return GetValue(ColumnDefinitionsProperty); } set @@ -199,13 +197,6 @@ public RowDefinitions RowDefinitions { get { - if (_data == null) { _data = new ExtendedData(); } - if (_data.RowDefinitions == null) - { - _data.RowDefinitions = new RowDefinitions() { Parent = this }; - SetValue(RowDefinitionsProperty, _data.RowDefinitions); - } - return GetValue(RowDefinitionsProperty); } set @@ -2617,7 +2608,7 @@ private bool CellsStructureDirty get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } set { SetFlags(!value, Flags.ValidCellsStructure); } } - + /// /// Convenience accessor to ListenToNotifications bit flag. /// From 4af4000ed2e94484d8cc76b4b74dfd926dd61512 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 7 Aug 2020 19:53:05 +0800 Subject: [PATCH 15/26] revert --- src/Avalonia.Controls/Grid.cs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 630f5ed0548..fc787d98896 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -44,13 +44,6 @@ static Grid() /// public Grid() { - _data = new ExtendedData(); - - _data.RowDefinitions = new RowDefinitions() { Parent = this }; - RowDefinitions = _data.RowDefinitions; - - _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; - ColumnDefinitions = _data.ColumnDefinitions; } /// @@ -181,6 +174,15 @@ public ColumnDefinitions ColumnDefinitions { get { + if (_data is null) + _data = new ExtendedData(); + + if (_data.ColumnDefinitions is null) + { + _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; + SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); + } + return GetValue(ColumnDefinitionsProperty); } set @@ -197,6 +199,13 @@ public RowDefinitions RowDefinitions { get { + if (_data == null) { _data = new ExtendedData(); } + if (_data.RowDefinitions == null) + { + _data.RowDefinitions = new RowDefinitions() { Parent = this }; + SetValue(RowDefinitionsProperty, _data.RowDefinitions); + } + return GetValue(RowDefinitionsProperty); } set @@ -2608,7 +2617,7 @@ private bool CellsStructureDirty get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } set { SetFlags(!value, Flags.ValidCellsStructure); } } - + /// /// Convenience accessor to ListenToNotifications bit flag. /// From c144f5fcb1d56bfef5e43361e791cb6ec959c0ac Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 7 Aug 2020 19:53:58 +0800 Subject: [PATCH 16/26] add more test --- .../Avalonia.Controls.UnitTests/GridTests.cs | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index db4ca01cbf9..211c3e7fc38 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Avalonia.Styling; using Avalonia.UnitTests; using Xunit; using Xunit.Abstractions; @@ -1691,6 +1692,94 @@ public void Removing_Child_Should_Invalidate_Grid_And_Be_Operational() Assert.Equal(100, grid.Children[0].Bounds.Width); } + [Fact] + public void Setting_ColumnDefinition_via_Styles_Should_Apply() + { + using (UnitTestApplication.Start(TestServices.RealStyler)) + { + var grid = new Grid(); + + var root = new TestRoot + { + Styles = + { + new Style(x => x.OfType()) + { + Setters = + { + new Setter(Grid.ColumnDefinitionsProperty, ColumnDefinitions.Parse("*,*")) + } + } + }, + Child = grid, + }; + + grid.Children.Add(new Panel() + { + [Grid.ColumnProperty] = 0, + [Grid.ColumnSpanProperty] = 1 + }); + + grid.Children.Add(new Panel() + { + [Grid.ColumnProperty] = 1, + [Grid.ColumnSpanProperty] = 1 + }); + + var size = new Size(100, 100); + + grid.Measure(size); + + grid.Arrange(new Rect(size)); + + Assert.Equal(50, grid.Children[0].Bounds.Width); + Assert.Equal(50, grid.Children[1].Bounds.Width); + } + } + + [Fact] + public void Setting_RowDefinition_via_Styles_Should_Apply() + { + using (UnitTestApplication.Start(TestServices.RealStyler)) + { + var grid = new Grid(); + + var root = new TestRoot + { + Styles = + { + new Style(x => x.OfType()) + { + Setters = + { + new Setter(Grid.RowDefinitionsProperty, RowDefinitions.Parse("*,*")) + } + } + }, + Child = grid, + }; + + grid.Children.Add(new Panel() + { + [Grid.RowProperty] = 0, + [Grid.RowSpanProperty] = 1 + }); + + grid.Children.Add(new Panel() + { + [Grid.RowProperty] = 1, + [Grid.RowSpanProperty] = 1 + }); + + var size = new Size(100, 100); + grid.Measure(size); + grid.Arrange(new Rect(size)); + + Assert.Equal(50, grid.Children[0].Bounds.Height); + Assert.Equal(50, grid.Children[1].Bounds.Height); + } + } + [Fact] public void Adding_Child_Should_Invalidate_Grid_And_Be_Operational() { From 9bc1ee0ce8dfb4885c44a62ee9ec0859f5cb948b Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 8 Aug 2020 01:43:09 +0800 Subject: [PATCH 17/26] almost passed the tests --- src/Avalonia.Controls/Grid.cs | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index fc787d98896..50045a877fb 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -44,6 +44,23 @@ static Grid() /// public Grid() { + RowDefinitions.CollectionChanged += RowDefColChanged; + ColumnDefinitions.CollectionChanged += ColDefColChanged; + } + + private void ColDefColChanged(object sender, NotifyCollectionChangedEventArgs e) + { + CheckAndSetIfDefListMakesGridTrivial(ColumnDefinitions); + } + + private void RowDefColChanged(object sender, NotifyCollectionChangedEventArgs e) + { + CheckAndSetIfDefListMakesGridTrivial(RowDefinitions); + } + + void CheckAndSetIfDefListMakesGridTrivial(IReadOnlyList defList) + { + GridIsTrivial = !(defList.Count > 1); } /// @@ -215,6 +232,8 @@ public RowDefinitions RowDefinitions } } + bool GridIsTrivial = true; + /// /// Content measurement. /// @@ -230,7 +249,7 @@ protected override Size MeasureOverride(Size constraint) ListenToNotifications = true; MeasureOverrideInProgress = true; - if (extData == null) + if (GridIsTrivial) { gridDesiredSize = new Size(); var children = this.Children; @@ -534,7 +553,7 @@ protected override Size ArrangeOverride(Size arrangeSize) { ArrangeOverrideInProgress = true; - if (_data == null) + if (GridIsTrivial) { var children = this.Children; @@ -2454,6 +2473,10 @@ private static void SynchronizeColumnDefinitions(Grid target, ColumnDefinitions colDef.IsDirty = true; colDef.Parent = target; target._data.ColumnDefinitions = colDef; + + + + target.GridIsTrivial = colDef.Count == 0; } private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs rowDef) @@ -2477,8 +2500,13 @@ private static void SynchronizeRowDefinitions(Grid target, RowDefinitions rowDef rowDef.IsDirty = true; rowDef.Parent = target; target._data.RowDefinitions = rowDef; + + target.GridIsTrivial = rowDef.Count == 0; + } + + /// /// Helper for Comparer methods. /// @@ -2617,7 +2645,7 @@ private bool CellsStructureDirty get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } set { SetFlags(!value, Flags.ValidCellsStructure); } } - + /// /// Convenience accessor to ListenToNotifications bit flag. /// From 69d7e8827692fd59eead7dfb03eb650dd4582336 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 8 Aug 2020 09:39:35 +0800 Subject: [PATCH 18/26] make stuff work finally gof --- src/Avalonia.Controls/Grid.cs | 44 +++++++---------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 50045a877fb..b1a0e10dd26 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -9,6 +9,7 @@ using System.Collections.Specialized; using System.Diagnostics; using System.Threading; +using Avalonia.Data; using Avalonia.Layout; using Avalonia.Media; using Avalonia.Utilities; @@ -44,6 +45,9 @@ static Grid() /// public Grid() { + SetValue(ColumnDefinitionsProperty, new ColumnDefinitions() { Parent = this }, BindingPriority.TemplatedParent); + SetValue(RowDefinitionsProperty, new RowDefinitions() { Parent = this }, BindingPriority.TemplatedParent); + RowDefinitions.CollectionChanged += RowDefColChanged; ColumnDefinitions.CollectionChanged += ColDefColChanged; } @@ -60,7 +64,7 @@ private void RowDefColChanged(object sender, NotifyCollectionChangedEventArgs e) void CheckAndSetIfDefListMakesGridTrivial(IReadOnlyList defList) { - GridIsTrivial = !(defList.Count > 1); + GridIsTrivial = !(defList.Count > 0); } /// @@ -189,24 +193,8 @@ public bool ShowGridLines /// public ColumnDefinitions ColumnDefinitions { - get - { - if (_data is null) - _data = new ExtendedData(); - - if (_data.ColumnDefinitions is null) - { - _data.ColumnDefinitions = new ColumnDefinitions() { Parent = this }; - SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); - } - - return GetValue(ColumnDefinitionsProperty); - } - set - { - SynchronizeColumnDefinitions(this, value); - SetValue(ColumnDefinitionsProperty, _data.ColumnDefinitions); - } + get { return GetValue(ColumnDefinitionsProperty); } + set { SetValue(ColumnDefinitionsProperty, value); } } /// @@ -214,22 +202,8 @@ public ColumnDefinitions ColumnDefinitions /// public RowDefinitions RowDefinitions { - get - { - if (_data == null) { _data = new ExtendedData(); } - if (_data.RowDefinitions == null) - { - _data.RowDefinitions = new RowDefinitions() { Parent = this }; - SetValue(RowDefinitionsProperty, _data.RowDefinitions); - } - - return GetValue(RowDefinitionsProperty); - } - set - { - SynchronizeRowDefinitions(this, value); - SetValue(RowDefinitionsProperty, _data.RowDefinitions); - } + get { return GetValue(RowDefinitionsProperty); } + set { SetValue(RowDefinitionsProperty, value); } } bool GridIsTrivial = true; From a346964b39bb8710df21378cbccf36134987640c Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 14 Aug 2020 19:07:28 +0800 Subject: [PATCH 19/26] make the damn Grid work for once --- .../ControlCatalog/Pages/SplitViewPage.xaml | 7 +- src/Avalonia.Controls/DefinitionList.cs | 1 + src/Avalonia.Controls/Grid.cs | 515 ++++++++---------- src/Avalonia.Dialogs/ManagedFileChooser.xaml | 20 +- src/Avalonia.Themes.Default/CalendarItem.xaml | 52 +- src/Avalonia.Themes.Default/Slider.xaml | 16 +- src/Avalonia.Themes.Default/SplitView.xaml | 14 +- src/Avalonia.Themes.Default/ToggleSwitch.xaml | 16 +- src/Avalonia.Themes.Fluent/CalendarItem.xaml | 40 +- src/Avalonia.Themes.Fluent/MenuItem.xaml | 16 +- src/Avalonia.Themes.Fluent/Slider.xaml | 16 +- src/Avalonia.Themes.Fluent/SplitView.xaml | 12 +- src/Avalonia.Themes.Fluent/ToggleSwitch.xaml | 16 +- .../Avalonia.Controls.UnitTests.csproj | 2 +- .../Avalonia.Controls.UnitTests/GridTests.cs | 4 +- .../Xaml/BasicTests.cs | 20 +- 16 files changed, 341 insertions(+), 426 deletions(-) diff --git a/samples/ControlCatalog/Pages/SplitViewPage.xaml b/samples/ControlCatalog/Pages/SplitViewPage.xaml index 7e629db2daf..fecd78db408 100644 --- a/samples/ControlCatalog/Pages/SplitViewPage.xaml +++ b/samples/ControlCatalog/Pages/SplitViewPage.xaml @@ -56,12 +56,7 @@ CompactPaneLength="{Binding Value, ElementName=CompactPaneLengthSlider}" DisplayMode="{Binding CurrentDisplayMode}"> - - - - - - + diff --git a/src/Avalonia.Controls/DefinitionList.cs b/src/Avalonia.Controls/DefinitionList.cs index bb815171c0d..d0c79334412 100644 --- a/src/Avalonia.Controls/DefinitionList.cs +++ b/src/Avalonia.Controls/DefinitionList.cs @@ -52,6 +52,7 @@ internal void OnCollectionChanged(object sender, NotifyCollectionChangedEventArg } IsDirty = true; + Parent?.DefinitionListIsMakingGridTrivial(); } } } \ No newline at end of file diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index b1a0e10dd26..2614886eddf 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -9,6 +9,7 @@ using System.Collections.Specialized; using System.Diagnostics; using System.Threading; +using Avalonia.Collections; using Avalonia.Data; using Avalonia.Layout; using Avalonia.Media; @@ -24,8 +25,6 @@ public class Grid : Panel { static Grid() { - ShowGridLinesProperty.Changed.AddClassHandler(OnShowGridLinesPropertyChanged); - IsSharedSizeScopeProperty.Changed.AddClassHandler(DefinitionBase.OnIsSharedSizeScopePropertyChanged); ColumnProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); ColumnSpanProperty.Changed.AddClassHandler(OnCellAttachedPropertyChanged); @@ -34,6 +33,7 @@ static Grid() AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty); AffectsMeasure(ColumnDefinitionsProperty, RowDefinitionsProperty); + AffectsRender(ShowGridLinesProperty); RowDefinitionsProperty.Changed.AddClassHandler(RowDefinitionsPropertyChanged); ColumnDefinitionsProperty.Changed.AddClassHandler(ColumnDefinitionsPropertyChanged); @@ -45,26 +45,6 @@ static Grid() /// public Grid() { - SetValue(ColumnDefinitionsProperty, new ColumnDefinitions() { Parent = this }, BindingPriority.TemplatedParent); - SetValue(RowDefinitionsProperty, new RowDefinitions() { Parent = this }, BindingPriority.TemplatedParent); - - RowDefinitions.CollectionChanged += RowDefColChanged; - ColumnDefinitions.CollectionChanged += ColDefColChanged; - } - - private void ColDefColChanged(object sender, NotifyCollectionChangedEventArgs e) - { - CheckAndSetIfDefListMakesGridTrivial(ColumnDefinitions); - } - - private void RowDefColChanged(object sender, NotifyCollectionChangedEventArgs e) - { - CheckAndSetIfDefListMakesGridTrivial(RowDefinitions); - } - - void CheckAndSetIfDefListMakesGridTrivial(IReadOnlyList defList) - { - GridIsTrivial = !(defList.Count > 0); } /// @@ -206,7 +186,8 @@ public RowDefinitions RowDefinitions set { SetValue(RowDefinitionsProperty, value); } } - bool GridIsTrivial = true; + bool IsTrivial = true; + bool RowOrColumnDefChanged = true; /// /// Content measurement. @@ -216,14 +197,37 @@ public RowDefinitions RowDefinitions protected override Size MeasureOverride(Size constraint) { Size gridDesiredSize; - ExtendedData extData = ExtData; try { ListenToNotifications = true; MeasureOverrideInProgress = true; - if (GridIsTrivial) + if (RowOrColumnDefChanged) + { + if (RowIsEmpty & ColIsEmpty) + { + IsTrivial = true; + } + else + { + if (ColIsEmpty) + DefinitionsU = new DefinitionBase[] { new ColumnDefinition() { Parent = this } }; + else + DefinitionsU = ColumnDefinitions; + + if (RowIsEmpty) + DefinitionsV = new DefinitionBase[] { new RowDefinition() { Parent = this } }; + else + DefinitionsV = RowDefinitions; + + IsTrivial = false; + } + + RowOrColumnDefChanged = false; + } + + if (IsTrivial) { gridDesiredSize = new Size(); var children = this.Children; @@ -246,7 +250,7 @@ protected override Size MeasureOverride(Size constraint) bool sizeToContentV = double.IsPositiveInfinity(constraint.Height); // Clear index information and rounding errors - if (RowDefinitionsDirty || ColumnDefinitionsDirty) + // if (RowOrColumnDefinitionsDirty) { if (_definitionIndices != null) { @@ -264,10 +268,10 @@ protected override Size MeasureOverride(Size constraint) } } - ValidateDefinitionsUStructure(); + // ValidateDefinitionsUStructure(); ValidateDefinitionsLayout(DefinitionsU, sizeToContentU); - ValidateDefinitionsVStructure(); + // ValidateDefinitionsVStructure(); ValidateDefinitionsLayout(DefinitionsV, sizeToContentV); // Include the prior value just in case it was explicitly @@ -276,11 +280,11 @@ protected override Size MeasureOverride(Size constraint) CellsStructureDirty = CellsStructureDirty || SizeToContentU != sizeToContentU || SizeToContentV != sizeToContentV || - _data.OldColumnCount != DefinitionsU.Count || - _data.OldRowCount != DefinitionsV.Count; + _OldColumnCount != DefinitionsU.Count || + _OldRowCount != DefinitionsV.Count; - _data.OldColumnCount = DefinitionsU.Count; - _data.OldRowCount = DefinitionsV.Count; + _OldColumnCount = DefinitionsU.Count; + _OldRowCount = DefinitionsV.Count; SizeToContentU = sizeToContentU; SizeToContentV = sizeToContentV; @@ -440,7 +444,7 @@ protected override Size MeasureOverride(Size constraint) // appears in Auto column. // - MeasureCellsGroup(extData.CellGroup1, constraint, false, false); + MeasureCellsGroup(_CellGroup1, constraint, false, false); { // after Group1 is measured, only Group3 may have cells belonging to Auto rows. @@ -449,19 +453,19 @@ protected override Size MeasureOverride(Size constraint) if (canResolveStarsV) { if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } - MeasureCellsGroup(extData.CellGroup2, constraint, false, false); + MeasureCellsGroup(_CellGroup2, constraint, false, false); if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } - MeasureCellsGroup(extData.CellGroup3, constraint, false, false); + MeasureCellsGroup(_CellGroup3, constraint, false, false); } else { // if at least one cell exists in Group2, it must be measured before // StarsU can be resolved. - bool canResolveStarsU = extData.CellGroup2 > PrivateCells.Length; + bool canResolveStarsU = _CellGroup2 > _PrivateCells.Length; if (canResolveStarsU) { if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } - MeasureCellsGroup(extData.CellGroup3, constraint, false, false); + MeasureCellsGroup(_CellGroup3, constraint, false, false); if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } } else @@ -475,10 +479,10 @@ protected override Size MeasureOverride(Size constraint) int cnt = 0; // Cache Group2MinWidths & Group3MinHeights - double[] group2MinSizes = CacheMinSizes(extData.CellGroup2, false); - double[] group3MinSizes = CacheMinSizes(extData.CellGroup3, true); + double[] group2MinSizes = CacheMinSizes(_CellGroup2, false); + double[] group3MinSizes = CacheMinSizes(_CellGroup3, true); - MeasureCellsGroup(extData.CellGroup2, constraint, false, true); + MeasureCellsGroup(_CellGroup2, constraint, false, true); do { @@ -489,20 +493,20 @@ protected override Size MeasureOverride(Size constraint) } if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } - MeasureCellsGroup(extData.CellGroup3, constraint, false, false); + MeasureCellsGroup(_CellGroup3, constraint, false, false); // Reset cached Group2Widths ApplyCachedMinSizes(group2MinSizes, false); if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } - MeasureCellsGroup(extData.CellGroup2, constraint, cnt == c_layoutLoopMaxCount, false, out hasDesiredSizeUChanged); + MeasureCellsGroup(_CellGroup2, constraint, cnt == c_layoutLoopMaxCount, false, out hasDesiredSizeUChanged); } while (hasDesiredSizeUChanged && ++cnt <= c_layoutLoopMaxCount); } } } - MeasureCellsGroup(extData.CellGroup4, constraint, false, false); + MeasureCellsGroup(_CellGroup4, constraint, false, false); gridDesiredSize = new Size( CalculateDesiredSize(DefinitionsU), @@ -527,7 +531,7 @@ protected override Size ArrangeOverride(Size arrangeSize) { ArrangeOverrideInProgress = true; - if (GridIsTrivial) + if (IsTrivial) { var children = this.Children; @@ -549,10 +553,10 @@ protected override Size ArrangeOverride(Size arrangeSize) var children = this.Children; - for (int currentCell = 0; currentCell < PrivateCells.Length; ++currentCell) + for (int currentCell = 0; currentCell < _PrivateCells.Length; ++currentCell) { var cell = children[currentCell]; - var privCell = PrivateCells[currentCell]; + var privCell = _PrivateCells[currentCell]; if (cell is null || privCell.Skip) { @@ -616,10 +620,10 @@ internal double GetFinalColumnDefinitionWidth(int columnIndex) { double value = 0.0; - Contract.Requires(_data != null); + Debug.Assert(!IsTrivial); // actual value calculations require structure to be up-to-date - if (!ColumnDefinitionsDirty) + if (!RowOrColumnDefChanged) { IReadOnlyList definitions = DefinitionsU; value = definitions[(columnIndex + 1) % definitions.Count].FinalOffset; @@ -638,10 +642,10 @@ internal double GetFinalRowDefinitionHeight(int rowIndex) { double value = 0.0; - Contract.Requires(_data != null); + Debug.Assert(!IsTrivial); // actual value calculations require structure to be up-to-date - if (!RowDefinitionsDirty) + if (!RowOrColumnDefChanged) { IReadOnlyList definitions = DefinitionsV; value = definitions[(rowIndex + 1) % definitions.Count].FinalOffset; @@ -668,23 +672,17 @@ internal bool ArrangeOverrideInProgress set { SetFlags(value, Flags.ArrangeOverrideInProgress); } } - /// - /// Convenience accessor to ValidDefinitionsUStructure bit flag. - /// - internal bool ColumnDefinitionsDirty - { - get => ColumnDefinitions?.IsDirty ?? false; - set => ColumnDefinitions.IsDirty = value; - } - - /// - /// Convenience accessor to ValidDefinitionsVStructure bit flag. - /// - internal bool RowDefinitionsDirty - { - get => RowDefinitions?.IsDirty ?? false; - set => RowDefinitions.IsDirty = value; - } + // internal bool RowOrColumnDefinitionsDirty + // { + // get + // { + // if (ColumnDefinitions is null || RowDefinitions is null) + // return true; + // if (ColumnDefinitions.IsDirty || RowDefinitions.IsDirty) + // return true; + // return false; + // } + // } /// /// Lays out cells according to rows and columns, and creates lookup grids. @@ -704,19 +702,18 @@ private void ValidateCells() private void ValidateCellsCore() { var children = this.Children; - ExtendedData extData = ExtData; - extData.CellCachesCollection = new CellCache[children.Count]; - extData.CellGroup1 = int.MaxValue; - extData.CellGroup2 = int.MaxValue; - extData.CellGroup3 = int.MaxValue; - extData.CellGroup4 = int.MaxValue; + _PrivateCells = new CellCache[children.Count]; + _CellGroup1 = int.MaxValue; + _CellGroup2 = int.MaxValue; + _CellGroup3 = int.MaxValue; + _CellGroup4 = int.MaxValue; bool hasStarCellsU = false; bool hasStarCellsV = false; bool hasGroup3CellsInAutoRows = false; - for (int i = PrivateCells.Length - 1; i >= 0; --i) + for (int i = _PrivateCells.Length - 1; i >= 0; --i) { var child = children[i]; if (child == null) @@ -750,7 +747,7 @@ private void ValidateCellsCore() if (isOverCol || isOverRow) { cell.Skip = true; - PrivateCells[i] = cell; + _PrivateCells[i] = cell; continue; } @@ -768,13 +765,13 @@ private void ValidateCellsCore() { if (!cell.IsStarU) { - cell.Next = extData.CellGroup1; - extData.CellGroup1 = i; + cell.Next = _CellGroup1; + _CellGroup1 = i; } else { - cell.Next = extData.CellGroup3; - extData.CellGroup3 = i; + cell.Next = _CellGroup3; + _CellGroup3 = i; // Remember if this cell belongs to auto row hasGroup3CellsInAutoRows |= cell.IsAutoV; @@ -786,17 +783,17 @@ private void ValidateCellsCore() // Note below: if spans through Star column it is NOT Auto && !cell.IsStarU) { - cell.Next = extData.CellGroup2; - extData.CellGroup2 = i; + cell.Next = _CellGroup2; + _CellGroup2 = i; } else { - cell.Next = extData.CellGroup4; - extData.CellGroup4 = i; + cell.Next = _CellGroup4; + _CellGroup4 = i; } } - PrivateCells[i] = cell; + _PrivateCells[i] = cell; } HasStarCellsU = hasStarCellsU; @@ -812,38 +809,38 @@ private void ValidateCellsCore() /// This is one of two methods, where ColumnDefinitions and DefinitionsU are directly accessed. /// All the rest measure / arrange / render code must use DefinitionsU. /// - private void ValidateDefinitionsUStructure() - { - if (ColumnDefinitionsDirty) - { - ExtendedData extData = ExtData; - - if (extData.ColumnDefinitions == null) - { - if (extData.DefinitionsU == null) - { - extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() { Parent = this } }; - } - } - else - { - if (extData.ColumnDefinitions.Count == 0) - { - // if column definitions collection is empty - // mockup array with one column - extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() { Parent = this } }; - } - else - { - extData.DefinitionsU = extData.ColumnDefinitions; - } - } - - ColumnDefinitionsDirty = false; - } - - Debug.Assert(ExtData.DefinitionsU != null && ExtData.DefinitionsU.Count > 0); - } + // private void ValidateDefinitionsUStructure() + // { + // if (ColumnDefinitionsDirty) + // { + // + + // if (_ColumnDefinitions == null) + // { + // if (_DefinitionsU == null) + // { + // _DefinitionsU = new DefinitionBase[] { new ColumnDefinition() { Parent = this } }; + // } + // } + // else + // { + // if (_ColumnDefinitions.Count == 0) + // { + // // if column definitions collection is empty + // // mockup array with one column + // _DefinitionsU = new DefinitionBase[] { new ColumnDefinition() { Parent = this } }; + // } + // else + // { + // _DefinitionsU = _ColumnDefinitions; + // } + // } + + // ColumnDefinitionsDirty = false; + // } + + // Debug.Assert(_DefinitionsU != null && _DefinitionsU.Count > 0); + // } /// /// Initializes DefinitionsV memeber either to user supplied RowDefinitions collection @@ -853,38 +850,38 @@ private void ValidateDefinitionsUStructure() /// This is one of two methods, where RowDefinitions and DefinitionsV are directly accessed. /// All the rest measure / arrange / render code must use DefinitionsV. /// - private void ValidateDefinitionsVStructure() - { - if (RowDefinitionsDirty) - { - ExtendedData extData = ExtData; - - if (extData.RowDefinitions == null) - { - if (extData.DefinitionsV == null) - { - extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() { Parent = this } }; - } - } - else - { - if (extData.RowDefinitions.Count == 0) - { - // if row definitions collection is empty - // mockup array with one row - extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() { Parent = this } }; - } - else - { - extData.DefinitionsV = extData.RowDefinitions; - } - } - - RowDefinitionsDirty = false; - } - - Debug.Assert(ExtData.DefinitionsV != null && ExtData.DefinitionsV.Count > 0); - } + // private void ValidateDefinitionsVStructure() + // { + // if (RowDefinitionsDirty) + // { + // + + // if (_RowDefinitions == null) + // { + // if (_DefinitionsV == null) + // { + // _DefinitionsV = new DefinitionBase[] { new RowDefinition() { Parent = this } }; + // } + // } + // else + // { + // if (_RowDefinitions.Count == 0) + // { + // // if row definitions collection is empty + // // mockup array with one row + // _DefinitionsV = new DefinitionBase[] { new RowDefinition() { Parent = this } }; + // } + // else + // { + // _DefinitionsV = _RowDefinitions; + // } + // } + + // RowDefinitionsDirty = false; + // } + + // Debug.Assert(_DefinitionsV != null && _DefinitionsV.Count > 0); + // } /// /// Validates layout time size type information on given array of definitions. @@ -952,15 +949,15 @@ private double[] CacheMinSizes(int cellsHead, bool isRows) { if (isRows) { - minSizes[PrivateCells[i].RowIndex] = DefinitionsV[PrivateCells[i].RowIndex].MinSize; + minSizes[_PrivateCells[i].RowIndex] = DefinitionsV[_PrivateCells[i].RowIndex].MinSize; } else { - minSizes[PrivateCells[i].ColumnIndex] = DefinitionsU[PrivateCells[i].ColumnIndex].MinSize; + minSizes[_PrivateCells[i].ColumnIndex] = DefinitionsU[_PrivateCells[i].ColumnIndex].MinSize; } - i = PrivateCells[i].Next; - } while (i < PrivateCells.Length); + i = _PrivateCells[i].Next; + } while (i < _PrivateCells.Length); return minSizes; } @@ -1012,7 +1009,7 @@ private void MeasureCellsGroup( { hasDesiredSizeUChanged = false; - if (cellsHead >= PrivateCells.Length) + if (cellsHead >= _PrivateCells.Length) { return; } @@ -1033,16 +1030,16 @@ private void MeasureCellsGroup( if (!ignoreDesiredSizeU) { - if (PrivateCells[i].ColumnSpan == 1) + if (_PrivateCells[i].ColumnSpan == 1) { - DefinitionsU[PrivateCells[i].ColumnIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Width, DefinitionsU[PrivateCells[i].ColumnIndex].UserMaxSize)); + DefinitionsU[_PrivateCells[i].ColumnIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Width, DefinitionsU[_PrivateCells[i].ColumnIndex].UserMaxSize)); } else { RegisterSpan( ref spanStore, - PrivateCells[i].ColumnIndex, - PrivateCells[i].ColumnSpan, + _PrivateCells[i].ColumnIndex, + _PrivateCells[i].ColumnSpan, true, children[i].DesiredSize.Width); } @@ -1050,23 +1047,23 @@ private void MeasureCellsGroup( if (!ignoreDesiredSizeV) { - if (PrivateCells[i].RowSpan == 1) + if (_PrivateCells[i].RowSpan == 1) { - DefinitionsV[PrivateCells[i].RowIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Height, DefinitionsV[PrivateCells[i].RowIndex].UserMaxSize)); + DefinitionsV[_PrivateCells[i].RowIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Height, DefinitionsV[_PrivateCells[i].RowIndex].UserMaxSize)); } else { RegisterSpan( ref spanStore, - PrivateCells[i].RowIndex, - PrivateCells[i].RowSpan, + _PrivateCells[i].RowIndex, + _PrivateCells[i].RowSpan, false, children[i].DesiredSize.Height); } } - i = PrivateCells[i].Next; - } while (i < PrivateCells.Length); + i = _PrivateCells[i].Next; + } while (i < _PrivateCells.Length); if (spanStore != null) { @@ -1130,8 +1127,8 @@ private void MeasureCell( double cellMeasureWidth; double cellMeasureHeight; - if (PrivateCells[cell].IsAutoU - && !PrivateCells[cell].IsStarU) + if (_PrivateCells[cell].IsAutoU + && !_PrivateCells[cell].IsStarU) { // if cell belongs to at least one Auto column and not a single Star column // then it should be calculated "to content", thus it is possible to "shortcut" @@ -1143,16 +1140,16 @@ private void MeasureCell( // otherwise... cellMeasureWidth = GetMeasureSizeForRange( DefinitionsU, - PrivateCells[cell].ColumnIndex, - PrivateCells[cell].ColumnSpan); + _PrivateCells[cell].ColumnIndex, + _PrivateCells[cell].ColumnSpan); } if (forceInfinityV) { cellMeasureHeight = double.PositiveInfinity; } - else if (PrivateCells[cell].IsAutoV - && !PrivateCells[cell].IsStarV) + else if (_PrivateCells[cell].IsAutoV + && !_PrivateCells[cell].IsStarV) { // if cell belongs to at least one Auto row and not a single Star row // then it should be calculated "to content", thus it is possible to "shortcut" @@ -1163,8 +1160,8 @@ private void MeasureCell( { cellMeasureHeight = GetMeasureSizeForRange( DefinitionsV, - PrivateCells[cell].RowIndex, - PrivateCells[cell].RowSpan); + _PrivateCells[cell].RowIndex, + _PrivateCells[cell].RowSpan); } @@ -2326,17 +2323,16 @@ private double GetFinalSizeForRange( /// private void SetValid() { - ExtendedData extData = ExtData; - if (extData != null) + if (!IsTrivial) { // for (int i = 0; i < PrivateColumnCount; ++i) DefinitionsU[i].SetValid (); // for (int i = 0; i < PrivateRowCount; ++i) DefinitionsV[i].SetValid (); - if (extData.TempDefinitions != null) + if (_TempDefinitions != null) { // TempDefinitions has to be cleared to avoid "memory leaks" - Array.Clear(extData.TempDefinitions, 0, Math.Max(DefinitionsU.Count, DefinitionsV.Count)); - extData.TempDefinitions = null; + Array.Clear(_TempDefinitions, 0, Math.Max(DefinitionsU.Count, DefinitionsV.Count)); + _TempDefinitions = null; } } } @@ -2397,18 +2393,18 @@ private bool CheckFlagsOr(Flags flags) return (flags == 0 || (_flags & flags) != 0); } - private static void OnShowGridLinesPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) - { - Grid grid = (Grid)d; + // private static void OnShowGridLinesPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) + // { + // Grid grid = (Grid)d; - if (grid.ExtData != null // trivial grid is 1 by 1. there is no grid lines anyway - && grid.ListenToNotifications) - { - grid.InvalidateVisual(); - } + // if (!grid // trivial grid is 1 by 1. there is no grid lines anyway + // && grid.ListenToNotifications) + // { + // grid.InvalidateVisual(); + // } - grid.SetFlags((bool)e.NewValue, Flags.ShowGridLinesPropertyValue); - } + // grid.SetFlags((bool)e.NewValue, Flags.ShowGridLinesPropertyValue); + // } private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { @@ -2417,69 +2413,57 @@ private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaProp if (child != null) { Grid grid = child.GetVisualParent(); - if (grid != null - && grid.ExtData != null - && grid.ListenToNotifications) + if (grid != null) { - grid.CellsStructureDirty = true; + grid.Invalidate(); } } } - private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) - { - var val = e.NewValue as ColumnDefinitions; - SynchronizeColumnDefinitions(target, val); - } - /// - /// Reflects the changes on the ColumnDefinition StyledProperty - /// to the backing ExtendedData class. + /// Reflects the changes on the ColumnDefinition StyledProperty to the target grid. /// - private static void SynchronizeColumnDefinitions(Grid target, ColumnDefinitions colDef) + private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) { - if (colDef is null) - return; + var col = e.NewValue as ColumnDefinitions; - if (target._data is null) - target._data = new ExtendedData(); + var isEmpty = (col is null); - colDef.IsDirty = true; - colDef.Parent = target; - target._data.ColumnDefinitions = colDef; + target.ColIsEmpty = isEmpty; - - - target.GridIsTrivial = colDef.Count == 0; - } - - private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs rowDef) - { - var val = rowDef.NewValue as RowDefinitions; - SynchronizeRowDefinitions(target, val); + if (!isEmpty) + { + col.Parent = target; + } } /// - /// Reflects the changes on the RowDefinition StyledProperty - /// to the backing ExtendedData class. + /// Reflects the changes on the RowDefinition StyledProperty to the target grid. /// - private static void SynchronizeRowDefinitions(Grid target, RowDefinitions rowDef) + private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) { - if (rowDef is null) - return; + var row = e.NewValue as RowDefinitions; - if (target._data is null) - target._data = new ExtendedData(); + var isEmpty = (row is null); - rowDef.IsDirty = true; - rowDef.Parent = target; - target._data.RowDefinitions = rowDef; + target.RowIsEmpty = isEmpty; - target.GridIsTrivial = rowDef.Count == 0; + if (!isEmpty) + { + row.IsDirty = true; + row.Parent = target; + } + target.RowOrColumnDefChanged = true; } + internal void DefinitionListIsMakingGridTrivial() + { + RowIsEmpty = (RowDefinitions?.Count ?? 0) == 0; + ColIsEmpty = (ColumnDefinitions?.Count ?? 0) == 0; + RowOrColumnDefChanged = true; + } /// /// Helper for Comparer methods. @@ -2517,18 +2501,12 @@ private static bool CompareNullRefs(object x, object y, out int result) /// /// Private version returning array of column definitions. /// - private IReadOnlyList DefinitionsU - { - get { return (ExtData.DefinitionsU); } - } + private IReadOnlyList DefinitionsU; /// /// Private version returning array of row definitions. /// - private IReadOnlyList DefinitionsV - { - get { return (ExtData.DefinitionsV); } - } + private IReadOnlyList DefinitionsV; /// /// Helper accessor to layout time array of definitions. @@ -2537,30 +2515,30 @@ private DefinitionBase[] TempDefinitions { get { - ExtendedData extData = ExtData; + int requiredLength = Math.Max(DefinitionsU.Count, DefinitionsV.Count) * 2; - if (extData.TempDefinitions == null - || extData.TempDefinitions.Length < requiredLength) + if (_TempDefinitions == null + || _TempDefinitions.Length < requiredLength) { WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(s_tempDefinitionsDataSlot); if (tempDefinitionsWeakRef == null) { - extData.TempDefinitions = new DefinitionBase[requiredLength]; - Thread.SetData(s_tempDefinitionsDataSlot, new WeakReference(extData.TempDefinitions)); + _TempDefinitions = new DefinitionBase[requiredLength]; + Thread.SetData(s_tempDefinitionsDataSlot, new WeakReference(_TempDefinitions)); } else { - extData.TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target; - if (extData.TempDefinitions == null - || extData.TempDefinitions.Length < requiredLength) + _TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target; + if (_TempDefinitions == null + || _TempDefinitions.Length < requiredLength) { - extData.TempDefinitions = new DefinitionBase[requiredLength]; - tempDefinitionsWeakRef.Target = extData.TempDefinitions; + _TempDefinitions = new DefinitionBase[requiredLength]; + tempDefinitionsWeakRef.Target = _TempDefinitions; } } } - return (extData.TempDefinitions); + return (_TempDefinitions); } } @@ -2603,14 +2581,6 @@ private double[] RoundingErrors } } - /// - /// Private version returning array of cells. - /// - private CellCache[] PrivateCells - { - get { return (ExtData.CellCachesCollection); } - } - /// /// Convenience accessor to ValidCellsStructure bit flag. /// @@ -2674,14 +2644,6 @@ private bool HasGroup3CellsInAutoRows set { SetFlags(value, Flags.HasGroup3CellsInAutoRows); } } - /// - /// Returns reference to extended data bag. - /// - private ExtendedData ExtData - { - get { return (_data); } - } - /// /// Returns *-weight, adjusted for scale computed during Phase 1 /// @@ -2700,8 +2662,7 @@ static double StarWeight(DefinitionBase def, double scale) } } - // Extended data instantiated on demand, for non-trivial case handling only - private ExtendedData _data; + // Grid validity / property caches dirtiness flags private Flags _flags; @@ -2712,6 +2673,8 @@ static double StarWeight(DefinitionBase def, double scale) // Stores unrounded values and rounding errors during layout rounding. double[] _roundingErrors; + private bool RowIsEmpty = true; + private bool ColIsEmpty = true; // 5 is an arbitrary constant chosen to end the measure loop private const int c_layoutLoopMaxCount = 5; @@ -2726,22 +2689,16 @@ static double StarWeight(DefinitionBase def, double scale) /// /// Extended data instantiated on demand, when grid handles non-trivial case. /// - private class ExtendedData - { - internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support) - internal RowDefinitions RowDefinitions; // Collection of row definitions (logical tree support) - internal IReadOnlyList DefinitionsU; // Collection of column definitions used during calc - internal IReadOnlyList DefinitionsV; // Collection of row definitions used during calc - internal CellCache[] CellCachesCollection; // Backing store for logical children - internal int CellGroup1; // Index of the first cell in first cell group - internal int CellGroup2; // Index of the first cell in second cell group - internal int CellGroup3; // Index of the first cell in third cell group - internal int CellGroup4; // Index of the first cell in forth cell group - internal DefinitionBase[] TempDefinitions; // Temporary array used during layout for various purposes - // TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length) - internal int OldColumnCount; // Count of the previous column definition list. Invalidates the cells when it doesn't match up. - internal int OldRowCount; // Count of the previous row definition list. Invalidates the cells when it doesn't match up. - } + CellCache[] _PrivateCells; // Backing store for logical children + int _CellGroup1; // Index of the first cell in first cell group + int _CellGroup2; // Index of the first cell in second cell group + int _CellGroup3; // Index of the first cell in third cell group + int _CellGroup4; // Index of the first cell in forth cell group + DefinitionBase[] _TempDefinitions; // Temporary array used during layout for various purposes + // TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length) + int _OldColumnCount; // Count of the previous column definition list. Invalidates the cells when it doesn't match up. + int _OldRowCount; // Count of the previous row definition list. Invalidates the cells when it doesn't match up. + /// /// Grid validity / property caches dirtiness flags diff --git a/src/Avalonia.Dialogs/ManagedFileChooser.xaml b/src/Avalonia.Dialogs/ManagedFileChooser.xaml index 227cc1afc05..17610c5c333 100644 --- a/src/Avalonia.Dialogs/ManagedFileChooser.xaml +++ b/src/Avalonia.Dialogs/ManagedFileChooser.xaml @@ -89,15 +89,17 @@ - - - - - - - - - + + + + + + + + + + + diff --git a/src/Avalonia.Themes.Default/CalendarItem.xaml b/src/Avalonia.Themes.Default/CalendarItem.xaml index dfd89ed82fa..962bab85a98 100644 --- a/src/Avalonia.Themes.Default/CalendarItem.xaml +++ b/src/Avalonia.Themes.Default/CalendarItem.xaml @@ -20,17 +20,7 @@ - - - - - - - - - - - + - - - - - - -"; - - var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); - var target1 = window.Find("target1"); - var target2 = window.Find("target2"); - var mouse = new MouseTestHelper(); - - Assert.NotNull(target1.ContextMenu); - Assert.NotNull(target2.ContextMenu); - Assert.Same(target1.ContextMenu, target2.ContextMenu); - - window.Show(); - - var menu = target1.ContextMenu; - mouse.Click(target1, MouseButton.Right); - Assert.True(menu.IsOpen); - mouse.Click(target2, MouseButton.Right); - Assert.True(menu.IsOpen); - } - } +// [Fact] +// public void Context_Menu_In_Resources_Can_Be_Shared() +// { +// using (Application()) +// { +// var xaml = @" +// +// +// +// Foo +// +// + +// +// +// +// +// "; + +// var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); +// var target1 = window.Find("target1"); +// var target2 = window.Find("target2"); +// var mouse = new MouseTestHelper(); + +// Assert.NotNull(target1.ContextMenu); +// Assert.NotNull(target2.ContextMenu); +// Assert.Same(target1.ContextMenu, target2.ContextMenu); + +// window.Show(); + +// var menu = target1.ContextMenu; +// mouse.Click(target1, MouseButton.Right); +// Assert.True(menu.IsOpen); +// mouse.Click(target2, MouseButton.Right); +// Assert.True(menu.IsOpen); +// } +// } + +// [Fact] +// public void Context_Menu_Can_Be_Set_In_Style() +// { +// using (Application()) +// { +// var xaml = @" +// +// +// +// + +// +// +// +// +// "; + +// var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); +// var target1 = window.Find("target1"); +// var target2 = window.Find("target2"); +// var mouse = new MouseTestHelper(); + +// Assert.NotNull(target1.ContextMenu); +// Assert.NotNull(target2.ContextMenu); +// Assert.Same(target1.ContextMenu, target2.ContextMenu); + +// window.Show(); + +// var menu = target1.ContextMenu; +// mouse.Click(target1, MouseButton.Right); +// Assert.True(menu.IsOpen); +// mouse.Click(target2, MouseButton.Right); +// Assert.True(menu.IsOpen); +// } +// } [Fact(Skip = "The only reason this test was 'passing' before was that the author forgot to call Window.ApplyTemplate()")] public void Cancelling_Closing_Leaves_ContextMenuOpen() From f7bdee389d254510cc8a318c33107d9e436676ea Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 14 Aug 2020 23:25:07 +0800 Subject: [PATCH 26/26] remove flags --- src/Avalonia.Controls/Grid.cs | 182 ++++------------------------------ 1 file changed, 21 insertions(+), 161 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 58b4c6465c4..41c03adc9b5 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -53,10 +53,9 @@ static Grid() private static readonly IComparer s_minRatioComparer = new MinRatioComparer(); private static readonly IComparer s_maxRatioComparer = new MaxRatioComparer(); private static readonly IComparer s_starWeightComparer = new StarWeightComparer(); - - private Flags _flags; // Grid validity / property caches dirtiness flags + private GridLinesRenderer _gridLinesRenderer; // Keeps track of definition indices. - + private int[] _definitionIndices; private double[] _roundingErrors; // Stores unrounded values and rounding errors during layout rounding. @@ -228,9 +227,6 @@ protected override Size MeasureOverride(Size constraint) try { - ListenToNotifications = true; - MeasureOverrideInProgress = true; - if (RowOrColumnDefChanged) { if (ColIsEmpty) @@ -536,7 +532,7 @@ protected override Size MeasureOverride(Size constraint) } finally { - MeasureOverrideInProgress = false; + } return (gridDesiredSize); @@ -550,8 +546,6 @@ protected override Size ArrangeOverride(Size arrangeSize) { try { - ArrangeOverrideInProgress = true; - if (IsTrivial) { var children = this.Children; @@ -608,7 +602,6 @@ protected override Size ArrangeOverride(Size arrangeSize) finally { SetValid(); - ArrangeOverrideInProgress = false; } return (arrangeSize); } @@ -675,35 +668,6 @@ internal double GetFinalRowDefinitionHeight(int rowIndex) return (value); } - /// - /// Convenience accessor to MeasureOverrideInProgress bit flag. - /// - internal bool MeasureOverrideInProgress - { - get { return (CheckFlagsAnd(Flags.MeasureOverrideInProgress)); } - set { SetFlags(value, Flags.MeasureOverrideInProgress); } - } - - /// - /// Convenience accessor to ArrangeOverrideInProgress bit flag. - /// - internal bool ArrangeOverrideInProgress - { - get { return (CheckFlagsAnd(Flags.ArrangeOverrideInProgress)); } - set { SetFlags(value, Flags.ArrangeOverrideInProgress); } - } - - // internal bool RowOrColumnDefinitionsDirty - // { - // get - // { - // if (ColumnDefinitions is null || RowDefinitions is null) - // return true; - // if (ColumnDefinitions.IsDirty || RowDefinitions.IsDirty) - // return true; - // return false; - // } - // } /// /// Lays out cells according to rows and columns, and creates lookup grids. @@ -2301,53 +2265,20 @@ private GridLinesRenderer EnsureGridLinesRenderer() return (_gridLinesRenderer); } - /// - /// SetFlags is used to set or unset one or multiple - /// flags on the object. - /// - private void SetFlags(bool value, Flags flags) - { - _flags = value ? (_flags | flags) : (_flags & (~flags)); - } - - /// - /// CheckFlagsAnd returns true if all the flags in the - /// given bitmask are set on the object. - /// - private bool CheckFlagsAnd(Flags flags) - { - return ((_flags & flags) == flags); - } - - /// - /// CheckFlagsOr returns true if at least one flag in the - /// given bitmask is set. - /// - /// - /// If no bits are set in the given bitmask, the method returns - /// true. - /// - private bool CheckFlagsOr(Flags flags) - { - return (flags == 0 || (_flags & flags) != 0); - } - private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { - Visual child = d as Visual; + var child = d as Visual; if (child != null) { - Grid grid = child.GetVisualParent(); - if (grid != null) - { - grid.Invalidate(); - } + var grid = child.GetVisualParent(); + if (grid != null & !grid.IsTrivial) + grid.InvalidateMeasure(); } } /// - /// Reflects the changes on the ColumnDefinition StyledProperty to the target grid. + /// Update internal flags when ColumnDefinition changes /// private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) { @@ -2364,7 +2295,7 @@ private static void ColumnDefinitionsPropertyChanged(Grid target, AvaloniaProper } /// - /// Reflects the changes on the RowDefinition StyledProperty to the target grid. + /// Update internal flags when RowDefinitions changes. /// private static void RowDefinitionsPropertyChanged(Grid target, AvaloniaPropertyChangedEventArgs e) { @@ -2497,67 +2428,34 @@ private double[] RoundingErrors } /// - /// Convenience accessor to ValidCellsStructure bit flag. + /// This field is true if the cells needs to be recalculated /// - private bool CellsStructureDirty - { - get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } - set { SetFlags(!value, Flags.ValidCellsStructure); } - } + private bool CellsStructureDirty; /// - /// Convenience accessor to ListenToNotifications bit flag. + /// This field is true if calculating to content in U direction. /// - private bool ListenToNotifications - { - get { return (CheckFlagsAnd(Flags.ListenToNotifications)); } - set { SetFlags(value, Flags.ListenToNotifications); } - } + private bool SizeToContentU; /// - /// Convenience accessor to SizeToContentU bit flag. + /// This field is true if calculating to content in V direction. /// - private bool SizeToContentU - { - get { return (CheckFlagsAnd(Flags.SizeToContentU)); } - set { SetFlags(value, Flags.SizeToContentU); } - } + private bool SizeToContentV; /// - /// Convenience accessor to SizeToContentV bit flag. + /// This field is true if at least one cell belongs to a Star column. /// - private bool SizeToContentV - { - get { return (CheckFlagsAnd(Flags.SizeToContentV)); } - set { SetFlags(value, Flags.SizeToContentV); } - } + private bool HasStarCellsU; /// - /// Convenience accessor to HasStarCellsU bit flag. + // This field is true if at least one cell belongs to a Star row. /// - private bool HasStarCellsU - { - get { return (CheckFlagsAnd(Flags.HasStarCellsU)); } - set { SetFlags(value, Flags.HasStarCellsU); } - } + private bool HasStarCellsV; /// - /// Convenience accessor to HasStarCellsV bit flag. + // This field is true if at least one cell of group 3 belongs to an Auto row. /// - private bool HasStarCellsV - { - get { return (CheckFlagsAnd(Flags.HasStarCellsV)); } - set { SetFlags(value, Flags.HasStarCellsV); } - } - - /// - /// Convenience accessor to HasGroup3CellsInAutoRows bit flag. - /// - private bool HasGroup3CellsInAutoRows - { - get { return (CheckFlagsAnd(Flags.HasGroup3CellsInAutoRows)); } - set { SetFlags(value, Flags.HasGroup3CellsInAutoRows); } - } + private bool HasGroup3CellsInAutoRows; /// /// Returns *-weight, adjusted for scale computed during Phase 1 @@ -2577,44 +2475,6 @@ static double StarWeight(DefinitionBase def, double scale) } } - - - - - /// - /// Grid validity / property caches dirtiness flags - /// - [System.Flags] - private enum Flags - { - // - // the foolowing flags let grid tracking dirtiness in more granular manner: - // * Valid???Structure flags indicate that elements were added or removed. - // * Valid???Layout flags indicate that layout time portion of the information - // stored on the objects should be updated. - // - ValidDefinitionsUStructure = 0x00000001, - ValidDefinitionsVStructure = 0x00000002, - ValidCellsStructure = 0x00000004, - - // - // boolean properties state - // - ShowGridLinesPropertyValue = 0x00000100, // show grid lines ? - - // - // boolean flags - // - ListenToNotifications = 0x00001000, // "0" when all notifications are ignored - SizeToContentU = 0x00002000, // "1" if calculating to content in U direction - SizeToContentV = 0x00004000, // "1" if calculating to content in V direction - HasStarCellsU = 0x00008000, // "1" if at least one cell belongs to a Star column - HasStarCellsV = 0x00010000, // "1" if at least one cell belongs to a Star row - HasGroup3CellsInAutoRows = 0x00020000, // "1" if at least one cell of group 3 belongs to an Auto row - MeasureOverrideInProgress = 0x00040000, // "1" while in the context of Grid.MeasureOverride - ArrangeOverrideInProgress = 0x00080000, // "1" while in the context of Grid.ArrangeOverride - } - /// /// Defines the property. ///