Browse Source

Merge branch 'master' into ValueStoreDeferredSetter

pull/1732/head
Steven Kirk 8 years ago
committed by GitHub
parent
commit
d8a8e473d6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Avalonia.Controls/Application.cs
  2. 2
      src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
  3. 2
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
  4. 2
      src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
  5. 1
      src/Avalonia.Controls/Primitives/AdornerLayer.cs
  6. 18
      src/Avalonia.Controls/TopLevel.cs
  7. 18
      src/Avalonia.Controls/Window.cs
  8. 5
      src/Avalonia.Controls/WindowBase.cs
  9. 5
      src/Avalonia.Layout/ILayoutRoot.cs
  10. 7
      src/Avalonia.Layout/LayoutManager.cs
  11. 10
      src/Avalonia.Layout/Layoutable.cs
  12. 2
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  13. 14
      tests/Avalonia.Benchmarks/Layout/Measure.cs
  14. 18
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  15. 123
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  16. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  17. 17
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  18. 2
      tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
  19. 21
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  20. 7
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  21. 325
      tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs
  22. 87
      tests/Avalonia.Layout.UnitTests/LayoutableTests.cs
  23. 28
      tests/Avalonia.LeakTests/ControlTests.cs
  24. 4
      tests/Avalonia.UnitTests/TestRoot.cs
  25. 11
      tests/Avalonia.UnitTests/TestServices.cs
  26. 4
      tests/Avalonia.UnitTests/TestTemplatedRoot.cs
  27. 1
      tests/Avalonia.UnitTests/UnitTestApplication.cs
  28. 29
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  29. 20
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs

1
src/Avalonia.Controls/Application.cs

@ -332,7 +332,6 @@ namespace Avalonia
.Bind<IInputManager>().ToConstant(InputManager) .Bind<IInputManager>().ToConstant(InputManager)
.Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>() .Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>()
.Bind<IStyler>().ToConstant(_styler) .Bind<IStyler>().ToConstant(_styler)
.Bind<ILayoutManager>().ToSingleton<LayoutManager>()
.Bind<IApplicationLifecycle>().ToConstant(this) .Bind<IApplicationLifecycle>().ToConstant(this)
.Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance) .Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance)
.Bind<IDragDropDevice>().ToConstant(DragDropDevice.Instance) .Bind<IDragDropDevice>().ToConstant(DragDropDevice.Instance)

2
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@ -28,7 +28,7 @@ namespace Avalonia.Controls.Embedding
{ {
EnsureInitialized(); EnsureInitialized();
ApplyTemplate(); ApplyTemplate();
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.ExecuteInitialLayoutPass(this);
} }
private void EnsureInitialized() private void EnsureInitialized()

2
src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs

@ -22,7 +22,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
{ {
EnsureInitialized(); EnsureInitialized();
ApplyTemplate(); ApplyTemplate();
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.ExecuteInitialLayoutPass(this);
} }
private void EnsureInitialized() private void EnsureInitialized()

2
src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs

@ -518,7 +518,7 @@ namespace Avalonia.Controls.Presenters
} }
var container = generator.ContainerFromIndex(index); var container = generator.ContainerFromIndex(index);
var layoutManager = LayoutManager.Instance; var layoutManager = (Owner.GetVisualRoot() as ILayoutRoot)?.LayoutManager;
// We need to do a layout here because it's possible that the container we moved to // We need to do a layout here because it's possible that the container we moved to
// is only partially visible due to differing item sizes. If the container is only // is only partially visible due to differing item sizes. If the container is only

1
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@ -21,7 +21,6 @@ namespace Avalonia.Controls.Primitives
static AdornerLayer() static AdornerLayer()
{ {
AdornedElementProperty.Changed.Subscribe(AdornedElementChanged); AdornedElementProperty.Changed.Subscribe(AdornedElementChanged);
IsHitTestVisibleProperty.OverrideDefaultValue(typeof(AdornerLayer), false);
} }
public AdornerLayer() public AdornerLayer()

18
src/Avalonia.Controls/TopLevel.cs

@ -54,6 +54,7 @@ namespace Avalonia.Controls
private readonly IApplicationLifecycle _applicationLifecycle; private readonly IApplicationLifecycle _applicationLifecycle;
private readonly IPlatformRenderInterface _renderInterface; private readonly IPlatformRenderInterface _renderInterface;
private Size _clientSize; private Size _clientSize;
private ILayoutManager _layoutManager;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="TopLevel"/> class. /// Initializes static members of the <see cref="TopLevel"/> class.
@ -147,6 +148,16 @@ namespace Avalonia.Controls
protected set { SetAndRaise(ClientSizeProperty, ref _clientSize, value); } protected set { SetAndRaise(ClientSizeProperty, ref _clientSize, value); }
} }
public ILayoutManager LayoutManager
{
get
{
if (_layoutManager == null)
_layoutManager = CreateLayoutManager();
return _layoutManager;
}
}
/// <summary> /// <summary>
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
@ -235,6 +246,11 @@ namespace Avalonia.Controls
{ {
return PlatformImpl?.PointToScreen(p) ?? default(Point); return PlatformImpl?.PointToScreen(p) ?? default(Point);
} }
/// <summary>
/// Creates the layout manager for this <see cref="TopLevel" />.
/// </summary>
protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager();
/// <summary> /// <summary>
/// Handles a paint notification from <see cref="ITopLevelImpl.Resized"/>. /// Handles a paint notification from <see cref="ITopLevelImpl.Resized"/>.
@ -267,7 +283,7 @@ namespace Avalonia.Controls
ClientSize = clientSize; ClientSize = clientSize;
Width = clientSize.Width; Width = clientSize.Width;
Height = clientSize.Height; Height = clientSize.Height;
LayoutManager.Instance.ExecuteLayoutPass(); LayoutManager.ExecuteLayoutPass();
Renderer?.Resized(clientSize); Renderer?.Resized(clientSize);
} }

18
src/Avalonia.Controls/Window.cs

@ -302,18 +302,17 @@ namespace Avalonia.Controls
internal void Close(bool ignoreCancel) internal void Close(bool ignoreCancel)
{ {
var cancelClosing = false;
try try
{ {
cancelClosing = HandleClosing(); if (!ignoreCancel && HandleClosing())
{
return;
}
} }
finally finally
{ {
if (ignoreCancel || !cancelClosing) PlatformImpl?.Dispose();
{ HandleClosed();
PlatformImpl?.Dispose();
HandleClosed();
}
} }
} }
@ -324,6 +323,7 @@ namespace Avalonia.Controls
{ {
var args = new CancelEventArgs(); var args = new CancelEventArgs();
Closing?.Invoke(this, args); Closing?.Invoke(this, args);
return args.Cancel; return args.Cancel;
} }
@ -374,7 +374,7 @@ namespace Avalonia.Controls
EnsureInitialized(); EnsureInitialized();
IsVisible = true; IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {
@ -416,7 +416,7 @@ namespace Avalonia.Controls
EnsureInitialized(); EnsureInitialized();
SetWindowStartupLocation(); SetWindowStartupLocation();
IsVisible = true; IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing()) using (BeginAutoSizing())
{ {

5
src/Avalonia.Controls/WindowBase.cs

@ -179,10 +179,9 @@ namespace Avalonia.Controls
if (!_hasExecutedInitialLayoutPass) if (!_hasExecutedInitialLayoutPass)
{ {
LayoutManager.Instance.ExecuteInitialLayoutPass(this); LayoutManager.ExecuteInitialLayoutPass(this);
_hasExecutedInitialLayoutPass = true; _hasExecutedInitialLayoutPass = true;
} }
PlatformImpl?.Show(); PlatformImpl?.Show();
Renderer?.Start(); Renderer?.Start();
} }
@ -262,7 +261,7 @@ namespace Avalonia.Controls
Height = clientSize.Height; Height = clientSize.Height;
} }
ClientSize = clientSize; ClientSize = clientSize;
LayoutManager.Instance.ExecuteLayoutPass(); LayoutManager.ExecuteLayoutPass();
Renderer?.Resized(clientSize); Renderer?.Resized(clientSize);
} }

