From ef0464a7e76dfe2182782c03786e7258ecf34479 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 11:10:37 +0300 Subject: [PATCH 01/19] add failing tests for grid: when column/row (width/height ...) properties are changed grid doesn't react --- .../Avalonia.Controls.UnitTests/GridTests.cs | 122 ++++++++++++++++-- 1 file changed, 113 insertions(+), 9 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 2b9197e20b..353e5ecd42 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1,11 +1,6 @@ +using System; using System.Collections.Generic; using System.Linq; -using Avalonia.Controls.Primitives; -using Avalonia.Input; -using Avalonia.Platform; -using Avalonia.UnitTests; - -using Moq; using Xunit; using Xunit.Abstractions; @@ -34,7 +29,6 @@ namespace Avalonia.Controls.UnitTests private Grid CreateGrid(params (string name, GridLength width, double minWidth, double maxWidth)[] columns) { - var grid = new Grid(); foreach (var k in columns.Select(c => new ColumnDefinition { @@ -1270,11 +1264,11 @@ namespace Avalonia.Controls.UnitTests // grid.Measure(new Size(100, 100)); // grid.Arrange(new Rect(new Point(), new Point(100, 100))); // PrintColumnDefinitions(grid); - + // NOTE: THIS IS BROKEN IN WPF // all in group are equal to width (MinWidth) of the sizer in the second column // Assert.All(grid.ColumnDefinitions.Where(cd => cd.SharedSizeGroup == "A"), cd => Assert.Equal(6 + 1 * 6, cd.ActualWidth)); - + // NOTE: THIS IS BROKEN IN WPF // grid.ColumnDefinitions[2].SharedSizeGroup = null; @@ -1382,6 +1376,116 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Size(100, 100), grid.Bounds.Size); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Column_Width_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.ColumnDefinitions[0][ColumnDefinition.WidthProperty] = new GridLength(5); + else + grid.ColumnDefinitions[0].Width = new GridLength(5); + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Column_MinWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.ColumnDefinitions[0][ColumnDefinition.MinWidthProperty] = 5; + else + grid.ColumnDefinitions[0].MinWidth = 5; + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Column_MaxWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.ColumnDefinitions[0][ColumnDefinition.MaxWidthProperty] = 5; + else + grid.ColumnDefinitions[0].MaxWidth = 5; + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Row_Height_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.RowDefinitions[0][RowDefinition.HeightProperty] = new GridLength(5); + else + grid.RowDefinitions[0].Height = new GridLength(5); + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Row_MinHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.RowDefinitions[0][RowDefinition.MinHeightProperty] = 5; + else + grid.RowDefinitions[0].MinHeight = 5; + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Change_Row_MaxHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + if (setUsingAvaloniaProperty) + grid.RowDefinitions[0][RowDefinition.MaxHeightProperty] = 5; + else + grid.RowDefinitions[0].MaxHeight = 5; + }); + } + + private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) + { + grid.Measure(new Size(100, 100)); + grid.Arrange(new Rect(grid.DesiredSize)); + + Assert.True(grid.IsMeasureValid); + Assert.True(grid.IsArrangeValid); + + change(); + + Assert.False(grid.IsMeasureValid); + Assert.False(grid.IsArrangeValid); + } + private class TestControl : Control { public Size MeasureSize { get; set; } From 4f82615868d86e815631d08901284937666d835a Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:11:23 +0300 Subject: [PATCH 02/19] fix problem when grid row/col properties (width/height ...) are changed grid to invalidate calculations --- src/Avalonia.Controls/ColumnDefinition.cs | 11 ++++++++--- src/Avalonia.Controls/DefinitionBase.cs | 17 +++++++++++++++++ src/Avalonia.Controls/RowDefinition.cs | 11 ++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/ColumnDefinition.cs b/src/Avalonia.Controls/ColumnDefinition.cs index 9c520c434e..6cad357e93 100644 --- a/src/Avalonia.Controls/ColumnDefinition.cs +++ b/src/Avalonia.Controls/ColumnDefinition.cs @@ -26,6 +26,14 @@ namespace Avalonia.Controls public static readonly StyledProperty WidthProperty = AvaloniaProperty.Register(nameof(Width), new GridLength(1, GridUnitType.Star)); + /// + /// Initializes static members of the class. + /// + static ColumnDefinition() + { + AffectsParentMeasure(WidthProperty, MinWidthProperty, MaxWidthProperty); + } + /// /// Initializes a new instance of the class. /// @@ -68,7 +76,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(MaxWidthProperty, value); } } @@ -84,7 +91,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(MinWidthProperty, value); } } @@ -100,7 +106,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(WidthProperty, value); } } diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index a68fe1265f..37c77ddb9c 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -730,5 +730,22 @@ namespace Avalonia.Controls SharedSizeGroupProperty.Changed.AddClassHandler(OnSharedSizeGroupPropertyChanged); PrivateSharedSizeScopeProperty.Changed.AddClassHandler(OnPrivateSharedSizeScopePropertyChanged); } + + /// + /// Marks a property on a definition as affecting the parent grid's measurement. + /// + /// The properties. + protected static void AffectsParentMeasure(params AvaloniaProperty[] properties) + { + void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + (e.Sender as DefinitionBase)?.Parent?.InvalidateMeasure(); + } + + foreach (var property in properties) + { + property.Changed.Subscribe(Invalidate); + } + } } } diff --git a/src/Avalonia.Controls/RowDefinition.cs b/src/Avalonia.Controls/RowDefinition.cs index 1f2f738670..1a1a7e770b 100644 --- a/src/Avalonia.Controls/RowDefinition.cs +++ b/src/Avalonia.Controls/RowDefinition.cs @@ -26,6 +26,14 @@ namespace Avalonia.Controls public static readonly StyledProperty HeightProperty = AvaloniaProperty.Register(nameof(Height), new GridLength(1, GridUnitType.Star)); + /// + /// Initializes static members of the class. + /// + static RowDefinition() + { + AffectsParentMeasure(HeightProperty, MaxHeightProperty, MinHeightProperty); + } + /// /// Initializes a new instance of the class. /// @@ -68,7 +76,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(MaxHeightProperty, value); } } @@ -84,7 +91,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(MinHeightProperty, value); } } @@ -100,7 +106,6 @@ namespace Avalonia.Controls } set { - Parent?.InvalidateMeasure(); SetValue(HeightProperty, value); } } From fe4866d763539e0471785b80f705e58a1def2104 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:04:05 +0300 Subject: [PATCH 03/19] issue: #3141 add failing tests for grid: when col/row are added grid doesn't trigger layout update --- .../Avalonia.Controls.UnitTests/GridTests.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 353e5ecd42..84ae12984c 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1472,6 +1472,27 @@ namespace Avalonia.Controls.UnitTests }); } + [Fact] + public void Add_Column_Should_Invalidate_Grid() + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(5))); + }); + } + + [Fact] + public void Add_Row_Should_Invalidate_Grid() + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.RowDefinitions.Add(new RowDefinition(new GridLength(5))); + }); + } private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) { grid.Measure(new Size(100, 100)); From acf0d42a8139b146859fb1b9cab19e9c8f6afba1 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:14:17 +0300 Subject: [PATCH 04/19] fix issue: #3141 when col/row are added grid trigger layout update --- src/Avalonia.Controls/DefinitionBase.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 37c77ddb9c..3052728222 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -50,6 +50,8 @@ namespace Avalonia.Controls } } } + + Parent?.InvalidateMeasure(); } /// From b0eb2a10187d1cb60a359994bd2b22146ba643fd Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:07:49 +0300 Subject: [PATCH 05/19] issue: #3141 add failing tests for grid: when col/row are removed grid doesn't trigger layout update --- .../Avalonia.Controls.UnitTests/GridTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 84ae12984c..187255a89b 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1493,6 +1493,28 @@ namespace Avalonia.Controls.UnitTests grid.RowDefinitions.Add(new RowDefinition(new GridLength(5))); }); } + + [Fact] + public void Remove_Column_Should_Invalidate_Grid() + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.ColumnDefinitions.RemoveAt(0); + }); + } + + [Fact] + public void Remove_Row_Should_Invalidate_Grid() + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.RowDefinitions.RemoveAt(0); + }); + } private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) { grid.Measure(new Size(100, 100)); From 4b275a8f29c70106cdf57ab19d6ef4505f4a24a6 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:14:55 +0300 Subject: [PATCH 06/19] fixed issue: #3141 when col/row are removed grid trigger layout update --- src/Avalonia.Controls/DefinitionBase.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 3052728222..6ad32f080a 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -65,6 +65,8 @@ namespace Avalonia.Controls _sharedState.RemoveMember(this); _sharedState = null; } + + Parent?.InvalidateMeasure(); } /// From a7f0851efb98d3f23b17d5eb4c8d46b38dddc916 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:37:52 +0300 Subject: [PATCH 07/19] add failing test for grid when columns/row are replaced grid doesn't invalidate --- .../Avalonia.Controls.UnitTests/GridTests.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 187255a89b..192b8b2172 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1494,6 +1494,28 @@ namespace Avalonia.Controls.UnitTests }); } + [Fact] + public void Replace_Columns_Should_Invalidate_Grid() + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.ColumnDefinitions = ColumnDefinitions.Parse("2*,1*"); + }); + } + + [Fact] + public void Replace_Rows_Should_Invalidate_Grid() + { + var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; + + Change_Propery_And_Verify_Measure_Requested(grid, () => + { + grid.RowDefinitions = RowDefinitions.Parse("2*,1*"); + }); + } + [Fact] public void Remove_Column_Should_Invalidate_Grid() { @@ -1515,6 +1537,7 @@ namespace Avalonia.Controls.UnitTests grid.RowDefinitions.RemoveAt(0); }); } + private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) { grid.Measure(new Size(100, 100)); From 7f2b3261b4db52c1bea46c4e228a0a48cb22e778 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 15:38:28 +0300 Subject: [PATCH 08/19] fix grid to invalidate when columns/rows are replaced --- src/Avalonia.Controls/Grid.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 8ecfe349f8..ef202178df 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -178,6 +178,7 @@ namespace Avalonia.Controls if (_data == null) { _data = new ExtendedData(); } _data.ColumnDefinitions = value; _data.ColumnDefinitions.Parent = this; + InvalidateMeasure(); } } @@ -198,6 +199,7 @@ namespace Avalonia.Controls if (_data == null) { _data = new ExtendedData(); } _data.RowDefinitions = value; _data.RowDefinitions.Parent = this; + InvalidateMeasure(); } } From 56cfbc1e465e25efee7410edd6c021c9b2ab8404 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 16:13:35 +0300 Subject: [PATCH 09/19] add failing test for issue #3155 add/remove grid child runtime throws exception --- .../Avalonia.Controls.UnitTests/GridTests.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 192b8b2172..5db28238f4 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1538,6 +1538,69 @@ namespace Avalonia.Controls.UnitTests }); } + [Fact] + public void Remove_Child_Should_Invalidate_Grid_And_Be_Operational() + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") }; + + grid.Children.Add(new Decorator() { [Grid.ColumnProperty] = 0 }); + grid.Children.Add(new Decorator() { Width = 10, Height = 10, [Grid.ColumnProperty] = 1 }); + + var size = new Size(100, 100); + grid.Measure(size); + grid.Arrange(new Rect(size)); + + Assert.True(grid.IsMeasureValid); + Assert.True(grid.IsArrangeValid); + + Assert.Equal(90, grid.Children[0].Bounds.Width); + Assert.Equal(10, grid.Children[1].Bounds.Width); + + grid.Children.RemoveAt(1); + + Assert.False(grid.IsMeasureValid); + Assert.False(grid.IsArrangeValid); + + grid.Measure(size); + grid.Arrange(new Rect(size)); + + Assert.True(grid.IsMeasureValid); + Assert.True(grid.IsArrangeValid); + + Assert.Equal(100, grid.Children[0].Bounds.Width); + } + + [Fact] + public void Add_Child_Should_Invalidate_Grid_And_Be_Operational() + { + var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") }; + + grid.Children.Add(new Decorator() { [Grid.ColumnProperty] = 0 }); + + var size = new Size(100, 100); + grid.Measure(size); + grid.Arrange(new Rect(size)); + + Assert.True(grid.IsMeasureValid); + Assert.True(grid.IsArrangeValid); + + Assert.Equal(100, grid.Children[0].Bounds.Width); + + grid.Children.Add(new Decorator() { Width = 10, Height = 10, [Grid.ColumnProperty] = 1 }); + + Assert.False(grid.IsMeasureValid); + Assert.False(grid.IsArrangeValid); + + grid.Measure(size); + grid.Arrange(new Rect(size)); + + Assert.True(grid.IsMeasureValid); + Assert.True(grid.IsArrangeValid); + + Assert.Equal(90, grid.Children[0].Bounds.Width); + Assert.Equal(10, grid.Children[1].Bounds.Width); + } + private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) { grid.Measure(new Size(100, 100)); From d478572e7452a5d79625ab42f39b75d32aa2d2c8 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 16:14:36 +0300 Subject: [PATCH 10/19] fix issue #3155 add/remove grid child runtime works properly --- src/Avalonia.Controls/Grid.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index ef202178df..23c1cd4794 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -6,6 +6,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; using System.Diagnostics; using System.Linq; using System.Threading; @@ -571,6 +572,15 @@ namespace Avalonia.Controls return (arrangeSize); } + /// + /// + /// + protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) + { + CellsStructureDirty = true; + base.ChildrenChanged(sender, e); + } + /// /// Invalidates grid caches and makes the grid dirty for measure. /// From 3054a513ee33ec96c9220b57817721226522838f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 25 Oct 2019 16:44:36 +0300 Subject: [PATCH 11/19] Fix AppBuilderBase.Start --- src/Avalonia.Controls/AppBuilderBase.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index d9be9171ed..85eab3be7b 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -126,8 +126,7 @@ namespace Avalonia.Controls // Copy-pasted because we can't call extension methods due to generic constraints var lifetime = new ClassicDesktopStyleApplicationLifetime(Instance) {ShutdownMode = ShutdownMode.OnMainWindowClose}; - Instance.ApplicationLifetime = lifetime; - SetupWithoutStarting(); + SetupWithLifetime(lifetime); lifetime.Start(Array.Empty()); } From 171a75eaed1ce5b0bfa1245fdc2f98ff6c67017c Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 25 Oct 2019 16:46:37 +0300 Subject: [PATCH 12/19] pr comments --- .../Avalonia.Controls.UnitTests/GridTests.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index 5db28238f4..b74dd641df 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1379,7 +1379,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Column_Width_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Column_Width_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1395,7 +1395,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Column_MinWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Column_MinWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1411,7 +1411,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Column_MaxWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Column_MaxWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1427,7 +1427,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Row_Height_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Row_Height_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1443,7 +1443,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Row_MinHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Row_MinHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1459,7 +1459,7 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(true)] [InlineData(false)] - public void Change_Row_MaxHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) + public void Changing_Row_MaxHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty) { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1473,7 +1473,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Add_Column_Should_Invalidate_Grid() + public void Adding_Column_Should_Invalidate_Grid() { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1484,7 +1484,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Add_Row_Should_Invalidate_Grid() + public void Adding_Row_Should_Invalidate_Grid() { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1495,7 +1495,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Replace_Columns_Should_Invalidate_Grid() + public void Replacing_Columns_Should_Invalidate_Grid() { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1506,7 +1506,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Replace_Rows_Should_Invalidate_Grid() + public void Replacing_Rows_Should_Invalidate_Grid() { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1517,7 +1517,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Remove_Column_Should_Invalidate_Grid() + public void Removing_Column_Should_Invalidate_Grid() { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; @@ -1528,7 +1528,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Remove_Row_Should_Invalidate_Grid() + public void Removing_Row_Should_Invalidate_Grid() { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; @@ -1539,7 +1539,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Remove_Child_Should_Invalidate_Grid_And_Be_Operational() + public void Removing_Child_Should_Invalidate_Grid_And_Be_Operational() { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") }; @@ -1571,7 +1571,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Add_Child_Should_Invalidate_Grid_And_Be_Operational() + public void Adding_Child_Should_Invalidate_Grid_And_Be_Operational() { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") }; From b9bd57e25bb99430622a7c2c91f2a4e9904b6c74 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 25 Oct 2019 19:09:48 +0300 Subject: [PATCH 13/19] Removed `Application` parameter from ClassicDesktopStyleApplicationLifetime since it wasn't used anyway --- src/Avalonia.Controls/AppBuilderBase.cs | 2 +- .../ClassicDesktopStyleApplicationLifetime.cs | 9 ++++----- .../DesktopStyleApplicationLifetimeTests.cs | 18 +++++++++--------- .../AutoSuspendHelperTest.cs | 6 +++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index 85eab3be7b..3b644191c2 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -125,7 +125,7 @@ namespace Avalonia.Controls }); // Copy-pasted because we can't call extension methods due to generic constraints - var lifetime = new ClassicDesktopStyleApplicationLifetime(Instance) {ShutdownMode = ShutdownMode.OnMainWindowClose}; + var lifetime = new ClassicDesktopStyleApplicationLifetime() {ShutdownMode = ShutdownMode.OnMainWindowClose}; SetupWithLifetime(lifetime); lifetime.Start(Array.Empty()); } diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index 2533191ae4..6dd5b8cc81 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -5,12 +5,12 @@ using System.Threading; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Interactivity; +using Avalonia.Threading; namespace Avalonia.Controls.ApplicationLifetimes { public class ClassicDesktopStyleApplicationLifetime : IClassicDesktopStyleApplicationLifetime, IDisposable { - private readonly Application _app; private int _exitCode; private CancellationTokenSource _cts; private bool _isShuttingDown; @@ -34,12 +34,11 @@ namespace Avalonia.Controls.ApplicationLifetimes _activeLifetime?._windows.Add((Window)sender); } - public ClassicDesktopStyleApplicationLifetime(Application app) + public ClassicDesktopStyleApplicationLifetime() { if (_activeLifetime != null) throw new InvalidOperationException( "Can not have multiple active ClassicDesktopStyleApplicationLifetime instances and the previously created one was not disposed"); - _app = app; _activeLifetime = this; } @@ -103,7 +102,7 @@ namespace Avalonia.Controls.ApplicationLifetimes Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args)); _cts = new CancellationTokenSource(); MainWindow?.Show(); - _app.Run(_cts.Token); + Dispatcher.UIThread.MainLoop(_cts.Token); Environment.ExitCode = _exitCode; return _exitCode; } @@ -124,7 +123,7 @@ namespace Avalonia this T builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose) where T : AppBuilderBase, new() { - var lifetime = new ClassicDesktopStyleApplicationLifetime(builder.Instance) {ShutdownMode = shutdownMode}; + var lifetime = new ClassicDesktopStyleApplicationLifetime() {ShutdownMode = shutdownMode}; builder.SetupWithLifetime(lifetime); return lifetime.Start(args); } diff --git a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs index 74523d4193..dee7a84812 100644 --- a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs @@ -16,7 +16,7 @@ namespace Avalonia.Controls.UnitTests public void Should_Set_ExitCode_After_Shutdown() { using (UnitTestApplication.Start(TestServices.MockThreadingInterface)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { lifetime.Shutdown(1337); @@ -31,7 +31,7 @@ namespace Avalonia.Controls.UnitTests public void Should_Close_All_Remaining_Open_Windows_After_Explicit_Exit_Call() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var windows = new List { new Window(), new Window(), new Window(), new Window() }; @@ -50,7 +50,7 @@ namespace Avalonia.Controls.UnitTests public void Should_Only_Exit_On_Explicit_Exit() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { lifetime.ShutdownMode = ShutdownMode.OnExplicitShutdown; @@ -84,7 +84,7 @@ namespace Avalonia.Controls.UnitTests public void Should_Exit_After_MainWindow_Closed() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { lifetime.ShutdownMode = ShutdownMode.OnMainWindowClose; @@ -112,7 +112,7 @@ namespace Avalonia.Controls.UnitTests public void Should_Exit_After_Last_Window_Closed() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { lifetime.ShutdownMode = ShutdownMode.OnLastWindowClose; @@ -142,7 +142,7 @@ namespace Avalonia.Controls.UnitTests public void Show_Should_Add_Window_To_OpenWindows() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var window = new Window(); @@ -156,7 +156,7 @@ namespace Avalonia.Controls.UnitTests public void Window_Should_Be_Added_To_OpenWindows_Only_Once() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var window = new Window(); @@ -174,7 +174,7 @@ namespace Avalonia.Controls.UnitTests public void Close_Should_Remove_Window_From_OpenWindows() { using (UnitTestApplication.Start(TestServices.StyledWindow)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var window = new Window(); @@ -197,7 +197,7 @@ namespace Avalonia.Controls.UnitTests windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object)); using (UnitTestApplication.Start(services)) - using(var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var window = new Window(); diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs index 56b14c3936..c263a80ef3 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs @@ -45,7 +45,7 @@ namespace Avalonia.ReactiveUI.UnitTests public void AutoSuspendHelper_Should_Immediately_Fire_IsLaunchingNew() { using (UnitTestApplication.Start(TestServices.MockWindowingPlatform)) - using (var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using (var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var isLaunchingReceived = false; var application = AvaloniaLocator.Current.GetService(); @@ -86,7 +86,7 @@ namespace Avalonia.ReactiveUI.UnitTests public void ShouldPersistState_Should_Fire_On_App_Exit_When_SuspensionDriver_Is_Initialized() { using (UnitTestApplication.Start(TestServices.MockWindowingPlatform)) - using (var lifetime = new ClassicDesktopStyleApplicationLifetime(Application.Current)) + using (var lifetime = new ClassicDesktopStyleApplicationLifetime()) { var shouldPersistReceived = false; var application = AvaloniaLocator.Current.GetService(); @@ -105,4 +105,4 @@ namespace Avalonia.ReactiveUI.UnitTests } } } -} \ No newline at end of file +} From ab26c18a8f882b1665cbd62dfdbc5a877c5c534e Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Sat, 26 Oct 2019 21:01:43 +0300 Subject: [PATCH 14/19] typo fix --- .../Avalonia.Controls.UnitTests/GridTests.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index b74dd641df..a2d6f14b26 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1383,7 +1383,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.ColumnDefinitions[0][ColumnDefinition.WidthProperty] = new GridLength(5); @@ -1399,7 +1399,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.ColumnDefinitions[0][ColumnDefinition.MinWidthProperty] = 5; @@ -1415,7 +1415,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.ColumnDefinitions[0][ColumnDefinition.MaxWidthProperty] = 5; @@ -1431,7 +1431,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.RowDefinitions[0][RowDefinition.HeightProperty] = new GridLength(5); @@ -1447,7 +1447,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.RowDefinitions[0][RowDefinition.MinHeightProperty] = 5; @@ -1463,7 +1463,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { if (setUsingAvaloniaProperty) grid.RowDefinitions[0][RowDefinition.MaxHeightProperty] = 5; @@ -1477,7 +1477,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(5))); }); @@ -1488,7 +1488,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.RowDefinitions.Add(new RowDefinition(new GridLength(5))); }); @@ -1499,7 +1499,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.ColumnDefinitions = ColumnDefinitions.Parse("2*,1*"); }); @@ -1510,7 +1510,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.RowDefinitions = RowDefinitions.Parse("2*,1*"); }); @@ -1521,7 +1521,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.ColumnDefinitions.RemoveAt(0); }); @@ -1532,7 +1532,7 @@ namespace Avalonia.Controls.UnitTests { var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") }; - Change_Propery_And_Verify_Measure_Requested(grid, () => + Change_Property_And_Verify_Measure_Requested(grid, () => { grid.RowDefinitions.RemoveAt(0); }); @@ -1601,7 +1601,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(10, grid.Children[1].Bounds.Width); } - private static void Change_Propery_And_Verify_Measure_Requested(Grid grid, Action change) + private static void Change_Property_And_Verify_Measure_Requested(Grid grid, Action change) { grid.Measure(new Size(100, 100)); grid.Arrange(new Rect(grid.DesiredSize)); From 9c5e688958c2f2590644d8e54f1951d92d8551c6 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 27 Oct 2019 22:13:49 +0100 Subject: [PATCH 15/19] Fix Grid shared scope not being updated when resizing row/column definitions. --- src/Avalonia.Controls/ColumnDefinition.cs | 4 ++- src/Avalonia.Controls/DefinitionBase.cs | 33 +++++++++++++++-- src/Avalonia.Controls/RowDefinition.cs | 4 ++- .../Avalonia.Controls.UnitTests/GridTests.cs | 35 +++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/ColumnDefinition.cs b/src/Avalonia.Controls/ColumnDefinition.cs index 6cad357e93..293b6326d6 100644 --- a/src/Avalonia.Controls/ColumnDefinition.cs +++ b/src/Avalonia.Controls/ColumnDefinition.cs @@ -31,7 +31,9 @@ namespace Avalonia.Controls /// static ColumnDefinition() { - AffectsParentMeasure(WidthProperty, MinWidthProperty, MaxWidthProperty); + AffectsParentMeasure(MinWidthProperty, MaxWidthProperty); + + WidthProperty.Changed.AddClassHandler(OnUserSizePropertyChanged); } /// diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 6ad32f080a..0b45d7e16a 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -7,9 +7,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; - -using Avalonia; -using Avalonia.Collections; using Avalonia.Utilities; namespace Avalonia.Controls @@ -118,6 +115,36 @@ namespace Avalonia.Controls } } + /// + /// This method needs to be internal to be accessable from derived classes. + /// + internal static void OnUserSizePropertyChanged(DefinitionBase definition, AvaloniaPropertyChangedEventArgs e) + { + if (definition.Parent == null) + { + return; + } + + if (definition._sharedState != null) + { + definition._sharedState.Invalidate(); + } + else + { + GridUnitType oldUnitType = ((GridLength)e.OldValue).GridUnitType; + GridUnitType newUnitType = ((GridLength)e.NewValue).GridUnitType; + + if (oldUnitType != newUnitType) + { + definition.Parent.Invalidate(); + } + else + { + definition.Parent.InvalidateMeasure(); + } + } + } + /// /// Returns true if this definition is a part of shared group. /// diff --git a/src/Avalonia.Controls/RowDefinition.cs b/src/Avalonia.Controls/RowDefinition.cs index 1a1a7e770b..85e7ed6519 100644 --- a/src/Avalonia.Controls/RowDefinition.cs +++ b/src/Avalonia.Controls/RowDefinition.cs @@ -31,7 +31,9 @@ namespace Avalonia.Controls /// static RowDefinition() { - AffectsParentMeasure(HeightProperty, MaxHeightProperty, MinHeightProperty); + AffectsParentMeasure(MaxHeightProperty, MinHeightProperty); + + HeightProperty.Changed.AddClassHandler(OnUserSizePropertyChanged); } /// diff --git a/tests/Avalonia.Controls.UnitTests/GridTests.cs b/tests/Avalonia.Controls.UnitTests/GridTests.cs index a2d6f14b26..353bb9c98d 100644 --- a/tests/Avalonia.Controls.UnitTests/GridTests.cs +++ b/tests/Avalonia.Controls.UnitTests/GridTests.cs @@ -1172,6 +1172,41 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(0, grids[0].ColumnDefinitions[0].ActualWidth); } + [Fact] + public void Size_Group_Definition_Resizes_Are_Tracked() + { + var grids = new[] { + CreateGrid(("A", new GridLength(5, GridUnitType.Pixel)), (null, new GridLength())), + CreateGrid(("A", new GridLength(5, GridUnitType.Pixel)), (null, new GridLength())) }; + var scope = new Grid(); + foreach (var xgrids in grids) + scope.Children.Add(xgrids); + + var root = new Grid(); + root.UseLayoutRounding = false; + root.SetValue(Grid.IsSharedSizeScopeProperty, true); + root.Children.Add(scope); + + root.Measure(new Size(50, 50)); + root.Arrange(new Rect(new Point(), new Point(50, 50))); + + PrintColumnDefinitions(grids[0]); + Assert.Equal(5, grids[0].ColumnDefinitions[0].ActualWidth); + Assert.Equal(5, grids[1].ColumnDefinitions[0].ActualWidth); + + grids[0].ColumnDefinitions[0].Width = new GridLength(10, GridUnitType.Pixel); + + foreach (Grid grid in grids) + { + grid.Measure(new Size(50, 50)); + grid.Arrange(new Rect(new Point(), new Point(50, 50))); + } + + PrintColumnDefinitions(grids[0]); + Assert.Equal(10, grids[0].ColumnDefinitions[0].ActualWidth); + Assert.Equal(10, grids[1].ColumnDefinitions[0].ActualWidth); + } + [Fact] public void Collection_Changes_Are_Tracked() { From 969166422eff8622f2f48963cf169f9f39b40c7d Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 27 Oct 2019 22:23:38 +0100 Subject: [PATCH 16/19] Comment fix. --- src/Avalonia.Controls/DefinitionBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index 0b45d7e16a..e4ae777453 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -116,7 +116,7 @@ namespace Avalonia.Controls } /// - /// This method needs to be internal to be accessable from derived classes. + /// Notifies parent or size scope that definition size has been changed. /// internal static void OnUserSizePropertyChanged(DefinitionBase definition, AvaloniaPropertyChangedEventArgs e) { From 5fea821c94e210f72c4f8c0c1aa812a6ce8a4c14 Mon Sep 17 00:00:00 2001 From: mstr2 Date: Mon, 28 Oct 2019 22:48:12 +0100 Subject: [PATCH 17/19] Failing test for bug #3170 --- .../AvaloniaObjectTests_Validation.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs index 2cf1eb1a97..f0e93dbb3a 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Validation.cs @@ -78,6 +78,18 @@ namespace Avalonia.Base.UnitTests Assert.Equal(10, target.GetValue(Class1.AttachedProperty)); } + [Fact] + public void PropertyChanged_Event_Uses_Coerced_Value() + { + var inst = new Class1(); + inst.PropertyChanged += (sender, e) => + { + Assert.Equal(10, e.NewValue); + }; + + inst.SetValue(Class1.QuxProperty, 15); + } + private class Class1 : AvaloniaObject { public static readonly StyledProperty QuxProperty = From e46cb674234d60cae9da83d11733c98617722c3e Mon Sep 17 00:00:00 2001 From: mstr2 Date: Mon, 28 Oct 2019 22:50:01 +0100 Subject: [PATCH 18/19] Fixed a bug where ValueStore.Changed could be called with pre-validation value --- src/Avalonia.Base/ValueStore.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Base/ValueStore.cs b/src/Avalonia.Base/ValueStore.cs index 1bdbd4ca7c..e06c5996c9 100644 --- a/src/Avalonia.Base/ValueStore.cs +++ b/src/Avalonia.Base/ValueStore.cs @@ -57,7 +57,8 @@ namespace Avalonia { if (priority == (int)BindingPriority.LocalValue) { - _propertyValues.SetValue(property, Validate(property, value)); + Validate(property, ref value); + _propertyValues.SetValue(property, value); Changed(property, priority, v, value); return; } @@ -78,7 +79,8 @@ namespace Avalonia if (priority == (int)BindingPriority.LocalValue) { - _propertyValues.AddValue(property, Validate(property, value)); + Validate(property, ref value); + _propertyValues.AddValue(property, value); Changed(property, priority, AvaloniaProperty.UnsetValue, value); return; } @@ -166,16 +168,14 @@ namespace Avalonia validate2); } - private object Validate(AvaloniaProperty property, object value) + private void Validate(AvaloniaProperty property, ref object value) { var validate = ((IStyledPropertyAccessor)property).GetValidationFunc(_owner.GetType()); if (validate != null && value != AvaloniaProperty.UnsetValue) { - return validate(_owner, value); + value = validate(_owner, value); } - - return value; } private DeferredSetter GetDeferredSetter(AvaloniaProperty property) From e27c7c0fff35b04663cff08bdb75e848e8501990 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 29 Oct 2019 10:21:14 +0300 Subject: [PATCH 19/19] Fixed parameter order in OnSelectionChanged in AutoCompleteBox Apparently Silverlight has different constructor argument order --- src/Avalonia.Controls/AutoCompleteBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs index ce4358648b..64db832a81 100644 --- a/src/Avalonia.Controls/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox.cs @@ -704,7 +704,7 @@ namespace Avalonia.Controls added.Add(e.NewValue); } - OnSelectionChanged(new SelectionChangedEventArgs(SelectionChangedEvent, removed, added)); + OnSelectionChanged(new SelectionChangedEventArgs(SelectionChangedEvent, added, removed)); } ///