Browse Source

Merge branch 'master' into fix-filedialog-bugs

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

156
.editorconfig

@ -1,11 +1,159 @@
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://EditorConfig.org
# editorconfig.org
# top-most EditorConfig file
root = true
# Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*]
end_of_line = CRLF
insert_final_newline = true
indent_style = space
indent_size = 4
# C# files
[*.cs]
indent_style = space
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = one_less_than_current
# avoid this. unless absolutely necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# prefer var
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere = true:suggestion
# use language keywords instead of BCL types
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# static fields should have s_ prefix
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_prefix_style.required_prefix = s_
dotnet_naming_style.static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# Code style defaults
dotnet_sort_system_directives_first = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Pattern matching
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
# Null checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Xaml files
[*.xaml]
indent_size = 4
# Xml project files
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
indent_size = 2
# Xml build files
[*.builds]
indent_size = 2
# Xml files
[*.{xml,stylecop,resx,ruleset}]
indent_size = 2
# Xml config files
[*.{props,targets,config,nuspec}]
indent_size = 2
# Shell scripts
[*.sh]
end_of_line = lf
[*.{cmd, bat}]
end_of_line = crlf

1
Avalonia.sln

@ -58,6 +58,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9B9E
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
src\Shared\SharedAssemblyInfo.cs = src\Shared\SharedAssemblyInfo.cs
EndProjectSection
EndProject

2
readme.md

