From 5741d0ef140f3da153a8803dd7d1aefb94e1c82c Mon Sep 17 00:00:00 2001 From: wojciech krysiak Date: Wed, 3 Oct 2018 16:49:56 +0200 Subject: [PATCH] Base case works --- src/Avalonia.Controls/Grid.cs | 136 ++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 54 deletions(-) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 5dc90414ee..d89c2947ce 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -60,6 +60,7 @@ namespace Avalonia.Controls private class MeasurementCache { + public MeasurementCache(Grid grid) { Grid = grid; @@ -67,19 +68,20 @@ namespace Avalonia.Controls .Concat(grid.ColumnDefinitions) .Select(d => new MeasurementResult(d)) .ToList(); + + grid.RowDefinitions. + } public void UpdateMeasureResult(GridLayout.MeasureResult rowResult, GridLayout.MeasureResult columnResult) { - RowResult = rowResult; - ColumnResult = columnResult; MeasurementState = MeasurementState.Cached; - for (int i = 0; i < rowResult.LengthList.Count; i++) + for (int i = 0; i < Grid.RowDefinitions.Count; i++) { Results[i].MeasuredResult = rowResult.LengthList[i]; } - for (int i = 0; i < columnResult.LengthList.Count; i++) + for (int i = 0; i < Grid.ColumnDefinitions.Count; i++) { Results[i + rowResult.LengthList.Count].MeasuredResult = columnResult.LengthList[i]; } @@ -92,8 +94,6 @@ namespace Avalonia.Controls } public Grid Grid { get; } - public GridLayout.MeasureResult RowResult { get; private set; } - public GridLayout.MeasureResult ColumnResult { get; private set; } public MeasurementState MeasurementState { get; private set; } public List Results { get; } @@ -103,9 +103,9 @@ namespace Avalonia.Controls private class MeasurementResult { - public MeasurementResult(DefinitionBase @base) + public MeasurementResult(DefinitionBase definition) { - Definition = @base; + Definition = definition; MeasuredResult = double.NaN; } @@ -113,22 +113,16 @@ namespace Avalonia.Controls public double MeasuredResult { get; set; } } - private enum ScopeType - { - Auto, - Fixed - } - private class Group { public bool IsFixed { get; set; } - public List Results { get; } + public List Results { get; } = new List(); public double CalculatedLength { get; } } - private Dictionary _groups = new Dictionary(); + private readonly Dictionary _groups = new Dictionary(); public SharedSizeScopeHost(Control scope) @@ -158,57 +152,79 @@ namespace Avalonia.Controls cache.UpdateMeasureResult(rowResult, columnResult); } - internal (GridLayout.MeasureResult, GridLayout.MeasureResult) HandleArrange(Grid grid, GridLayout.MeasureResult rowResult, GridLayout.MeasureResult columnResult) + private double Gather(IEnumerable measurements) { - var rowConventions = rowResult.LeanLengthList.ToList(); - var rowLengths = rowResult.LengthList.ToList(); - var rowDesiredLength = 0.0; - for (int i = 0; i < grid.RowDefinitions.Count; i++) + var result = 0.0d; + + bool onlyFixed = false; + + foreach (var measurement in measurements) { - var definition = grid.RowDefinitions[i]; - if (string.IsNullOrEmpty(definition.SharedSizeGroup)) + if (measurement.Definition is ColumnDefinition column) { - rowDesiredLength += rowResult.LengthList[i]; - continue; + if (!onlyFixed && column.Width.IsAbsolute) + { + onlyFixed = true; + result = measurement.MeasuredResult; + } + else if (onlyFixed == column.Width.IsAbsolute) + result = Math.Max(result, measurement.MeasuredResult); + + result = Math.Max(result, column.MinWidth); } + if (measurement.Definition is RowDefinition row) + { + if (!onlyFixed && row.Height.IsAbsolute) + { + onlyFixed = true; + result = measurement.MeasuredResult; + } + else if (onlyFixed == row.Height.IsAbsolute) + result = Math.Max(result, measurement.MeasuredResult); + + result = Math.Max(result, row.MinHeight); + } + } - var group = _groups[definition.SharedSizeGroup]; - - var length = group.Results.Max(g => g.MeasuredResult); - rowConventions[i] = new GridLayout.LengthConvention( - new GridLength(length), - rowResult.LeanLengthList[i].MinLength, - rowResult.LeanLengthList[i].MaxLength - ); - rowLengths[i] = length; - rowDesiredLength += length; + return result; + } - } - var columnConventions = columnResult.LeanLengthList.ToList(); - var columnLengths = columnResult.LengthList.ToList(); - var columnDesiredLength = 0.0; - for (int i = 0; i < grid.ColumnDefinitions.Count; i++) + (List, List, double) Arrange(IReadOnlyList definitions, GridLayout.MeasureResult measureResult) + { + var conventions = measureResult.LeanLengthList.ToList(); + var lengths = measureResult.LengthList.ToList(); + var desiredLength = 0.0; + for (int i = 0; i < definitions.Count; i++) { - var definition = grid.ColumnDefinitions[i]; + var definition = definitions[i]; if (string.IsNullOrEmpty(definition.SharedSizeGroup)) { - columnDesiredLength += rowResult.LengthList[i]; + desiredLength += measureResult.LengthList[i]; continue; } var group = _groups[definition.SharedSizeGroup]; - var length = group.Results.Max(g => g.MeasuredResult); - columnConventions[i] = new GridLayout.LengthConvention( + var length = Gather(group.Results); + + conventions[i] = new GridLayout.LengthConvention( new GridLength(length), - columnResult.LeanLengthList[i].MinLength, - columnResult.LeanLengthList[i].MaxLength - ); - columnLengths[i] = length; - columnDesiredLength += length; + measureResult.LeanLengthList[i].MinLength, + measureResult.LeanLengthList[i].MaxLength + ); + lengths[i] = length; + desiredLength += length; } + return (conventions, lengths, desiredLength); + } + + internal (GridLayout.MeasureResult, GridLayout.MeasureResult) HandleArrange(Grid grid, GridLayout.MeasureResult rowResult, GridLayout.MeasureResult columnResult) + { + var (rowConventions, rowLengths, rowDesiredLength) = Arrange(grid.RowDefinitions, rowResult); + var (columnConventions, columnLengths, columnDesiredLength) = Arrange(grid.ColumnDefinitions, columnResult); + return ( new GridLayout.MeasureResult( rowResult.ContainerLength, @@ -231,6 +247,8 @@ namespace Avalonia.Controls foreach (var result in cache.Results) { var scopeName = result.Definition.SharedSizeGroup; + if (string.IsNullOrEmpty(scopeName)) + continue; if (!_groups.TryGetValue(scopeName, out var group)) _groups.Add(scopeName, group = new Group()); @@ -250,6 +268,8 @@ namespace Avalonia.Controls foreach (var result in cache.Results) { var scopeName = result.Definition.SharedSizeGroup; + if (string.IsNullOrEmpty(scopeName)) + continue; Debug.Assert(_groups.TryGetValue(scopeName, out var group)); group.Results.Remove(result); @@ -346,14 +366,14 @@ namespace Avalonia.Controls if ((bool)arg2.NewValue) { Debug.Assert(source.GetValue(s_sharedSizeScopeHostProperty) == null); - source.SetValue(IsSharedSizeScopeProperty, new SharedSizeScopeHost(source)); + source.SetValue(s_sharedSizeScopeHostProperty, new SharedSizeScopeHost(source)); } else { var host = source.GetValue(s_sharedSizeScopeHostProperty) as SharedSizeScopeHost; Debug.Assert(host != null); host.Dispose(); - source.SetValue(IsSharedSizeScopeProperty, null); + source.SetValue(s_sharedSizeScopeHostProperty, null); } } @@ -626,11 +646,19 @@ namespace Avalonia.Controls var columnLayout = _columnLayoutCache; var rowLayout = _rowLayoutCache; - var (rowCache, columnCache) = _sharedSizeHost?.HandleArrange(this, _rowMeasureCache, _columnMeasureCache) ?? (_rowMeasureCache, _columnMeasureCache); + var (rowCache, columnCache) = + _sharedSizeHost?.HandleArrange(this, _rowMeasureCache, _columnMeasureCache) ?? + (_rowMeasureCache, _columnMeasureCache); + + if (_sharedSizeHost != null) + { + rowCache = rowLayout.Measure(finalSize.Width, rowCache.LeanLengthList); + columnCache = columnLayout.Measure(finalSize.Width, columnCache.LeanLengthList); + } // Calculate for arrange result. - var columnResult = columnLayout.Arrange(finalSize.Width, rowCache); - var rowResult = rowLayout.Arrange(finalSize.Height, columnCache); + var columnResult = columnLayout.Arrange(finalSize.Width, columnCache); + var rowResult = rowLayout.Arrange(finalSize.Height, rowCache); // Arrange the children. foreach (var child in Children.OfType()) {