From 04b5b5468f5560e71659cf334d86a9ba37a7d7de Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Thu, 30 May 2019 18:36:32 +0800 Subject: [PATCH] Disable legacy GridLength.Star algorithms. Turn DefBase[] into IReadOnlyList. Fix DefBase, turn it into AvaloniaObject, change WPF types to Avalonia's and add a Parent prop. --- src/Avalonia.Controls/DefinitionBase.cs | 53 +++---- src/Avalonia.Controls/Grid.cs | 190 ++++++++++++------------ 2 files changed, 123 insertions(+), 120 deletions(-) diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 81c88b2638..7099befdcd 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -10,6 +10,7 @@ using System.Diagnostics; using Avalonia; using Avalonia.Collections; +using Avalonia.Utilities; namespace Avalonia.Controls { @@ -17,7 +18,7 @@ namespace Avalonia.Controls /// DefinitionBase provides core functionality used internally by Grid /// and ColumnDefinitionCollection / RowDefinitionCollection /// - public abstract class DefinitionBase : FrameworkContentElement + public abstract class DefinitionBase : AvaloniaObject { //------------------------------------------------------ // @@ -27,11 +28,11 @@ namespace Avalonia.Controls #region Constructors - internal DefinitionBase(bool isColumnDefinition) + /* internal DefinitionBase(bool isColumnDefinition) { _isColumnDefinition = isColumnDefinition; _parentIndex = -1; - } + }*/ #endregion Constructors @@ -134,7 +135,7 @@ namespace Avalonia.Controls /// /// This method needs to be internal to be accessable from derived classes. /// - internal static void OnUserSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + internal static void OnUserSizePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; @@ -161,7 +162,7 @@ namespace Avalonia.Controls } /// - /// + /// /// /// /// This method needs to be internal to be accessable from derived classes. @@ -177,7 +178,7 @@ namespace Avalonia.Controls /// /// This method needs to be internal to be accessable from derived classes. /// - internal static void OnUserMinSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + internal static void OnUserMinSizePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; @@ -189,7 +190,7 @@ namespace Avalonia.Controls } /// - /// + /// /// /// /// This method needs to be internal to be accessable from derived classes. @@ -197,7 +198,7 @@ namespace Avalonia.Controls internal static bool IsUserMinSizePropertyValueValid(object value) { double v = (double)value; - return (!DoubleUtil.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); + return (!double.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); } /// @@ -206,7 +207,7 @@ namespace Avalonia.Controls /// /// This method needs to be internal to be accessable from derived classes. /// - internal static void OnUserMaxSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + internal static void OnUserMaxSizePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; @@ -218,7 +219,7 @@ namespace Avalonia.Controls } /// - /// + /// /// /// /// This method needs to be internal to be accessable from derived classes. @@ -226,7 +227,7 @@ namespace Avalonia.Controls internal static bool IsUserMaxSizePropertyValueValid(object value) { double v = (double)value; - return (!DoubleUtil.IsNaN(v) && v >= 0.0d); + return (!double.IsNaN(v) && v >= 0.0d); } /// @@ -240,7 +241,7 @@ namespace Avalonia.Controls /// elements belonging to a certain scope can easily access SharedSizeState collection. As well /// as been norified about enter / exit a scope. /// - internal static void OnIsSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + internal static void OnIsSharedSizeScopePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { // is it possible to optimize here something like this: // if ((bool)d.GetValue(Grid.IsSharedSizeScopeProperty) == (d.GetLocalValue(PrivateSharedSizeScopeProperty) != null) @@ -456,6 +457,8 @@ namespace Avalonia.Controls get { return (_parentIndex != -1); } } + internal Grid Parent { get; set; } + #endregion Internal Properties //------------------------------------------------------ @@ -487,7 +490,7 @@ namespace Avalonia.Controls /// /// /// - private static void OnSharedSizeGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + private static void OnSharedSizeGroupPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase) d; @@ -518,7 +521,7 @@ namespace Avalonia.Controls } /// - /// + /// /// /// /// Verifies that Shared Size Group Property string @@ -569,7 +572,7 @@ namespace Avalonia.Controls /// existing scope just left. In both cases if the DefinitionBase object is already registered /// in SharedSizeState, it should un-register and register itself in a new one. /// - private static void OnPrivateSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + private static void OnPrivateSharedSizeScopePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) { DefinitionBase definition = (DefinitionBase)d; @@ -646,7 +649,7 @@ namespace Avalonia.Controls #region Private Fields private readonly bool _isColumnDefinition; // when "true", this is a ColumnDefinition; when "false" this is a RowDefinition (faster than a type check) private Flags _flags; // flags reflecting various aspects of internal state - private int _parentIndex; // this instance's index in parent's children collection + private int _parentIndex = -1; // this instance's index in parent's children collection private Grid.LayoutTimeSizeType _sizeType; // layout-time user size type. it may differ from _userSizeValueCache.UnitType when calculating "to-content" @@ -783,7 +786,7 @@ namespace Avalonia.Controls /// /// Makes sure that one and only one layout updated handler is registered for this shared state. /// - internal void EnsureDeferredValidation(UIElement layoutUpdatedHost) + internal void EnsureDeferredValidation(Control layoutUpdatedHost) { if (_layoutUpdatedHost == null) { @@ -861,7 +864,7 @@ namespace Avalonia.Controls sharedMinSize = Math.Max(sharedMinSize, _registry[i].MinSize); } - bool sharedMinSizeChanged = !DoubleUtil.AreClose(_minSize, sharedMinSize); + bool sharedMinSizeChanged = !MathUtilities.AreClose(_minSize, sharedMinSize); // compare accumulated min size with min sizes of the individual definitions for (int i = 0, count = _registry.Count; i < count; ++i) @@ -871,7 +874,7 @@ namespace Avalonia.Controls if (sharedMinSizeChanged || definitionBase.LayoutWasUpdated) { // if definition's min size is different, then need to re-measure - if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.MinSize)) + if (!MathUtilities.AreClose(sharedMinSize, definitionBase.MinSize)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateMeasure(); @@ -884,7 +887,7 @@ namespace Avalonia.Controls // if measure is valid then also need to check arrange. // Note: definitionBase.SizeCache is volatile but at this point // it contains up-to-date final size - if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache)) + if (!MathUtilities.AreClose(sharedMinSize, definitionBase.SizeCache)) { Grid parentGrid = (Grid)definitionBase.Parent; parentGrid.InvalidateArrange(); @@ -907,7 +910,7 @@ namespace Avalonia.Controls private readonly string _sharedSizeGroupId; // Id of the shared size group this object is servicing private readonly List _registry; // registry of participating definitions private readonly EventHandler _layoutUpdated; // instance event handler for layout updated event - private UIElement _layoutUpdatedHost; // UIElement for which layout updated event handler is registered + private Control _layoutUpdatedHost; // Control for which layout updated event handler is registered private bool _broadcastInvalidation; // "true" when broadcasting of invalidation is needed private bool _userSizeValid; // "true" when _userSize is up to date private GridLength _userSize; // shared state @@ -928,8 +931,8 @@ namespace Avalonia.Controls /// Private shared size scope property holds a collection of shared state objects for the a given shared size scope. /// /// - internal static readonly DependencyProperty PrivateSharedSizeScopeProperty = - DependencyProperty.RegisterAttached( + internal static readonly AvaloniaProperty PrivateSharedSizeScopeProperty = + AvaloniaProperty.RegisterAttached( "PrivateSharedSizeScope", typeof(SharedSizeScope), typeof(DefinitionBase), @@ -954,8 +957,8 @@ namespace Avalonia.Controls /// /// /// - public static readonly DependencyProperty SharedSizeGroupProperty = - DependencyProperty.Register( + public static readonly AvaloniaProperty SharedSizeGroupProperty = + AvaloniaProperty.Register( "SharedSizeGroup", typeof(string), typeof(DefinitionBase), diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 1bb2cd556f..d32534faa5 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -209,7 +209,7 @@ namespace Avalonia.Controls get { if (_data == null) { _data = new ExtendedData(); } - if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitions(this); } + if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitions(); } return (_data.ColumnDefinitions); } @@ -223,7 +223,7 @@ namespace Avalonia.Controls get { if (_data == null) { _data = new ExtendedData(); } - if (_data.RowDefinitions == null) { _data.RowDefinitions = new RowDefinitions(this); } + if (_data.RowDefinitions == null) { _data.RowDefinitions = new RowDefinitions(); } return (_data.RowDefinitions); } @@ -347,7 +347,7 @@ namespace Avalonia.Controls ValidateCells(); - Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0); + Debug.Assert(DefinitionsU.Count > 0 && DefinitionsV.Count > 0); // Grid classifies cells into four groups depending on // the column / row type a cell belongs to (number corresponds to @@ -606,7 +606,7 @@ namespace Avalonia.Controls } else { - Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0); + Debug.Assert(DefinitionsU.Count > 0 && DefinitionsV.Count > 0); @@ -661,14 +661,14 @@ namespace Avalonia.Controls /// /// /// - protected internal override void OnVisualChildrenChanged( + /*protected internal override void OnVisualChildrenChanged( AvaloniaObject visualAdded, AvaloniaObject visualRemoved) { CellsStructureDirty = true; base.OnVisualChildrenChanged(visualAdded, visualRemoved); - } + }*/ //------------------------------------------------------ // @@ -700,8 +700,8 @@ namespace Avalonia.Controls // actual value calculations require structure to be up-to-date if (!ColumnDefinitionsDirty) { - DefinitionBase[] definitions = DefinitionsU; - value = definitions[(columnIndex + 1) % definitions.Length].FinalOffset; + IReadOnlyList definitions = DefinitionsU; + value = definitions[(columnIndex + 1) % definitions.Count].FinalOffset; if (columnIndex != 0) { value -= definitions[columnIndex].FinalOffset; } } return (value); @@ -722,8 +722,8 @@ namespace Avalonia.Controls // actual value calculations require structure to be up-to-date if (!RowDefinitionsDirty) { - DefinitionBase[] definitions = DefinitionsV; - value = definitions[(rowIndex + 1) % definitions.Length].FinalOffset; + IReadOnlyList definitions = DefinitionsV; + value = definitions[(rowIndex + 1) % definitions.Count].FinalOffset; if (rowIndex != 0) { value -= definitions[rowIndex].FinalOffset; } } return (value); @@ -828,22 +828,22 @@ 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.Count - 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.Count - 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.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(child), DefinitionsV.Length - cell.RowIndex); + cell.RowSpan = Math.Min(GetRowSpan(child), DefinitionsV.Count - 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.Count); + Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Count); // // calculate and cache length types for the child @@ -924,9 +924,9 @@ namespace Avalonia.Controls } else { - extData.ColumnDefinitions.InternalTrimToSize(); + // extData.ColumnDefinitions.InternalTrimToSize(); - if (extData.ColumnDefinitions.InternalCount == 0) + if (extData.ColumnDefinitions.Count == 0) { // if column definitions collection is empty // mockup array with one column @@ -934,14 +934,14 @@ namespace Avalonia.Controls } else { - extData.DefinitionsU = extData.ColumnDefinitions.InternalItems; + extData.DefinitionsU = extData.ColumnDefinitions; } } ColumnDefinitionsDirty = false; } - Debug.Assert(ExtData.DefinitionsU != null && ExtData.DefinitionsU.Length > 0); + Debug.Assert(ExtData.DefinitionsU != null && ExtData.DefinitionsU.Count > 0); } @@ -971,9 +971,9 @@ namespace Avalonia.Controls } else { - extData.RowDefinitions.InternalTrimToSize(); + // extData.RowDefinitions.InternalTrimToSize(); - if (extData.RowDefinitions.InternalCount == 0) + if (extData.RowDefinitions.Count == 0) { // if row definitions collection is empty // mockup array with one row @@ -981,14 +981,14 @@ namespace Avalonia.Controls } else { - extData.DefinitionsV = extData.RowDefinitions.InternalItems; + extData.DefinitionsV = extData.RowDefinitions; } } RowDefinitionsDirty = false; } - Debug.Assert(ExtData.DefinitionsV != null && ExtData.DefinitionsV.Length > 0); + Debug.Assert(ExtData.DefinitionsV != null && ExtData.DefinitionsV.Count > 0); } @@ -1000,10 +1000,10 @@ namespace Avalonia.Controls /// Array of definitions to update. /// if "true" then star definitions are treated as Auto. private void ValidateDefinitionsLayout( - DefinitionBase[] definitions, + IReadOnlyList definitions, bool treatStarAsAuto) { - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { definitions[i].OnBeforeLayout(this); @@ -1047,7 +1047,7 @@ 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.Count] : new double[DefinitionsU.Count]; for (int j=0; j private double GetMeasureSizeForRange( - DefinitionBase[] definitions, + IReadOnlyList definitions, int start, int count) { - Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length); + Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Count); double measureSize = 0; int i = start + count - 1; @@ -1324,11 +1324,11 @@ namespace Avalonia.Controls /// Number of definitions included in the range. /// Length type for given range. private LayoutTimeSizeType GetLengthTypeForRange( - DefinitionBase[] definitions, + IReadOnlyList definitions, int start, int count) { - Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length); + Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Count); LayoutTimeSizeType lengthType = LayoutTimeSizeType.None; int i = start + count - 1; @@ -1350,13 +1350,13 @@ namespace Avalonia.Controls /// Definition array receiving distribution. /// Size used to resolve percentages. private void EnsureMinSizeInDefinitionRange( - DefinitionBase[] definitions, + IReadOnlyList definitions, int start, int count, double requestedSize, double percentReferenceSize) { - Debug.Assert(1 < count && 0 <= start && (start + count) <= definitions.Length); + Debug.Assert(1 < count && 0 <= start && (start + count) <= definitions.Count); // avoid processing when asked to distribute "0" if (!_IsZero(requestedSize)) @@ -1536,29 +1536,29 @@ namespace Avalonia.Controls /// Must initialize LayoutSize for all Star entries in given array of definitions. /// private void ResolveStar( - DefinitionBase[] definitions, + IReadOnlyList definitions, double availableSize) { - if (FrameworkAppContextSwitches.GridStarDefinitionsCanExceedAvailableSpace) - { - ResolveStarLegacy(definitions, availableSize); - } - else - { + // if (FrameworkAppContextSwitches.GridStarDefinitionsCanExceedAvailableSpace) + // { + // ResolveStarLegacy(definitions, availableSize); + // } + // else + // { ResolveStarMaxDiscrepancy(definitions, availableSize); - } + // } } // original implementation, used from 3.0 through 4.6.2 private void ResolveStarLegacy( - DefinitionBase[] definitions, + IReadOnlyList definitions, double availableSize) { DefinitionBase[] tempDefinitions = TempDefinitions; int starDefinitionsCount = 0; double takenSize = 0; - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { switch (definitions[i].SizeType) { @@ -1651,10 +1651,10 @@ namespace Avalonia.Controls // change in available space resulting in large change to one def's allocation. // 3. Correct handling of large *-values, including Infinity. private void ResolveStarMaxDiscrepancy( - DefinitionBase[] definitions, + IReadOnlyList definitions, double availableSize) { - int defCount = definitions.Length; + int defCount = definitions.Count; DefinitionBase[] tempDefinitions = TempDefinitions; int minCount = 0, maxCount = 0; double takenSize = 0; @@ -1948,11 +1948,11 @@ namespace Avalonia.Controls /// Array of definitions to use for calculations. /// Desired size. private double CalculateDesiredSize( - DefinitionBase[] definitions) + IReadOnlyList definitions) { double desiredSize = 0; - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { desiredSize += definitions[i].MinSize; } @@ -1967,28 +1967,28 @@ namespace Avalonia.Controls /// Final size to lay out to. /// True if sizing row definitions, false for columns private void SetFinalSize( - DefinitionBase[] definitions, + IReadOnlyList definitions, double finalSize, bool columns) { - if (FrameworkAppContextSwitches.GridStarDefinitionsCanExceedAvailableSpace) - { - SetFinalSizeLegacy(definitions, finalSize, columns); - } - else - { + // if (FrameworkAppContextSwitches.GridStarDefinitionsCanExceedAvailableSpace) + // { + // SetFinalSizeLegacy(definitions, finalSize, columns); + // } + // else + // { SetFinalSizeMaxDiscrepancy(definitions, finalSize, columns); - } + // } } // original implementation, used from 3.0 through 4.6.2 private void SetFinalSizeLegacy( - DefinitionBase[] definitions, + IReadOnlyList definitions, double finalSize, bool columns) { int starDefinitionsCount = 0; // traverses form the first entry up - int nonStarIndex = definitions.Length; // traverses from the last entry down + int nonStarIndex = definitions.Count; // traverses from the last entry down double allPreferredArrangeSize = 0; bool useLayoutRounding = this.UseLayoutRounding; int[] definitionIndices = DefinitionIndices; @@ -2004,7 +2004,7 @@ namespace Avalonia.Controls roundingErrors = RoundingErrors; } - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { // if definition is shared then is cannot be star Debug.Assert(!definitions[i].IsShared || !definitions[i].UserSize.IsStar); @@ -2134,13 +2134,13 @@ namespace Avalonia.Controls && !_AreClose(allPreferredArrangeSize, finalSize) ) { DistributionOrderIndexComparer distributionOrderIndexComparer = new DistributionOrderIndexComparer(definitions); - Array.Sort(definitionIndices, 0, definitions.Length, distributionOrderIndexComparer); + Array.Sort(definitionIndices, 0, definitions.Count, distributionOrderIndexComparer); double sizeToDistribute = finalSize - allPreferredArrangeSize; - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { int definitionIndex = definitionIndices[i]; - double final = definitions[definitionIndex].SizeCache + (sizeToDistribute / (definitions.Length - i)); + double final = definitions[definitionIndex].SizeCache + (sizeToDistribute / (definitions.Count - i)); double finalOld = final; final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange); final = Math.Min(final, definitions[definitionIndex].SizeCache); @@ -2165,7 +2165,7 @@ namespace Avalonia.Controls if (!_AreClose(allPreferredArrangeSize, finalSize)) { // Compute deltas - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { roundingErrors[i] = roundingErrors[i] - definitions[i].SizeCache; definitionIndices[i] = i; @@ -2173,13 +2173,13 @@ namespace Avalonia.Controls // Sort rounding errors RoundingErrorIndexComparer roundingErrorIndexComparer = new RoundingErrorIndexComparer(roundingErrors); - Array.Sort(definitionIndices, 0, definitions.Length, roundingErrorIndexComparer); + Array.Sort(definitionIndices, 0, definitions.Count, roundingErrorIndexComparer); double adjustedSize = allPreferredArrangeSize; double dpiIncrement = Control.RoundLayoutValue(1.0, dpi); if (allPreferredArrangeSize > finalSize) { - int i = definitions.Length - 1; + int i = definitions.Count - 1; while ((adjustedSize > finalSize && !_AreClose(adjustedSize, finalSize)) && i >= 0) { DefinitionBase definition = definitions[definitionIndices[i]]; @@ -2196,7 +2196,7 @@ namespace Avalonia.Controls else if (allPreferredArrangeSize < finalSize) { int i = 0; - while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Length) + while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Count) { DefinitionBase definition = definitions[definitionIndices[i]]; double final = definition.SizeCache + dpiIncrement; @@ -2213,9 +2213,9 @@ namespace Avalonia.Controls } definitions[0].FinalOffset = 0.0; - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { - definitions[(i + 1) % definitions.Length].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; + definitions[(i + 1) % definitions.Count].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; } } @@ -2232,11 +2232,11 @@ namespace Avalonia.Controls // comes into play at high DPI - greater than 134. // 3. Applies rounding only to real pixel values (not to ratios) private void SetFinalSizeMaxDiscrepancy( - DefinitionBase[] definitions, + IReadOnlyList definitions, double finalSize, bool columns) { - int defCount = definitions.Length; + int defCount = definitions.Count; int[] definitionIndices = DefinitionIndices; int minCount = 0, maxCount = 0; double takenSize = 0.0; @@ -2571,7 +2571,7 @@ namespace Avalonia.Controls double roundedTakenSize = 0.0; // round each of the allocated sizes, keeping track of the deltas - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { DefinitionBase def = definitions[i]; double roundedSize = Control.RoundLayoutValue(def.SizeCache, dpi); @@ -2625,20 +2625,20 @@ namespace Avalonia.Controls if (!_AreClose(roundedTakenSize, finalSize)) { // Compute deltas - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { definitionIndices[i] = i; } // Sort rounding errors RoundingErrorIndexComparer roundingErrorIndexComparer = new RoundingErrorIndexComparer(roundingErrors); - Array.Sort(definitionIndices, 0, definitions.Length, roundingErrorIndexComparer); + Array.Sort(definitionIndices, 0, definitions.Count, roundingErrorIndexComparer); double adjustedSize = roundedTakenSize; double dpiIncrement = 1.0/dpi; if (roundedTakenSize > finalSize) { - int i = definitions.Length - 1; + int i = definitions.Count - 1; while ((adjustedSize > finalSize && !_AreClose(adjustedSize, finalSize)) && i >= 0) { DefinitionBase definition = definitions[definitionIndices[i]]; @@ -2655,7 +2655,7 @@ namespace Avalonia.Controls else if (roundedTakenSize < finalSize) { int i = 0; - while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Length) + while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Count) { DefinitionBase definition = definitions[definitionIndices[i]]; double final = definition.SizeCache + dpiIncrement; @@ -2673,9 +2673,9 @@ namespace Avalonia.Controls // Phase 6. Compute final offsets definitions[0].FinalOffset = 0.0; - for (int i = 0; i < definitions.Length; ++i) + for (int i = 0; i < definitions.Count; ++i) { - definitions[(i + 1) % definitions.Length].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; + definitions[(i + 1) % definitions.Count].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; } } @@ -2753,7 +2753,7 @@ namespace Avalonia.Controls /// Number of items in the range. /// Final size. private double GetFinalSizeForRange( - DefinitionBase[] definitions, + IReadOnlyList definitions, int start, int count) { @@ -2782,7 +2782,7 @@ namespace Avalonia.Controls if (extData.TempDefinitions != null) { // TempDefinitions has to be cleared to avoid "memory leaks" - Array.Clear(extData.TempDefinitions, 0, Math.Max(DefinitionsU.Length, DefinitionsV.Length)); + Array.Clear(extData.TempDefinitions, 0, Math.Max(DefinitionsU.Count, DefinitionsV.Count)); extData.TempDefinitions = null; } } @@ -2960,7 +2960,7 @@ namespace Avalonia.Controls /// /// Private version returning array of column definitions. /// - private DefinitionBase[] DefinitionsU + private IReadOnlyList DefinitionsU { get { return (ExtData.DefinitionsU); } } @@ -2968,7 +2968,7 @@ namespace Avalonia.Controls /// /// Private version returning array of row definitions. /// - private DefinitionBase[] DefinitionsV + private IReadOnlyList DefinitionsV { get { return (ExtData.DefinitionsV); } } @@ -2981,7 +2981,7 @@ namespace Avalonia.Controls get { ExtendedData extData = ExtData; - int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length) * 2; + int requiredLength = Math.Max(DefinitionsU.Count, DefinitionsV.Count) * 2; if ( extData.TempDefinitions == null || extData.TempDefinitions.Length < requiredLength ) @@ -3014,7 +3014,7 @@ namespace Avalonia.Controls { get { - int requiredLength = Math.Max(Math.Max(DefinitionsU.Length, DefinitionsV.Length), 1) * 2; + int requiredLength = Math.Max(Math.Max(DefinitionsU.Count, DefinitionsV.Count), 1) * 2; if (_definitionIndices == null || _definitionIndices.Length < requiredLength) { @@ -3032,7 +3032,7 @@ namespace Avalonia.Controls { get { - int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); + int requiredLength = Math.Max(DefinitionsU.Count, DefinitionsV.Count); if (_roundingErrors == null && requiredLength == 0) { @@ -3209,8 +3209,8 @@ namespace Avalonia.Controls { internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support) internal RowDefinitions RowDefinitions; // collection of row definitions (logical tree support) - internal DefinitionBase[] DefinitionsU; // collection of column definitions used during calc - internal DefinitionBase[] DefinitionsV; // collection of row definitions used during calc + 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 @@ -3589,9 +3589,9 @@ namespace Avalonia.Controls /// private class StarDistributionOrderIndexComparer : IComparer { - private readonly DefinitionBase[] definitions; + private readonly IReadOnlyList definitions; - internal StarDistributionOrderIndexComparer(DefinitionBase[] definitions) + internal StarDistributionOrderIndexComparer(IReadOnlyList definitions) { Contract.Requires(definitions != null); this.definitions = definitions; @@ -3630,9 +3630,9 @@ namespace Avalonia.Controls /// private class DistributionOrderIndexComparer : IComparer { - private readonly DefinitionBase[] definitions; + private readonly IReadOnlyList definitions; - internal DistributionOrderIndexComparer(DefinitionBase[] definitions) + internal DistributionOrderIndexComparer(IReadOnlyList definitions) { Contract.Requires(definitions != null); this.definitions = definitions; @@ -3772,9 +3772,9 @@ namespace Avalonia.Controls /// private class MinRatioIndexComparer : IComparer { - private readonly DefinitionBase[] definitions; + private readonly IReadOnlyList definitions; - internal MinRatioIndexComparer(DefinitionBase[] definitions) + internal MinRatioIndexComparer(IReadOnlyList definitions) { Contract.Requires(definitions != null); this.definitions = definitions; @@ -3813,9 +3813,9 @@ namespace Avalonia.Controls /// private class MaxRatioIndexComparer : IComparer { - private readonly DefinitionBase[] definitions; + private readonly IReadOnlyList definitions; - internal MaxRatioIndexComparer(DefinitionBase[] definitions) + internal MaxRatioIndexComparer(IReadOnlyList definitions) { Contract.Requires(definitions != null); this.definitions = definitions; @@ -3854,9 +3854,9 @@ namespace Avalonia.Controls /// private class StarWeightIndexComparer : IComparer { - private readonly DefinitionBase[] definitions; + private readonly IReadOnlyList definitions; - internal StarWeightIndexComparer(DefinitionBase[] definitions) + internal StarWeightIndexComparer(IReadOnlyList definitions) { Contract.Requires(definitions != null); this.definitions = definitions;