@ -20,6 +20,8 @@ Avalonia is a WPF-inspired cross-platform XAML-based UI framework providing a fl
Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (<a href="http://avaloniaui.net/docs/quickstart/images/new-project-dialog.png">screenshot</a>). Now you can write code and markup that will work on multiple platforms!
For those without Visual Studio, starter guide for .NET Core CLI can be found [here](http://avaloniaui.net/docs/quickstart/create-new-project#net-core).
Avalonia is delivered via <b>NuGet</b> package manager. You can find the packages here: ([stable(ish)](https://www.nuget.org/packages/Avalonia/), [nightly](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed))
Use these commands in Package Manager console to install Avalonia manually:

1
src/Avalonia.Controls/Application.cs

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

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

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

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

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

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

@ -518,7 +518,7 @@ namespace Avalonia.Controls.Presenters
}
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
// is only partially visible due to differing item sizes. If the container is only

18
src/Avalonia.Controls/TopLevel.cs

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

4
src/Avalonia.Controls/Window.cs

@ -374,7 +374,7 @@ namespace Avalonia.Controls
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
LayoutManager.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing())
{
@ -416,7 +416,7 @@ namespace Avalonia.Controls
EnsureInitialized();
SetWindowStartupLocation();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
LayoutManager.ExecuteInitialLayoutPass(this);
using (BeginAutoSizing())
{

5
src/Avalonia.Controls/WindowBase.cs

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

5
src/Avalonia.Layout/ILayoutRoot.cs

@ -22,5 +22,10 @@ namespace Avalonia.Layout
/// The scaling factor to use in layout.
/// </summary>
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 _running;
/// <summary>
/// Gets the layout manager.
/// </summary>
public static ILayoutManager Instance => AvaloniaLocator.Current.GetService<ILayoutManager>();
/// <inheritdoc/>
public void InvalidateMeasure(ILayoutable control)
{
@ -170,7 +165,7 @@ namespace Avalonia.Layout
{
root.Measure(Size.Infinity);
}
else
else if (control.PreviousMeasure.HasValue)
{
control.Measure(control.PreviousMeasure.Value);
}

10
src/Avalonia.Layout/Layoutable.cs

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

5
src/Avalonia.Themes.Default/MenuItem.xaml

@ -122,11 +122,6 @@
</Setter>
</Style>
<Style Selector="MenuItem:selected /template/ Border#root">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeAccentBrush}"/>
</Style>
<Style Selector="MenuItem:pointerover /template/ Border#root">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeAccentBrush}"/>

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

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

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

@ -8,26 +8,18 @@ using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Layout
{
[MemoryDiagnoser]
public class Measure : IDisposable
public class Measure
{
private IDisposable _app;
private TestRoot root;
private List<Control> controls = new List<Control>();
public Measure()
{
_app = UnitTestApplication.Start(TestServices.RealLayoutManager);
var panel = new StackPanel();
root = new TestRoot { Child = panel };
controls.Add(panel);
CreateChildren(panel, 3, 5);
LayoutManager.Instance.ExecuteInitialLayoutPass(root);
}
public void Dispose()
{
_app.Dispose();
root.LayoutManager.ExecuteInitialLayoutPass(root);
}
[Benchmark]
@ -43,7 +35,7 @@ namespace Avalonia.Benchmarks.Layout
}
}
LayoutManager.Instance.ExecuteLayoutPass();
root.LayoutManager.ExecuteLayoutPass();
}
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.Rendering;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Xunit;
namespace Avalonia.Controls.UnitTests.Presenters
@ -219,13 +220,13 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact]
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 scroll = (ScrollContentPresenter)target.Parent;
var scroll = (TestScroller)target.Parent;
scroll.Measure(new Size(100, 100));
scroll.Arrange(new Rect(0, 0, 100, 100));
scroll.Width = scroll.Height = 100;
scroll.LayoutManager.ExecuteInitialLayoutPass(scroll);
// 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
@ -237,7 +238,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
};
target.VirtualizationMode = ItemVirtualizationMode.Simple;
LayoutManager.Instance.ExecuteLayoutPass();
((ILayoutRoot)scroll.GetVisualRoot()).LayoutManager.ExecuteLayoutPass();
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 Size ClientSize { get; }
public double RenderScaling => 1;
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget()
{
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.Templates;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.UnitTests;
@ -564,11 +565,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact]
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 items = (IList<string>)target.Items;
target.ApplyTemplate();
target.Measure(Size.Empty);
target.Arrange(Rect.Empty);
@ -723,10 +723,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Down_Should_Return_Existing_Container_If_Materialized()
{
var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
scroller.Width = scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[5];
var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -740,10 +740,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Down_Should_Scroll_If_Necessary()
{
var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
scroller.Width = scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[9];
var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -757,44 +757,40 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact]
public void GetControlInDirection_Down_Should_Scroll_If_Partially_Visible()
{
using (UnitTestApplication.Start(TestServices.RealLayoutManager))
{
var target = CreateTarget();
var scroller = (ScrollContentPresenter)target.Parent;
var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
scroller.Measure(new Size(100, 95));
scroller.Arrange(new Rect(0, 0, 100, 95));
scroller.Width = 100;
scroller.Height = 95;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Down,
from);
var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Down,
from);
Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result);
}
Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result);
}
[Fact]
public void GetControlInDirection_Up_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
{
using (UnitTestApplication.Start(TestServices.RealLayoutManager))
{
var target = CreateTarget();
var scroller = (ScrollContentPresenter)target.Parent;
var target = CreateTarget();
var scroller = (TestScroller)target.Parent;
scroller.Measure(new Size(100, 95));
scroller.Arrange(new Rect(0, 0, 100, 95));
((ILogicalScrollable)target).Offset = new Vector(0, 11);
scroller.Width = 100;
scroller.Height = 95;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
((ILogicalScrollable)target).Offset = new Vector(0, 11);
var from = target.Panel.Children[1];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Up,
from);
var from = target.Panel.Children[1];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Up,
from);
Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[0], result);
}
Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[0], result);
}
[Fact]
@ -835,10 +831,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Right_Should_Return_Existing_Container_If_Materialized()
{
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
scroller.Width = scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[5];
var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -852,10 +848,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void GetControlInDirection_Right_Should_Scroll_If_Necessary()
{
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
scroller.Width = scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[9];
var result = ((ILogicalScrollable)target).GetControlInDirection(
@ -869,32 +865,31 @@ namespace Avalonia.Controls.UnitTests.Presenters
[Fact]
public void GetControlInDirection_Right_Should_Scroll_If_Partially_Visible()
{
using (UnitTestApplication.Start(TestServices.RealLayoutManager))
{
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (ScrollContentPresenter)target.Parent;
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
scroller.Measure(new Size(95, 100));
scroller.Arrange(new Rect(0, 0, 95, 100));
scroller.Width = 95;
scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Right,
from);
var from = target.Panel.Children[8];
var result = ((ILogicalScrollable)target).GetControlInDirection(
NavigationDirection.Right,
from);
Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result);
}
Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
Assert.Same(target.Panel.Children[8], result);
}
[Fact]
public void GetControlInDirection_Left_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
{
var target = CreateTarget(orientation: Orientation.Horizontal);
var scroller = (TestScroller)target.Parent;
target.ApplyTemplate();
target.Measure(new Size(95, 100));
target.Arrange(new Rect(0, 0, 95, 100));
scroller.Width = 95;
scroller.Height = 100;
scroller.LayoutManager.ExecuteInitialLayoutPass(scroller);
((ILogicalScrollable)target).Offset = new Vector(11, 0);
var from = target.Panel.Children[1];
@ -1010,7 +1005,6 @@ namespace Avalonia.Controls.UnitTests.Presenters
};
scroller.UpdateChild();
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 Size ClientSize { get; }
public double RenderScaling => 1;
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
@ -1057,6 +1057,11 @@ namespace Avalonia.Controls.UnitTests.Presenters
{
throw new NotImplementedException();
}
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
}
}
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>();
AvaloniaLocator.CurrentMutable
.Bind<ILayoutManager>().ToTransient<LayoutManager>()
.Bind<IGlobalStyles>().ToFunc(() => globalStyles.Object)
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
.Bind<IStyler>().ToTransient<Styler>()

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

