diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 8297b9e9c..93be94c8f 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -179,7 +179,7 @@ public static partial class Application /// to use. If neither or are /// specified the default driver for the platform will be used. /// - public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (() => new Toplevel (), driver, driverName); } + public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (driver, driverName); } internal static bool _initialized; internal static int _mainThreadId = -1; @@ -194,7 +194,6 @@ public static partial class Application // // calledViaRunT: If false (default) all state will be reset. If true the state will not be reset. internal static void InternalInit ( - Func topLevelFactory, ConsoleDriver driver = null, string driverName = null, bool calledViaRunT = false @@ -292,13 +291,6 @@ public static partial class Application SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ()); - Top = topLevelFactory (); - Current = Top; - _initialTop = Top; - - // Ensure Top's layout is up to date. - Current.SetRelativeLayout (Driver.Bounds); - SupportedCultures = GetSupportedCultures (); _mainThreadId = Thread.CurrentThread.ManagedThreadId; _initialized = true; @@ -346,8 +338,6 @@ public static partial class Application #region Run (Begin, Run, End, Stop) - private static Toplevel _initialTop; - /// /// Notify that a new was created ( was called). The token is /// created in and this event will be fired before that function exits. @@ -523,7 +513,7 @@ public static partial class Application /// . /// /// See for more details. - public static void Run (Func errorHandler = null) { Run (Top, errorHandler); } + public static void Run (Func errorHandler = null) { Run (errorHandler);} /// /// Runs the application by calling with a new instance of the @@ -544,35 +534,16 @@ public static partial class Application public static void Run (Func errorHandler = null, ConsoleDriver driver = null) where T : Toplevel, new() { + var top = new T () as Toplevel; + + if (top is null) + { + throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel"); + } + if (_initialized) { - // Init created Application.Top. If it hasn't been disposed... - if (Top is { }) - { - Top.Dispose (); - Top = null; - } - - if (Driver is { }) - { - // Init() has been called and we have a driver, so just run the app. - // This Toplevel will get disposed in `Shutdown` - var top = new T (); - Type type = top.GetType ().BaseType; - - while (type != typeof (Toplevel) && type != typeof (object)) - { - type = type.BaseType; - } - - if (type != typeof (Toplevel)) - { - throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel"); - } - - Run (top, errorHandler); - } - else + if (Driver is null) { // This code path should be impossible because Init(null, null) will select the platform default driver throw new InvalidOperationException ( @@ -583,9 +554,10 @@ public static partial class Application else { // Init() has NOT been called. - InternalInit (() => new T (), driver, null, true); - Run (Top, errorHandler); + InternalInit (driver, null, true); } + + Run (top, errorHandler); } /// Runs the main loop on the given container. @@ -1049,11 +1021,6 @@ public static partial class Application runState.Toplevel?.Dispose (); runState.Toplevel = null; runState.Dispose (); - - if (_topLevels.Count == 0) - { - Top = _initialTop; - } } #endregion Run (Begin, Run, End) diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index c67166e22..de519450c 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -265,7 +265,6 @@ public class ApplicationTests Assert.Throws ( () => Application.InternalInit ( - () => topLevel = new TestToplevel (), new FakeDriver () ) ); @@ -277,7 +276,7 @@ public class ApplicationTests // Now try the other way topLevel = null; - Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver ()); + Application.InternalInit (new FakeDriver ()); Assert.Throws (() => Application.Init (new FakeDriver ())); Shutdown (); @@ -297,7 +296,7 @@ public class ApplicationTests // NOTE: Run, when called after Init has been called behaves differently than // when called if Init has not been called. Toplevel topLevel = null; - Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver ()); + Application.InternalInit (new FakeDriver ()); RunState runstate = null; @@ -911,9 +910,66 @@ public class ApplicationTests Application.Shutdown (); Assert.NotNull (w); Assert.Equal (string.Empty, w.Title); // Invalid - w has been disposed -> Valid - w isn't Application.Top but the original created by Init - Assert.Null (Application.Top); Assert.Null (Application.Current); Assert.NotNull (top); + Assert.Null (Application.Top); + } + + [Fact] + public void Run_Creates_Top_With_Init () + { + Application.Init (new FakeDriver ()); + + Assert.Null (Application.Top); + + Application.Iteration += (s, e) => + { + Assert.NotNull (Application.Top); + Application.RequestStop (); + }; + Application.Run (); + Assert.NotNull (Application.Top); + + Application.Shutdown (); + Assert.Null (Application.Top); + } + + [Fact] + public void Run_T_Creates_Top_Without_Init () + { + var driver = new FakeDriver (); + + Assert.Null (Application.Top); + + Application.Iteration += (s, e) => + { + Assert.NotNull (Application.Top); + Application.RequestStop (); + }; + Application.Run (null, driver); + Assert.NotNull (Application.Top); + + Application.Shutdown (); + Assert.Null (Application.Top); + } + + [Fact] + public void Run_t_Creates_Top_With_Init () + { + Application.Init (new FakeDriver ()); + + Assert.Null (Application.Top); + + Application.Iteration += (s, e) => + { + Assert.NotNull (Application.Top); + Application.RequestStop (); + }; + Application.Run (new Toplevel ()); + Assert.NotNull (Application.Top); + + Application.Shutdown (); + Assert.Null (Application.Top); } // TODO: Add tests for Run that test errorHandler