From c8900ec3d214bca055b7ae5100f6696d964fc339 Mon Sep 17 00:00:00 2001 From: Stanislav Silin Date: Thu, 11 Aug 2022 21:09:34 +0300 Subject: [PATCH 1/3] Limit RelativePanel height and width in case when available size is infinite. --- src/Avalonia.Controls/RelativePanel.cs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/RelativePanel.cs b/src/Avalonia.Controls/RelativePanel.cs index 1125f0eb0e..ab8e064028 100644 --- a/src/Avalonia.Controls/RelativePanel.cs +++ b/src/Avalonia.Controls/RelativePanel.cs @@ -36,7 +36,10 @@ namespace Avalonia.Controls foreach (Layoutable child in Children) { if (child == null) + { continue; + } + var node = _childGraph.AddNode(child); node.AlignLeftWithNode = _childGraph.AddLink(node, GetDependencyElement(AlignLeftWithProperty, child)); @@ -51,17 +54,18 @@ namespace Avalonia.Controls node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetDependencyElement(AlignHorizontalCenterWithProperty, child)); node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetDependencyElement(AlignVerticalCenterWithProperty, child)); - } + _childGraph.Measure(availableSize); _childGraph.Reset(false); - var calcWidth = Width.IsNaN() && HorizontalAlignment != HorizontalAlignment.Stretch; - var calcHeight = Height.IsNaN() && VerticalAlignment != VerticalAlignment.Stretch; + var calcWidth = Width.IsNaN() && (HorizontalAlignment != HorizontalAlignment.Stretch); + var calcHeight = Height.IsNaN() && (VerticalAlignment != VerticalAlignment.Stretch); var boundingSize = _childGraph.GetBoundingSize(calcWidth, calcHeight); _childGraph.Reset(); _childGraph.Measure(boundingSize); + return boundingSize; } @@ -171,6 +175,7 @@ namespace Avalonia.Controls prevSize = prevSize.WithWidth(prevSize.Width + prevNode.OriginDesiredSize.Width); prevNode.HorizontalOffsetFlag = true; } + if (node.VerticalOffsetFlag) { prevNode.VerticalOffsetFlag = true; @@ -186,6 +191,7 @@ namespace Avalonia.Controls prevSize = prevSize.WithHeight(prevSize.Height + node.OriginDesiredSize.Height); prevNode.VerticalOffsetFlag = true; } + if (node.HorizontalOffsetFlag) { prevNode.HorizontalOffsetFlag = true; @@ -269,16 +275,16 @@ namespace Avalonia.Controls MeasureChild(node); continue; } - + if (node.OutgoingNodes.All(item => item.Measured)) { MeasureChild(node); continue; } - + if (!set.Add(node.Element)) throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete."); - + Measure(node.OutgoingNodes, set); if (!node.Measured) @@ -507,8 +513,11 @@ namespace Avalonia.Controls boundingSize = boundingSize.WithHeight(Math.Max(boundingSize.Height, size.Height)); } - boundingSize = boundingSize.WithWidth(calcWidth ? boundingSize.Width : AvailableSize.Width); - boundingSize = boundingSize.WithHeight(calcHeight ? boundingSize.Height : AvailableSize.Height); + var availableWidth = double.IsInfinity(AvailableSize.Width) ? boundingSize.Width : AvailableSize.Width; + var availableHeight = double.IsInfinity(AvailableSize.Height) ? boundingSize.Height : AvailableSize.Height; + + boundingSize = boundingSize.WithWidth(calcWidth ? boundingSize.Width : availableWidth); + boundingSize = boundingSize.WithHeight(calcHeight ? boundingSize.Height : availableHeight); return boundingSize; } } From 5033e8a6f10115f7a933c3ec167c160dbc6028b1 Mon Sep 17 00:00:00 2001 From: Stanislav Silin Date: Wed, 17 Aug 2022 18:43:12 +0300 Subject: [PATCH 2/3] Add test for stretched relative panel. --- .../RelativePanelTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs index 6b2f05c923..070b9b6935 100644 --- a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs @@ -138,5 +138,34 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds); Assert.Equal(new Rect(0, -20, 20, 20), target.Children[1].Bounds); } + + [Theory] + [InlineData(100, 100, 100, 100)] + [InlineData(100, double.PositiveInfinity, 100, 20)] + [InlineData(double.PositiveInfinity, 100, 20, 100)] + [InlineData(double.PositiveInfinity, double.PositiveInfinity, 20, 20)] + public void StretchedPanel_Measures_Correctly(double availableWidth, double availableHeight, double desiredWidth, double desiredHeight) + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + var rect1 = new Rectangle { Height = 20, Width = 20 }; + var rect2 = new Rectangle { Height = 20, Width = 20 }; + + var target = new RelativePanel + { + VerticalAlignment = Layout.VerticalAlignment.Stretch, + HorizontalAlignment = Layout.HorizontalAlignment.Stretch, + Children = + { + rect1, rect2 + } + }; + + RelativePanel.SetAbove(rect2, rect1); + target.Measure(new Size(availableWidth, availableHeight)); + target.Arrange(new Rect(target.DesiredSize)); + + Assert.Equal(desiredWidth, target.DesiredSize.Width); + Assert.Equal(desiredHeight, target.DesiredSize.Height); + } } } From 93019b8da0db7cb97c426e4176decbfddae0c451 Mon Sep 17 00:00:00 2001 From: Stanislav Silin Date: Wed, 17 Aug 2022 18:57:15 +0300 Subject: [PATCH 3/3] Fix stretched relative panel test. --- tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs index 070b9b6935..b3a75dafa7 100644 --- a/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs @@ -141,9 +141,9 @@ namespace Avalonia.Controls.UnitTests [Theory] [InlineData(100, 100, 100, 100)] - [InlineData(100, double.PositiveInfinity, 100, 20)] + [InlineData(100, double.PositiveInfinity, 100, 40)] [InlineData(double.PositiveInfinity, 100, 20, 100)] - [InlineData(double.PositiveInfinity, double.PositiveInfinity, 20, 20)] + [InlineData(double.PositiveInfinity, double.PositiveInfinity, 20, 40)] public void StretchedPanel_Measures_Correctly(double availableWidth, double availableHeight, double desiredWidth, double desiredHeight) { using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); @@ -160,7 +160,7 @@ namespace Avalonia.Controls.UnitTests } }; - RelativePanel.SetAbove(rect2, rect1); + RelativePanel.SetBelow(rect2, rect1); target.Measure(new Size(availableWidth, availableHeight)); target.Arrange(new Rect(target.DesiredSize));