5
src/Avalonia.Layout/ILayoutRoot.cs

@ -22,5 +22,10 @@ namespace Avalonia.Layout
/// The scaling factor to use in layout. /// The scaling factor to use in layout.
/// </summary> /// </summary>
double LayoutScaling { get; } double LayoutScaling { get; }
/// <summary>
/// Associated instance of layout manager
/// </summary>
ILayoutManager LayoutManager { get; }
} }
} }

7
src/Avalonia.Layout/LayoutManager.cs

@ -19,11 +19,6 @@ namespace Avalonia.Layout
private bool _queued; private bool _queued;
private bool _running; private bool _running;
/// <summary>
/// Gets the layout manager.
/// </summary>
public static ILayoutManager Instance => AvaloniaLocator.Current.GetService<ILayoutManager>();
/// <inheritdoc/> /// <inheritdoc/>
public void InvalidateMeasure(ILayoutable control) public void InvalidateMeasure(ILayoutable control)
{ {
@ -170,7 +165,7 @@ namespace Avalonia.Layout
{ {
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
} }
else else if (control.PreviousMeasure.HasValue)
{ {
control.Measure(control.PreviousMeasure.Value); control.Measure(control.PreviousMeasure.Value);
} }

10
src/Avalonia.Layout/Layoutable.cs

@ -389,7 +389,7 @@ namespace Avalonia.Layout
if (((ILayoutable)this).IsAttachedToVisualTree) if (((ILayoutable)this).IsAttachedToVisualTree)
{ {
LayoutManager.Instance?.InvalidateMeasure(this); (VisualRoot as ILayoutRoot)?.LayoutManager.InvalidateMeasure(this);
InvalidateVisual(); InvalidateVisual();
} }
OnMeasureInvalidated(); OnMeasureInvalidated();
@ -406,12 +406,8 @@ namespace Avalonia.Layout
Logger.Verbose(LogArea.Layout, this, "Invalidated arrange"); Logger.Verbose(LogArea.Layout, this, "Invalidated arrange");
IsArrangeValid = false; IsArrangeValid = false;
(VisualRoot as ILayoutRoot)?.LayoutManager?.InvalidateArrange(this);
if (((ILayoutable)this).IsAttachedToVisualTree) InvalidateVisual();
{
LayoutManager.Instance?.InvalidateArrange(this);
InvalidateVisual();
}
} }
} }

2
src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs

@ -49,7 +49,7 @@ namespace Avalonia.Win32.Interop.Wpf
protected override void HandleResized(Size clientSize) protected override void HandleResized(Size clientSize)
{ {
ClientSize = clientSize; ClientSize = clientSize;
LayoutManager.Instance.ExecuteLayoutPass(); LayoutManager.ExecuteLayoutPass();
Renderer?.Resized(clientSize); Renderer?.Resized(clientSize);
} }

14
tests/Avalonia.Benchmarks/Layout/Measure.cs

@ -8,26 +8,18 @@ using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Layout namespace Avalonia.Benchmarks.Layout
{ {
[MemoryDiagnoser] [MemoryDiagnoser]
public class Measure : IDisposable public class Measure
{ {
private IDisposable _app;
private TestRoot root; private TestRoot root;
private List<Control> controls = new List<Control>(); private List<Control> controls = new List<Control>();
public Measure() public Measure()
{ {
_app = UnitTestApplication.Start(TestServices.RealLayoutManager);
var panel = new StackPanel(); var panel = new StackPanel();
root = new TestRoot { Child = panel }; root = new TestRoot { Child = panel };
controls.Add(panel); controls.Add(panel);
CreateChildren(panel, 3, 5); CreateChildren(panel, 3, 5);
LayoutManager.Instance.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
}
public void Dispose()
{
_app.Dispose();
} }
[Benchmark] [Benchmark]
@ -43,7 +35,7 @@ namespace Avalonia.Benchmarks.Layout
} }
} }
LayoutManager.Instance.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
} }
private void CreateChildren(IPanel parent, int childCount, int iterations) private void CreateChildren(IPanel parent, int childCount, int iterations)

