Browse Source

More reorganizing + refactoring...

pull/2563/head
Jumar Macato 7 years ago
parent
commit
5b62d7c859
No known key found for this signature in database GPG Key ID: B19884DAC3A5BF3F
  1. 0
      src/Avalonia.Controls/Grid/ColumnDefinition.cs
  2. 0
      src/Avalonia.Controls/Grid/ColumnDefinitions.cs
  3. 453
      src/Avalonia.Controls/Grid/Grid.cs
  4. 0
      src/Avalonia.Controls/Grid/RowDefinition.cs
  5. 0
      src/Avalonia.Controls/Grid/RowDefinitions.cs

0
src/Avalonia.Controls/ColumnDefinition.cs → src/Avalonia.Controls/Grid/ColumnDefinition.cs

0
src/Avalonia.Controls/ColumnDefinitions.cs → src/Avalonia.Controls/Grid/ColumnDefinitions.cs

453
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;
/// <summary>
/// Helper for Comparer methods.
/// </summary>
/// <returns>
/// true if one or both of x and y are null, in which case result holds
/// the relative sort order.
/// </returns>
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;
/// <summary>
/// Helper accessor to layout time array of definitions.
/// </summary>
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);
}
}
/// <summary>
/// Helper accessor to definition indices.
/// </summary>
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;
}
}
/// <summary>
/// Helper accessor to rounding errors.
/// </summary>
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<Grid>(OnShowGridLinesPropertyChanged);
@ -128,6 +229,86 @@ namespace Avalonia.Controls
set { SetValue(ShowGridLinesProperty, value); }
}
/// <summary>
/// Gets or sets the columns definitions for the grid.
/// </summary>
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<DefinitionBase>().ToArray();
_columnDefinitions.CollectionChanged += delegate
{
if (_columnDefinitions.Count == 0)
{
_definitionsU = new DefinitionBase[1] { new ColumnDefinition() };
}
else
{
_definitionsU = _columnDefinitions.Cast<DefinitionBase>().ToArray();
DefinitionsDirty = true;
}
Invalidate();
};
}
}
/// <summary>
/// Gets or sets the row definitions for the grid.
/// </summary>
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<DefinitionBase>().ToArray();
_rowDefinitions.CollectionChanged += delegate
{
if (_rowDefinitions.Count == 0)
{
_definitionsV = new DefinitionBase[1] { new RowDefinition() };
}
else
{
_definitionsV = _rowDefinitions.Cast<DefinitionBase>().ToArray();
DefinitionsDirty = true;
}
Invalidate();
};
}
}
/// <summary>
/// Gets the value of the Column attached property for a control.
/// </summary>
@ -218,95 +399,6 @@ namespace Avalonia.Controls
element.SetValue(RowSpanProperty, value);
}
private ColumnDefinitions _columnDefinitions;
private RowDefinitions _rowDefinitions;
/// <summary>
/// Gets or sets the columns definitions for the grid.
/// </summary>
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<DefinitionBase>().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<DefinitionBase>().ToArray();
ColumnDefinitionsDirty = true;
}
Invalidate();
};
}
}
/// <summary>
/// Gets or sets the row definitions for the grid.
/// </summary>
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<DefinitionBase>().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<DefinitionBase>().ToArray();
RowDefinitionsDirty = true;
}
Invalidate();
};
}
}
internal bool IsTrivialGrid => (_definitionsU?.Length <= 1) &&
(_definitionsV?.Length <= 1);
/// <summary>
/// Content measurement.
/// </summary>
@ -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;
}
}
/// <summary>
/// Content arrangement.
/// </summary>
@ -554,12 +624,12 @@ namespace Avalonia.Controls
/// <remarks>
/// Used from public ColumnDefinition ActualWidth. Calculates final width using offset data.
/// </remarks>
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
/// <remarks>
/// Used from public RowDefinition ActualHeight. Calculates final height using offset data.
/// </remarks>
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
/// <summary>
/// Invalidates grid caches and makes the grid dirty for measure.
/// </summary>
internal void Invalidate()
private void Invalidate()
{
CellsStructureDirty = true;
InvalidateMeasure();
@ -2111,14 +2181,11 @@ namespace Avalonia.Controls
/// </summary>
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
}
}
/// <summary>
/// Helper for Comparer methods.
/// </summary>
/// <returns>
/// true if one or both of x and y are null, in which case result holds
/// the relative sort order.
/// </returns>
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);
}
/// <summary>
/// Helper accessor to layout time array of definitions.
/// </summary>
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);
}
}
/// <summary>
/// Helper accessor to definition indices.
/// </summary>
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;
}
}
/// <summary>
/// Helper accessor to rounding errors.
/// </summary>
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;
}
}
/// <summary>
/// Returns *-weight, adjusted for scale computed during Phase 1
/// </summary>
static double StarWeight(DefinitionBase def, double scale)
private static double StarWeight(DefinitionBase def, double scale)
{
if (scale < 0.0)
{

0
src/Avalonia.Controls/RowDefinition.cs → src/Avalonia.Controls/Grid/RowDefinition.cs

0
src/Avalonia.Controls/RowDefinitions.cs → src/Avalonia.Controls/Grid/RowDefinitions.cs

Loading…
Cancel
Save