diff --git a/src/Avalonia.Controls/ColumnDefinition.cs b/src/Avalonia.Controls/Grid/ColumnDefinition.cs
similarity index 100%
rename from src/Avalonia.Controls/ColumnDefinition.cs
rename to src/Avalonia.Controls/Grid/ColumnDefinition.cs
diff --git a/src/Avalonia.Controls/ColumnDefinitions.cs b/src/Avalonia.Controls/Grid/ColumnDefinitions.cs
similarity index 100%
rename from src/Avalonia.Controls/ColumnDefinitions.cs
rename to src/Avalonia.Controls/Grid/ColumnDefinitions.cs
diff --git a/src/Avalonia.Controls/Grid/Grid.cs b/src/Avalonia.Controls/Grid/Grid.cs
index 9291426c7f..5def043136 100644
--- a/src/Avalonia.Controls/Grid/Grid.cs
+++ b/src/Avalonia.Controls/Grid/Grid.cs
@@ -21,31 +21,58 @@ namespace Avalonia.Controls
{
public class Grid : Panel
{
-
internal bool CellsStructureDirty = true;
internal bool SizeToContentU;
internal bool SizeToContentV;
internal bool HasStarCellsU;
internal bool HasStarCellsV;
internal bool HasGroup3CellsInAutoRows;
- internal bool ColumnDefinitionsDirty = true;
- internal bool RowDefinitionsDirty = true;
-
- // index of the first cell in first cell group
+ internal bool DefinitionsDirty;
+ internal bool IsTrivialGrid => (_definitionsU?.Length <= 1) &&
+ (_definitionsV?.Length <= 1);
internal int CellGroup1;
-
- // index of the first cell in second cell group
internal int CellGroup2;
-
- // index of the first cell in third cell group
internal int CellGroup3;
-
- // index of the first cell in fourth cell group
internal int CellGroup4;
+ ///
+ /// Helper for Comparer methods.
+ ///
+ ///
+ /// true if one or both of x and y are null, in which case result holds
+ /// the relative sort order.
+ ///
+ internal static bool CompareNullRefs(object x, object y, out int result)
+ {
+ result = 2;
+
+ if (x == null)
+ {
+ if (y == null)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -1;
+ }
+ }
+ else
+ {
+ if (y == null)
+ {
+ result = 1;
+ }
+ }
+
+ return (result != 2);
+ }
+
// temporary array used during layout for various purposes
// TempDefinitions.Length == Max(DefinitionsU.Length, DefinitionsV.Length)
private DefinitionBase[] _tempDefinitions;
+
+
private GridLinesRenderer _gridLinesRenderer;
// Keeps track of definition indices.
@@ -55,8 +82,10 @@ namespace Avalonia.Controls
// Stores unrounded values and rounding errors during layout rounding.
private double[] _roundingErrors;
- private DefinitionBase[] _definitionsU;
- private DefinitionBase[] _definitionsV;
+ private ColumnDefinitions _columnDefinitions;
+ private RowDefinitions _rowDefinitions;
+ private DefinitionBase[] _definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
+ private DefinitionBase[] _definitionsV = new DefinitionBase[1] { new RowDefinition() };
// 5 is an arbitrary constant chosen to end the measure loop
private const int _layoutLoopMaxCount = 5;
@@ -67,6 +96,78 @@ namespace Avalonia.Controls
private static readonly IComparer _maxRatioComparer;
private static readonly IComparer _starWeightComparer;
+ ///
+ /// Helper accessor to layout time array of definitions.
+ ///
+ private DefinitionBase[] TempDefinitions
+ {
+ get
+ {
+ int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length) * 2;
+
+ if (_tempDefinitions == null
+ || _tempDefinitions.Length < requiredLength)
+ {
+ WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(_tempDefinitionsDataSlot);
+ if (tempDefinitionsWeakRef == null)
+ {
+ _tempDefinitions = new DefinitionBase[requiredLength];
+ Thread.SetData(_tempDefinitionsDataSlot, new WeakReference(_tempDefinitions));
+ }
+ else
+ {
+ _tempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target;
+ if (_tempDefinitions == null
+ || _tempDefinitions.Length < requiredLength)
+ {
+ _tempDefinitions = new DefinitionBase[requiredLength];
+ tempDefinitionsWeakRef.Target = _tempDefinitions;
+ }
+ }
+ }
+ return (_tempDefinitions);
+ }
+ }
+
+ ///
+ /// Helper accessor to definition indices.
+ ///
+ private int[] DefinitionIndices
+ {
+ get
+ {
+ int requiredLength = Math.Max(Math.Max(_definitionsU.Length, _definitionsV.Length), 1) * 2;
+
+ if (_definitionIndices == null || _definitionIndices.Length < requiredLength)
+ {
+ _definitionIndices = new int[requiredLength];
+ }
+
+ return _definitionIndices;
+ }
+ }
+
+ ///
+ /// Helper accessor to rounding errors.
+ ///
+ private double[] RoundingErrors
+ {
+ get
+ {
+ int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length);
+
+ if (_roundingErrors == null && requiredLength == 0)
+ {
+ _roundingErrors = new double[1];
+ }
+ else if (_roundingErrors == null || _roundingErrors.Length < requiredLength)
+ {
+ _roundingErrors = new double[requiredLength];
+ }
+ return _roundingErrors;
+ }
+ }
+
static Grid()
{
ShowGridLinesProperty.Changed.AddClassHandler(OnShowGridLinesPropertyChanged);
@@ -128,6 +229,86 @@ namespace Avalonia.Controls
set { SetValue(ShowGridLinesProperty, value); }
}
+ ///
+ /// Gets or sets the columns definitions for the grid.
+ ///
+ public ColumnDefinitions ColumnDefinitions
+ {
+ get
+ {
+ if (_columnDefinitions == null)
+ {
+ ColumnDefinitions = new ColumnDefinitions();
+ }
+
+ return _columnDefinitions;
+ }
+ set
+ {
+ _columnDefinitions = value;
+ _columnDefinitions.TrackItemPropertyChanged(_ => Invalidate());
+ DefinitionsDirty = true;
+
+ if (_columnDefinitions.Count > 0)
+ _definitionsU = _columnDefinitions.Cast().ToArray();
+
+ _columnDefinitions.CollectionChanged += delegate
+ {
+ if (_columnDefinitions.Count == 0)
+ {
+ _definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
+ }
+ else
+ {
+ _definitionsU = _columnDefinitions.Cast().ToArray();
+ DefinitionsDirty = true;
+ }
+ Invalidate();
+ };
+ }
+ }
+
+ ///
+ /// Gets or sets the row definitions for the grid.
+ ///
+ public RowDefinitions RowDefinitions
+ {
+ get
+ {
+ if (_rowDefinitions == null)
+ {
+ RowDefinitions = new RowDefinitions();
+ }
+
+ return _rowDefinitions;
+ }
+ set
+ {
+ _rowDefinitions = value;
+ _rowDefinitions.TrackItemPropertyChanged(_ => Invalidate());
+
+ DefinitionsDirty = true;
+
+ if (_rowDefinitions.Count > 0)
+ _definitionsV = _rowDefinitions.Cast().ToArray();
+
+ _rowDefinitions.CollectionChanged += delegate
+ {
+ if (_rowDefinitions.Count == 0)
+ {
+ _definitionsV = new DefinitionBase[1] { new RowDefinition() };
+ }
+ else
+ {
+ _definitionsV = _rowDefinitions.Cast().ToArray();
+ DefinitionsDirty = true;
+ }
+ Invalidate();
+ };
+ }
+ }
+
+
///
/// Gets the value of the Column attached property for a control.
///
@@ -218,95 +399,6 @@ namespace Avalonia.Controls
element.SetValue(RowSpanProperty, value);
}
- private ColumnDefinitions _columnDefinitions;
- private RowDefinitions _rowDefinitions;
-
- ///
- /// Gets or sets the columns definitions for the grid.
- ///
- public ColumnDefinitions ColumnDefinitions
- {
- get
- {
- if (_columnDefinitions == null)
- {
- ColumnDefinitions = new ColumnDefinitions();
- }
-
- return _columnDefinitions;
- }
- set
- {
- _columnDefinitions = value;
- _columnDefinitions.TrackItemPropertyChanged(_ => Invalidate());
- ColumnDefinitionsDirty = true;
-
- if (_columnDefinitions.Count > 0)
- _definitionsU = _columnDefinitions.Cast().ToArray();
- else
- _definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
-
- _columnDefinitions.CollectionChanged += (_, e) =>
- {
- if (_columnDefinitions.Count == 0)
- {
- _definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
- }
- else
- {
- _definitionsU = _columnDefinitions.Cast().ToArray();
- ColumnDefinitionsDirty = true;
- }
- Invalidate();
- };
- }
- }
-
- ///
- /// Gets or sets the row definitions for the grid.
- ///
- public RowDefinitions RowDefinitions
- {
- get
- {
- if (_rowDefinitions == null)
- {
- RowDefinitions = new RowDefinitions();
- }
-
- return _rowDefinitions;
- }
- set
- {
- _rowDefinitions = value;
- _rowDefinitions.TrackItemPropertyChanged(_ => Invalidate());
-
- RowDefinitionsDirty = true;
-
- if (_rowDefinitions.Count > 0)
- _definitionsV = _rowDefinitions.Cast().ToArray();
- else
- _definitionsV = new DefinitionBase[1] { new RowDefinition() };
-
- _rowDefinitions.CollectionChanged += (_, e) =>
- {
- if (_rowDefinitions.Count == 0)
- {
- _definitionsV = new DefinitionBase[1] { new RowDefinition() };
- }
- else
- {
- _definitionsV = _rowDefinitions.Cast().ToArray();
- RowDefinitionsDirty = true;
- }
- Invalidate();
- };
- }
- }
-
- internal bool IsTrivialGrid => (_definitionsU?.Length <= 1) &&
- (_definitionsV?.Length <= 1);
-
///
/// Content measurement.
///
@@ -341,7 +433,7 @@ namespace Avalonia.Controls
bool sizeToContentV = double.IsPositiveInfinity(constraint.Height);
// Clear index information and rounding errors
- if (RowDefinitionsDirty || ColumnDefinitionsDirty)
+ if (DefinitionsDirty)
{
if (_definitionIndices != null)
{
@@ -357,12 +449,11 @@ namespace Avalonia.Controls
_roundingErrors = null;
}
}
+
+ DefinitionsDirty = false;
}
- ValidateColumnDefinitionsStructure();
ValidateDefinitionsLayout(_definitionsU, sizeToContentU);
-
- ValidateRowDefinitionsStructure();
ValidateDefinitionsLayout(_definitionsV, sizeToContentV);
CellsStructureDirty |= (SizeToContentU != sizeToContentU)
@@ -453,27 +544,6 @@ namespace Avalonia.Controls
return (gridDesiredSize);
}
- private void ValidateColumnDefinitionsStructure()
- {
- if (ColumnDefinitionsDirty)
- {
- if (_definitionsU == null)
- _definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
- ColumnDefinitionsDirty = false;
- }
- }
-
- private void ValidateRowDefinitionsStructure()
- {
- if (RowDefinitionsDirty)
- {
- if (_definitionsV == null)
- _definitionsV = new DefinitionBase[1] { new RowDefinition() };
-
- RowDefinitionsDirty = false;
- }
- }
-
///
/// Content arrangement.
///
@@ -554,12 +624,12 @@ namespace Avalonia.Controls
///
/// Used from public ColumnDefinition ActualWidth. Calculates final width using offset data.
///
- internal double GetFinalColumnDefinitionWidth(int columnIndex)
+ private double GetFinalColumnDefinitionWidth(int columnIndex)
{
double value = 0.0;
// actual value calculations require structure to be up-to-date
- if (!ColumnDefinitionsDirty)
+ if (!DefinitionsDirty)
{
value = _definitionsU[(columnIndex + 1) % _definitionsU.Length].FinalOffset;
if (columnIndex != 0) { value -= _definitionsU[columnIndex].FinalOffset; }
@@ -573,12 +643,12 @@ namespace Avalonia.Controls
///
/// Used from public RowDefinition ActualHeight. Calculates final height using offset data.
///
- internal double GetFinalRowDefinitionHeight(int rowIndex)
+ private double GetFinalRowDefinitionHeight(int rowIndex)
{
double value = 0.0;
// actual value calculations require structure to be up-to-date
- if (!RowDefinitionsDirty)
+ if (!DefinitionsDirty)
{
value = _definitionsV[(rowIndex + 1) % _definitionsV.Length].FinalOffset;
if (rowIndex != 0) { value -= _definitionsV[rowIndex].FinalOffset; }
@@ -589,7 +659,7 @@ namespace Avalonia.Controls
///
/// Invalidates grid caches and makes the grid dirty for measure.
///
- internal void Invalidate()
+ private void Invalidate()
{
CellsStructureDirty = true;
InvalidateMeasure();
@@ -2111,14 +2181,11 @@ namespace Avalonia.Controls
///
private void SetValid()
{
- if (IsTrivialGrid)
+ if (IsTrivialGrid && _tempDefinitions != null)
{
- if (_tempDefinitions != null)
- {
- // TempDefinitions has to be cleared to avoid "memory leaks"
- Array.Clear(_tempDefinitions, 0, Math.Max(_definitionsU.Length, _definitionsV.Length));
- _tempDefinitions = null;
- }
+ // TempDefinitions has to be cleared to avoid "memory leaks"
+ Array.Clear(_tempDefinitions, 0, Math.Max(_definitionsU.Length, _definitionsV.Length));
+ _tempDefinitions = null;
}
}
@@ -2171,7 +2238,6 @@ namespace Avalonia.Controls
return newValue;
}
-
private static int ValidateColumn(AvaloniaObject o, int value)
{
if (value < 0)
@@ -2200,115 +2266,10 @@ namespace Avalonia.Controls
}
}
- ///
- /// Helper for Comparer methods.
- ///
- ///
- /// true if one or both of x and y are null, in which case result holds
- /// the relative sort order.
- ///
- internal static bool CompareNullRefs(object x, object y, out int result)
- {
- result = 2;
-
- if (x == null)
- {
- if (y == null)
- {
- result = 0;
- }
- else
- {
- result = -1;
- }
- }
- else
- {
- if (y == null)
- {
- result = 1;
- }
- }
-
- return (result != 2);
- }
-
- ///
- /// Helper accessor to layout time array of definitions.
- ///
- private DefinitionBase[] TempDefinitions
- {
- get
- {
- int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length) * 2;
-
- if (_tempDefinitions == null
- || _tempDefinitions.Length < requiredLength)
- {
- WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(_tempDefinitionsDataSlot);
- if (tempDefinitionsWeakRef == null)
- {
- _tempDefinitions = new DefinitionBase[requiredLength];
- Thread.SetData(_tempDefinitionsDataSlot, new WeakReference(_tempDefinitions));
- }
- else
- {
- _tempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target;
- if (_tempDefinitions == null
- || _tempDefinitions.Length < requiredLength)
- {
- _tempDefinitions = new DefinitionBase[requiredLength];
- tempDefinitionsWeakRef.Target = _tempDefinitions;
- }
- }
- }
- return (_tempDefinitions);
- }
- }
-
- ///
- /// Helper accessor to definition indices.
- ///
- private int[] DefinitionIndices
- {
- get
- {
- int requiredLength = Math.Max(Math.Max(_definitionsU.Length, _definitionsV.Length), 1) * 2;
-
- if (_definitionIndices == null || _definitionIndices.Length < requiredLength)
- {
- _definitionIndices = new int[requiredLength];
- }
-
- return _definitionIndices;
- }
- }
-
- ///
- /// Helper accessor to rounding errors.
- ///
- private double[] RoundingErrors
- {
- get
- {
- int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length);
-
- if (_roundingErrors == null && requiredLength == 0)
- {
- _roundingErrors = new double[1];
- }
- else if (_roundingErrors == null || _roundingErrors.Length < requiredLength)
- {
- _roundingErrors = new double[requiredLength];
- }
- return _roundingErrors;
- }
- }
-
///
/// Returns *-weight, adjusted for scale computed during Phase 1
///
- static double StarWeight(DefinitionBase def, double scale)
+ private static double StarWeight(DefinitionBase def, double scale)
{
if (scale < 0.0)
{
diff --git a/src/Avalonia.Controls/RowDefinition.cs b/src/Avalonia.Controls/Grid/RowDefinition.cs
similarity index 100%
rename from src/Avalonia.Controls/RowDefinition.cs
rename to src/Avalonia.Controls/Grid/RowDefinition.cs
diff --git a/src/Avalonia.Controls/RowDefinitions.cs b/src/Avalonia.Controls/Grid/RowDefinitions.cs
similarity index 100%
rename from src/Avalonia.Controls/RowDefinitions.cs
rename to src/Avalonia.Controls/Grid/RowDefinitions.cs