18
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -12,6 +12,7 @@ using Avalonia.Layout;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.UnitTests; using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Xunit; using Xunit;
namespace Avalonia.Controls.UnitTests.Presenters namespace Avalonia.Controls.UnitTests.Presenters
@ -219,13 +220,13 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact] [Fact]
public void Changing_VirtualizationMode_None_To_Simple_Should_Add_Correct_Number_Of_Controls() public void Changing_VirtualizationMode_None_To_Simple_Should_Add_Correct_Number_Of_Controls()
{ {
using (UnitTestApplication.Start(TestServices.RealLayoutManager)) using (UnitTestApplication.Start(new TestServices()))
{ {
var target = CreateTarget(mode: ItemVirtualizationMode.None); var target = CreateTarget(mode: ItemVirtualizationMode.None);
var scroll = (ScrollContentPresenter)target.Parent; var scroll = (TestScroller)target.Parent;
scroll.Measure(new Size(100, 100)); scroll.Width = scroll.Height = 100;
scroll.Arrange(new Rect(0, 0, 100, 100)); scroll.LayoutManager.ExecuteInitialLayoutPass(scroll);
// Ensure than an intermediate measure pass doesn't add more controls than it // Ensure than an intermediate measure pass doesn't add more controls than it
// should. This can happen if target gets measured with Size.Infinity which // should. This can happen if target gets measured with Size.Infinity which
@ -237,7 +238,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
}; };
target.VirtualizationMode = ItemVirtualizationMode.Simple; target.VirtualizationMode = ItemVirtualizationMode.Simple;
LayoutManager.Instance.ExecuteLayoutPass(); ((ILayoutRoot)scroll.GetVisualRoot()).LayoutManager.ExecuteLayoutPass();
Assert.Equal(10, target.Panel.Children.Count); Assert.Equal(10, target.Panel.Children.Count);
} }
@ -315,12 +316,17 @@ namespace Avalonia.Controls.UnitTests.Presenters
}); });
} }
private class TestScroller : ScrollContentPresenter, IRenderRoot private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot
{ {
public IRenderer Renderer { get; } public IRenderer Renderer { get; }
public Size ClientSize { get; } public Size ClientSize { get; }
public double RenderScaling => 1; public double RenderScaling => 1;
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget() public IRenderTarget CreateRenderTarget()
{ {
throw new NotImplementedException(); throw new NotImplementedException();

123
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -12,6 +12,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.UnitTests; using Avalonia.UnitTests;
@ -564,11 +565,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact] [Fact]
public void Scrolling_To_Item_In_Zero_Sized_Presenter_Doesnt_Throw() public void Scrolling_To_Item_In_Zero_Sized_Presenter_Doesnt_Throw()
{ {
using (UnitTestApplication.Start(TestServices.RealLayoutManager)) using (UnitTestApplication.Start(new TestServices()))
{ {
var target = CreateTarget(itemCount: 10); var target = CreateTarget(itemCount: 10);
var items = (IList<string>)target.Items; var items = (IList<string>)target.Items;
target.ApplyTemplate(); target.ApplyTemplate();
target.Measure(Size.Empty); target.Measure(Size.Empty);
target.Arrange(Rect.Empty); target.Arrange(Rect.Empty);
@ -723,10 +723,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Down_Should_Return_Existing_Container_If_Materialized() public void GetControlInDirection_Down_Should_Return_Existing_Container_If_Materialized()
{ {
var target = CreateTarget(); var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate(); scroller.Width = scroller.Height = 100;
target.Measure(new Size(100, 100)); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
target.Arrange(new Rect(0, 0, 100, 100));
var from = target.Panel.Children[5]; var from = target.Panel.Children[5];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -740,10 +740,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Down_Should_Scroll_If_Necessary() public void GetControlInDirection_Down_Should_Scroll_If_Necessary()
{ {
var target = CreateTarget(); var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate(); scroller.Width = scroller.Height = 100;
target.Measure(new Size(100, 100)); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
target.Arrange(new Rect(0, 0, 100, 100));
var from = target.Panel.Children[9]; var from = target.Panel.Children[9];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -757,44 +757,40 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact] [Fact]
public void GetControlInDirection_Down_Should_Scroll_If_Partially_Visible() public void GetControlInDirection_Down_Should_Scroll_If_Partially_Visible()
{ {
using (UnitTestApplication.Start(TestServices.RealLayoutManager)) var target = CreateTarget();
{ var scroller = (TestScroller)target.Parent;
var target = CreateTarget();
var scroller = (ScrollContentPresenter)target.Parent;
scroller.Measure(new Size(100, 95)); scroller.Width = 100;
scroller.Arrange(new Rect(0, 0, 100, 95)); scroller.Height = 95;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[8]; var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Down, NavigationDirection.Down,
from); from);
Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset); Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result); Assert.Same(target.Panel.Children[8], result);
}
} }
[Fact] [Fact]
public void GetControlInDirection_Up_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown() public void GetControlInDirection_Up_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
{ {
using (UnitTestApplication.Start(TestServices.RealLayoutManager)) var target = CreateTarget();
{ var scroller = (TestScroller)target.Parent;
var target = CreateTarget();
var scroller = (ScrollContentPresenter)target.Parent;
scroller.Measure(new Size(100, 95)); scroller.Width = 100;
scroller.Arrange(new Rect(0, 0, 100, 95)); scroller.Height = 95;
((ILogicalScrollable)target).Offset = new Vector(0, 11); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
((ILogicalScrollable)target).Offset = new Vector(0, 11);
var from = target.Panel.Children[1]; var from = target.Panel.Children[1];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Up, NavigationDirection.Up,
from); from);
Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset); Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[0], result); Assert.Same(target.Panel.Children[0], result);
}
} }
[Fact] [Fact]
@ -835,10 +831,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Right_Should_Return_Existing_Container_If_Materialized() public void GetControlInDirection_Right_Should_Return_Existing_Container_If_Materialized()
{ {
var target = CreateTarget(orientation: Orientation.Horizontal); var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate(); scroller.Width = scroller.Height = 100;
target.Measure(new Size(100, 100)); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
target.Arrange(new Rect(0, 0, 100, 100));
var from = target.Panel.Children[5]; var from = target.Panel.Children[5];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -852,10 +848,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Right_Should_Scroll_If_Necessary() public void GetControlInDirection_Right_Should_Scroll_If_Necessary()
{ {
var target = CreateTarget(orientation: Orientation.Horizontal); var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate(); scroller.Width = scroller.Height = 100;
target.Measure(new Size(100, 100)); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
target.Arrange(new Rect(0, 0, 100, 100));
var from = target.Panel.Children[9]; var from = target.Panel.Children[9];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -869,32 +865,31 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact] [Fact]
public void GetControlInDirection_Right_Should_Scroll_If_Partially_Visible() public void GetControlInDirection_Right_Should_Scroll_If_Partially_Visible()
{ {
using (UnitTestApplication.Start(TestServices.RealLayoutManager)) var target = CreateTarget(orientation: Orientation.Horizontal);
{ var scroller = (TestScroller)target.Parent;
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (ScrollContentPresenter)target.Parent;
scroller.Measure(new Size(95, 100)); scroller.Width = 95;
scroller.Arrange(new Rect(0, 0, 95, 100)); scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[8]; var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection( var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Right, NavigationDirection.Right,
from); from);
Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset); Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result); Assert.Same(target.Panel.Children[8], result);
}
} }
[Fact] [Fact]
public void GetControlInDirection_Left_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown() public void GetControlInDirection_Left_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
{ {
var target = CreateTarget(orientation: Orientation.Horizontal); var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate(); scroller.Width = 95;
target.Measure(new Size(95, 100)); scroller.Height = 100;
target.Arrange(new Rect(0, 0, 95, 100)); scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
((ILogicalScrollable)target).Offset = new Vector(11, 0); ((ILogicalScrollable)target).Offset = new Vector(11, 0);
var from = target.Panel.Children[1]; var from = target.Panel.Children[1];
@ -1010,7 +1005,6 @@ namespace Avalonia.Controls.UnitTests.Presenters
}; };
scroller.UpdateChild(); scroller.UpdateChild();
return result; return result;
} }
@ -1032,12 +1026,18 @@ namespace Avalonia.Controls.UnitTests.Presenters
}); });
} }
private class TestScroller : ScrollContentPresenter, IRenderRoot private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot
{ {
public IRenderer Renderer { get; } public IRenderer Renderer { get; }
public Size ClientSize { get; } public Size ClientSize { get; }
public double RenderScaling => 1; public double RenderScaling => 1;
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget() public IRenderTarget CreateRenderTarget()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@ -1057,6 +1057,11 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
}
} }
private class TestItemsPresenter : ItemsPresenter private class TestItemsPresenter : ItemsPresenter

1
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -306,7 +306,6 @@ namespace Avalonia.Controls.UnitTests.Primitives
var renderInterface = new Mock<IPlatformRenderInterface>(); var renderInterface = new Mock<IPlatformRenderInterface>();
AvaloniaLocator.CurrentMutable AvaloniaLocator.CurrentMutable
.Bind<ILayoutManager>().ToTransient<LayoutManager>()
.Bind<IGlobalStyles>().ToFunc(() => globalStyles.Object) .Bind<IGlobalStyles>().ToFunc(() => globalStyles.Object)
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock()) .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
.Bind<IStyler>().ToTransient<Styler>() .Bind<IStyler>().ToTransient<Styler>()