@ -74,15 +74,16 @@ namespace Avalonia.Controls.UnitTests
[Fact]
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))
{
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.
var layoutManagerMock = Mock.Get(LayoutManager.Instance);
var layoutManagerMock = Mock.Get(target.LayoutManager);
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);
}
@ -122,7 +123,7 @@ namespace Avalonia.Controls.UnitTests
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
var target = new TestTopLevel(impl.Object);
LayoutManager.Instance.ExecuteLayoutPass();
target.LayoutManager.ExecuteLayoutPass();
Assert.Equal(double.NaN, target.Width);
Assert.Equal(double.NaN, target.Height);
@ -248,13 +249,17 @@ namespace Avalonia.Controls.UnitTests
private class TestTopLevel : TopLevel
{
private readonly ILayoutManager _layoutManager;
public bool IsClosed { get; private set; }
public TestTopLevel(ITopLevelImpl impl)
public TestTopLevel(ITopLevelImpl impl, ILayoutManager layoutManager = null)
: base(impl)
{
_layoutManager = layoutManager ?? new LayoutManager();
}
protected override ILayoutManager CreateLayoutManager() => _layoutManager;
protected override void HandleApplicationExiting()
{
base.HandleApplicationExiting();

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

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

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

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

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

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

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

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

28
tests/Avalonia.LeakTests/ControlTests.cs

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

4
tests/Avalonia.UnitTests/TestRoot.cs

@ -43,9 +43,9 @@ namespace Avalonia.UnitTests
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; }

11
tests/Avalonia.UnitTests/TestServices.cs

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

4
tests/Avalonia.UnitTests/TestTemplatedRoot.cs

@ -39,9 +39,9 @@ namespace Avalonia.UnitTests
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;

1
tests/Avalonia.UnitTests/UnitTestApplication.cs

@ -50,7 +50,6 @@ namespace Avalonia.UnitTests
.Bind<IInputManager>().ToConstant(Services.InputManager)
.Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke())
.Bind<IKeyboardNavigationHandler>().ToConstant(Services.KeyboardNavigation)
.Bind<ILayoutManager>().ToConstant(Services.LayoutManager)
.Bind<IMouseDevice>().ToConstant(Services.MouseDevice?.Invoke())
.Bind<IRuntimePlatform>().ToConstant(Services.Platform)
.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]
public void Should_Update_ClipBounds_For_Negative_Margin()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var scene = new Scene(tree);
@ -566,7 +566,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Should_Update_Descendent_Tranform_When_Margin_Changed()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var scene = new Scene(tree);
@ -613,7 +613,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void DirtyRects_Should_Contain_Old_And_New_Bounds_When_Margin_Changed()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var scene = new Scene(tree);
@ -660,7 +660,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Resizing_Scene_Should_Add_DirtyRects()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
Border border;
@ -707,7 +707,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Setting_Opacity_Should_Add_Descendent_Bounds_To_DirtyRects()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
Border border;
@ -744,7 +744,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Should_Set_GeometryClip()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
Decorator decorator;
@ -768,7 +768,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Disposing_Scene_Releases_DrawOperation_References()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
Image img;
@ -800,7 +800,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Replacing_Control_Releases_DrawOperation_Reference()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>());
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]
public void Control_With_Animated_Opacity_And_Children_Should_Start_New_Layer()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var animation = new BehaviorSubject<double>(0.5);
@ -85,7 +85,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Control_With_Animated_Opacity_And_No_Children_Should_Not_Start_New_Layer()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var animation = new BehaviorSubject<double>(0.5);
@ -121,7 +121,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Removing_Control_With_Animated_Opacity_Should_Remove_Layers()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var animation = new BehaviorSubject<double>(0.5);
@ -171,7 +171,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void Hiding_Transparent_Control_Should_Remove_Layers()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator decorator;
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);
var animation = new BehaviorSubject<double>(0.5);
@ -221,7 +221,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
[Fact]
public void GeometryClip_Should_Affect_Child_Layers()
{
using (TestApplication())
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
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);
var animation = new BehaviorSubject<double>(0.5);

Loading…
Cancel
Save