From 479c11710360a79fd52303cec93f1445e30169e9 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 29 Oct 2017 18:08:40 +0300 Subject: [PATCH 1/4] Allow to pass CancellationToken to Application.Run --- src/Avalonia.Controls/Application.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index abae080515..06c1a8b4cc 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -175,6 +175,15 @@ namespace Avalonia closable.Closed += (s, e) => source.Cancel(); Dispatcher.UIThread.MainLoop(source.Token); } + + /// + /// Runs the application's main loop until the is cancelled. + /// + /// The token to track + public void Run(CancellationToken token) + { + Dispatcher.UIThread.MainLoop(token); + } /// /// Exits the application From 37c5414922ec93d77716764cef1a92a3d4934d91 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 29 Oct 2017 18:09:03 +0300 Subject: [PATCH 2/4] Don't allow to call AppBuilder.Setup twice --- src/Avalonia.Controls/AppBuilderBase.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index 1610d33f9b..4167539455 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -14,6 +14,8 @@ namespace Avalonia.Controls /// The type of the AppBuilder class itself. public abstract class AppBuilderBase where TAppBuilder : AppBuilderBase, new() { + private static bool s_setupWasAlreadyCalled; + /// /// Gets or sets the instance. /// @@ -252,6 +254,9 @@ namespace Avalonia.Controls throw new InvalidOperationException("No rendering system configured."); } + if (s_setupWasAlreadyCalled) + throw new InvalidOperationException("Setup was already called on one of AppBuilder instances"); + Instance.RegisterServices(); RuntimePlatformServicesInitializer(); WindowingSubsystemInitializer(); From af1da0a9c9bdc89db52ea88eb59a47d7e6289aa9 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 2 Nov 2017 23:34:37 -0500 Subject: [PATCH 3/4] Add missing assignment. --- src/Avalonia.Controls/AppBuilderBase.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index 4167539455..ebbd682f28 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -255,7 +255,11 @@ namespace Avalonia.Controls } if (s_setupWasAlreadyCalled) + { throw new InvalidOperationException("Setup was already called on one of AppBuilder instances"); + } + + s_setupWasAlreadyCalled = true; Instance.RegisterServices(); RuntimePlatformServicesInitializer(); From ba481365f6469d2d3379d2a5d648a3acf935b45e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 15 Dec 2017 20:27:30 -0600 Subject: [PATCH 4/4] Enable turning off the setup check for appbuilder tests. --- src/Avalonia.Controls/AppBuilderBase.cs | 13 ++++++++++++- .../Avalonia.Controls.UnitTests/AppBuilderTests.cs | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index ebbd682f28..7af3deef34 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -209,6 +209,17 @@ namespace Avalonia.Controls public TAppBuilder UseAvaloniaModules() => AfterSetup(builder => SetupAvaloniaModules()); + private bool CheckSetup { get; set; } = true; + + /// + /// Set this AppBuilder to ignore the setup check. Used for testing purposes. + /// + internal TAppBuilder IgnoreSetupCheck() + { + CheckSetup = false; + return Self; + } + private void SetupAvaloniaModules() { var moduleInitializers = from assembly in AvaloniaLocator.Current.GetService().GetLoadedAssemblies() @@ -254,7 +265,7 @@ namespace Avalonia.Controls throw new InvalidOperationException("No rendering system configured."); } - if (s_setupWasAlreadyCalled) + if (s_setupWasAlreadyCalled && CheckSetup) { throw new InvalidOperationException("Setup was already called on one of AppBuilder instances"); } diff --git a/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs b/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs index 867f740a3a..60c53d126c 100644 --- a/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs @@ -65,6 +65,7 @@ namespace Avalonia.Controls.UnitTests { ResetModuleLoadStates(); AppBuilder.Configure() + .IgnoreSetupCheck() .UseWindowingSubsystem(() => { }) .UseRenderingSubsystem(() => { }) .UseAvaloniaModules() @@ -81,6 +82,7 @@ namespace Avalonia.Controls.UnitTests { ResetModuleLoadStates(); var builder = AppBuilder.Configure() + .IgnoreSetupCheck() .UseWindowingSubsystem(() => { }) .UseRenderingSubsystem(() => { }, "Direct2D1"); builder.UseAvaloniaModules().SetupWithoutStarting(); @@ -90,6 +92,7 @@ namespace Avalonia.Controls.UnitTests ResetModuleLoadStates(); builder = AppBuilder.Configure() + .IgnoreSetupCheck() .UseWindowingSubsystem(() => { }) .UseRenderingSubsystem(() => { }, "Skia"); builder.UseAvaloniaModules().SetupWithoutStarting(); @@ -99,13 +102,14 @@ namespace Avalonia.Controls.UnitTests } } - [Fact (Skip = "We don't have rendering modules with dependencies right now")] + [Fact] public void LoadsRenderingModuleWithoutDependenciesWhenNoModuleMatches() { using (AvaloniaLocator.EnterScope()) { ResetModuleLoadStates(); var builder = AppBuilder.Configure() + .IgnoreSetupCheck() .UseWindowingSubsystem(() => { }) .UseRenderingSubsystem(() => { }, "TBD"); builder.UseAvaloniaModules().SetupWithoutStarting();