17
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@ -74,15 +74,16 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Layout_Pass_Should_Not_Be_Automatically_Scheduled() public void Layout_Pass_Should_Not_Be_Automatically_Scheduled()
{ {
var services = TestServices.StyledWindow.With(layoutManager: Mock.Of<ILayoutManager>()); var services = TestServices.StyledWindow;
using (UnitTestApplication.Start(services)) using (UnitTestApplication.Start(services))
{ {
var impl = new Mock<ITopLevelImpl>(); var impl = new Mock<ITopLevelImpl>();
var target = new TestTopLevel(impl.Object);
var target = new TestTopLevel(impl.Object, Mock.Of<ILayoutManager>());
// The layout pass should be scheduled by the derived class. // The layout pass should be scheduled by the derived class.
var layoutManagerMock = Mock.Get(LayoutManager.Instance); var layoutManagerMock = Mock.Get(target.LayoutManager);
layoutManagerMock.Verify(x => x.ExecuteLayoutPass(), Times.Never); layoutManagerMock.Verify(x => x.ExecuteLayoutPass(), Times.Never);
} }
} }
@ -107,7 +108,7 @@ namespace Avalonia.Controls.UnitTests
} }
}; };
LayoutManager.Instance.ExecuteInitialLayoutPass(target); target.LayoutManager.ExecuteInitialLayoutPass(target);
Assert.Equal(new Rect(0, 0, 321, 432), target.Bounds); Assert.Equal(new Rect(0, 0, 321, 432), target.Bounds);
} }
@ -122,7 +123,7 @@ namespace Avalonia.Controls.UnitTests
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456)); impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
var target = new TestTopLevel(impl.Object); var target = new TestTopLevel(impl.Object);
LayoutManager.Instance.ExecuteLayoutPass(); target.LayoutManager.ExecuteLayoutPass();
Assert.Equal(double.NaN, target.Width); Assert.Equal(double.NaN, target.Width);
Assert.Equal(double.NaN, target.Height); Assert.Equal(double.NaN, target.Height);
@ -248,13 +249,17 @@ namespace Avalonia.Controls.UnitTests
private class TestTopLevel : TopLevel private class TestTopLevel : TopLevel
{ {
private readonly ILayoutManager _layoutManager;
public bool IsClosed { get; private set; } public bool IsClosed { get; private set; }
public TestTopLevel(ITopLevelImpl impl) public TestTopLevel(ITopLevelImpl impl, ILayoutManager layoutManager = null)
: base(impl) : base(impl)
{ {
_layoutManager = layoutManager ?? new LayoutManager();
} }
protected override ILayoutManager CreateLayoutManager() => _layoutManager;
protected override void HandleApplicationExiting() protected override void HandleApplicationExiting()
{ {
base.HandleApplicationExiting(); base.HandleApplicationExiting();

2
tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs

@ -40,7 +40,7 @@ namespace Avalonia.Controls.UnitTests
IsVisible = true, IsVisible = true,
}; };
LayoutManager.Instance.ExecuteInitialLayoutPass(target); target.LayoutManager.ExecuteInitialLayoutPass(target);
Mock.Get(impl).Verify(x => x.Resize(new Size(321, 432))); Mock.Get(impl).Verify(x => x.Resize(new Size(321, 432)));
} }

21
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -188,6 +188,27 @@ namespace Avalonia.Controls.UnitTests
} }
} }
[Fact]
public void Closing_Should_Only_Be_Invoked_Once()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new Window();
var count = 0;
window.Closing +=
(sender, e) =>
{
count++;
};
window.Show();
window.Close();
Assert.Equal(1, count);
}
}
[Fact] [Fact]
public void Showing_Should_Start_Renderer() public void Showing_Should_Start_Renderer()
{ {

7
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -57,11 +57,11 @@ namespace Avalonia.Layout.UnitTests
}; };
window.Show(); window.Show();
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.Equal(new Size(400, 400), border.Bounds.Size); Assert.Equal(new Size(400, 400), border.Bounds.Size);
textBlock.Width = 200; textBlock.Width = 200;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Equal(new Size(200, 400), border.Bounds.Size); Assert.Equal(new Size(200, 400), border.Bounds.Size);
} }
@ -99,7 +99,7 @@ namespace Avalonia.Layout.UnitTests
}; };
window.Show(); window.Show();
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.Equal(new Size(800, 600), window.Bounds.Size); Assert.Equal(new Size(800, 600), window.Bounds.Size);
Assert.Equal(new Size(200, 200), scrollViewer.Bounds.Size); Assert.Equal(new Size(200, 200), scrollViewer.Bounds.Size);
@ -200,7 +200,6 @@ namespace Avalonia.Layout.UnitTests
.Bind<IAssetLoader>().ToConstant(new AssetLoader()) .Bind<IAssetLoader>().ToConstant(new AssetLoader())
.Bind<IInputManager>().ToConstant(new Mock<IInputManager>().Object) .Bind<IInputManager>().ToConstant(new Mock<IInputManager>().Object)
.Bind<IGlobalStyles>().ToConstant(globalStyles.Object) .Bind<IGlobalStyles>().ToConstant(globalStyles.Object)
.Bind<ILayoutManager>().ToConstant(new LayoutManager())
.Bind<IRuntimePlatform>().ToConstant(new AppBuilder().RuntimePlatform) .Bind<IRuntimePlatform>().ToConstant(new AppBuilder().RuntimePlatform)
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface.Object) .Bind<IPlatformRenderInterface>().ToConstant(renderInterface.Object)
.Bind<IStyler>().ToConstant(new Styler()) .Bind<IStyler>().ToConstant(new Styler())

325
tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs

@ -14,290 +14,231 @@ namespace Avalonia.Layout.UnitTests
[Fact] [Fact]
public void Measures_And_Arranges_InvalidateMeasured_Control() public void Measures_And_Arranges_InvalidateMeasured_Control()
{ {
var target = new LayoutManager(); var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
using (Start(target)) root.LayoutManager.ExecuteInitialLayoutPass(root);
{ control.Measured = control.Arranged = false;
var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
target.ExecuteInitialLayoutPass(root);
control.Measured = control.Arranged = false;
control.InvalidateMeasure(); control.InvalidateMeasure();
target.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
Assert.True(control.Measured); Assert.True(control.Measured);
Assert.True(control.Arranged); Assert.True(control.Arranged);
}
} }
[Fact] [Fact]
public void Arranges_InvalidateArranged_Control() public void Arranges_InvalidateArranged_Control()
{ {
var target = new LayoutManager(); var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
using (Start(target)) root.LayoutManager.ExecuteInitialLayoutPass(root);
{ control.Measured = control.Arranged = false;
var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
target.ExecuteInitialLayoutPass(root); control.InvalidateArrange();
control.Measured = control.Arranged = false; root.LayoutManager.ExecuteLayoutPass();
control.InvalidateArrange(); Assert.False(control.Measured);
target.ExecuteLayoutPass(); Assert.True(control.Arranged);
Assert.False(control.Measured);
Assert.True(control.Arranged);
}
} }
[Fact] [Fact]
public void Measures_Parent_Of_Newly_Added_Control() public void Measures_Parent_Of_Newly_Added_Control()
{ {
var target = new LayoutManager(); var control = new LayoutTestControl();
var root = new LayoutTestRoot();
using (Start(target))
{
var control = new LayoutTestControl();
var root = new LayoutTestRoot();
target.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
root.Child = control; root.Child = control;
root.Measured = root.Arranged = false; root.Measured = root.Arranged = false;
target.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
Assert.True(root.Measured); Assert.True(root.Measured);
Assert.True(root.Arranged); Assert.True(root.Arranged);
Assert.True(control.Measured); Assert.True(control.Measured);
Assert.True(control.Arranged); Assert.True(control.Arranged);
}
} }
[Fact] [Fact]
public void Measures_In_Correct_Order() public void Measures_In_Correct_Order()
{ {
var target = new LayoutManager(); LayoutTestControl control1;
LayoutTestControl control2;
using (Start(target)) var root = new LayoutTestRoot
{ {
LayoutTestControl control1; Child = control1 = new LayoutTestControl
LayoutTestControl control2;
var root = new LayoutTestRoot
{ {
Child = control1 = new LayoutTestControl Child = control2 = new LayoutTestControl(),
{ }
Child = control2 = new LayoutTestControl(), };
}
};
var order = new List<ILayoutable>(); var order = new List<ILayoutable>();
Size MeasureOverride(ILayoutable control, Size size) Size MeasureOverride(ILayoutable control, Size size)
{ {
order.Add(control); order.Add(control);
return new Size(10, 10); return new Size(10, 10);
} }
root.DoMeasureOverride = MeasureOverride; root.DoMeasureOverride = MeasureOverride;
control1.DoMeasureOverride = MeasureOverride; control1.DoMeasureOverride = MeasureOverride;
control2.DoMeasureOverride = MeasureOverride; control2.DoMeasureOverride = MeasureOverride;
target.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
control2.InvalidateMeasure(); control2.InvalidateMeasure();
control1.InvalidateMeasure(); control1.InvalidateMeasure();
root.InvalidateMeasure(); root.InvalidateMeasure();
order.Clear(); order.Clear();
target.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
Assert.Equal(new ILayoutable[] { root, control1, control2 }, order); Assert.Equal(new ILayoutable[] { root, control1, control2 }, order);
}
} }
[Fact] [Fact]
public void Measures_Root_And_Grandparent_In_Correct_Order() public void Measures_Root_And_Grandparent_In_Correct_Order()
{ {
var target = new LayoutManager(); LayoutTestControl control1;
LayoutTestControl control2;
using (Start(target)) var root = new LayoutTestRoot
{ {
LayoutTestControl control1; Child = control1 = new LayoutTestControl
LayoutTestControl control2;
var root = new LayoutTestRoot
{ {
Child = control1 = new LayoutTestControl Child = control2 = new LayoutTestControl(),
{ }
Child = control2 = new LayoutTestControl(), };
}
};
var order = new List<ILayoutable>(); var order = new List<ILayoutable>();
Size MeasureOverride(ILayoutable control, Size size) Size MeasureOverride(ILayoutable control, Size size)
{ {
order.Add(control); order.Add(control);
return new Size(10, 10); return new Size(10, 10);
} }
root.DoMeasureOverride = MeasureOverride; root.DoMeasureOverride = MeasureOverride;
control1.DoMeasureOverride = MeasureOverride; control1.DoMeasureOverride = MeasureOverride;
control2.DoMeasureOverride = MeasureOverride; control2.DoMeasureOverride = MeasureOverride;
target.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
control2.InvalidateMeasure(); control2.InvalidateMeasure();
root.InvalidateMeasure(); root.InvalidateMeasure();
order.Clear(); order.Clear();
target.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
Assert.Equal(new ILayoutable[] { root, control2 }, order); Assert.Equal(new ILayoutable[] { root, control2 }, order);
}
} }
[Fact] [Fact]
public void Doesnt_Measure_Non_Invalidated_Root() public void Doesnt_Measure_Non_Invalidated_Root()
{ {
var target = new LayoutManager(); var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
using (Start(target)) root.LayoutManager.ExecuteInitialLayoutPass(root);
{ root.Measured = root.Arranged = false;
var control = new LayoutTestControl(); control.Measured = control.Arranged = false;
var root = new LayoutTestRoot { Child = control };
target.ExecuteInitialLayoutPass(root);
root.Measured = root.Arranged = false;
control.Measured = control.Arranged = false;
control.InvalidateMeasure(); control.InvalidateMeasure();
target.ExecuteLayoutPass(); root.LayoutManager.ExecuteLayoutPass();
Assert.False(root.Measured); Assert.False(root.Measured);
Assert.False(root.Arranged); Assert.False(root.Arranged);
Assert.True(control.Measured); Assert.True(control.Measured);
Assert.True(control.Arranged); Assert.True(control.Arranged);
}
} }
[Fact] [Fact]
public void Doesnt_Measure_Removed_Control() public void Doesnt_Measure_Removed_Control()
{ {
var target = new LayoutManager(); var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
using (Start(target)) root.LayoutManager.ExecuteInitialLayoutPass(root);
{ control.Measured = control.Arranged = false;
var control = new LayoutTestControl();
var root = new LayoutTestRoot { Child = control };
target.ExecuteInitialLayoutPass(root); control.InvalidateMeasure();
control.Measured = control.Arranged = false; root.Child = null;
root.LayoutManager.ExecuteLayoutPass();
control.InvalidateMeasure(); Assert.False(control.Measured);
root.Child = null; Assert.False(control.Arranged);
target.ExecuteLayoutPass();
Assert.False(control.Measured);
Assert.False(control.Arranged);
}
} }
[Fact] [Fact]
public void Measures_Root_With_Infinity() public void Measures_Root_With_Infinity()
{ {
var target = new LayoutManager(); var root = new LayoutTestRoot();
var availableSize = default(Size);
using (Start(target)) // Should not measure with this size.
{ root.MaxClientSize = new Size(123, 456);
var root = new LayoutTestRoot();
var availableSize = default(Size);
// Should not measure with this size. root.DoMeasureOverride = (_, s) =>
root.MaxClientSize = new Size(123, 456); {
availableSize = s;
root.DoMeasureOverride = (_, s) => return new Size(100, 100);
{ };
availableSize = s;
return new Size(100, 100);
};
target.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
Assert.Equal(Size.Infinity, availableSize); Assert.Equal(Size.Infinity, availableSize);
}
} }
[Fact] [Fact]
public void Arranges_Root_With_DesiredSize() public void Arranges_Root_With_DesiredSize()
{ {
var target = new LayoutManager(); var root = new LayoutTestRoot
using (Start(target))
{ {
var root = new LayoutTestRoot Width = 100,
{ Height = 100,
Width = 100, };
Height = 100,
};
var arrangeSize = default(Size); var arrangeSize = default(Size);
root.DoArrangeOverride = (_, s) => root.DoArrangeOverride = (_, s) =>
{ {
arrangeSize = s; arrangeSize = s;
return s; return s;
}; };
target.ExecuteInitialLayoutPass(root); root.LayoutManager.ExecuteInitialLayoutPass(root);
Assert.Equal(new Size(100, 100), arrangeSize); Assert.Equal(new Size(100, 100), arrangeSize);
root.Width = 120;
target.ExecuteLayoutPass(); root.Width = 120;
Assert.Equal(new Size(120, 100), arrangeSize);
} root.LayoutManager.ExecuteLayoutPass();
Assert.Equal(new Size(120, 100), arrangeSize);
} }
[Fact] [Fact]
public void Invalidating_Child_Remeasures_Parent() public void Invalidating_Child_Remeasures_Parent()
{ {
var target = new LayoutManager(); Border border;
StackPanel panel;
using (Start(target)) var root = new LayoutTestRoot
{ {
AvaloniaLocator.CurrentMutable.Bind<ILayoutManager>().ToConstant(target); Child = panel = new StackPanel
Border border;
StackPanel panel;
var root = new LayoutTestRoot
{ {
Child = panel = new StackPanel Children =
{ {
Children = (border = new Border())
{
(border = new Border())
}
} }
}; }
};
target.ExecuteInitialLayoutPass(root);
Assert.Equal(new Size(0, 0), root.DesiredSize);
border.Width = 100; root.LayoutManager.ExecuteInitialLayoutPass(root);
border.Height = 100; Assert.Equal(new Size(0, 0), root.DesiredSize);
target.ExecuteLayoutPass(); border.Width = 100;
Assert.Equal(new Size(100, 100), panel.DesiredSize); border.Height = 100;
}
}
private IDisposable Start(LayoutManager layoutManager) root.LayoutManager.ExecuteLayoutPass();
{ Assert.Equal(new Size(100, 100), panel.DesiredSize);
var result = AvaloniaLocator.EnterScope();
AvaloniaLocator.CurrentMutable.Bind<ILayoutManager>().ToConstant(layoutManager);
return result;
} }
} }
} }

87
tests/Avalonia.Layout.UnitTests/LayoutableTests.cs

@ -102,80 +102,73 @@ namespace Avalonia.Layout.UnitTests
public void Only_Calls_LayoutManager_InvalidateMeasure_Once() public void Only_Calls_LayoutManager_InvalidateMeasure_Once()
{ {
var target = new Mock<ILayoutManager>(); var target = new Mock<ILayoutManager>();
var control = new Decorator();
using (Start(target.Object)) var root = new LayoutTestRoot
{ {
var control = new Decorator(); Child = control,
var root = new LayoutTestRoot { Child = control }; LayoutManager = target.Object,
};
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
target.ResetCalls(); target.ResetCalls();
control.InvalidateMeasure(); control.InvalidateMeasure();
control.InvalidateMeasure(); control.InvalidateMeasure();
target.Verify(x => x.InvalidateMeasure(control), Times.Once()); target.Verify(x => x.InvalidateMeasure(control), Times.Once());
}
} }
[Fact] [Fact]
public void Only_Calls_LayoutManager_InvalidateArrange_Once() public void Only_Calls_LayoutManager_InvalidateArrange_Once()
{ {
var target = new Mock<ILayoutManager>(); var target = new Mock<ILayoutManager>();
var control = new Decorator();
using (Start(target.Object)) var root = new LayoutTestRoot
{ {
var control = new Decorator(); Child = control,
var root = new LayoutTestRoot { Child = control }; LayoutManager = target.Object,
};
root.Measure(Size.Infinity); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
target.ResetCalls(); target.ResetCalls();
control.InvalidateArrange(); control.InvalidateArrange();
control.InvalidateArrange(); control.InvalidateArrange();
target.Verify(x => x.InvalidateArrange(control), Times.Once()); target.Verify(x => x.InvalidateArrange(control), Times.Once());
}
} }
[Fact] [Fact]
public void Attaching_Control_To_Tree_Invalidates_Parent_Measure() public void Attaching_Control_To_Tree_Invalidates_Parent_Measure()
{ {
var target = new Mock<ILayoutManager>(); var target = new Mock<ILayoutManager>();
var control = new Decorator();
using (Start(target.Object)) var root = new LayoutTestRoot
{ {
var control = new Decorator(); Child = control,
var root = new LayoutTestRoot { Child = control }; LayoutManager = target.Object,
};
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
Assert.True(control.IsMeasureValid);
root.Child = null; root.Measure(Size.Infinity);
root.Measure(Size.Infinity); root.Arrange(new Rect(root.DesiredSize));
root.Arrange(new Rect(root.DesiredSize)); Assert.True(control.IsMeasureValid);
Assert.False(control.IsMeasureValid); root.Child = null;
Assert.True(root.IsMeasureValid); root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
target.ResetCalls(); Assert.False(control.IsMeasureValid);
Assert.True(root.IsMeasureValid);
root.Child = control; target.ResetCalls();
Assert.False(root.IsMeasureValid); root.Child = control;
Assert.False(control.IsMeasureValid);
target.Verify(x => x.InvalidateMeasure(root), Times.Once());
}
}
private IDisposable Start(ILayoutManager layoutManager) Assert.False(root.IsMeasureValid);
{ Assert.False(control.IsMeasureValid);
var result = AvaloniaLocator.EnterScope(); target.Verify(x => x.InvalidateMeasure(root), Times.Once());
AvaloniaLocator.CurrentMutable.Bind<ILayoutManager>().ToConstant(layoutManager);
return result;
} }
private class TestLayoutable : Layoutable private class TestLayoutable : Layoutable

28
tests/Avalonia.LeakTests/ControlTests.cs

@ -42,12 +42,12 @@ namespace Avalonia.LeakTests
window.Show(); window.Show();
// Do a layout and make sure that Canvas gets added to visual tree. // Do a layout and make sure that Canvas gets added to visual tree.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.IsType<Canvas>(window.Presenter.Child); Assert.IsType<Canvas>(window.Presenter.Child);
// Clear the content and ensure the Canvas is removed. // Clear the content and ensure the Canvas is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;
@ -78,13 +78,13 @@ namespace Avalonia.LeakTests
window.Show(); window.Show();
// Do a layout and make sure that Canvas gets added to visual tree. // Do a layout and make sure that Canvas gets added to visual tree.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.IsType<Canvas>(window.Find<Canvas>("foo")); Assert.IsType<Canvas>(window.Find<Canvas>("foo"));
Assert.IsType<Canvas>(window.Presenter.Child); Assert.IsType<Canvas>(window.Presenter.Child);
// Clear the content and ensure the Canvas is removed. // Clear the content and ensure the Canvas is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;
@ -116,13 +116,13 @@ namespace Avalonia.LeakTests
// Do a layout and make sure that ScrollViewer gets added to visual tree and its // Do a layout and make sure that ScrollViewer gets added to visual tree and its
// template applied. // template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.IsType<ScrollViewer>(window.Presenter.Child); Assert.IsType<ScrollViewer>(window.Presenter.Child);
Assert.IsType<Canvas>(((ScrollViewer)window.Presenter.Child).Presenter.Child); Assert.IsType<Canvas>(((ScrollViewer)window.Presenter.Child).Presenter.Child);
// Clear the content and ensure the ScrollViewer is removed. // Clear the content and ensure the ScrollViewer is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;
@ -153,13 +153,13 @@ namespace Avalonia.LeakTests
// Do a layout and make sure that TextBox gets added to visual tree and its // Do a layout and make sure that TextBox gets added to visual tree and its
// template applied. // template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.IsType<TextBox>(window.Presenter.Child); Assert.IsType<TextBox>(window.Presenter.Child);
Assert.NotEmpty(window.Presenter.Child.GetVisualChildren()); Assert.NotEmpty(window.Presenter.Child.GetVisualChildren());
// Clear the content and ensure the TextBox is removed. // Clear the content and ensure the TextBox is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;
@ -197,14 +197,14 @@ namespace Avalonia.LeakTests
// Do a layout and make sure that TextBox gets added to visual tree and its // Do a layout and make sure that TextBox gets added to visual tree and its
// Text property set. // Text property set.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.IsType<TextBox>(window.Presenter.Child); Assert.IsType<TextBox>(window.Presenter.Child);
Assert.Equal("foo", ((TextBox)window.Presenter.Child).Text); Assert.Equal("foo", ((TextBox)window.Presenter.Child).Text);
// Clear the content and DataContext and ensure the TextBox is removed. // Clear the content and DataContext and ensure the TextBox is removed.
window.Content = null; window.Content = null;
window.DataContext = null; window.DataContext = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;
@ -235,7 +235,7 @@ namespace Avalonia.LeakTests
// Do a layout and make sure that TextBox gets added to visual tree and its // Do a layout and make sure that TextBox gets added to visual tree and its
// template applied. // template applied.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.Same(textBox, window.Presenter.Child); Assert.Same(textBox, window.Presenter.Child);
// Get the border from the TextBox template. // Get the border from the TextBox template.
@ -247,7 +247,7 @@ namespace Avalonia.LeakTests
// Clear the content and ensure the TextBox is removed. // Clear the content and ensure the TextBox is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
// Check that the TextBox has no subscriptions to its Classes collection. // Check that the TextBox has no subscriptions to its Classes collection.
@ -289,12 +289,12 @@ namespace Avalonia.LeakTests
window.Show(); window.Show();
// Do a layout and make sure that TreeViewItems get realized. // Do a layout and make sure that TreeViewItems get realized.
LayoutManager.Instance.ExecuteInitialLayoutPass(window); window.LayoutManager.ExecuteInitialLayoutPass(window);
Assert.Single(target.ItemContainerGenerator.Containers); Assert.Single(target.ItemContainerGenerator.Containers);
// Clear the content and ensure the TreeView is removed. // Clear the content and ensure the TreeView is removed.
window.Content = null; window.Content = null;
LayoutManager.Instance.ExecuteLayoutPass(); window.LayoutManager.ExecuteLayoutPass();
Assert.Null(window.Presenter.Child); Assert.Null(window.Presenter.Child);
return window; return window;

4
tests/Avalonia.UnitTests/TestRoot.cs

@ -43,9 +43,9 @@ namespace Avalonia.UnitTests
public double LayoutScaling => 1; public double LayoutScaling => 1;
public double RenderScaling => 1; public ILayoutManager LayoutManager { get; set; } = new LayoutManager();
public ILayoutManager LayoutManager => AvaloniaLocator.Current.GetService<ILayoutManager>(); public double RenderScaling => 1;
public IRenderer Renderer { get; set; } public IRenderer Renderer { get; set; }

11
tests/Avalonia.UnitTests/TestServices.cs

@ -23,7 +23,6 @@ namespace Avalonia.UnitTests
{ {
public static readonly TestServices StyledWindow = new TestServices( public static readonly TestServices StyledWindow = new TestServices(
assetLoader: new AssetLoader(), assetLoader: new AssetLoader(),
layoutManager: new LayoutManager(),
platform: new AppBuilder().RuntimePlatform, platform: new AppBuilder().RuntimePlatform,
renderInterface: new MockPlatformRenderInterface(), renderInterface: new MockPlatformRenderInterface(),
standardCursorFactory: Mock.Of<IStandardCursorFactory>(), standardCursorFactory: Mock.Of<IStandardCursorFactory>(),
@ -52,10 +51,7 @@ namespace Avalonia.UnitTests
keyboardDevice: () => new KeyboardDevice(), keyboardDevice: () => new KeyboardDevice(),
keyboardNavigation: new KeyboardNavigationHandler(), keyboardNavigation: new KeyboardNavigationHandler(),
inputManager: new InputManager()); inputManager: new InputManager());
public static readonly TestServices RealLayoutManager = new TestServices(
layoutManager: new LayoutManager());
public static readonly TestServices RealStyler = new TestServices( public static readonly TestServices RealStyler = new TestServices(
styler: new Styler()); styler: new Styler());
@ -65,7 +61,6 @@ namespace Avalonia.UnitTests
IInputManager inputManager = null, IInputManager inputManager = null,
Func<IKeyboardDevice> keyboardDevice = null, Func<IKeyboardDevice> keyboardDevice = null,
IKeyboardNavigationHandler keyboardNavigation = null, IKeyboardNavigationHandler keyboardNavigation = null,
ILayoutManager layoutManager = null,
Func<IMouseDevice> mouseDevice = null, Func<IMouseDevice> mouseDevice = null,
IRuntimePlatform platform = null, IRuntimePlatform platform = null,
IPlatformRenderInterface renderInterface = null, IPlatformRenderInterface renderInterface = null,
@ -83,7 +78,6 @@ namespace Avalonia.UnitTests
InputManager = inputManager; InputManager = inputManager;
KeyboardDevice = keyboardDevice; KeyboardDevice = keyboardDevice;
KeyboardNavigation = keyboardNavigation; KeyboardNavigation = keyboardNavigation;
LayoutManager = layoutManager;
MouseDevice = mouseDevice; MouseDevice = mouseDevice;
Platform = platform; Platform = platform;
RenderInterface = renderInterface; RenderInterface = renderInterface;
@ -101,7 +95,6 @@ namespace Avalonia.UnitTests
public IFocusManager FocusManager { get; } public IFocusManager FocusManager { get; }
public Func<IKeyboardDevice> KeyboardDevice { get; } public Func<IKeyboardDevice> KeyboardDevice { get; }
public IKeyboardNavigationHandler KeyboardNavigation { get; } public IKeyboardNavigationHandler KeyboardNavigation { get; }
public ILayoutManager LayoutManager { get; }
public Func<IMouseDevice> MouseDevice { get; } public Func<IMouseDevice> MouseDevice { get; }
public IRuntimePlatform Platform { get; } public IRuntimePlatform Platform { get; }
public IPlatformRenderInterface RenderInterface { get; } public IPlatformRenderInterface RenderInterface { get; }
@ -119,7 +112,6 @@ namespace Avalonia.UnitTests
IInputManager inputManager = null, IInputManager inputManager = null,
Func<IKeyboardDevice> keyboardDevice = null, Func<IKeyboardDevice> keyboardDevice = null,
IKeyboardNavigationHandler keyboardNavigation = null, IKeyboardNavigationHandler keyboardNavigation = null,
ILayoutManager layoutManager = null,
Func<IMouseDevice> mouseDevice = null, Func<IMouseDevice> mouseDevice = null,
IRuntimePlatform platform = null, IRuntimePlatform platform = null,
IPlatformRenderInterface renderInterface = null, IPlatformRenderInterface renderInterface = null,
@ -138,7 +130,6 @@ namespace Avalonia.UnitTests
inputManager: inputManager ?? InputManager, inputManager: inputManager ?? InputManager,
keyboardDevice: keyboardDevice ?? KeyboardDevice, keyboardDevice: keyboardDevice ?? KeyboardDevice,
keyboardNavigation: keyboardNavigation ?? KeyboardNavigation, keyboardNavigation: keyboardNavigation ?? KeyboardNavigation,
layoutManager: layoutManager ?? LayoutManager,
mouseDevice: mouseDevice ?? MouseDevice, mouseDevice: mouseDevice ?? MouseDevice,
platform: platform ?? Platform, platform: platform ?? Platform,
renderInterface: renderInterface ?? RenderInterface, renderInterface: renderInterface ?? RenderInterface,

4
tests/Avalonia.UnitTests/TestTemplatedRoot.cs

@ -39,9 +39,9 @@ namespace Avalonia.UnitTests
public double LayoutScaling => 1; public double LayoutScaling => 1;
public double RenderScaling => 1; public ILayoutManager LayoutManager { get; set; } = new LayoutManager();
public ILayoutManager LayoutManager => AvaloniaLocator.Current.GetService<ILayoutManager>(); public double RenderScaling => 1;
public IRenderTarget RenderTarget => null; public IRenderTarget RenderTarget => null;

1
tests/Avalonia.UnitTests/UnitTestApplication.cs

@ -50,7 +50,6 @@ namespace Avalonia.UnitTests
.Bind<IInputManager>().ToConstant(Services.InputManager) .Bind<IInputManager>().ToConstant(Services.InputManager)
.Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke()) .Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke())
.Bind<IKeyboardNavigationHandler>().ToConstant(Services.KeyboardNavigation) .Bind<IKeyboardNavigationHandler>().ToConstant(Services.KeyboardNavigation)
.Bind<ILayoutManager>().ToConstant(Services.LayoutManager)
.Bind<IMouseDevice>().ToConstant(Services.MouseDevice?.Invoke()) .Bind<IMouseDevice>().ToConstant(Services.MouseDevice?.Invoke())
.Bind<IRuntimePlatform>().ToConstant(Services.Platform) .Bind<IRuntimePlatform>().ToConstant(Services.Platform)
.Bind<IPlatformRenderInterface>().ToConstant(Services.RenderInterface) .Bind<IPlatformRenderInterface>().ToConstant(Services.RenderInterface)

