committed by
GitHub
51 changed files with 1667 additions and 356 deletions
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Interactivity; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Controls.Primitives |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Holds data for the <see cref="Popup.Closed"/> event.
|
||||
|
/// </summary>
|
||||
|
public class PopupClosedEventArgs : EventArgs |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PopupClosedEventArgs"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="closeEvent"></param>
|
||||
|
public PopupClosedEventArgs(EventArgs? closeEvent) |
||||
|
{ |
||||
|
CloseEvent = closeEvent; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the event that closed the popup, if any.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// If <see cref="Popup.StaysOpen"/> is false, then this property will hold details of the
|
||||
|
/// interaction that caused the popup to close if the close was caused by e.g. a pointer press
|
||||
|
/// outside the popup. It can be used to mark the event as handled if the event should not
|
||||
|
/// be propagated.
|
||||
|
/// </remarks>
|
||||
|
public EventArgs? CloseEvent { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
// This source file is adapted from the WinUI project.
|
||||
|
// (https://github.com/microsoft/microsoft-ui-xaml)
|
||||
|
//
|
||||
|
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.Layout |
||||
|
{ |
||||
|
internal class LayoutContextAdapter : VirtualizingLayoutContext |
||||
|
{ |
||||
|
private readonly NonVirtualizingLayoutContext _nonVirtualizingContext; |
||||
|
|
||||
|
public LayoutContextAdapter(NonVirtualizingLayoutContext nonVirtualizingContext) |
||||
|
{ |
||||
|
_nonVirtualizingContext = nonVirtualizingContext; |
||||
|
} |
||||
|
|
||||
|
protected override object LayoutStateCore |
||||
|
{ |
||||
|
get => _nonVirtualizingContext.LayoutState; |
||||
|
set => _nonVirtualizingContext.LayoutState = value; |
||||
|
} |
||||
|
|
||||
|
protected override Point LayoutOriginCore |
||||
|
{ |
||||
|
get => default; |
||||
|
set |
||||
|
{ |
||||
|
if (value != default) |
||||
|
{ |
||||
|
throw new InvalidOperationException("LayoutOrigin must be at (0,0) when RealizationRect is infinite sized."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override Rect RealizationRectCore() => new Rect(Size.Infinity); |
||||
|
|
||||
|
protected override int ItemCountCore() => _nonVirtualizingContext.Children.Count; |
||||
|
protected override object GetItemAtCore(int index) => _nonVirtualizingContext.Children[index]; |
||||
|
protected override ILayoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options) => |
||||
|
_nonVirtualizingContext.Children[index]; |
||||
|
protected override void RecycleElementCore(ILayoutable element) { } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,160 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using Avalonia.Data; |
||||
|
|
||||
|
namespace Avalonia.Layout |
||||
|
{ |
||||
|
public class NonVirtualizingStackLayout : NonVirtualizingLayout |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Orientation"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<Orientation> OrientationProperty = |
||||
|
StackLayout.OrientationProperty.AddOwner<NonVirtualizingStackLayout>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Spacing"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<double> SpacingProperty = |
||||
|
StackLayout.SpacingProperty.AddOwner<NonVirtualizingStackLayout>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the axis along which items are laid out.
|
||||
|
/// </summary>
|
||||
|
/// <value>
|
||||
|
/// One of the enumeration values that specifies the axis along which items are laid out.
|
||||
|
/// The default is Vertical.
|
||||
|
/// </value>
|
||||
|
public Orientation Orientation |
||||
|
{ |
||||
|
get => GetValue(OrientationProperty); |
||||
|
set => SetValue(OrientationProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets a uniform distance (in pixels) between stacked items. It is applied in the
|
||||
|
/// direction of the StackLayout's Orientation.
|
||||
|
/// </summary>
|
||||
|
public double Spacing |
||||
|
{ |
||||
|
get => GetValue(SpacingProperty); |
||||
|
set => SetValue(SpacingProperty, value); |
||||
|
} |
||||
|
|
||||
|
protected internal override Size MeasureOverride( |
||||
|
NonVirtualizingLayoutContext context, |
||||
|
Size availableSize) |
||||
|
{ |
||||
|
var extentU = 0.0; |
||||
|
var extentV = 0.0; |
||||
|
var childCount = context.Children.Count; |
||||
|
var isVertical = Orientation == Orientation.Vertical; |
||||
|
var spacing = Spacing; |
||||
|
var constraint = isVertical ? |
||||
|
availableSize.WithHeight(double.PositiveInfinity) : |
||||
|
availableSize.WithWidth(double.PositiveInfinity); |
||||
|
|
||||
|
for (var i = 0; i < childCount; ++i) |
||||
|
{ |
||||
|
var element = context.Children[i]; |
||||
|
|
||||
|
if (!element.IsVisible) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
element.Measure(constraint); |
||||
|
|
||||
|
if (isVertical) |
||||
|
{ |
||||
|
extentU += element.DesiredSize.Height; |
||||
|
extentV = Math.Max(extentV, element.DesiredSize.Width); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
extentU += element.DesiredSize.Width; |
||||
|
extentV = Math.Max(extentV, element.DesiredSize.Height); |
||||
|
} |
||||
|
|
||||
|
if (i < childCount - 1) |
||||
|
{ |
||||
|
extentU += spacing; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return isVertical ? new Size(extentV, extentU) : new Size(extentU, extentV); |
||||
|
} |
||||
|
|
||||
|
protected internal override Size ArrangeOverride( |
||||
|
NonVirtualizingLayoutContext context, |
||||
|
Size finalSize) |
||||
|
{ |
||||
|
var u = 0.0; |
||||
|
var childCount = context.Children.Count; |
||||
|
var isVertical = Orientation == Orientation.Vertical; |
||||
|
var spacing = Spacing; |
||||
|
var bounds = new Rect(); |
||||
|
|
||||
|
for (var i = 0; i < childCount; ++i) |
||||
|
{ |
||||
|
var element = context.Children[i]; |
||||
|
|
||||
|
if (!element.IsVisible) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
bounds = isVertical ? |
||||
|
LayoutVertical(element, u, finalSize) : |
||||
|
LayoutHorizontal(element, u, finalSize); |
||||
|
element.Arrange(bounds); |
||||
|
u = (isVertical ? bounds.Bottom : bounds.Right) + spacing; |
||||
|
} |
||||
|
|
||||
|
return new Size(bounds.Right, bounds.Bottom); |
||||
|
} |
||||
|
|
||||
|
private static Rect LayoutVertical(ILayoutable element, double y, Size constraint) |
||||
|
{ |
||||
|
var x = 0.0; |
||||
|
var width = element.DesiredSize.Width; |
||||
|
|
||||
|
switch (element.HorizontalAlignment) |
||||
|
{ |
||||
|
case HorizontalAlignment.Center: |
||||
|
x += (constraint.Width - element.DesiredSize.Width) / 2; |
||||
|
break; |
||||
|
case HorizontalAlignment.Right: |
||||
|
x += constraint.Width - element.DesiredSize.Width; |
||||
|
break; |
||||
|
case HorizontalAlignment.Stretch: |
||||
|
width = constraint.Width; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
return new Rect(x, y, width, element.DesiredSize.Height); |
||||
|
} |
||||
|
|
||||
|
private static Rect LayoutHorizontal(ILayoutable element, double x, Size constraint) |
||||
|
{ |
||||
|
var y = 0.0; |
||||
|
var height = element.DesiredSize.Height; |
||||
|
|
||||
|
switch (element.VerticalAlignment) |
||||
|
{ |
||||
|
case VerticalAlignment.Center: |
||||
|
y += (constraint.Height - element.DesiredSize.Height) / 2; |
||||
|
break; |
||||
|
case VerticalAlignment.Bottom: |
||||
|
y += constraint.Height - element.DesiredSize.Height; |
||||
|
break; |
||||
|
case VerticalAlignment.Stretch: |
||||
|
height = constraint.Height; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
return new Rect(x, y, element.DesiredSize.Width, height); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Avalonia.Layout |
||||
|
{ |
||||
|
public class VirtualLayoutContextAdapter : NonVirtualizingLayoutContext |
||||
|
{ |
||||
|
private readonly VirtualizingLayoutContext _virtualizingContext; |
||||
|
private ChildrenCollection _children; |
||||
|
|
||||
|
public VirtualLayoutContextAdapter(VirtualizingLayoutContext virtualizingContext) |
||||
|
{ |
||||
|
_virtualizingContext = virtualizingContext; |
||||
|
} |
||||
|
|
||||
|
protected override object LayoutStateCore |
||||
|
{ |
||||
|
get => _virtualizingContext.LayoutState; |
||||
|
set => _virtualizingContext.LayoutState = value; |
||||
|
} |
||||
|
|
||||
|
protected override IReadOnlyList<ILayoutable> ChildrenCore => |
||||
|
_children ?? (_children = new ChildrenCollection(_virtualizingContext)); |
||||
|
|
||||
|
private class ChildrenCollection : IReadOnlyList<ILayoutable> |
||||
|
{ |
||||
|
private readonly VirtualizingLayoutContext _context; |
||||
|
public ChildrenCollection(VirtualizingLayoutContext context) => _context = context; |
||||
|
public ILayoutable this[int index] => _context.GetOrCreateElementAt(index); |
||||
|
public int Count => _context.ItemCount; |
||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); |
||||
|
|
||||
|
public IEnumerator<ILayoutable> GetEnumerator() |
||||
|
{ |
||||
|
for (var i = 0; i < Count; ++i) |
||||
|
{ |
||||
|
yield return this[i]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,335 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Avalonia.Controls; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Layout.UnitTests |
||||
|
{ |
||||
|
public class NonVirtualizingStackLayoutTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Lays_Out_Children_Vertically() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout { Orientation = Orientation.Vertical }; |
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new Border { Height = 20, Width = 120 }, |
||||
|
new Border { Height = 30 }, |
||||
|
new Border { Height = 50 }, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, Size.Infinity); |
||||
|
var arrangeSize = target.Arrange(context, desiredSize); |
||||
|
|
||||
|
Assert.Equal(new Size(120, 100), desiredSize); |
||||
|
Assert.Equal(new Size(120, 100), arrangeSize); |
||||
|
Assert.Equal(new Rect(0, 0, 120, 20), context.Children[0].Bounds); |
||||
|
Assert.Equal(new Rect(0, 20, 120, 30), context.Children[1].Bounds); |
||||
|
Assert.Equal(new Rect(0, 50, 120, 50), context.Children[2].Bounds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Lays_Out_Children_Horizontally() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout { Orientation = Orientation.Horizontal }; |
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new Border { Width = 20, Height = 120 }, |
||||
|
new Border { Width = 30 }, |
||||
|
new Border { Width = 50 }, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, Size.Infinity); |
||||
|
var arrangeSize = target.Arrange(context, desiredSize); |
||||
|
|
||||
|
Assert.Equal(new Size(100, 120), desiredSize); |
||||
|
Assert.Equal(new Size(100, 120), arrangeSize); |
||||
|
Assert.Equal(new Rect(0, 0, 20, 120), context.Children[0].Bounds); |
||||
|
Assert.Equal(new Rect(20, 0, 30, 120), context.Children[1].Bounds); |
||||
|
Assert.Equal(new Rect(50, 0, 50, 120), context.Children[2].Bounds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Lays_Out_Children_Vertically_With_Spacing() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Orientation = Orientation.Vertical, |
||||
|
Spacing = 10, |
||||
|
}; |
||||
|
|
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new Border { Height = 20, Width = 120 }, |
||||
|
new Border { Height = 30 }, |
||||
|
new Border { Height = 50 }, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, Size.Infinity); |
||||
|
var arrangeSize = target.Arrange(context, desiredSize); |
||||
|
|
||||
|
Assert.Equal(new Size(120, 120), desiredSize); |
||||
|
Assert.Equal(new Size(120, 120), arrangeSize); |
||||
|
Assert.Equal(new Rect(0, 0, 120, 20), context.Children[0].Bounds); |
||||
|
Assert.Equal(new Rect(0, 30, 120, 30), context.Children[1].Bounds); |
||||
|
Assert.Equal(new Rect(0, 70, 120, 50), context.Children[2].Bounds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Lays_Out_Children_Horizontally_With_Spacing() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Orientation = Orientation.Horizontal, |
||||
|
Spacing = 10, |
||||
|
}; |
||||
|
|
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new Border { Width = 20, Height = 120 }, |
||||
|
new Border { Width = 30 }, |
||||
|
new Border { Width = 50 }, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, Size.Infinity); |
||||
|
var arrangeSize = target.Arrange(context, desiredSize); |
||||
|
|
||||
|
Assert.Equal(new Size(120, 120), desiredSize); |
||||
|
Assert.Equal(new Size(120, 120), arrangeSize); |
||||
|
Assert.Equal(new Rect(0, 0, 20, 120), context.Children[0].Bounds); |
||||
|
Assert.Equal(new Rect(30, 0, 30, 120), context.Children[1].Bounds); |
||||
|
Assert.Equal(new Rect(70, 0, 50, 120), context.Children[2].Bounds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Arranges_Vertical_Children_With_Correct_Bounds() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Orientation = Orientation.Vertical |
||||
|
}; |
||||
|
|
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Left, |
||||
|
MeasureSize = new Size(50, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Left, |
||||
|
MeasureSize = new Size(150, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Center, |
||||
|
MeasureSize = new Size(50, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Center, |
||||
|
MeasureSize = new Size(150, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Right, |
||||
|
MeasureSize = new Size(50, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Right, |
||||
|
MeasureSize = new Size(150, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Stretch, |
||||
|
MeasureSize = new Size(50, 10), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
HorizontalAlignment = HorizontalAlignment.Stretch, |
||||
|
MeasureSize = new Size(150, 10), |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, new Size(100, 150)); |
||||
|
Assert.Equal(new Size(100, 80), desiredSize); |
||||
|
|
||||
|
target.Arrange(context, desiredSize); |
||||
|
|
||||
|
var bounds = context.Children.Select(x => x.Bounds).ToArray(); |
||||
|
|
||||
|
Assert.Equal( |
||||
|
new[] |
||||
|
{ |
||||
|
new Rect(0, 0, 50, 10), |
||||
|
new Rect(0, 10, 100, 10), |
||||
|
new Rect(25, 20, 50, 10), |
||||
|
new Rect(0, 30, 100, 10), |
||||
|
new Rect(50, 40, 50, 10), |
||||
|
new Rect(0, 50, 100, 10), |
||||
|
new Rect(0, 60, 100, 10), |
||||
|
new Rect(0, 70, 100, 10), |
||||
|
|
||||
|
}, bounds); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Arranges_Horizontal_Children_With_Correct_Bounds() |
||||
|
{ |
||||
|
var target = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Orientation = Orientation.Horizontal |
||||
|
}; |
||||
|
|
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Top, |
||||
|
MeasureSize = new Size(10, 50), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Top, |
||||
|
MeasureSize = new Size(10, 150), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Center, |
||||
|
MeasureSize = new Size(10, 50), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Center, |
||||
|
MeasureSize = new Size(10, 150), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Bottom, |
||||
|
MeasureSize = new Size(10, 50), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Bottom, |
||||
|
MeasureSize = new Size(10, 150), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Stretch, |
||||
|
MeasureSize = new Size(10, 50), |
||||
|
}, |
||||
|
new TestControl |
||||
|
{ |
||||
|
VerticalAlignment = VerticalAlignment.Stretch, |
||||
|
MeasureSize = new Size(10, 150), |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, new Size(150, 100)); |
||||
|
Assert.Equal(new Size(80, 100), desiredSize); |
||||
|
|
||||
|
target.Arrange(context, desiredSize); |
||||
|
|
||||
|
var bounds = context.Children.Select(x => x.Bounds).ToArray(); |
||||
|
|
||||
|
Assert.Equal( |
||||
|
new[] |
||||
|
{ |
||||
|
new Rect(0, 0, 10, 50), |
||||
|
new Rect(10, 0, 10, 100), |
||||
|
new Rect(20, 25, 10, 50), |
||||
|
new Rect(30, 0, 10, 100), |
||||
|
new Rect(40, 50, 10, 50), |
||||
|
new Rect(50, 0, 10, 100), |
||||
|
new Rect(60, 0, 10, 100), |
||||
|
new Rect(70, 0, 10, 100), |
||||
|
}, bounds); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(Orientation.Horizontal)] |
||||
|
[InlineData(Orientation.Vertical)] |
||||
|
public void Spacing_Not_Added_For_Invisible_Children(Orientation orientation) |
||||
|
{ |
||||
|
var targetThreeChildrenOneInvisble = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Orientation = orientation, |
||||
|
Spacing = 40, |
||||
|
}; |
||||
|
|
||||
|
var contextThreeChildrenOneInvisble = CreateContext(new[] |
||||
|
{ |
||||
|
new StackPanel { Width = 10, Height= 10, IsVisible = false }, |
||||
|
new StackPanel { Width = 10, Height= 10 }, |
||||
|
new StackPanel { Width = 10, Height= 10 }, |
||||
|
}); |
||||
|
|
||||
|
var targetTwoChildrenNoneInvisible = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Spacing = 40, |
||||
|
Orientation = orientation, |
||||
|
}; |
||||
|
|
||||
|
var contextTwoChildrenNoneInvisible = CreateContext(new[] |
||||
|
{ |
||||
|
new StackPanel { Width = 10, Height = 10 }, |
||||
|
new StackPanel { Width = 10, Height = 10 } |
||||
|
}); |
||||
|
|
||||
|
var desiredSize1 = targetThreeChildrenOneInvisble.Measure(contextThreeChildrenOneInvisble, Size.Infinity); |
||||
|
var desiredSize2 = targetTwoChildrenNoneInvisible.Measure(contextTwoChildrenNoneInvisible, Size.Infinity); |
||||
|
|
||||
|
Assert.Equal(desiredSize2, desiredSize1); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(Orientation.Horizontal)] |
||||
|
[InlineData(Orientation.Vertical)] |
||||
|
public void Only_Arrange_Visible_Children(Orientation orientation) |
||||
|
{ |
||||
|
var hiddenPanel = new Panel { Width = 10, Height = 10, IsVisible = false }; |
||||
|
var panel = new Panel { Width = 10, Height = 10 }; |
||||
|
|
||||
|
var target = new NonVirtualizingStackLayout |
||||
|
{ |
||||
|
Spacing = 40, |
||||
|
Orientation = orientation, |
||||
|
}; |
||||
|
|
||||
|
var context = CreateContext(new[] |
||||
|
{ |
||||
|
hiddenPanel, |
||||
|
panel |
||||
|
}); |
||||
|
|
||||
|
var desiredSize = target.Measure(context, Size.Infinity); |
||||
|
var arrangeSize = target.Arrange(context, desiredSize); |
||||
|
Assert.Equal(new Size(10, 10), arrangeSize); |
||||
|
} |
||||
|
|
||||
|
private NonVirtualizingLayoutContext CreateContext(Control[] children) |
||||
|
{ |
||||
|
return new TestLayoutContext(children); |
||||
|
} |
||||
|
|
||||
|
private class TestLayoutContext : NonVirtualizingLayoutContext |
||||
|
{ |
||||
|
public TestLayoutContext(Control[] children) => ChildrenCore = children; |
||||
|
protected override IReadOnlyList<ILayoutable> ChildrenCore { get; } |
||||
|
} |
||||
|
|
||||
|
private class TestControl : Control |
||||
|
{ |
||||
|
public Size MeasureConstraint { get; private set; } |
||||
|
public Size MeasureSize { get; set; } |
||||
|
|
||||
|
protected override Size MeasureOverride(Size availableSize) |
||||
|
{ |
||||
|
MeasureConstraint = availableSize; |
||||
|
return MeasureSize; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue