Browse Source

Merge pull request #8727 from byme8/fix/relative-layout-crash-with-infinite-size

Fix RelativePanel crash inside StackPanel
pull/8778/head
Max Katz 4 years ago
committed by GitHub
parent
commit
f9faa6a2f3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      src/Avalonia.Controls/RelativePanel.cs
  2. 29
      tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs

25
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;
}
}

29
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, 40)]
[InlineData(double.PositiveInfinity, 100, 20, 100)]
[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);
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.SetBelow(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);
}
}
}

Loading…
Cancel
Save