29
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs

@ -522,7 +522,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Should_Update_ClipBounds_For_Negative_Margin() public void Should_Update_ClipBounds_For_Negative_Margin()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -542,7 +542,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var scene = new Scene(tree); var scene = new Scene(tree);
@ -566,7 +566,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Should_Update_Descendent_Tranform_When_Margin_Changed() public void Should_Update_Descendent_Tranform_When_Margin_Changed()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -585,7 +585,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var scene = new Scene(tree); var scene = new Scene(tree);
@ -613,7 +613,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void DirtyRects_Should_Contain_Old_And_New_Bounds_When_Margin_Changed() public void DirtyRects_Should_Contain_Old_And_New_Bounds_When_Margin_Changed()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -633,7 +633,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var scene = new Scene(tree); var scene = new Scene(tree);
@ -660,7 +660,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Resizing_Scene_Should_Add_DirtyRects() public void Resizing_Scene_Should_Add_DirtyRects()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -707,7 +707,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Setting_Opacity_Should_Add_Descendent_Bounds_To_DirtyRects() public void Setting_Opacity_Should_Add_Descendent_Bounds_To_DirtyRects()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -744,7 +744,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Should_Set_GeometryClip() public void Should_Set_GeometryClip()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var clip = StreamGeometry.Parse("M100,0 L0,100 100,100"); var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
Decorator decorator; Decorator decorator;
@ -768,7 +768,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Disposing_Scene_Releases_DrawOperation_References() public void Disposing_Scene_Releases_DrawOperation_References()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>()); var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
Image img; Image img;
@ -800,7 +800,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Replacing_Control_Releases_DrawOperation_Reference() public void Replacing_Control_Releases_DrawOperation_Reference()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>()); var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
Image img; Image img;
@ -830,12 +830,5 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
} }
} }
private IDisposable TestApplication()
{
return UnitTestApplication.Start(
TestServices.MockPlatformRenderInterface.With(
layoutManager: new LayoutManager()));
}
} }
} }

20
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs

@ -17,7 +17,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Control_With_Animated_Opacity_And_Children_Should_Start_New_Layer() public void Control_With_Animated_Opacity_And_Children_Should_Start_New_Layer()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -39,7 +39,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var animation = new BehaviorSubject<double>(0.5); var animation = new BehaviorSubject<double>(0.5);
@ -85,7 +85,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Control_With_Animated_Opacity_And_No_Children_Should_Not_Start_New_Layer() public void Control_With_Animated_Opacity_And_No_Children_Should_Not_Start_New_Layer()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -104,7 +104,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var animation = new BehaviorSubject<double>(0.5); var animation = new BehaviorSubject<double>(0.5);
@ -121,7 +121,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Removing_Control_With_Animated_Opacity_Should_Remove_Layers() public void Removing_Control_With_Animated_Opacity_Should_Remove_Layers()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -146,7 +146,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var animation = new BehaviorSubject<double>(0.5); var animation = new BehaviorSubject<double>(0.5);
@ -171,7 +171,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void Hiding_Transparent_Control_Should_Remove_Layers() public void Hiding_Transparent_Control_Should_Remove_Layers()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Decorator decorator; Decorator decorator;
Border border; Border border;
@ -196,7 +196,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var animation = new BehaviorSubject<double>(0.5); var animation = new BehaviorSubject<double>(0.5);
@ -221,7 +221,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact] [Fact]
public void GeometryClip_Should_Affect_Child_Layers() public void GeometryClip_Should_Affect_Child_Layers()
{ {
using (TestApplication()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var clip = StreamGeometry.Parse("M100,0 L0,100 100,100"); var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
Decorator decorator; Decorator decorator;
@ -240,7 +240,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
}; };
var layout = AvaloniaLocator.Current.GetService<ILayoutManager>(); var layout = tree.LayoutManager;
layout.ExecuteInitialLayoutPass(tree); layout.ExecuteInitialLayoutPass(tree);
var animation = new BehaviorSubject<double>(0.5); var animation = new BehaviorSubject<double>(0.5);

Loading…
Cancel
Save