From 6d2601b54c581fa5bd5a332c84270d77ea333c78 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Mon, 27 May 2019 17:16:45 +0800 Subject: [PATCH] Some refactoring... --- src/Avalonia.Controls/DefinitionBase.cs | 8 +- src/Avalonia.Controls/GridWPF.cs | 182 +++++++++++++----------- 2 files changed, 100 insertions(+), 90 deletions(-) diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 3301d23f61..3dd4819ca7 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -48,6 +48,7 @@ namespace Avalonia.Controls /// Layout-time user size type. /// internal Grid.LayoutTimeSizeType SizeType { get; set; } + /// /// Returns or sets measure size for the definition. /// @@ -79,7 +80,7 @@ namespace Avalonia.Controls internal double SizeCache { get; set; } /// - /// Used during measure to accumulate size for "Auto" and "Star" DefinitionBase's + /// Used during measure and arrange to accumulate size for "Auto" and "Star" DefinitionBase's /// internal double MinSize { get; set; } @@ -96,10 +97,5 @@ namespace Avalonia.Controls /// Offset. /// internal double FinalOffset { get; set; } - - /// - /// Returns true if this definition is a part of shared group. - /// - internal bool IsShared { get; set; } } } \ No newline at end of file diff --git a/src/Avalonia.Controls/GridWPF.cs b/src/Avalonia.Controls/GridWPF.cs index 970b4de865..35a38a6423 100644 --- a/src/Avalonia.Controls/GridWPF.cs +++ b/src/Avalonia.Controls/GridWPF.cs @@ -60,22 +60,29 @@ namespace Avalonia.Controls // Stores unrounded values and rounding errors during layout rounding. private double[] _roundingErrors; - private DefinitionBase[] DefinitionsU; - private DefinitionBase[] DefinitionsV; + private DefinitionBase[] _definitionsU; + private DefinitionBase[] _definitionsV; // 5 is an arbitrary constant chosen to end the measure loop private const int _layoutLoopMaxCount = 5; - private static readonly LocalDataStoreSlot _tempDefinitionsDataSlot = Thread.AllocateDataSlot(); - private static readonly IComparer _spanPreferredDistributionOrderComparer = new SpanPreferredDistributionOrderComparer(); - private static readonly IComparer _spanMaxDistributionOrderComparer = new SpanMaxDistributionOrderComparer(); - private static readonly IComparer _minRatioComparer = new MinRatioComparer(); - private static readonly IComparer _maxRatioComparer = new MaxRatioComparer(); - private static readonly IComparer _starWeightComparer = new StarWeightComparer(); + private static readonly LocalDataStoreSlot _tempDefinitionsDataSlot; + private static readonly IComparer _spanPreferredDistributionOrderComparer; + private static readonly IComparer _spanMaxDistributionOrderComparer; + private static readonly IComparer _minRatioComparer; + private static readonly IComparer _maxRatioComparer; + private static readonly IComparer _starWeightComparer; static Grid() { ShowGridLinesProperty.Changed.AddClassHandler(OnShowGridLinesPropertyChanged); AffectsParentMeasure(ColumnProperty, ColumnSpanProperty, RowProperty, RowSpanProperty); + + _tempDefinitionsDataSlot = Thread.AllocateDataSlot(); + _spanPreferredDistributionOrderComparer = new SpanPreferredDistributionOrderComparer(); + _spanMaxDistributionOrderComparer = new SpanMaxDistributionOrderComparer(); + _minRatioComparer = new MinRatioComparer(); + _maxRatioComparer = new MaxRatioComparer(); + _starWeightComparer = new StarWeightComparer(); } /// @@ -240,19 +247,19 @@ namespace Avalonia.Controls ColumnDefinitionsDirty = true; if (_columnDefinitions.Count > 0) - DefinitionsU = _columnDefinitions.Cast().ToArray(); + _definitionsU = _columnDefinitions.Cast().ToArray(); else - DefinitionsU = new DefinitionBase[1] { new ColumnDefinition() }; + _definitionsU = new DefinitionBase[1] { new ColumnDefinition() }; _columnDefinitions.CollectionChanged += (_, e) => { if (_columnDefinitions.Count == 0) { - DefinitionsU = new DefinitionBase[1] { new ColumnDefinition() }; + _definitionsU = new DefinitionBase[1] { new ColumnDefinition() }; } else { - DefinitionsU = _columnDefinitions.Cast().ToArray(); + _definitionsU = _columnDefinitions.Cast().ToArray(); ColumnDefinitionsDirty = true; } Invalidate(); @@ -282,19 +289,19 @@ namespace Avalonia.Controls RowDefinitionsDirty = true; if (_rowDefinitions.Count > 0) - DefinitionsV = _rowDefinitions.Cast().ToArray(); + _definitionsV = _rowDefinitions.Cast().ToArray(); else - DefinitionsV = new DefinitionBase[1] { new RowDefinition() }; + _definitionsV = new DefinitionBase[1] { new RowDefinition() }; _rowDefinitions.CollectionChanged += (_, e) => { if (_rowDefinitions.Count == 0) { - DefinitionsV = new DefinitionBase[1] { new RowDefinition() }; + _definitionsV = new DefinitionBase[1] { new RowDefinition() }; } else { - DefinitionsV = _rowDefinitions.Cast().ToArray(); + _definitionsV = _rowDefinitions.Cast().ToArray(); RowDefinitionsDirty = true; } Invalidate(); @@ -302,8 +309,8 @@ namespace Avalonia.Controls } } - private bool IsTrivialGrid => (DefinitionsU?.Length <= 1) && - (DefinitionsV?.Length <= 1); + private bool IsTrivialGrid => (_definitionsU?.Length <= 1) && + (_definitionsV?.Length <= 1); /// /// Content measurement. @@ -358,12 +365,13 @@ namespace Avalonia.Controls } ValidateColumnDefinitionsStructure(); - ValidateDefinitionsLayout(DefinitionsU, sizeToContentU); + ValidateDefinitionsLayout(_definitionsU, sizeToContentU); ValidateRowDefinitionsStructure(); - ValidateDefinitionsLayout(DefinitionsV, sizeToContentV); + ValidateDefinitionsLayout(_definitionsV, sizeToContentV); - CellsStructureDirty |= (SizeToContentU != sizeToContentU) || (SizeToContentV != sizeToContentV); + CellsStructureDirty |= (SizeToContentU != sizeToContentU) + || (SizeToContentV != sizeToContentV); SizeToContentU = sizeToContentU; SizeToContentV = sizeToContentV; @@ -371,7 +379,7 @@ namespace Avalonia.Controls ValidateCells(); - Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0); + Debug.Assert(_definitionsU.Length > 0 && _definitionsV.Length > 0); MeasureCellsGroup(CellGroup1, constraint, false, false); @@ -381,9 +389,9 @@ namespace Avalonia.Controls if (canResolveStarsV) { - if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } + if (HasStarCellsV) { ResolveStar(_definitionsV, constraint.Height); } MeasureCellsGroup(CellGroup2, constraint, false, false); - if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } + if (HasStarCellsU) { ResolveStar(_definitionsU, constraint.Width); } MeasureCellsGroup(CellGroup3, constraint, false, false); } else @@ -393,9 +401,9 @@ namespace Avalonia.Controls bool canResolveStarsU = CellGroup2 > _cellCache.Length; if (canResolveStarsU) { - if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } + if (HasStarCellsU) { ResolveStar(_definitionsU, constraint.Width); } MeasureCellsGroup(CellGroup3, constraint, false, false); - if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } + if (HasStarCellsV) { ResolveStar(_definitionsV, constraint.Height); } } else { @@ -421,14 +429,15 @@ namespace Avalonia.Controls ApplyCachedMinSizes(group3MinSizes, true); } - if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } + if (HasStarCellsU) { ResolveStar(_definitionsU, constraint.Width); } MeasureCellsGroup(CellGroup3, constraint, false, false); // Reset cached Group2Widths ApplyCachedMinSizes(group2MinSizes, false); - if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } - MeasureCellsGroup(CellGroup2, constraint, cnt == _layoutLoopMaxCount, false, out hasDesiredSizeUChanged); + if (HasStarCellsV) { ResolveStar(_definitionsV, constraint.Height); } + MeasureCellsGroup(CellGroup2, constraint, + cnt == _layoutLoopMaxCount, false, out hasDesiredSizeUChanged); } while (hasDesiredSizeUChanged && ++cnt <= _layoutLoopMaxCount); } @@ -438,8 +447,8 @@ namespace Avalonia.Controls MeasureCellsGroup(CellGroup4, constraint, false, false); gridDesiredSize = new Size( - CalculateDesiredSize(DefinitionsU), - CalculateDesiredSize(DefinitionsV)); + CalculateDesiredSize(_definitionsU), + CalculateDesiredSize(_definitionsV)); } } finally @@ -453,8 +462,8 @@ namespace Avalonia.Controls { if (ColumnDefinitionsDirty) { - if (DefinitionsU == null) - DefinitionsU = new DefinitionBase[1] { new ColumnDefinition() }; + if (_definitionsU == null) + _definitionsU = new DefinitionBase[1] { new ColumnDefinition() }; ColumnDefinitionsDirty = false; } } @@ -463,8 +472,8 @@ namespace Avalonia.Controls { if (RowDefinitionsDirty) { - if (DefinitionsV == null) - DefinitionsV = new DefinitionBase[1] { new RowDefinition() }; + if (_definitionsV == null) + _definitionsV = new DefinitionBase[1] { new RowDefinition() }; RowDefinitionsDirty = false; } @@ -491,10 +500,10 @@ namespace Avalonia.Controls } else { - Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0); + Debug.Assert(_definitionsU.Length > 0 && _definitionsV.Length > 0); - SetFinalSize(DefinitionsU, arrangeSize.Width, true); - SetFinalSize(DefinitionsV, arrangeSize.Height, false); + SetFinalSize(_definitionsU, arrangeSize.Width, true); + SetFinalSize(_definitionsV, arrangeSize.Height, false); for (int currentCell = 0; currentCell < _cellCache.Length; ++currentCell) { @@ -510,10 +519,10 @@ namespace Avalonia.Controls int rowSpan = _cellCache[currentCell].RowSpan; Rect 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)); + 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); } @@ -557,8 +566,8 @@ namespace Avalonia.Controls // actual value calculations require structure to be up-to-date if (!ColumnDefinitionsDirty) { - value = DefinitionsU[(columnIndex + 1) % DefinitionsU.Length].FinalOffset; - if (columnIndex != 0) { value -= DefinitionsU[columnIndex].FinalOffset; } + value = _definitionsU[(columnIndex + 1) % _definitionsU.Length].FinalOffset; + if (columnIndex != 0) { value -= _definitionsU[columnIndex].FinalOffset; } } return (value); } @@ -576,8 +585,8 @@ namespace Avalonia.Controls // actual value calculations require structure to be up-to-date if (!RowDefinitionsDirty) { - value = DefinitionsV[(rowIndex + 1) % DefinitionsV.Length].FinalOffset; - if (rowIndex != 0) { value -= DefinitionsV[rowIndex].FinalOffset; } + value = _definitionsV[(rowIndex + 1) % _definitionsV.Length].FinalOffset; + if (rowIndex != 0) { value -= _definitionsV[rowIndex].FinalOffset; } } return (value); } @@ -622,29 +631,29 @@ namespace Avalonia.Controls // 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(child), DefinitionsU.Length - 1); + cell.ColumnIndex = Math.Min(GetColumn(child), _definitionsU.Length - 1); + // clamp to value < number_of_rows // row >= 0 is guaranteed by property value validation callback - cell.RowIndex = Math.Min(GetRow(child), DefinitionsV.Length - 1); + cell.RowIndex = Math.Min(GetRow(child), _definitionsV.Length - 1); // 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(child), DefinitionsU.Length - cell.ColumnIndex); + cell.ColumnSpan = Math.Min(GetColumnSpan(child), _definitionsU.Length - 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(child), DefinitionsV.Length - cell.RowIndex); + cell.RowSpan = Math.Min(GetRowSpan(child), _definitionsV.Length - cell.RowIndex); - Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < DefinitionsU.Length); - Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Length); + Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < _definitionsU.Length); + Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < _definitionsV.Length); // // calculate and cache length types for the child // - - cell.SizeTypeU = GetLengthTypeForRange(DefinitionsU, cell.ColumnIndex, cell.ColumnSpan); - cell.SizeTypeV = GetLengthTypeForRange(DefinitionsV, cell.RowIndex, cell.RowSpan); + cell.SizeTypeU = GetLengthTypeForRange(_definitionsU, cell.ColumnIndex, cell.ColumnSpan); + cell.SizeTypeV = GetLengthTypeForRange(_definitionsV, cell.RowIndex, cell.RowSpan); hasStarCellsU |= cell.IsStarU; hasStarCellsV |= cell.IsStarV; @@ -652,7 +661,6 @@ namespace Avalonia.Controls // // distribute cells into four groups. // - if (!cell.IsStarV) { if (!cell.IsStarU) @@ -751,7 +759,8 @@ namespace Avalonia.Controls private double[] CacheMinSizes(int cellsHead, bool isRows) { - double[] minSizes = isRows ? new double[DefinitionsV.Length] : new double[DefinitionsU.Length]; + double[] minSizes = isRows ? new double[_definitionsV.Length] + : new double[_definitionsU.Length]; for (int j = 0; j < minSizes.Length; j++) { @@ -763,11 +772,11 @@ namespace Avalonia.Controls { if (isRows) { - minSizes[_cellCache[i].RowIndex] = DefinitionsV[_cellCache[i].RowIndex].MinSize; + minSizes[_cellCache[i].RowIndex] = _definitionsV[_cellCache[i].RowIndex].MinSize; } else { - minSizes[_cellCache[i].ColumnIndex] = DefinitionsU[_cellCache[i].ColumnIndex].MinSize; + minSizes[_cellCache[i].ColumnIndex] = _definitionsU[_cellCache[i].ColumnIndex].MinSize; } i = _cellCache[i].Next; @@ -784,11 +793,11 @@ namespace Avalonia.Controls { if (isRows) { - DefinitionsV[i].MinSize = minSizes[i]; + _definitionsV[i].MinSize = minSizes[i]; } else { - DefinitionsU[i].MinSize = minSizes[i]; + _definitionsU[i].MinSize = minSizes[i]; } } } @@ -801,7 +810,8 @@ namespace Avalonia.Controls bool forceInfinityV) { bool unusedHasDesiredSizeUChanged; - MeasureCellsGroup(cellsHead, referenceSize, ignoreDesiredSizeU, forceInfinityV, out unusedHasDesiredSizeUChanged); + MeasureCellsGroup(cellsHead, referenceSize, ignoreDesiredSizeU, + forceInfinityV, out unusedHasDesiredSizeUChanged); } /// @@ -844,7 +854,9 @@ namespace Avalonia.Controls { if (_cellCache[i].ColumnSpan == 1) { - DefinitionsU[_cellCache[i].ColumnIndex].UpdateMinSize(Math.Min(Children[i].DesiredSize.Width, DefinitionsU[_cellCache[i].ColumnIndex].UserMaxSize)); + _definitionsU[_cellCache[i].ColumnIndex] + .UpdateMinSize(Math.Min(Children[i].DesiredSize.Width, + _definitionsU[_cellCache[i].ColumnIndex].UserMaxSize)); } else { @@ -861,7 +873,9 @@ namespace Avalonia.Controls { if (_cellCache[i].RowSpan == 1) { - DefinitionsV[_cellCache[i].RowIndex].UpdateMinSize(Math.Min(Children[i].DesiredSize.Height, DefinitionsV[_cellCache[i].RowIndex].UserMaxSize)); + _definitionsV[_cellCache[i].RowIndex] + .UpdateMinSize(Math.Min(Children[i].DesiredSize.Height, + _definitionsV[_cellCache[i].RowIndex].UserMaxSize)); } else { @@ -885,7 +899,7 @@ namespace Avalonia.Controls double requestedSize = (double)e.Value; EnsureMinSizeInDefinitionRange( - key.U ? DefinitionsU : DefinitionsV, + key.U ? _definitionsU : _definitionsV, key.Start, key.Count, requestedSize, @@ -949,7 +963,7 @@ namespace Avalonia.Controls { // otherwise... cellMeasureWidth = GetMeasureSizeForRange( - DefinitionsU, + _definitionsU, _cellCache[cell].ColumnIndex, _cellCache[cell].ColumnSpan); } @@ -969,7 +983,7 @@ namespace Avalonia.Controls else { cellMeasureHeight = GetMeasureSizeForRange( - DefinitionsV, + _definitionsV, _cellCache[cell].RowIndex, _cellCache[cell].RowSpan); } @@ -1631,7 +1645,7 @@ namespace Avalonia.Controls if (def.UserSize.IsStar) { - Debug.Assert(!def.IsShared, "*-defs cannot be shared"); + // Debug.Assert(!def.IsShared, "*-defs cannot be shared"); if (def.MeasureSize < 0.0) { @@ -1675,18 +1689,18 @@ namespace Avalonia.Controls double userMaxSize; - if (def.IsShared) - { - // overriding userMaxSize effectively prevents squishy-ness. - // this is a "solution" to avoid shared definitions from been sized to - // different final size at arrange time, if / when different grids receive - // different final sizes. - userMaxSize = userSize; - } - else - { - userMaxSize = def.UserMaxSize; - } + // if (def.IsShared) + // { + // // overriding userMaxSize effectively prevents squishy-ness. + // // this is a "solution" to avoid shared definitions from been sized to + // // different final size at arrange time, if / when different grids receive + // // different final sizes. + // userMaxSize = userSize; + // } + // else + // { + userMaxSize = def.UserMaxSize; + // } def.SizeCache = Math.Max(def.MinSize, Math.Min(userSize, userMaxSize)); takenSize += def.SizeCache; @@ -2107,7 +2121,7 @@ namespace Avalonia.Controls if (_tempDefinitions != null) { // TempDefinitions has to be cleared to avoid "memory leaks" - Array.Clear(_tempDefinitions, 0, Math.Max(DefinitionsU.Length, DefinitionsV.Length)); + Array.Clear(_tempDefinitions, 0, Math.Max(_definitionsU.Length, _definitionsV.Length)); _tempDefinitions = null; } } @@ -2232,7 +2246,7 @@ namespace Avalonia.Controls { get { - int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length) * 2; + int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length) * 2; if (_tempDefinitions == null || _tempDefinitions.Length < requiredLength) @@ -2265,7 +2279,7 @@ namespace Avalonia.Controls { get { - int requiredLength = Math.Max(Math.Max(DefinitionsU.Length, DefinitionsV.Length), 1) * 2; + int requiredLength = Math.Max(Math.Max(_definitionsU.Length, _definitionsV.Length), 1) * 2; if (_definitionIndices == null || _definitionIndices.Length < requiredLength) { @@ -2283,7 +2297,7 @@ namespace Avalonia.Controls { get { - int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); + int requiredLength = Math.Max(_definitionsU.Length, _definitionsV.Length); if (_roundingErrors == null && requiredLength == 0) {