diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs
index 0a228511a..bf654d3a7 100644
--- a/Terminal.Gui/Application.cs
+++ b/Terminal.Gui/Application.cs
@@ -170,12 +170,12 @@ public static partial class Application
///
///
/// must be called when the application is closing (typically after
- /// has returned) to ensure resources are cleaned up and terminal settings
+ /// has returned) to ensure resources are cleaned up and terminal settings
/// restored.
///
///
/// The function combines
- /// and into a single
+ /// and into a single
/// call. An application cam use without explicitly calling
/// .
///
@@ -334,7 +334,7 @@ public static partial class Application
/// Shutdown an application initialized with .
///
/// Shutdown must be called for every call to or
- /// to ensure all resources are cleaned up (Disposed)
+ /// to ensure all resources are cleaned up (Disposed)
/// and terminal settings are restored.
///
public static void Shutdown ()
@@ -533,14 +533,14 @@ public static partial class Application
}
///
- /// Runs the application by calling with the value of
+ /// Runs the application by calling with the value of
/// .
///
- /// See for more details.
- public static void Run (Func errorHandler = null) { Run (errorHandler);}
+ /// See for more details.
+ public static void Run (Func errorHandler = null, ConsoleDriver driver = null) { Run (errorHandler, driver);}
///
- /// Runs the application by calling with a new instance of the
+ /// Runs the application by calling with a new instance of the
/// specified -derived class.
/// Calling first is not needed as this function will initialize the application.
///
@@ -548,7 +548,7 @@ public static partial class Application
/// ensure resources are cleaned up and terminal settings restored.
///
///
- /// See for more details.
+ /// See for more details.
///
///
/// The to use. If not specified the default driver for the platform will
@@ -560,28 +560,9 @@ public static partial class Application
{
var top = new T () as Toplevel;
- if (top is null)
- {
- throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel");
- }
+ EnsureValidInitialization (top, driver);
- if (_initialized)
- {
- if (Driver is null)
- {
- // This code path should be impossible because Init(null, null) will select the platform default driver
- throw new InvalidOperationException (
- "Init() completed without a driver being set (this should be impossible); Run() cannot be called."
- );
- }
- }
- else
- {
- // Init() has NOT been called.
- InternalInit (driver, null, true);
- }
-
- Run (top, errorHandler);
+ RunApp (top, errorHandler);
}
/// Runs the main loop on the given container.
@@ -591,11 +572,11 @@ public static partial class Application
/// modal s such as boxes.
///
///
- /// To make a stop execution, call
+ /// To make a stop execution, call
/// .
///
///
- /// Calling is equivalent to calling
+ /// Calling is equivalent to calling
/// , followed by , and then calling
/// .
///
@@ -618,7 +599,19 @@ public static partial class Application
/// RELEASE builds only: Handler for any unhandled exceptions (resumes when returns true,
/// rethrows when null).
///
- public static void Run (Toplevel view, Func errorHandler = null)
+ ///
+ /// The to use. If not specified the default driver for the platform will
+ /// be used ( , , or ). Must be
+ /// if has already been called.
+ ///
+ public static void Run (Toplevel view, Func errorHandler = null, ConsoleDriver driver = null)
+ {
+ EnsureValidInitialization (view, driver);
+
+ RunApp (view, errorHandler);
+ }
+
+ private static void RunApp (Toplevel view, Func errorHandler = null)
{
var resume = true;
@@ -654,6 +647,30 @@ public static partial class Application
}
}
+ private static void EnsureValidInitialization (Toplevel top, ConsoleDriver driver)
+ {
+ if (top is null)
+ {
+ throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel");
+ }
+
+ if (_initialized)
+ {
+ if (Driver is null)
+ {
+ // This code path should be impossible because Init(null, null) will select the platform default driver
+ throw new InvalidOperationException (
+ "Init() completed without a driver being set (this should be impossible); Run() cannot be called."
+ );
+ }
+ }
+ else
+ {
+ // Init() has NOT been called.
+ InternalInit (driver, null, true);
+ }
+ }
+
/// Adds a timeout to the application.
///
/// When time specified passes, the callback will be invoked. If the callback returns true, the timeout will be
@@ -844,7 +861,7 @@ public static partial class Application
/// Stops running the most recent or the if provided.
/// The to stop.
///
- /// This will cause to return.
+ /// This will cause to return.
///
/// Calling is equivalent to setting the
/// property on the currently running to false.
@@ -1065,7 +1082,7 @@ public static partial class Application
///
/// The current object. This is updated when
- /// enters and leaves to point to the current
+ /// enters and leaves to point to the current
/// .
///
/// The current.
@@ -1185,7 +1202,7 @@ public static partial class Application
&& top != OverlappedTop
&& top != Current
&& Current?.Running == false
- && !top.Running)
+ && top?.Running == false)
{
lock (_topLevels)
{
diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs
index de519450c..71714e5f8 100644
--- a/UnitTests/Application/ApplicationTests.cs
+++ b/UnitTests/Application/ApplicationTests.cs
@@ -916,9 +916,9 @@ public class ApplicationTests
}
[Fact]
- public void Run_Creates_Top_With_Init ()
+ public void Run_Creates_Top_Without_Init ()
{
- Application.Init (new FakeDriver ());
+ var driver = new FakeDriver ();
Assert.Null (Application.Top);
@@ -927,7 +927,16 @@ public class ApplicationTests
Assert.NotNull (Application.Top);
Application.RequestStop ();
};
- Application.Run ();
+ Application.Run (null, driver);
+#if DEBUG_IDISPOSABLE
+ Assert.False (Application.Top.WasDisposed);
+ var exception = Record.Exception (() => Application.Shutdown ());
+ Assert.NotNull (exception);
+ Assert.False (Application.Top.WasDisposed);
+ // It's up to caller to dispose it
+ Application.Top.Dispose ();
+ Assert.True (Application.Top.WasDisposed);
+#endif
Assert.NotNull (Application.Top);
Application.Shutdown ();
@@ -947,6 +956,15 @@ public class ApplicationTests
Application.RequestStop ();
};
Application.Run (null, driver);
+#if DEBUG_IDISPOSABLE
+ Assert.False (Application.Top.WasDisposed);
+ var exception = Record.Exception (() => Application.Shutdown ());
+ Assert.NotNull (exception);
+ Assert.False (Application.Top.WasDisposed);
+ // It's up to caller to dispose it
+ Application.Top.Dispose ();
+ Assert.True (Application.Top.WasDisposed);
+#endif
Assert.NotNull (Application.Top);
Application.Shutdown ();
@@ -954,9 +972,9 @@ public class ApplicationTests
}
[Fact]
- public void Run_t_Creates_Top_With_Init ()
+ public void Run_t_Creates_Top_Without_Init ()
{
- Application.Init (new FakeDriver ());
+ var driver = new FakeDriver ();
Assert.Null (Application.Top);
@@ -965,7 +983,16 @@ public class ApplicationTests
Assert.NotNull (Application.Top);
Application.RequestStop ();
};
- Application.Run (new Toplevel ());
+ Application.Run (new (), null, driver);
+#if DEBUG_IDISPOSABLE
+ Assert.False (Application.Top.WasDisposed);
+ var exception = Record.Exception (() => Application.Shutdown ());
+ Assert.NotNull (exception);
+ Assert.False (Application.Top.WasDisposed);
+ // It's up to caller to dispose it
+ Application.Top.Dispose ();
+ Assert.True (Application.Top.WasDisposed);
+#endif
Assert.NotNull (Application.Top);
Application.Shutdown ();