feat: add tests.
This commit is contained in:
@@ -30,15 +30,21 @@ public class WrapPanelWithTrailingItem: Panel
|
|||||||
base.OnPropertyChanged(change);
|
base.OnPropertyChanged(change);
|
||||||
if (change.Property == TrailingItemProperty)
|
if (change.Property == TrailingItemProperty)
|
||||||
{
|
{
|
||||||
if(change.GetOldValue<Visual?>() is { } oldValue)
|
if(change.GetOldValue<Layoutable?>() is { } oldValue)
|
||||||
{
|
{
|
||||||
VisualChildren.Remove(oldValue);
|
VisualChildren.Remove(oldValue);
|
||||||
LogicalChildren.Remove(oldValue);
|
if (!IsItemsHost)
|
||||||
|
{
|
||||||
|
LogicalChildren.Remove(oldValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(change.GetNewValue<Visual?>() is {} newValue)
|
if(change.GetNewValue<Layoutable?>() is {} newValue)
|
||||||
{
|
{
|
||||||
VisualChildren.Add(newValue);
|
VisualChildren.Add(newValue);
|
||||||
LogicalChildren.Add(newValue);
|
if (!IsItemsHost)
|
||||||
|
{
|
||||||
|
LogicalChildren.Add(newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +86,7 @@ public class WrapPanelWithTrailingItem: Panel
|
|||||||
}
|
}
|
||||||
|
|
||||||
var last = TrailingItem;
|
var last = TrailingItem;
|
||||||
|
if (last is null) return new Size(availableSize.Width, totalHeight);
|
||||||
last.Measure(availableSize);
|
last.Measure(availableSize);
|
||||||
double lastDeltaX = availableSize.Width - currentLineX;
|
double lastDeltaX = availableSize.Width - currentLineX;
|
||||||
// If width is not enough, add a new line, and recalculate total height
|
// If width is not enough, add a new line, and recalculate total height
|
||||||
@@ -96,4 +103,56 @@ public class WrapPanelWithTrailingItem: Panel
|
|||||||
|
|
||||||
return new Size(availableSize.Width, totalHeight);
|
return new Size(availableSize.Width, totalHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
|
{
|
||||||
|
double currentLineX = 0;
|
||||||
|
double currentLineHeight = 0;
|
||||||
|
double totalHeight = 0;
|
||||||
|
var children = Children;
|
||||||
|
for (int i = 0; i < children.Count; i++)
|
||||||
|
{
|
||||||
|
var child = children[i];
|
||||||
|
double deltaX = finalSize.Width - currentLineX;
|
||||||
|
// Width is enough to place next child
|
||||||
|
if (MathHelpers.GreaterThan(deltaX, child.DesiredSize.Width))
|
||||||
|
{
|
||||||
|
child.Arrange(new Rect(currentLineX, totalHeight, child.DesiredSize.Width, Math.Max(child.DesiredSize.Height, currentLineHeight)));
|
||||||
|
currentLineX += child.DesiredSize.Width;
|
||||||
|
currentLineHeight = Math.Max(currentLineHeight, child.DesiredSize.Height);
|
||||||
|
}
|
||||||
|
// Width is not enough to place next child
|
||||||
|
// reset currentLineX and currentLineHeight
|
||||||
|
// accumulate last line height to total height.
|
||||||
|
// Notice: last line height accumulation only happens when restarting a new line, so it needs to finally add one more time outside iteration.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
totalHeight += currentLineHeight;
|
||||||
|
child.Arrange(new Rect(0, totalHeight, Math.Min(child.DesiredSize.Width, finalSize.Width), child.DesiredSize.Height));
|
||||||
|
currentLineX = child.DesiredSize.Width;
|
||||||
|
currentLineHeight = child.DesiredSize.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var last = TrailingItem;
|
||||||
|
if (last is null) return new Size(finalSize.Width, totalHeight);
|
||||||
|
double lastDeltaX = finalSize.Width - currentLineX;
|
||||||
|
// If width is not enough, add a new line, and recalculate total height
|
||||||
|
if (lastDeltaX < 30)
|
||||||
|
{
|
||||||
|
totalHeight += currentLineHeight;
|
||||||
|
last.Arrange(new Rect(0, totalHeight, finalSize.Width, last.DesiredSize.Height));
|
||||||
|
totalHeight += last.DesiredSize.Height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentLineHeight = children.Count == 1 ? finalSize.Height : currentLineHeight;
|
||||||
|
last.Arrange(new Rect(currentLineX, totalHeight, lastDeltaX,
|
||||||
|
Math.Max(currentLineHeight, last.DesiredSize.Height)));
|
||||||
|
currentLineHeight = Math.Max(currentLineHeight, last.DesiredSize.Height);
|
||||||
|
totalHeight += currentLineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Size(finalSize.Width, totalHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Headless.XUnit;
|
||||||
|
using Avalonia.Layout;
|
||||||
|
using Avalonia.LogicalTree;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
|
using Ursa.Controls.Panels;
|
||||||
|
|
||||||
|
namespace HeadlessTest.Ursa.Controls.PanelTests;
|
||||||
|
|
||||||
|
public class WrapPanelWithTrailingItemTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Visual_Children_Correct()
|
||||||
|
{
|
||||||
|
var panel = new WrapPanelWithTrailingItem();
|
||||||
|
var child1 = new Button { Content = "Button 1"};
|
||||||
|
var child2 = new Button { Content = "Button 2"};
|
||||||
|
var trailing = new Button { Content = "Trailing"};
|
||||||
|
|
||||||
|
panel.Children.Add(child1);
|
||||||
|
panel.Children.Add(child2);
|
||||||
|
panel.TrailingItem = trailing;
|
||||||
|
|
||||||
|
var visualChildren = panel.GetVisualChildren().ToList();
|
||||||
|
Assert.Equal(3, visualChildren.Count);
|
||||||
|
Assert.Equal(child1, visualChildren[0]);
|
||||||
|
Assert.Equal(child2, visualChildren[1]);
|
||||||
|
Assert.Equal(trailing, visualChildren[2]);
|
||||||
|
|
||||||
|
var child3 = new Button { Content = "Button 3"};
|
||||||
|
panel.Children.Add(child3);
|
||||||
|
|
||||||
|
visualChildren = panel.GetVisualChildren().ToList();
|
||||||
|
Assert.Equal(4, visualChildren.Count);
|
||||||
|
Assert.Equal(child1, visualChildren[0]);
|
||||||
|
Assert.Equal(child2, visualChildren[1]);
|
||||||
|
Assert.Equal(child3, visualChildren[2]);
|
||||||
|
Assert.Equal(trailing, visualChildren[3]);
|
||||||
|
|
||||||
|
var trailing2 = new Button { Content = "Trailing2"};
|
||||||
|
panel.TrailingItem = trailing2;
|
||||||
|
|
||||||
|
visualChildren = panel.GetVisualChildren().ToList();
|
||||||
|
Assert.Equal(4, visualChildren.Count);
|
||||||
|
Assert.Equal(child1, visualChildren[0]);
|
||||||
|
Assert.Equal(child2, visualChildren[1]);
|
||||||
|
Assert.Equal(child3, visualChildren[2]);
|
||||||
|
Assert.Equal(trailing2, visualChildren[3]);
|
||||||
|
|
||||||
|
panel.Children.Remove(child2);
|
||||||
|
|
||||||
|
visualChildren = panel.GetVisualChildren().ToList();
|
||||||
|
Assert.Equal(3, visualChildren.Count);
|
||||||
|
Assert.Equal(child1, visualChildren[0]);
|
||||||
|
Assert.Equal(child3, visualChildren[1]);
|
||||||
|
Assert.Equal(trailing2, visualChildren[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
// Items Appears in Logical Children because IsItemsHost is false for individual Panels
|
||||||
|
public void Logical_Children_Correct()
|
||||||
|
{
|
||||||
|
var panel = new WrapPanelWithTrailingItem();
|
||||||
|
var child1 = new Button { Content = "Button 1"};
|
||||||
|
var child2 = new Button { Content = "Button 2"};
|
||||||
|
var trailing = new Button { Content = "Trailing"};
|
||||||
|
|
||||||
|
panel.Children.Add(child1);
|
||||||
|
panel.Children.Add(child2);
|
||||||
|
panel.TrailingItem = trailing;
|
||||||
|
|
||||||
|
var logicalChildren = panel.GetLogicalChildren().ToList();
|
||||||
|
Assert.Equal(3, logicalChildren.Count);
|
||||||
|
Assert.Equal(child1, logicalChildren[0]);
|
||||||
|
Assert.Equal(child2, logicalChildren[1]);
|
||||||
|
Assert.Equal(trailing, logicalChildren[2]);
|
||||||
|
|
||||||
|
var child3 = new Button { Content = "Button 3"};
|
||||||
|
panel.Children.Add(child3);
|
||||||
|
|
||||||
|
logicalChildren = panel.GetLogicalChildren().ToList();
|
||||||
|
Assert.Equal(4, logicalChildren.Count);
|
||||||
|
Assert.Equal(child1, logicalChildren[0]);
|
||||||
|
Assert.Equal(child2, logicalChildren[1]);
|
||||||
|
Assert.Equal(child3, logicalChildren[2]);
|
||||||
|
Assert.Equal(trailing, logicalChildren[3]);
|
||||||
|
|
||||||
|
var trailing2 = new Button { Content = "Trailing2"};
|
||||||
|
panel.TrailingItem = trailing2;
|
||||||
|
|
||||||
|
logicalChildren = panel.GetLogicalChildren().ToList();
|
||||||
|
Assert.Equal(4, logicalChildren.Count);
|
||||||
|
Assert.Equal(child1, logicalChildren[0]);
|
||||||
|
Assert.Equal(child2, logicalChildren[1]);
|
||||||
|
Assert.Equal(child3, logicalChildren[2]);
|
||||||
|
Assert.Equal(trailing2, logicalChildren[3]);
|
||||||
|
|
||||||
|
panel.Children.Remove(child2);
|
||||||
|
|
||||||
|
logicalChildren = panel.GetLogicalChildren().ToList();
|
||||||
|
Assert.Equal(3, logicalChildren.Count);
|
||||||
|
Assert.Equal(child1, logicalChildren[0]);
|
||||||
|
Assert.Equal(child3, logicalChildren[1]);
|
||||||
|
Assert.Equal(trailing2, logicalChildren[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AvaloniaFact]
|
||||||
|
public void Measure_Arrange_Children()
|
||||||
|
{
|
||||||
|
var window = new Window()
|
||||||
|
{
|
||||||
|
Height = 1000, Width = 1000, VerticalContentAlignment = VerticalAlignment.Stretch
|
||||||
|
};
|
||||||
|
var panel = new WrapPanelWithTrailingItem();
|
||||||
|
var child1 = new Button { Content = "Button 1", Width = 200, Height = 100 };
|
||||||
|
var child2 = new Button { Content = "Button 2", Width = 300, Height = 100 };
|
||||||
|
var trailing = new Button
|
||||||
|
{
|
||||||
|
Content = "Trailing",
|
||||||
|
Height = 100,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Stretch
|
||||||
|
};
|
||||||
|
window.Content = panel;
|
||||||
|
panel.Children.Add(child1);
|
||||||
|
panel.Children.Add(child2);
|
||||||
|
panel.TrailingItem = trailing;
|
||||||
|
|
||||||
|
window.Show();
|
||||||
|
Dispatcher.UIThread.RunJobs();
|
||||||
|
Assert.Equal(200, child1.Bounds.Width);
|
||||||
|
Assert.Equal(300, child2.Bounds.Width);
|
||||||
|
Assert.Equal(500, trailing.Bounds.Width);
|
||||||
|
|
||||||
|
panel.Width = 600;
|
||||||
|
Dispatcher.UIThread.RunJobs();
|
||||||
|
Assert.Equal(200, child1.Bounds.Width);
|
||||||
|
Assert.Equal(300, child2.Bounds.Width);
|
||||||
|
Assert.Equal(100, trailing.Bounds.Width);
|
||||||
|
|
||||||
|
panel.Width = 510;
|
||||||
|
Dispatcher.UIThread.RunJobs();
|
||||||
|
Assert.Equal(200, child1.Bounds.Width);
|
||||||
|
Assert.Equal(300, child2.Bounds.Width);
|
||||||
|
Assert.Equal(510, trailing.Bounds.Width);
|
||||||
|
Assert.Equal(100, trailing.Bounds.Y);
|
||||||
|
|
||||||
|
panel.Width = 300;
|
||||||
|
Dispatcher.UIThread.RunJobs();
|
||||||
|
Assert.Equal(200, child1.Bounds.Width);
|
||||||
|
Assert.Equal(300, child2.Bounds.Width);
|
||||||
|
Assert.Equal(300, trailing.Bounds.Width);
|
||||||
|
Assert.Equal(200, trailing.Bounds.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user