Browse Source

Merge pull request #4301 from AvaloniaUI/fixes/more-relative-panel-fixes

Fixes/more relative panel fixes
pull/4304/head
danwalmsley 6 years ago
committed by GitHub
parent
commit
d023c41bb7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      src/Avalonia.Controls/RelativePanel.cs
  2. 50
      tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs

32
src/Avalonia.Controls/RelativePanel.cs

@ -54,7 +54,7 @@ namespace Avalonia.Controls
} }
_childGraph.Measure(availableSize); _childGraph.Measure(availableSize);
_childGraph.Reset(); _childGraph.Reset(false);
var boundingSize = _childGraph.GetBoundingSize(Width.IsNaN(), Height.IsNaN()); var boundingSize = _childGraph.GetBoundingSize(Width.IsNaN(), Height.IsNaN());
_childGraph.Reset(); _childGraph.Reset();
_childGraph.Measure(boundingSize); _childGraph.Measure(boundingSize);
@ -119,17 +119,22 @@ namespace Avalonia.Controls
public void Arrange(Size arrangeSize) => Element.Arrange(new Rect(Left, Top, Math.Max(arrangeSize.Width - Left - Right, 0), Math.Max(arrangeSize.Height - Top - Bottom, 0))); public void Arrange(Size arrangeSize) => Element.Arrange(new Rect(Left, Top, Math.Max(arrangeSize.Width - Left - Right, 0), Math.Max(arrangeSize.Height - Top - Bottom, 0)));
public void Reset() public void Reset(bool clearPos)
{ {
Left = double.NaN; if (clearPos)
Top = double.NaN; {
Right = double.NaN; Left = double.NaN;
Bottom = double.NaN; Top = double.NaN;
Right = double.NaN;
Bottom = double.NaN;
}
Measured = false; Measured = false;
} }
public Size GetBoundingSize() public Size GetBoundingSize()
{ {
if (Left < 0 || Top < 0) return default;
if (Measured) if (Measured)
return BoundingSize; return BoundingSize;
@ -209,7 +214,7 @@ namespace Avalonia.Controls
_nodeDic.Clear(); _nodeDic.Clear();
} }
public void Reset() => _nodeDic.Values.Do(node => node.Reset()); public void Reset(bool clearPos = true) => _nodeDic.Values.Do(node => node.Reset(clearPos));
public GraphNode? AddLink(GraphNode from, Layoutable? to) public GraphNode? AddLink(GraphNode from, Layoutable? to)
{ {
@ -255,28 +260,21 @@ namespace Avalonia.Controls
foreach (var node in nodes) foreach (var node in nodes)
{ {
/*
* 该节点无任何依赖,所以从这里开始计算元素位置。
* 因为无任何依赖,所以忽略同级元素
*/
if (!node.Measured && !node.OutgoingNodes.Any()) if (!node.Measured && !node.OutgoingNodes.Any())
{ {
MeasureChild(node); MeasureChild(node);
continue; continue;
} }
// 判断依赖元素是否全部排列完毕
if (node.OutgoingNodes.All(item => item.Measured)) if (node.OutgoingNodes.All(item => item.Measured))
{ {
MeasureChild(node); MeasureChild(node);
continue; continue;
} }
// 判断是否有循环
if (!set.Add(node.Element)) if (!set.Add(node.Element))
throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete."); throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete.");
// 没有循环,且有依赖,则继续往下
Measure(node.OutgoingNodes, set); Measure(node.OutgoingNodes, set);
if (!node.Measured) if (!node.Measured)

50
tests/Avalonia.Controls.UnitTests/RelativePanelTests.cs

@ -82,5 +82,55 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds); Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(0, 20, 20, 20), target.Children[1].Bounds); Assert.Equal(new Rect(0, 20, 20, 20), target.Children[1].Bounds);
} }
[Fact]
public void LeftOf_Measures_Correctly()
{
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
var target = new RelativePanel
{
VerticalAlignment = Layout.VerticalAlignment.Center,
HorizontalAlignment = Layout.HorizontalAlignment.Center,
Children =
{
rect1, rect2
}
};
RelativePanel.SetLeftOf(rect2, rect1);
target.Measure(new Size(400, 400));
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(20, 20), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(-20, 0, 20, 20), target.Children[1].Bounds);
}
[Fact]
public void Above_Measures_Correctly()
{
var rect1 = new Rectangle { Height = 20, Width = 20 };
var rect2 = new Rectangle { Height = 20, Width = 20 };
var target = new RelativePanel
{
VerticalAlignment = Layout.VerticalAlignment.Center,
HorizontalAlignment = Layout.HorizontalAlignment.Center,
Children =
{
rect1, rect2
}
};
RelativePanel.SetAbove(rect2, rect1);
target.Measure(new Size(400, 400));
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(20, 20), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 20, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(0, -20, 20, 20), target.Children[1].Bounds);
}
} }
} }

Loading…
Cancel
Save