diff --git a/Example/Example.cs b/Example/Example.cs index 406675ad4d..630e6560ff 100644 --- a/Example/Example.cs +++ b/Example/Example.cs @@ -6,9 +6,11 @@ using System; using Terminal.Gui; -Application.Run (); +var app = Application.Run (); -Console.WriteLine ($"Username: {((ExampleWindow)Application.Top).UserNameText.Text}"); +Console.WriteLine ($"Username: {app.UserNameText.Text}"); + +app.Dispose (); // Before the application exits, reset Terminal.Gui for clean shutdown Application.Shutdown (); diff --git a/Terminal.Gui/Application.MainLoopSyncContext.cs b/Terminal.Gui/Application.MainLoopSyncContext.cs index dfda0727ae..513608e8c1 100644 --- a/Terminal.Gui/Application.MainLoopSyncContext.cs +++ b/Terminal.Gui/Application.MainLoopSyncContext.cs @@ -12,7 +12,7 @@ private sealed class MainLoopSyncContext : SynchronizationContext public override void Post (SendOrPostCallback d, object state) { - MainLoop.AddIdle ( + MainLoop?.AddIdle ( () => { d (state); diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 929c13fa8b..660104f334 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -8,19 +8,12 @@ namespace Terminal.Gui; /// A static, singleton class representing the application. This class is the entry point for the application. /// /// -/// // A simple Terminal.Gui app that creates a window with a frame and title with -/// // 5 rows/columns of padding. -/// Application.Init(); -/// var win = new Window ($"Example App ({Application.QuitKey} to quit)") { -/// X = 5, -/// Y = 5, -/// Width = Dim.Fill (5), -/// Height = Dim.Fill (5) -/// }; -/// Application.Top.Add(win); -/// Application.Run(); -/// Application.Shutdown(); -/// +/// Application.Init(); +/// var win = new Window ($"Example App ({Application.QuitKey} to quit)"); +/// Application.Run(win); +/// win.Dispose(); +/// Application.Shutdown(); +/// /// /// TODO: Flush this out. public static partial class Application @@ -75,6 +68,10 @@ internal static List GetSupportedCultures () .ToList (); } + // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`. + // This variable is set in `End` in this case so that `Begin` correctly sets `Top`. + private static Toplevel _cachedRunStateToplevel; + // IMPORTANT: Ensure all property/fields are reset here. See Init_ResetState_Resets_Properties unit test. // Encapsulate all setting of initial state for Application; Having // this in a function like this ensures we don't make mistakes in @@ -88,13 +85,32 @@ internal static void ResetState () foreach (Toplevel t in _topLevels) { t.Running = false; - t.Dispose (); +#if DEBUG_IDISPOSABLE + + // Don't dispose the toplevels. It's up to caller dispose them + Debug.Assert (t.WasDisposed); +#endif } _topLevels.Clear (); Current = null; - Top?.Dispose (); +#if DEBUG_IDISPOSABLE + + // Don't dispose the Top. It's up to caller dispose it + if (Top is { }) + { + Debug.Assert (Top.WasDisposed); + + // If End wasn't called _cachedRunStateToplevel may be null + if (_cachedRunStateToplevel is { }) + { + Debug.Assert (_cachedRunStateToplevel.WasDisposed); + Debug.Assert (_cachedRunStateToplevel == Top); + } + } +#endif Top = null; + _cachedRunStateToplevel = null; // MainLoop stuff MainLoop?.Dispose (); @@ -161,12 +177,14 @@ internal static void ResetState () /// /// /// 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 /// . /// @@ -179,7 +197,7 @@ internal static void ResetState () /// 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 +212,6 @@ internal static void ResetState () // // 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 @@ -227,7 +244,8 @@ internal static void InternalInit ( // multiple times. We need to do this because some settings are only // valid after a Driver is loaded. In this cases we need just // `Settings` so we can determine which driver to use. - Load (true); + // Don't reset, so we can inherit the theme from the previous run. + Load (); Apply (); // Ignore Configuration for ForceDriver if driverName is specified @@ -292,12 +310,6 @@ internal static void InternalInit ( SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ()); - Top = topLevelFactory (); - Current = Top; - - // Ensure Top's layout is up to date. - Current.SetRelativeLayout (Driver.Bounds); - SupportedCultures = GetSupportedCultures (); _mainThreadId = Thread.CurrentThread.ManagedThreadId; _initialized = true; @@ -332,11 +344,13 @@ public static List GetDriverTypes () /// 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 () { + // TODO: Throw an exception if Init hasn't been called. ResetState (); PrintJsonErrors (); } @@ -369,59 +383,76 @@ public static void Shutdown () /// The handle that needs to be passed to the method upon /// completion. /// - /// The to prepare execution for. + /// The to prepare execution for. /// /// This method prepares the provided for running with the focus, it adds this to the list /// of s, lays out the Subviews, focuses the first element, and draws the /// in the screen. This is usually followed by executing the method, and then the /// method upon termination which will undo these changes. /// - public static RunState Begin (Toplevel Toplevel) + public static RunState Begin (Toplevel toplevel) { - if (Toplevel is null) - { - throw new ArgumentNullException (nameof (Toplevel)); - } + ArgumentNullException.ThrowIfNull (toplevel); #if DEBUG_IDISPOSABLE - Debug.Assert (!Toplevel.WasDisposed); + Debug.Assert (!toplevel.WasDisposed); + + if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel) + { + Debug.Assert (_cachedRunStateToplevel.WasDisposed); + } #endif - if (Toplevel.IsOverlappedContainer && OverlappedTop != Toplevel && OverlappedTop is { }) + if (toplevel.IsOverlappedContainer && OverlappedTop != toplevel && OverlappedTop is { }) { throw new InvalidOperationException ("Only one Overlapped Container is allowed."); } - // Ensure the mouse is ungrabed. + // Ensure the mouse is ungrabbed. MouseGrabView = null; - var rs = new RunState (Toplevel); + var rs = new RunState (toplevel); // View implements ISupportInitializeNotification which is derived from ISupportInitialize - if (!Toplevel.IsInitialized) + if (!toplevel.IsInitialized) { - Toplevel.BeginInit (); - Toplevel.EndInit (); + toplevel.BeginInit (); + toplevel.EndInit (); } +#if DEBUG_IDISPOSABLE + if (Top is { } && toplevel != Top && !_topLevels.Contains (Top)) + { + // This assertion confirm if the Top was already disposed + Debug.Assert (Top.WasDisposed); + Debug.Assert (Top == _cachedRunStateToplevel); + } +#endif + lock (_topLevels) { - // If Top was already initialized with Init, and Begin has never been called - // Top was not added to the Toplevels Stack. It will thus never get disposed. - // Clean it up here: - if (Top is { } && Toplevel != Top && !_topLevels.Contains (Top)) + if (Top is { } && toplevel != Top && !_topLevels.Contains (Top)) { - Top.Dispose (); - Top = null; + // If Top was already disposed and isn't on the Toplevels Stack, + // clean it up here if is the same as _cachedRunStateToplevel + if (Top == _cachedRunStateToplevel) + { + Top = null; + } + else + { + // Probably this will never hit + throw new ObjectDisposedException (Top.GetType ().FullName); + } } - else if (Top is { } && Toplevel != Top && _topLevels.Contains (Top)) + else if (OverlappedTop is { } && toplevel != Top && _topLevels.Contains (Top)) { - Top.OnLeave (Toplevel); + Top.OnLeave (toplevel); } // BUGBUG: We should not depend on `Id` internally. // BUGBUG: It is super unclear what this code does anyway. - if (string.IsNullOrEmpty (Toplevel.Id)) + if (string.IsNullOrEmpty (toplevel.Id)) { var count = 1; var id = (_topLevels.Count + count).ToString (); @@ -432,42 +463,46 @@ public static RunState Begin (Toplevel Toplevel) id = (_topLevels.Count + count).ToString (); } - Toplevel.Id = (_topLevels.Count + count).ToString (); + toplevel.Id = (_topLevels.Count + count).ToString (); - _topLevels.Push (Toplevel); + _topLevels.Push (toplevel); } else { - Toplevel dup = _topLevels.FirstOrDefault (x => x.Id == Toplevel.Id); + Toplevel dup = _topLevels.FirstOrDefault (x => x.Id == toplevel.Id); if (dup is null) { - _topLevels.Push (Toplevel); + _topLevels.Push (toplevel); } } if (_topLevels.FindDuplicates (new ToplevelEqualityComparer ()).Count > 0) { - throw new ArgumentException ("There are duplicates Toplevels Id's"); + throw new ArgumentException ("There are duplicates Toplevel IDs"); } } - if (Top is null || Toplevel.IsOverlappedContainer) + if (Top is null || toplevel.IsOverlappedContainer) { - Top = Toplevel; + Top = toplevel; } var refreshDriver = true; - if (OverlappedTop == null - || Toplevel.IsOverlappedContainer - || (Current?.Modal == false && Toplevel.Modal) - || (Current?.Modal == false && !Toplevel.Modal) - || (Current?.Modal == true && Toplevel.Modal)) + if (OverlappedTop is null + || toplevel.IsOverlappedContainer + || (Current?.Modal == false && toplevel.Modal) + || (Current?.Modal == false && !toplevel.Modal) + || (Current?.Modal == true && toplevel.Modal)) { - if (Toplevel.Visible) + if (toplevel.Visible) { - Current = Toplevel; + Current?.OnDeactivate (toplevel); + Toplevel previousCurrent = Current; + Current = toplevel; + Current.OnActivate (previousCurrent); + SetCurrentOverlappedAsTop (); } else @@ -476,13 +511,13 @@ public static RunState Begin (Toplevel Toplevel) } } else if ((OverlappedTop != null - && Toplevel != OverlappedTop + && toplevel != OverlappedTop && Current?.Modal == true && !_topLevels.Peek ().Modal) - || (OverlappedTop is { } && Toplevel != OverlappedTop && Current?.Running == false)) + || (OverlappedTop is { } && toplevel != OverlappedTop && Current?.Running == false)) { refreshDriver = false; - MoveCurrent (Toplevel); + MoveCurrent (toplevel); } else { @@ -490,113 +525,88 @@ public static RunState Begin (Toplevel Toplevel) MoveCurrent (Current); } - //if (Toplevel.LayoutStyle == LayoutStyle.Computed) { - Toplevel.SetRelativeLayout (Driver.Bounds); + toplevel.SetRelativeLayout (Driver.Bounds); - //} - - // BUGBUG: This call is likley not needed. - Toplevel.LayoutSubviews (); - Toplevel.PositionToplevels (); - Toplevel.FocusFirst (); + // BUGBUG: This call is likely not needed. + toplevel.LayoutSubviews (); + toplevel.PositionToplevels (); + toplevel.FocusFirst (); if (refreshDriver) { - OverlappedTop?.OnChildLoaded (Toplevel); - Toplevel.OnLoaded (); - Toplevel.SetNeedsDisplay (); - Toplevel.Draw (); - Toplevel.PositionCursor (); + OverlappedTop?.OnChildLoaded (toplevel); + toplevel.OnLoaded (); + toplevel.SetNeedsDisplay (); + toplevel.Draw (); + toplevel.PositionCursor (); Driver.Refresh (); } - NotifyNewRunState?.Invoke (Toplevel, new RunStateEventArgs (rs)); + NotifyNewRunState?.Invoke (toplevel, new (rs)); return rs; } /// - /// Runs the application by calling with the value of - /// . + /// Runs the application by creating a object and calling + /// . /// - /// See for more details. - public static void Run (Func errorHandler = null) { Run (Top, errorHandler); } + /// + /// Calling first is not needed as this function will initialize the application. + /// + /// must be called when the application is closing (typically after Run> has returned) to + /// ensure resources are cleaned up and terminal settings restored. + /// + /// + /// The caller is responsible for disposing the object returned by this method. + /// + /// + /// The created object. The caller is responsible for disposing this object. + public static Toplevel Run (Func errorHandler = null, ConsoleDriver driver = null) { return Run (errorHandler, driver); } /// - /// Runs the application by calling with a new instance of the - /// specified -derived class. + /// Runs the application by creating a -derived object of type T and calling + /// . + /// + /// /// Calling first is not needed as this function will initialize the application. /// /// must be called when the application is closing (typically after Run> has returned) to /// ensure resources are cleaned up and terminal settings restored. /// - /// - /// See for more details. + /// + /// The caller is responsible for disposing the object returned by this method. + /// + /// /// /// /// 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 (Func errorHandler = null, ConsoleDriver driver = null) + /// The created T object. The caller is responsible for disposing this object. + public static T Run (Func errorHandler = null, ConsoleDriver driver = null) where T : Toplevel, new() { - if (_initialized) - { - // Init created Application.Top. If it hasn't been disposed... - if (Top is { }) - { - Top.Dispose (); - Top = null; - } + var top = new T (); - 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; + Run (top, errorHandler, driver); - 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 - { - // 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 (() => new T (), driver, null, true); - Run (Top, errorHandler); - } + return top; } - /// Runs the main loop on the given container. + /// Runs the Application using the provided view. /// /// /// This method is used to start processing events for the main application, but it is also used to run other /// 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 /// . /// @@ -607,6 +617,7 @@ public static void Run (Func errorHandler = null, ConsoleDri /// method will only process any pending events, timers, idle handlers and then /// return control immediately. /// + /// Calling first is not needed as this function will initialize the application. /// /// RELEASE builds only: When is any exceptions will be /// rethrown. Otherwise, if will be called. If @@ -619,8 +630,34 @@ public static void Run (Func errorHandler = null, ConsoleDri /// 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 was called. + /// + public static void Run (Toplevel view, Func errorHandler = null, ConsoleDriver driver = null) { + ArgumentNullException.ThrowIfNull (view); + + if (_initialized) + { + if (Driver is null) + { + // Disposing before throwing + view.Dispose (); + + // 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); + } + var resume = true; while (resume) @@ -636,6 +673,16 @@ public static void Run (Toplevel view, Func errorHandler = null // by using NotifyStopRunState event. RunLoop (runState); + if (runState.Toplevel is null) + { +#if DEBUG_IDISPOSABLE + Debug.Assert (_topLevels.Count == 0); +#endif + runState.Dispose (); + + return; + } + if (!EndAfterFirstIteration) { End (runState); @@ -735,19 +782,12 @@ public static void Refresh () /// The state returned by the method. public static void RunLoop (RunState state) { - if (state is null) - { - throw new ArgumentNullException (nameof (state)); - } - - if (state.Toplevel is null) - { - throw new ObjectDisposedException ("state"); - } + ArgumentNullException.ThrowIfNull (state); + ObjectDisposedException.ThrowIf (state.Toplevel is null, "state"); var firstIteration = true; - for (state.Toplevel.Running = true; state.Toplevel.Running;) + for (state.Toplevel.Running = true; state.Toplevel?.Running == true;) { MainLoop.Running = true; @@ -783,7 +823,7 @@ public static void RunIteration (ref RunState state, ref bool firstIteration) } MainLoop.RunIteration (); - Iteration?.Invoke (null, new IterationEventArgs ()); + Iteration?.Invoke (null, new ()); EnsureModalOrVisibleAlwaysOnTop (state.Toplevel); if (state.Toplevel != Current) @@ -798,6 +838,11 @@ public static void RunIteration (ref RunState state, ref bool firstIteration) firstIteration = false; + if (Current == null) + { + return; + } + if (state.Toplevel != Top && (Top.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded)) { state.Toplevel.SetNeedsDisplay (state.Toplevel.Frame); @@ -842,10 +887,10 @@ public static void RunIteration (ref RunState state, ref bool firstIteration) } } - /// Stops running the most recent or the if provided. + /// Stops the provided , causing 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. @@ -880,7 +925,7 @@ public static void RequestStop (Toplevel top = null) return; } - ev = new ToplevelClosingEventArgs (top); + ev = new (top); top.OnClosing (ev); if (ev.Cancel) @@ -968,7 +1013,7 @@ private static void OnNotifyStopRunState (Toplevel top) { if (EndAfterFirstIteration) { - NotifyStopRunState?.Invoke (top, new ToplevelEventArgs (top)); + NotifyStopRunState?.Invoke (top, new (top)); } } @@ -979,10 +1024,7 @@ private static void OnNotifyStopRunState (Toplevel top) /// The returned by the method. public static void End (RunState runState) { - if (runState is null) - { - throw new ArgumentNullException (nameof (runState)); - } + ArgumentNullException.ThrowIfNull (runState); if (OverlappedTop is { }) { @@ -1024,6 +1066,11 @@ public static void End (RunState runState) } else { + if (_topLevels.Count > 1 && _topLevels.Peek () == OverlappedTop && OverlappedChildren.Any (t => t.Visible) is { }) + { + OverlappedMoveNext (); + } + Current = _topLevels.Peek (); if (_topLevels.Count == 1 && Current == OverlappedTop) @@ -1040,8 +1087,18 @@ public static void End (RunState runState) Refresh (); } - // Do NOT dispose .Toplevel here. It was not created by - // Run, but Init or someone else. + // Don't dispose runState.Toplevel. It's up to caller dispose it + // If it's not the same as the current in the RunIteration, + // it will be fixed later in the next RunIteration. + if (OverlappedTop is { } && !_topLevels.Contains (OverlappedTop)) + { + _cachedRunStateToplevel = OverlappedTop; + } + else + { + _cachedRunStateToplevel = runState.Toplevel; + } + runState.Toplevel = null; runState.Dispose (); } @@ -1061,10 +1118,13 @@ public static void End (RunState runState) public static Toplevel Top { get; private set; } /// - /// The current object. This is updated when - /// enters and leaves to point to the current + /// The current object. This is updated in enters and leaves to + /// point to the current /// . /// + /// + /// Only relevant in scenarios where is . + /// /// The current. public static Toplevel Current { get; private set; } @@ -1182,7 +1242,7 @@ private static bool MoveCurrent (Toplevel? top) && top != OverlappedTop && top != Current && Current?.Running == false - && !top.Running) + && top?.Running == false) { lock (_topLevels) { @@ -1250,7 +1310,7 @@ public static bool OnSizeChanging (SizeChangedEventArgs args) t.SetRelativeLayout (Rectangle.Empty with { Size = args.Size }); t.LayoutSubviews (); t.PositionToplevels (); - t.OnSizeChanging (new SizeChangedEventArgs (args.Size)); + t.OnSizeChanging (new (args.Size)); } Refresh (); @@ -1316,7 +1376,7 @@ public static void UngrabMouse () if (!OnUnGrabbingMouse (MouseGrabView)) { - var view = MouseGrabView; + View view = MouseGrabView; MouseGrabView = null; OnUnGrabbedMouse (view); } @@ -1355,7 +1415,7 @@ private static void OnGrabbedMouse (View view) return; } - GrabbedMouse?.Invoke (view, new ViewEventArgs (view)); + GrabbedMouse?.Invoke (view, new (view)); } private static void OnUnGrabbedMouse (View view) @@ -1365,7 +1425,7 @@ private static void OnUnGrabbedMouse (View view) return; } - UnGrabbedMouse?.Invoke (view, new ViewEventArgs (view)); + UnGrabbedMouse?.Invoke (view, new (view)); } #nullable enable @@ -1410,7 +1470,7 @@ internal static void OnMouseEvent (MouseEventEventArgs a) a.MouseEvent.View = view; } - MouseEvent?.Invoke (null, new MouseEventEventArgs (a.MouseEvent)); + MouseEvent?.Invoke (null, new (a.MouseEvent)); if (a.MouseEvent.Handled) { @@ -1477,9 +1537,9 @@ internal static void OnMouseEvent (MouseEventEventArgs a) if (view is Adornment adornment) { - var frameLoc = adornment.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y); + Point frameLoc = adornment.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y); - me = new MouseEvent + me = new () { X = frameLoc.X, Y = frameLoc.Y, @@ -1492,7 +1552,7 @@ internal static void OnMouseEvent (MouseEventEventArgs a) { Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y); - me = new MouseEvent + me = new () { X = boundsPoint.X, Y = boundsPoint.Y, @@ -1556,7 +1616,7 @@ public static Key AlternateForwardKey { Key oldKey = _alternateForwardKey; _alternateForwardKey = value; - OnAlternateForwardKeyChanged (new KeyChangedEventArgs (oldKey, value)); + OnAlternateForwardKeyChanged (new (oldKey, value)); } } } @@ -1583,7 +1643,7 @@ public static Key AlternateBackwardKey { Key oldKey = _alternateBackwardKey; _alternateBackwardKey = value; - OnAlternateBackwardKeyChanged (new KeyChangedEventArgs (oldKey, value)); + OnAlternateBackwardKeyChanged (new (oldKey, value)); } } } @@ -1610,7 +1670,7 @@ public static Key QuitKey { Key oldKey = _quitKey; _quitKey = value; - OnQuitKeyChanged (new KeyChangedEventArgs (oldKey, value)); + OnQuitKeyChanged (new (oldKey, value)); } } } diff --git a/Terminal.Gui/Configuration/ConfigurationManager.cs b/Terminal.Gui/Configuration/ConfigurationManager.cs index 03c66a87f0..2dbd2ba442 100644 --- a/Terminal.Gui/Configuration/ConfigurationManager.cs +++ b/Terminal.Gui/Configuration/ConfigurationManager.cs @@ -147,9 +147,8 @@ public static SettingsScope? Settings { if (_settings is null) { - throw new InvalidOperationException ( - "ConfigurationManager has not been initialized. Call ConfigurationManager.Reset() before accessing the Settings property." - ); + // If Settings is null, we need to initialize it. + Reset (); } return _settings; diff --git a/Terminal.Gui/Configuration/SettingsScope.cs b/Terminal.Gui/Configuration/SettingsScope.cs index 87e1b02dcf..d77a82b5e6 100644 --- a/Terminal.Gui/Configuration/SettingsScope.cs +++ b/Terminal.Gui/Configuration/SettingsScope.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; +using static Terminal.Gui.SpinnerStyle; namespace Terminal.Gui; @@ -44,7 +45,10 @@ public class SettingsScope : Scope Update (JsonSerializer.Deserialize (stream, _serializerOptions)!); OnUpdated (); Debug.WriteLine ($"ConfigurationManager: Read configuration from \"{source}\""); - Sources.Add (source); + if (!Sources.Contains (source)) + { + Sources.Add (source); + } return this; } @@ -70,7 +74,10 @@ public class SettingsScope : Scope if (!File.Exists (realPath)) { Debug.WriteLine ($"ConfigurationManager: Configuration file \"{realPath}\" does not exist."); - Sources.Add (filePath); + if (!Sources.Contains (filePath)) + { + Sources.Add (filePath); + } return this; } diff --git a/Terminal.Gui/FileServices/DefaultFileOperations.cs b/Terminal.Gui/FileServices/DefaultFileOperations.cs index 27c33dee64..85f450fd28 100644 --- a/Terminal.Gui/FileServices/DefaultFileOperations.cs +++ b/Terminal.Gui/FileServices/DefaultFileOperations.cs @@ -162,6 +162,7 @@ private bool Prompt (string title, string defaultText, out string result) dlg.AddButton (btnCancel); Application.Run (dlg); + dlg.Dispose (); result = tf.Text; diff --git a/Terminal.Gui/View/View.cs b/Terminal.Gui/View/View.cs index c78d327f5a..07235e638b 100644 --- a/Terminal.Gui/View/View.cs +++ b/Terminal.Gui/View/View.cs @@ -427,9 +427,24 @@ private static bool CanBeVisible (View view) /// The title. public string Title { - get => _title; + get + { +#if DEBUG_IDISPOSABLE + if (WasDisposed) + { + throw new ObjectDisposedException (GetType ().FullName); + } +#endif + return _title; + } set { +#if DEBUG_IDISPOSABLE + if (WasDisposed) + { + throw new ObjectDisposedException (GetType ().FullName); + } +#endif if (value == _title) { return; diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs index 7b821bf131..b22480ccc5 100644 --- a/Terminal.Gui/Views/Dialog.cs +++ b/Terminal.Gui/Views/Dialog.cs @@ -9,7 +9,7 @@ namespace Terminal.Gui; /// /// /// To run the modally, create the , and pass it to -/// . This will execute the dialog until it terminates via the +/// . This will execute the dialog until it terminates via the /// [ESC] or [CTRL-Q] key, or when one of the views or buttons added to the dialog calls /// . /// @@ -68,9 +68,45 @@ public Dialog () Modal = true; ButtonAlignment = DefaultButtonAlignment; + AddCommand (Command.QuitToplevel, () => + { + Canceled = true; + RequestStop (); + return true; + }); KeyBindings.Add (Key.Esc, Command.QuitToplevel); } + + private bool _canceled; + + /// Gets a value indicating whether the was canceled. + /// The default value is . + public bool Canceled + { + get + { +#if DEBUG_IDISPOSABLE + if (WasDisposed) + { + throw new ObjectDisposedException (GetType ().FullName); + } +#endif + return _canceled; + } + set + { +#if DEBUG_IDISPOSABLE + if (WasDisposed) + { + throw new ObjectDisposedException (GetType ().FullName); + } +#endif + _canceled = value; + return; + } + } + /// Determines how the s are aligned along the bottom of the dialog. public ButtonAlignments ButtonAlignment { get; set; } diff --git a/Terminal.Gui/Views/FileDialog.cs b/Terminal.Gui/Views/FileDialog.cs index f36099d291..ec29e69ba7 100644 --- a/Terminal.Gui/Views/FileDialog.cs +++ b/Terminal.Gui/Views/FileDialog.cs @@ -60,6 +60,9 @@ public FileDialog () : this (new FileSystem ()) { } /// This overload is mainly useful for testing. internal FileDialog (IFileSystem fileSystem) { + // Assume canceled + Canceled = true; + _fileSystem = fileSystem; Style = new FileDialogStyle (fileSystem); @@ -83,7 +86,10 @@ internal FileDialog (IFileSystem fileSystem) NavigateIf (k, KeyCode.CursorUp, _tableView); NavigateIf (k, KeyCode.CursorRight, _btnOk); }; - _btnCancel.Accept += (s, e) => { Application.RequestStop (); }; + _btnCancel.Accept += (s, e) => { + Canceled = true; + Application.RequestStop (); + }; _btnUp = new Button { X = 0, Y = 1, NoPadding = true }; _btnUp.Text = GetUpButtonText (); @@ -314,9 +320,6 @@ public bool AllowsMultipleSelection set => _tableView.MultiSelect = value; } - /// Gets a value indicating whether the was closed without confirming a selection. - public bool Canceled { get; private set; } = true; - /// The UI selected from combo box. May be null. public IAllowedType CurrentFilter { get; private set; } @@ -336,7 +339,7 @@ public bool AllowsMultipleSelection /// /// Gets all files/directories selected or an empty collection is - /// or . + /// or . /// /// If selecting only a single file/directory then you should use instead. public IReadOnlyList MultiSelected { get; private set; } @@ -356,7 +359,7 @@ public bool AllowsMultipleSelection /// /// Gets or Sets the selected path in the dialog. This is the result that should be used if - /// is off and is true. + /// is off and is true. /// public string Path { diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index 132be32131..783d593889 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -429,7 +429,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) /// public virtual bool MoveDown () { - if (_source.Count == 0) + if (_source is null || _source.Count == 0) { // Do we set lastSelectedItem to -1 here? return false; //Nothing for us to move to @@ -479,7 +479,7 @@ public virtual bool MoveDown () /// public virtual bool MoveEnd () { - if (_source.Count > 0 && _selected != _source.Count - 1) + if (_source is { Count: > 0 } && _selected != _source.Count - 1) { _selected = _source.Count - 1; @@ -517,6 +517,11 @@ public virtual bool MoveHome () /// public virtual bool MovePageDown () { + if (_source is null) + { + return true; + } + int n = _selected + Bounds.Height; if (n >= _source.Count) @@ -570,7 +575,7 @@ public virtual bool MovePageUp () /// public virtual bool MoveUp () { - if (_source.Count == 0) + if (_source is null || _source.Count == 0) { // Do we set lastSelectedItem to -1 here? return false; //Nothing for us to move to @@ -697,7 +702,7 @@ public override bool OnEnter (View view) /// if the event was fired. public bool OnOpenSelectedItem () { - if (_source.Count <= _selected || _selected < 0 || OpenSelectedItem is null) + if (_source is null || _source.Count <= _selected || _selected < 0 || OpenSelectedItem is null) { return false; } diff --git a/Terminal.Gui/Views/Menu/ContextMenu.cs b/Terminal.Gui/Views/Menu/ContextMenu.cs index f9ee4625f2..ae080a298f 100644 --- a/Terminal.Gui/Views/Menu/ContextMenu.cs +++ b/Terminal.Gui/Views/Menu/ContextMenu.cs @@ -116,6 +116,7 @@ public void Dispose () if (_container is { }) { _container.Closing -= Container_Closing; + _container.Deactivate -= Container_Deactivate; } } @@ -142,6 +143,7 @@ public void Show () _container = Application.Current; _container.Closing += Container_Closing; + _container.Deactivate += Container_Deactivate; Rectangle frame = Application.Driver.Bounds; Point position = Position; @@ -217,6 +219,7 @@ public void Show () _menuBar.OpenMenu (); } + private void Container_Deactivate (object sender, ToplevelEventArgs e) { Hide (); } private void Container_Closing (object sender, ToplevelClosingEventArgs obj) { Hide (); } private void MenuBar_MenuAllClosed (object sender, EventArgs e) { Dispose (); } } diff --git a/Terminal.Gui/Views/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs index 16395760a1..04e4c25b70 100644 --- a/Terminal.Gui/Views/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -468,6 +468,7 @@ params string [] buttons // Run the modal; do not shutdown the mainloop driver when done Application.Run (d); + d.Dispose (); return Clicked; } diff --git a/Terminal.Gui/Views/OpenDialog.cs b/Terminal.Gui/Views/OpenDialog.cs index c4631b44ac..ec7f8eb43b 100644 --- a/Terminal.Gui/Views/OpenDialog.cs +++ b/Terminal.Gui/Views/OpenDialog.cs @@ -36,7 +36,7 @@ public enum OpenMode /// /// /// To use, create an instance of , and pass it to -/// . This will run the dialog modally, and when this returns, +/// . This will run the dialog modally, and when this returns, /// the list of files will be available on the property. /// /// To select more than one file, users can use the spacebar, or control-t. diff --git a/Terminal.Gui/Views/SaveDialog.cs b/Terminal.Gui/Views/SaveDialog.cs index 3037e4732b..f1075159d4 100644 --- a/Terminal.Gui/Views/SaveDialog.cs +++ b/Terminal.Gui/Views/SaveDialog.cs @@ -17,7 +17,7 @@ namespace Terminal.Gui; /// /// /// To use, create an instance of , and pass it to -/// . This will run the dialog modally, and when this returns, +/// . This will run the dialog modally, and when this returns, /// the property will contain the selected file name or null if the user canceled. /// /// diff --git a/Terminal.Gui/Views/TableView/TableView.cs b/Terminal.Gui/Views/TableView/TableView.cs index 3525471681..34d3bfbe8d 100644 --- a/Terminal.Gui/Views/TableView/TableView.cs +++ b/Terminal.Gui/Views/TableView/TableView.cs @@ -2119,7 +2119,7 @@ out int idx ) { // if the column index provided is out of bounds - if (columnIndex < 0 || columnIndex >= table.Columns) + if (table is null || columnIndex < 0 || columnIndex >= table.Columns) { idx = columnIndex; diff --git a/Terminal.Gui/Views/Toplevel.cs b/Terminal.Gui/Views/Toplevel.cs index ed0a11501e..4bc5b111da 100644 --- a/Terminal.Gui/Views/Toplevel.cs +++ b/Terminal.Gui/Views/Toplevel.cs @@ -9,7 +9,7 @@ namespace Terminal.Gui; /// /// /// Toplevels can run as modal (popup) views, started by calling -/// . They return control to the caller when +/// . They return control to the caller when /// has been called (which sets the /// property to false). /// @@ -17,7 +17,7 @@ namespace Terminal.Gui; /// A Toplevel is created when an application initializes Terminal.Gui by calling . /// The application Toplevel can be accessed via . Additional Toplevels can be created /// and run (e.g. s. To run a Toplevel, create the and call -/// . +/// . /// /// public partial class Toplevel : View @@ -452,7 +452,7 @@ out StatusBar sb /// public override void Remove (View view) { - if (this is Toplevel Toplevel && Toplevel.MenuBar is { }) + if (this is Toplevel { MenuBar: { } }) { RemoveMenuStatusBar (view); } @@ -803,7 +803,7 @@ private void QuitToplevel () { if (Application.OverlappedTop is { }) { - Application.OverlappedTop.RequestStop (); + RequestStop (this); } else { diff --git a/Terminal.Gui/Views/Wizard/Wizard.cs b/Terminal.Gui/Views/Wizard/Wizard.cs index a21744607a..c3691b3e12 100644 --- a/Terminal.Gui/Views/Wizard/Wizard.cs +++ b/Terminal.Gui/Views/Wizard/Wizard.cs @@ -143,7 +143,7 @@ public WizardStep CurrentStep /// Add the Wizard to a containing view with . /// /// - /// If a non-Modal Wizard is added to the application after has + /// If a non-Modal Wizard is added to the application after has /// been called the first step must be explicitly set by setting to /// : /// diff --git a/UICatalog/KeyBindingsDialog.cs b/UICatalog/KeyBindingsDialog.cs index ab6c3e5345..128bff3edc 100644 --- a/UICatalog/KeyBindingsDialog.cs +++ b/UICatalog/KeyBindingsDialog.cs @@ -82,6 +82,7 @@ private void RemapKey (object sender, EventArgs e) Application.RequestStop (); }; Application.Run (dlg); + dlg.Dispose (); if (key.HasValue) { diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs index b864209dd6..e0eace794b 100644 --- a/UICatalog/Scenario.cs +++ b/UICatalog/Scenario.cs @@ -45,7 +45,7 @@ namespace UICatalog; /// /// /// The UI Catalog program uses reflection to find all scenarios and adds them to the ListViews. Press ENTER to -/// run the selected scenario. Press the default quit key to quit. / +/// run the selected scenario. Press the default quit key to quit. /// /// /// @@ -77,19 +77,6 @@ public class Scenario : IDisposable public string TopLevelColorScheme = "Base"; private bool _disposedValue; - /// - /// The Window for the . This should be set to in - /// most cases. - /// - public Window Win { get; set; } - - public void Dispose () - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose (true); - GC.SuppressFinalize (this); - } - /// /// Helper function to get the list of categories a belongs to (defined in /// ) @@ -130,7 +117,28 @@ public static List GetScenarios () } /// - /// Helper that provides the default implementation with a frame and label + /// Called by UI Catalog to run the . This is the main entry point for the + /// . + /// + /// + /// + /// Scenario developers are encouraged to override this method as the primary way of authoring a new + /// scenario. + /// + /// + /// The base implementation calls , , and . + /// + /// + public virtual void Main () + { + Init (); + Setup (); + Run (); + } + + /// + /// Helper that calls and creates the default + /// implementation with a frame and label /// showing the name of the and logic to exit back to the Scenario picker UI. Override /// to provide any behavior needed. /// @@ -144,6 +152,7 @@ public static List GetScenarios () /// creating any views or calling other Terminal.Gui APIs. /// /// + [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)] public virtual void Init () { Application.Init (); @@ -151,7 +160,9 @@ public virtual void Init () ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Win = new Window + Top = new (); + + Win = new () { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", X = 0, @@ -160,12 +171,9 @@ public virtual void Init () Height = Dim.Fill (), ColorScheme = Colors.ColorSchemes [TopLevelColorScheme] }; - Application.Top.Add (Win); + Top.Add (Win); } - /// Stops the scenario. Override to change shutdown behavior for the . - public virtual void RequestStop () { Application.RequestStop (); } - /// /// Runs the . Override to start the using a /// different than `Top`. @@ -174,53 +182,78 @@ public virtual void Init () /// Overrides that do not call the base., must call before /// returning. /// + [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)] public virtual void Run () { - // Must explicit call Application.Shutdown method to shutdown. - Application.Run (Application.Top); + // Must explicitly call Application.Shutdown method to shutdown. + Application.Run (Top); } /// Override this to implement the setup logic (create controls, etc...). /// This is typically the best place to put scenario logic code. + [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)] public virtual void Setup () { } + /// + /// The Toplevel for the . This should be set to . + /// + + //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)] + public Toplevel Top { get; set; } + /// Gets the Scenario Name + Description with the Description padded based on the longest known Scenario name. /// public override string ToString () { return $"{GetName ().PadRight (_maxScenarioNameLen)}{GetDescription ()}"; } + /// + /// The Window for the . This should be set to in + /// most cases. + /// + + //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)] + public Window Win { get; set; } + + #region IDispose + + public void Dispose () + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing) { if (!_disposedValue) { if (disposing) { - // TODO: dispose managed state (managed objects) + Top?.Dispose (); + Win?.Dispose (); } - // TODO: free unmanaged resources (unmanaged objects) and override finalizer - // TODO: set large fields to null _disposedValue = true; } } + #endregion IDispose + /// Returns a list of all Categories set by all of the s defined in the project. internal static List GetAllCategories () { List categories = new (); - foreach (Type type in typeof (Scenario).Assembly.GetTypes () - .Where ( - myType => myType.IsClass - && !myType.IsAbstract - && myType.IsSubclassOf (typeof (Scenario)) - )) - { - List attrs = System.Attribute.GetCustomAttributes (type).ToList (); - - categories = categories - .Union (attrs.Where (a => a is ScenarioCategory).Select (a => ((ScenarioCategory)a).Name)) - .ToList (); - } + categories = typeof (Scenario).Assembly.GetTypes () + .Where ( + myType => myType.IsClass + && !myType.IsAbstract + && myType.IsSubclassOf (typeof (Scenario))) + .Select (type => System.Attribute.GetCustomAttributes (type).ToList ()) + .Aggregate ( + categories, + (current, attrs) => current + .Union (attrs.Where (a => a is ScenarioCategory).Select (a => ((ScenarioCategory)a).Name)) + .ToList ()); // Sort categories = categories.OrderBy (c => c).ToList (); @@ -233,13 +266,8 @@ internal static List GetAllCategories () /// Defines the category names used to catagorize a [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class ScenarioCategory : System.Attribute + public class ScenarioCategory (string Name) : System.Attribute { - public ScenarioCategory (string Name) { this.Name = Name; } - - /// Category Name - public string Name { get; set; } - /// Static helper function to get the Categories given a Type /// /// list of category names @@ -256,23 +284,17 @@ public static List GetCategories (Type t) /// /// Name of the category public static string GetName (Type t) { return ((ScenarioCategory)GetCustomAttributes (t) [0]).Name; } + + /// Category Name + public string Name { get; set; } = Name; } /// Defines the metadata (Name and Description) for a [AttributeUsage (AttributeTargets.Class)] - public class ScenarioMetadata : System.Attribute + public class ScenarioMetadata (string Name, string Description) : System.Attribute { - public ScenarioMetadata (string Name, string Description) - { - this.Name = Name; - this.Description = Description; - } - /// Description - public string Description { get; set; } - - /// Name - public string Name { get; set; } + public string Description { get; set; } = Description; /// Static helper function to get the Description given a Type /// @@ -283,5 +305,8 @@ public ScenarioMetadata (string Name, string Description) /// /// public static string GetName (Type t) { return ((ScenarioMetadata)GetCustomAttributes (t) [0]).Name; } + + /// Name + public string Name { get; set; } = Name; } } diff --git a/UICatalog/Scenarios/ASCIICustomButton.cs b/UICatalog/Scenarios/ASCIICustomButton.cs index c597b18d9f..0ff22a80fa 100644 --- a/UICatalog/Scenarios/ASCIICustomButton.cs +++ b/UICatalog/Scenarios/ASCIICustomButton.cs @@ -50,8 +50,9 @@ public override void Init () ) ] }; - Application.Top.Add (menu, _scrollViewTestWindow); - Application.Run (); + Top = new (); + Top.Add (menu, _scrollViewTestWindow); + Application.Run (Top); } public override void Run () { } @@ -60,9 +61,9 @@ private void ChangeWindowSize () { _smallerWindow = (bool)(_miSmallerWindow.Checked = !_miSmallerWindow.Checked); _scrollViewTestWindow.Dispose (); - Application.Top.Remove (_scrollViewTestWindow); + Top.Remove (_scrollViewTestWindow); _scrollViewTestWindow = new ScrollViewTestWindow (); - Application.Top.Add (_scrollViewTestWindow); + Top.Add (_scrollViewTestWindow); } public class ASCIICustomButton : Button diff --git a/UICatalog/Scenarios/AdornmentExperiments.cs b/UICatalog/Scenarios/AdornmentExperiments.cs index d9356ec08f..a41c959613 100644 --- a/UICatalog/Scenarios/AdornmentExperiments.cs +++ b/UICatalog/Scenarios/AdornmentExperiments.cs @@ -8,33 +8,32 @@ public class AdornmentExperiments : Scenario { private ViewDiagnosticFlags _diagnosticFlags; + private View _frameView; + public override void Init () { Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; _diagnosticFlags = View.Diagnostics; //View.Diagnostics = ViewDiagnosticFlags.MouseEnter; - } - private View _frameView; - public override void Setup () - { _frameView = new View () { Title = "Frame View", X = 0, Y = 0, - Width = Dim.Percent(90), + Width = Dim.Percent (90), Height = Dim.Percent (90), CanFocus = true, }; - Application.Top.Add (_frameView); + Top.Add (_frameView); _frameView.Initialized += FrameView_Initialized; - Application.Top.Closed += (s, e) => View.Diagnostics = _diagnosticFlags; + Top.Closed += (s, e) => View.Diagnostics = _diagnosticFlags; } private void FrameView_Initialized (object sender, System.EventArgs e) diff --git a/UICatalog/Scenarios/Adornments.cs b/UICatalog/Scenarios/Adornments.cs index 132f015045..91c40f5a41 100644 --- a/UICatalog/Scenarios/Adornments.cs +++ b/UICatalog/Scenarios/Adornments.cs @@ -18,7 +18,8 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; var view = new Window { Title = "The _Window" }; var tf1 = new TextField { Width = 10, Text = "TextField" }; @@ -117,9 +118,11 @@ public override void Init () #endif }; - Application.Top.Closed += (s, e) => View.Diagnostics = _diagnosticFlags; + Top.Closed += (s, e) => View.Diagnostics = _diagnosticFlags; Application.Run (editor); + editor.Dispose (); + Application.Shutdown (); } diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs index 82ee73411a..22d6d11dcc 100644 --- a/UICatalog/Scenarios/AllViewsTester.cs +++ b/UICatalog/Scenarios/AllViewsTester.cs @@ -46,11 +46,9 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - } + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - public override void Setup () - { var statusBar = new StatusBar ( new StatusItem [] { @@ -66,7 +64,7 @@ public override void Setup () { View.Diagnostics ^= ViewDiagnosticFlags.Ruler; - Application.Top.SetNeedsDisplay (); + Top.SetNeedsDisplay (); } ), new ( @@ -76,12 +74,12 @@ public override void Setup () { View.Diagnostics ^= ViewDiagnosticFlags.Padding; - Application.Top.SetNeedsDisplay (); + Top.SetNeedsDisplay (); } ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); _viewClasses = GetAllViewClassesCollection () .OrderBy (t => t.Name) @@ -286,7 +284,7 @@ public override void Setup () ColorScheme = Colors.ColorSchemes ["Dialog"] }; - Application.Top.Add (_leftPane, _settingsPane, _hostPane); + Top.Add (_leftPane, _settingsPane, _hostPane); _curView = CreateClass (_viewClasses.First ().Value); } diff --git a/UICatalog/Scenarios/Animation.cs b/UICatalog/Scenarios/Animation.cs index b5c875519f..e1a7391122 100644 --- a/UICatalog/Scenarios/Animation.cs +++ b/UICatalog/Scenarios/Animation.cs @@ -17,22 +17,31 @@ public class Animation : Scenario { private bool _isDisposed; - public override void Setup () + public override void Main () { - base.Setup (); + Application.Init(); + + var win = new Window + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + X = 0, + Y = 0, + Width = Dim.Fill (), + Height = Dim.Fill (), + }; var imageView = new ImageView { Width = Dim.Fill (), Height = Dim.Fill () - 2 }; - Win.Add (imageView); + win.Add (imageView); var lbl = new Label { Y = Pos.AnchorEnd (2), Text = "Image by Wikiscient" }; - Win.Add (lbl); + win.Add (lbl); var lbl2 = new Label { Y = Pos.AnchorEnd (1), Text = "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif" }; - Win.Add (lbl2); + win.Add (lbl2); DirectoryInfo dir; @@ -78,6 +87,10 @@ public override void Setup () } } ); + + Application.Run (win); + win.Dispose (); + Application.Shutdown (); } protected override void Dispose (bool disposing) diff --git a/UICatalog/Scenarios/BackgroundWorkerCollection.cs b/UICatalog/Scenarios/BackgroundWorkerCollection.cs index 9445c226fb..e6f51d6f94 100644 --- a/UICatalog/Scenarios/BackgroundWorkerCollection.cs +++ b/UICatalog/Scenarios/BackgroundWorkerCollection.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Threading; using Terminal.Gui; @@ -13,13 +14,25 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Controls")] public class BackgroundWorkerCollection : Scenario { - public override void Run () { Application.Run (); } + public override void Main () + { + Application.Run ().Dispose (); + +#if DEBUG_IDISPOSABLE + if (Application.OverlappedChildren is { }) + { + Debug.Assert (Application.OverlappedChildren?.Count == 0); + Debug.Assert (Application.Top == Application.OverlappedTop); + } +#endif + + Application.Shutdown (); + } private class OverlappedMain : Toplevel { private readonly MenuBar _menu; - private readonly WorkerApp _workerApp; - private bool _canOpenWorkerApp; + private WorkerApp _workerApp; public OverlappedMain () { @@ -28,6 +41,8 @@ public OverlappedMain () IsOverlappedContainer = true; _workerApp = new WorkerApp { Visible = false }; + _workerApp.Border.Thickness = new (0, 1, 0, 0); + _workerApp.Border.LineStyle = LineStyle.Dashed; _menu = new MenuBar { @@ -90,29 +105,21 @@ public OverlappedMain () ); Add (statusBar); + Ready += OverlappedMain_Ready; Activate += OverlappedMain_Activate; Deactivate += OverlappedMain_Deactivate; - - Closed += OverlappedMain_Closed; - - Application.Iteration += (s, a) => - { - if (_canOpenWorkerApp && !_workerApp.Running && Application.OverlappedTop.Running) - { - Application.Run (_workerApp); - } - }; } - private void Menu_MenuOpening (object sender, MenuOpeningEventArgs menu) + private void OverlappedMain_Ready (object sender, EventArgs e) { - if (!_canOpenWorkerApp) + if (_workerApp?.Running == false) { - _canOpenWorkerApp = true; - - return; + Application.Run (_workerApp); } + } + private void Menu_MenuOpening (object sender, MenuOpeningEventArgs menu) + { if (menu.CurrentMenu.Title == "_Window") { menu.NewMenuBarItem = OpenedWindows (); @@ -165,15 +172,16 @@ private MenuBarItem OpenedWindows () return new MenuBarItem ("_Window", new List { menuItems.ToArray () }); } - private void OverlappedMain_Activate (object sender, ToplevelEventArgs top) { _workerApp.WriteLog ($"{top.Toplevel.Data} activate."); } + private void OverlappedMain_Activate (object sender, ToplevelEventArgs top) + { + _workerApp?.WriteLog ($"{(top.Toplevel is null ? ((Toplevel)sender).Data : top.Toplevel.Data)} activate."); + } - private void OverlappedMain_Closed (object sender, ToplevelEventArgs e) + private void OverlappedMain_Deactivate (object sender, ToplevelEventArgs top) { - _workerApp.Dispose (); - Dispose (); + _workerApp?.WriteLog ($"{top.Toplevel.Data} deactivate."); } - private void OverlappedMain_Deactivate (object sender, ToplevelEventArgs top) { _workerApp.WriteLog ($"{top.Toplevel.Data} deactivate."); } private void Quit () { RequestStop (); } private MenuBarItem View () @@ -208,6 +216,15 @@ private MenuBarItem View () new List { menuItems.Count == 0 ? new MenuItem [] { } : menuItems.ToArray () } ); } + + /// + protected override void Dispose (bool disposing) + { + _workerApp?.Dispose (); + _workerApp = null; + + base.Dispose (disposing); + } } private class Staging @@ -233,6 +250,7 @@ public StagingUIController (Staging staging, List list) : this () { Staging = staging; _label.Text = "Work list:"; + _listView.Enabled = true; _listView.SetSource (list); _start.Visible = false; Id = ""; @@ -258,7 +276,7 @@ public StagingUIController () }; Add (_label); - _listView = new ListView { X = 0, Y = 2, Width = Dim.Fill (), Height = Dim.Fill (2) }; + _listView = new ListView { X = 0, Y = 2, Width = Dim.Fill (), Height = Dim.Fill (2), Enabled = false }; Add (_listView); _start = new Button { Text = "Start", IsDefault = true, ClearOnVisibleFalse = false }; @@ -276,7 +294,7 @@ public StagingUIController () KeyDown += (s, e) => { - if (e.KeyCode == KeyCode.Esc) + if (e == Application.QuitKey) { OnReportClosed (this, EventArgs.Empty); } @@ -299,7 +317,6 @@ public StagingUIController () public Staging Staging { get; private set; } public event Action ReportClosed; - public void Run () { Application.Run (this); } private void OnReportClosed (object sender, EventArgs e) { @@ -322,24 +339,45 @@ private class WorkerApp : Toplevel public WorkerApp () { Data = "WorkerApp"; + Title = "Worker collection Log"; Width = Dim.Percent (80); Height = Dim.Percent (50); ColorScheme = Colors.ColorSchemes ["Base"]; - var label = new Label { X = Pos.Center (), Y = 0, Text = "Worker collection Log" }; - Add (label); - _listLog = new ListView { X = 0, - Y = Pos.Bottom (label), + Y = 0, Width = Dim.Fill (), Height = Dim.Fill (), Source = new ListWrapper (_log) }; Add (_listLog); + + // We don't want WorkerApp to respond to the quitkey + KeyBindings.Remove (Application.QuitKey); + + Closing += WorkerApp_Closing; + Closed += WorkerApp_Closed; + } + + private void WorkerApp_Closed (object sender, ToplevelEventArgs e) + { + CancelWorker (); + } + private void WorkerApp_Closing (object sender, ToplevelClosingEventArgs e) + { + Toplevel top = Application.OverlappedChildren.Find (x => x.Data.ToString () == "WorkerApp"); + + if (Visible && top == this) + { + Visible = false; + e.Cancel = true; + + Application.OverlappedMoveNext (); + } } public void CancelWorker () @@ -403,15 +441,7 @@ public void RunWorker () { // Failed WriteLog ( - $"Exception occurred { - e.Error.Message - } on Worker { - staging.StartStaging - }.{ - staging.StartStaging - :fff} at { - DateTime.Now - }" + $"Exception occurred {e.Error.Message} on Worker {staging.StartStaging}.{staging.StartStaging:fff} at {DateTime.Now}" ); } else if (e.Cancelled) @@ -446,8 +476,14 @@ public void RunWorker () _stagingsUi.Add (stagingUI); _stagingWorkers.Remove (staging); - - stagingUI.Run (); +#if DEBUG_IDISPOSABLE + if (Application.OverlappedTop is null) + { + stagingUI.Dispose (); + return; + } +#endif + Application.Run (stagingUI); } }; @@ -456,6 +492,7 @@ public void RunWorker () if (stagingUI.Staging != null && stagingUI.Staging.StartStaging != null) { staging = new Staging (stagingUI.Staging.StartStaging); + stagingUI.Dispose (); WriteLog ($"Worker is started at {staging.StartStaging}.{staging.StartStaging:fff}"); if (_stagingWorkers == null) @@ -465,6 +502,9 @@ public void RunWorker () _stagingWorkers.Add (staging, worker); worker.RunWorkerAsync (); + } + else + { stagingUI.Dispose (); } } @@ -479,6 +519,7 @@ private void StagingUI_ReportClosed (StagingUIController obj) { WriteLog ($"Report {obj.Staging.StartStaging}.{obj.Staging.StartStaging:fff} closed."); _stagingsUi.Remove (obj); + obj.Dispose (); } } } diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 90797c851e..78787e83c6 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -329,6 +329,6 @@ string MoveHotkey (string txt) } }; - Application.Top.Ready += (s, e) => radioGroup.Refresh (); + Top.Ready += (s, e) => radioGroup.Refresh (); } } diff --git a/UICatalog/Scenarios/CharacterMap.cs b/UICatalog/Scenarios/CharacterMap.cs index fdd05d91c7..bcac93b9b5 100644 --- a/UICatalog/Scenarios/CharacterMap.cs +++ b/UICatalog/Scenarios/CharacterMap.cs @@ -36,13 +36,14 @@ public class CharacterMap : Scenario public override void Init () { Application.Init (); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes ["Base"]; } public override void Setup () { _charMap = new() { X = 0, Y = 1, Height = Dim.Fill () }; - Application.Top.Add (_charMap); + Top.Add (_charMap); var jumpLabel = new Label { @@ -51,19 +52,19 @@ public override void Setup () HotKeySpecifier = (Rune)'_', Text = "_Jump To Code Point:" }; - Application.Top.Add (jumpLabel); + Top.Add (jumpLabel); var jumpEdit = new TextField { X = Pos.Right (jumpLabel) + 1, Y = Pos.Y (_charMap), Width = 10, Caption = "e.g. 01BE3" }; - Application.Top.Add (jumpEdit); + Top.Add (jumpEdit); _errorLabel = new() { X = Pos.Right (jumpEdit) + 1, Y = Pos.Y (_charMap), ColorScheme = Colors.ColorSchemes ["error"], Text = "err" }; - Application.Top.Add (_errorLabel); + Top.Add (_errorLabel); #if TEXT_CHANGED_TO_JUMP jumpEdit.TextChanged += JumpEdit_TextChanged; @@ -135,7 +136,7 @@ void JumpEditOnAccept (object sender, CancelEventArgs e) _charMap.StartCodePoint = table.Data.ToArray () [args.NewRow].Start; }; - Application.Top.Add (_categoryList); + Top.Add (_categoryList); _charMap.SelectedCodePoint = 0; _charMap.SetFocus (); @@ -164,7 +165,7 @@ void JumpEditOnAccept (object sender, CancelEventArgs e) ) ] }; - Application.Top.Add (menu); + Top.Add (menu); } private void _categoryList_Initialized (object sender, EventArgs e) { _charMap.Width = Dim.Fill () - _categoryList.Width; } @@ -898,6 +899,7 @@ private void ShowDetails () (s as Dialog)?.RequestStop (); }; Application.Run (waitIndicator); + waitIndicator.Dispose (); if (!string.IsNullOrEmpty (decResponse)) { @@ -1011,6 +1013,7 @@ private void ShowDetails () dlg.Add (json); Application.Run (dlg); + dlg.Dispose (); } else { diff --git a/UICatalog/Scenarios/ChineseUI.cs b/UICatalog/Scenarios/ChineseUI.cs index c59f85c143..96c2ea56ee 100644 --- a/UICatalog/Scenarios/ChineseUI.cs +++ b/UICatalog/Scenarios/ChineseUI.cs @@ -6,20 +6,18 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Unicode")] public class ChineseUI : Scenario { - public override void Init () + public override void Main () { Application.Init (); - Toplevel top = Application.Top; var win = new Window { - Title = "Test", + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - top.Add (win); var buttonPanel = new FrameView { @@ -34,20 +32,20 @@ public override void Init () var btn = new Button { X = 1, Y = 1, Text = "你" }; // v1: A btn.Accept += (s, e) => - { - int result = MessageBox.Query ( - "Confirm", - "Are you sure you want to quit ui?", - 0, - "Yes", - "No" - ); - - if (result == 0) - { - RequestStop (); - } - }; + { + int result = MessageBox.Query ( + "Confirm", + "Are you sure you want to quit ui?", + 0, + "Yes", + "No" + ); + + if (result == 0) + { + Application.RequestStop (); + } + }; buttonPanel.Add ( btn, @@ -55,8 +53,10 @@ public override void Init () new Button { X = 22, Y = 1, Text = "呀" } // v1: C ); - Application.Run (); - } + Application.Run (win); + + win.Dispose (); - public override void Run () { } + Application.Shutdown (); + } } diff --git a/UICatalog/Scenarios/ClassExplorer.cs b/UICatalog/Scenarios/ClassExplorer.cs index 389310111d..7cc3537f24 100644 --- a/UICatalog/Scenarios/ClassExplorer.cs +++ b/UICatalog/Scenarios/ClassExplorer.cs @@ -55,7 +55,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _treeView = new TreeView { X = 0, Y = 1, Width = Dim.Percent (50), Height = Dim.Fill () }; diff --git a/UICatalog/Scenarios/Clipping.cs b/UICatalog/Scenarios/Clipping.cs index 2b49aaadb7..4cdaff4bba 100644 --- a/UICatalog/Scenarios/Clipping.cs +++ b/UICatalog/Scenarios/Clipping.cs @@ -9,7 +9,8 @@ public class Clipping : Scenario public override void Init () { Application.Init (); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes ["Base"]; } public override void Setup () @@ -22,7 +23,7 @@ public override void Setup () { X = 0, Y = 0, Text = "ScrollView (new Rectangle (3, 3, 50, 20)) with a 200, 100 ContentSize..." }; - Application.Top.Add (label); + Top.Add (label); var scrollView = new ScrollView { X = 3, Y = 3, Width = 50, Height = 20 }; scrollView.ColorScheme = Colors.ColorSchemes ["Menu"]; @@ -79,6 +80,6 @@ public override void Setup () scrollView.Add (embedded1); - Application.Top.Add (scrollView); + Top.Add (scrollView); } } diff --git a/UICatalog/Scenarios/CollectionNavigatorTester.cs b/UICatalog/Scenarios/CollectionNavigatorTester.cs index b5174e54bf..9a0ed7687e 100644 --- a/UICatalog/Scenarios/CollectionNavigatorTester.cs +++ b/UICatalog/Scenarios/CollectionNavigatorTester.cs @@ -80,7 +80,8 @@ public class CollectionNavigatorTester : Scenario public override void Init () { Application.Init (); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes ["Base"]; } public override void Setup () @@ -126,13 +127,13 @@ public override void Setup () ] }; - Application.Top.Add (menu); + Top.Add (menu); _items.Sort (StringComparer.OrdinalIgnoreCase); CreateListView (); var vsep = new LineView (Orientation.Vertical) { X = Pos.Right (_listView), Y = 1, Height = Dim.Fill () }; - Application.Top.Add (vsep); + Top.Add (vsep); CreateTreeView (); } @@ -148,7 +149,7 @@ private void CreateListView () Width = Dim.Percent (50), Height = 1 }; - Application.Top.Add (label); + Top.Add (label); _listView = new ListView { @@ -159,7 +160,7 @@ private void CreateListView () AllowsMarking = false, AllowsMultipleSelection = false }; - Application.Top.Add (_listView); + Top.Add (_listView); _listView.SetSource (_items); @@ -178,14 +179,14 @@ private void CreateTreeView () Width = Dim.Percent (50), Height = 1 }; - Application.Top.Add (label); + Top.Add (label); _treeView = new TreeView { X = Pos.Right (_listView) + 1, Y = Pos.Bottom (label), Width = Dim.Fill (), Height = Dim.Fill () }; _treeView.Style.HighlightModelTextOnly = true; - Application.Top.Add (_treeView); + Top.Add (_treeView); var root = new TreeNode ("IsLetterOrDigit examples"); diff --git a/UICatalog/Scenarios/CombiningMarks.cs b/UICatalog/Scenarios/CombiningMarks.cs index 70c135a4ac..a6ee788daa 100644 --- a/UICatalog/Scenarios/CombiningMarks.cs +++ b/UICatalog/Scenarios/CombiningMarks.cs @@ -11,12 +11,13 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; } public override void Setup () { - Application.Top.DrawContentComplete += (s, e) => + Top.DrawContentComplete += (s, e) => { Application.Driver.Move (0, 0); Application.Driver.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616."); diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs index f15fc77267..682e89a5b7 100644 --- a/UICatalog/Scenarios/ComputedLayout.cs +++ b/UICatalog/Scenarios/ComputedLayout.cs @@ -18,7 +18,8 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; } public override void Setup () @@ -37,7 +38,7 @@ public override void Setup () Text = rule }; - Application.Top.Add (horizontalRuler); + Top.Add (horizontalRuler); // Demonstrate using Dim to create a vertical ruler that always measures the parent window's height const string vrule = "|\n1\n2\n3\n4\n5\n6\n7\n8\n9\n"; @@ -53,7 +54,7 @@ public override void Setup () Text = vrule }; - Application.Top.LayoutComplete += (s, a) => + Top.LayoutComplete += (s, a) => { horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling (horizontalRuler.Bounds.Width / (double)rule.Length)) [ @@ -64,15 +65,15 @@ public override void Setup () [..(verticalRuler.Bounds.Height * 2)]; }; - Application.Top.Add (verticalRuler); + Top.Add (verticalRuler); // Demonstrate At - Using Pos.At to locate a view in an absolute location var atButton = new Button { Text = "At(2,1)", X = Pos.At (2), Y = Pos.At (1) }; - Application.Top.Add (atButton); + Top.Add (atButton); // Throw in a literal absolute - Should function identically to above var absoluteButton = new Button { Text = "X = 30, Y = 1", X = 30, Y = 1 }; - Application.Top.Add (absoluteButton); + Top.Add (absoluteButton); // Demonstrate using Dim to create a window that fills the parent with a margin var margin = 10; @@ -83,7 +84,7 @@ public override void Setup () subWin.Title = $"{subWin.GetType ().Name} {{X={subWin.X},Y={subWin.Y},Width={subWin.Width},Height={subWin.Height}}}"; }; - Application.Top.Add (subWin); + Top.Add (subWin); var i = 1; var txt = "Resize the terminal to see computed layout in action."; @@ -208,7 +209,7 @@ public override void Setup () } ); frameView.Add (labelList.ToArray ()); - Application.Top.Add (frameView); + Top.Add (frameView); frameView = new FrameView { @@ -222,7 +223,7 @@ public override void Setup () fv.Title = $"{frameView.GetType ().Name} {{X={fv.X},Y={fv.Y},Width={fv.Width},Height={fv.Height}}}"; }; - Application.Top.Add (frameView); + Top.Add (frameView); // Demonstrate Dim & Pos using percentages - a TextField that is 30% height and 80% wide var textView = new TextView @@ -236,7 +237,7 @@ public override void Setup () textView.Text = "This TextView should horizontally & vertically centered and \n10% of the screeen height, and 80% of its width."; - Application.Top.Add (textView); + Top.Add (textView); var oddballButton = new Button { @@ -244,7 +245,7 @@ public override void Setup () X = Pos.Center (), Y = Pos.Bottom (textView) + 1 }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); #region Issue2358 @@ -252,19 +253,19 @@ public override void Setup () // Until https://github.com/gui-cs/Terminal.Gui/issues/2358 is fixed these won't work right oddballButton = new Button { Text = "Center + 0", X = Pos.Center () + 0, Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); oddballButton = new Button { Text = "Center + 1", X = Pos.Center () + 1, Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); oddballButton = new Button { Text = "0 + Center", X = 0 + Pos.Center (), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); oddballButton = new Button { Text = "1 + Center", X = 1 + Pos.Center (), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); oddballButton = new Button { Text = "Center - 1", X = Pos.Center () - 1, Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); // This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50) // The `- Pos.Percent(5)` is there so at least something is visible @@ -274,7 +275,7 @@ public override void Setup () X = Pos.Center () + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); // This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50) // The `- Pos.Percent(5)` is there so at least something is visible @@ -284,7 +285,7 @@ public override void Setup () X = Pos.Percent (50) + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); // This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50) // The `- Pos.Percent(5)` is there so at least something is visible @@ -294,7 +295,7 @@ public override void Setup () X = Pos.Center () + Pos.Percent (50) - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); #endregion @@ -305,14 +306,14 @@ public override void Setup () X = Pos.Center () + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); // This demonstrates combining Percents) oddballButton = new Button { Text = "Percent(40) + Percent(10)", X = Pos.Percent (40) + Pos.Percent (10), Y = Pos.Bottom (oddballButton) }; - Application.Top.Add (oddballButton); + Top.Add (oddballButton); // Demonstrate AnchorEnd - Button is anchored to bottom/right var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd () - 1 }; @@ -322,12 +323,12 @@ public override void Setup () { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Application.Top.LayoutSubviews causes the Computed layout to + // The call to Top.LayoutSubviews causes the Computed layout to // get updated. anchorButton.Text += "!"; - Application.Top.LayoutSubviews (); + Top.LayoutSubviews (); }; - Application.Top.Add (anchorButton); + Top.Add (anchorButton); // Demonstrate AnchorEnd(n) // This is intentionally convoluted to illustrate potential bugs. @@ -341,7 +342,7 @@ public override void Setup () X = 5, Y = Pos.AnchorEnd (2) }; - Application.Top.Add (anchorEndLabel1); + Top.Add (anchorEndLabel1); // Demonstrate DimCombine (via AnchorEnd(n) - 1) // This is intentionally convoluted to illustrate potential bugs. @@ -356,7 +357,7 @@ public override void Setup () X = 5, Y = Pos.AnchorEnd (2) - 1 // Pos.Combine }; - Application.Top.Add (anchorEndLabel2); + Top.Add (anchorEndLabel2); // Show positioning vertically using Pos.AnchorEnd via Pos.Combine var leftButton = new Button @@ -368,10 +369,10 @@ public override void Setup () { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Application.Top.LayoutSubviews causes the Computed layout to + // The call to Top.LayoutSubviews causes the Computed layout to // get updated. leftButton.Text += "!"; - Application.Top.LayoutSubviews (); + Top.LayoutSubviews (); }; // show positioning vertically using Pos.AnchorEnd @@ -384,10 +385,10 @@ public override void Setup () { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Application.Top.LayoutSubviews causes the Computed layout to + // The call to Top.LayoutSubviews causes the Computed layout to // get updated. centerButton.Text += "!"; - Application.Top.LayoutSubviews (); + Top.LayoutSubviews (); }; // show positioning vertically using another window and Pos.Bottom @@ -397,18 +398,18 @@ public override void Setup () { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Application.Top.LayoutSubviews causes the Computed layout to + // The call to Top.LayoutSubviews causes the Computed layout to // get updated. rightButton.Text += "!"; - Application.Top.LayoutSubviews (); + Top.LayoutSubviews (); }; // Center three buttons with 5 spaces between them leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5; rightButton.X = Pos.Right (centerButton) + 5; - Application.Top.Add (leftButton); - Application.Top.Add (centerButton); - Application.Top.Add (rightButton); + Top.Add (leftButton); + Top.Add (centerButton); + Top.Add (rightButton); } } diff --git a/UICatalog/Scenarios/ConfigurationEditor.cs b/UICatalog/Scenarios/ConfigurationEditor.cs index 29f743f0c9..b24e35592b 100644 --- a/UICatalog/Scenarios/ConfigurationEditor.cs +++ b/UICatalog/Scenarios/ConfigurationEditor.cs @@ -36,31 +36,17 @@ public static ColorScheme EditorColorScheme } } - // Don't create a Window, just return the top-level view - public override void Init () + public override void Main () { Application.Init (); - ConfigurationManager.Themes.Theme = Theme; - ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - } - - public void Save () - { - if (_tileView.MostFocused is ConfigTextView editor) - { - editor.Save (); - } - } - public override void Setup () - { + Toplevel top = new (); _tileView = new TileView (0) { Width = Dim.Fill (), Height = Dim.Fill (1), Orientation = Orientation.Vertical, LineStyle = LineStyle.Single }; - Application.Top.Add (_tileView); + top.Add (_tileView); _lenStatusItem = new StatusItem (KeyCode.CharMask, "Len: ", null); @@ -78,9 +64,9 @@ public override void Setup () } ); - Application.Top.Add (statusBar); + top.Add (statusBar); - Application.Top.Loaded += (s, a) => Open (); + top.Loaded += (s, a) => Open (); _editorColorSchemeChanged += () => { @@ -94,6 +80,18 @@ public override void Setup () }; _editorColorSchemeChanged.Invoke (); + + Application.Run (top); + top.Dispose (); + + Application.Shutdown (); + } + public void Save () + { + if (_tileView.MostFocused is ConfigTextView editor) + { + editor.Save (); + } } private void Open () diff --git a/UICatalog/Scenarios/ContextMenus.cs b/UICatalog/Scenarios/ContextMenus.cs index 400e133f51..35ac50c640 100644 --- a/UICatalog/Scenarios/ContextMenus.cs +++ b/UICatalog/Scenarios/ContextMenus.cs @@ -78,7 +78,7 @@ public override void Setup () Win.WantMousePositionReports = true; - Application.Top.Closed += (s, e) => + Top.Closed += (s, e) => { Thread.CurrentThread.CurrentUICulture = new CultureInfo ("en-US"); Application.MouseEvent -= ApplicationMouseEvent; diff --git a/UICatalog/Scenarios/CsvEditor.cs b/UICatalog/Scenarios/CsvEditor.cs index 6adb9d20a9..4279594abd 100644 --- a/UICatalog/Scenarios/CsvEditor.cs +++ b/UICatalog/Scenarios/CsvEditor.cs @@ -101,7 +101,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -123,7 +123,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); Win.Add (_tableView); @@ -316,6 +316,7 @@ private bool GetText (string title, string label, string initialText, out string tf.SetFocus (); Application.Run (d); + d.Dispose (); enteredText = okPressed ? tf.Text : null; @@ -455,6 +456,7 @@ private void Open () { Open (ofd.Path); } + ofd.Dispose (); } private void Open (string filename) diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs index 91db58805d..fa8cacd216 100644 --- a/UICatalog/Scenarios/Dialogs.cs +++ b/UICatalog/Scenarios/Dialogs.cs @@ -155,7 +155,7 @@ void Top_LayoutComplete (object sender, EventArgs args) + frame.GetAdornmentsThickness ().Vertical; } - Application.Top.LayoutComplete += Top_LayoutComplete; + Top.LayoutComplete += Top_LayoutComplete; Win.Add (frame); @@ -192,6 +192,7 @@ void Top_LayoutComplete (object sender, EventArgs args) buttonPressedLabel ); Application.Run (dlg); + dlg.Dispose (); }; Win.Add (showDialogButton); diff --git a/UICatalog/Scenarios/DynamicMenuBar.cs b/UICatalog/Scenarios/DynamicMenuBar.cs index 84a4535329..bb5451655a 100644 --- a/UICatalog/Scenarios/DynamicMenuBar.cs +++ b/UICatalog/Scenarios/DynamicMenuBar.cs @@ -18,9 +18,11 @@ public override void Init () { Application.Init (); - Application.Top.Add ( - new DynamicMenuBarSample { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" } - ); + Top = new (); + + Top.Add ( + new DynamicMenuBarSample { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" } + ); } public class Binding @@ -417,9 +419,9 @@ public DynamicMenuItem EnterMenuItem () EditMenuBarItem (_menuItem); } - var _btnOk = new Button { IsDefault = true, Text = "Ok" }; + var btnOk = new Button { IsDefault = true, Text = "Ok" }; - _btnOk.Accept += (s, e) => + btnOk.Accept += (s, e) => { if (string.IsNullOrEmpty (TextTitle.Text)) { @@ -431,21 +433,22 @@ public DynamicMenuItem EnterMenuItem () Application.RequestStop (); } }; - var _btnCancel = new Button { Text = "Cancel" }; + var btnCancel = new Button { Text = "Cancel" }; - _btnCancel.Accept += (s, e) => + btnCancel.Accept += (s, e) => { TextTitle.Text = string.Empty; Application.RequestStop (); }; - var _dialog = new Dialog { Title = "Enter the menu details.", Buttons = [_btnOk, _btnCancel] }; + var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel] }; Width = Dim.Fill (); Height = Dim.Fill () - 1; - _dialog.Add (this); + dialog.Add (this); TextTitle.SetFocus (); TextTitle.CursorPosition = TextTitle.Text.Length; - Application.Run (_dialog); + Application.Run (dialog); + dialog.Dispose (); if (valid) { diff --git a/UICatalog/Scenarios/DynamicStatusBar.cs b/UICatalog/Scenarios/DynamicStatusBar.cs index a37c94d673..55a114d384 100644 --- a/UICatalog/Scenarios/DynamicStatusBar.cs +++ b/UICatalog/Scenarios/DynamicStatusBar.cs @@ -17,9 +17,11 @@ public override void Init () { Application.Init (); - Application.Top.Add ( - new DynamicStatusBarSample { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" } - ); + Top = new (); + + Top.Add ( + new DynamicStatusBarSample { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" } + ); } public class Binding @@ -253,9 +255,9 @@ public DynamicStatusItem EnterStatusItem () EditStatusItem (_statusItem); } - var _btnOk = new Button { IsDefault = true, Text = "OK" }; + var btnOk = new Button { IsDefault = true, Text = "OK" }; - _btnOk.Accept += (s, e) => + btnOk.Accept += (s, e) => { if (string.IsNullOrEmpty (TextTitle.Text)) { @@ -275,21 +277,22 @@ public DynamicStatusItem EnterStatusItem () Application.RequestStop (); } }; - var _btnCancel = new Button { Text = "Cancel" }; + var btnCancel = new Button { Text = "Cancel" }; - _btnCancel.Accept += (s, e) => + btnCancel.Accept += (s, e) => { TextTitle.Text = string.Empty; Application.RequestStop (); }; - var _dialog = new Dialog { Title = "Enter the menu details.", Buttons = [_btnOk, _btnCancel] }; + var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel] }; Width = Dim.Fill (); Height = Dim.Fill () - 1; - _dialog.Add (this); + dialog.Add (this); TextTitle.SetFocus (); TextTitle.CursorPosition = TextTitle.Text.Length; - Application.Run (_dialog); + Application.Run (dialog); + dialog.Dispose (); return valid ? new DynamicStatusItem diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index 01cbb7c87d..bd6b083bd6 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -42,6 +42,8 @@ public override void Init () ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); + Top = new (); + Win = new Window { Title = _fileName ?? "Untitled", @@ -51,7 +53,7 @@ public override void Init () Height = Dim.Fill (), ColorScheme = Colors.ColorSchemes [TopLevelColorScheme] }; - Application.Top.Add (Win); + Top.Add (Win); _textView = new TextView { @@ -238,7 +240,7 @@ public override void Init () ] }; - Application.Top.Add (menu); + Top.Add (menu); var siCursorPosition = new StatusItem (KeyCode.Null, "", null); @@ -268,7 +270,7 @@ public override void Init () statusBar.SetNeedsDisplay (); }; - Application.Top.Add (statusBar); + Top.Add (statusBar); _scrollBar = new ScrollBarView (_textView, true); @@ -374,7 +376,7 @@ public override void Init () } }; - Application.Top.Closed += (s, e) => Thread.CurrentThread.CurrentUICulture = new CultureInfo ("en-US"); + Top.Closed += (s, e) => Thread.CurrentThread.CurrentUICulture = new CultureInfo ("en-US"); } public override void Setup () { } @@ -1061,6 +1063,7 @@ private void Open () _fileName = d.FilePaths [0]; LoadFile (); } + d.Dispose (); } private void Paste () @@ -1259,12 +1262,16 @@ private bool SaveAs () }; var sd = new SaveDialog { Title = "Save file", AllowedTypes = aTypes }; - sd.Path = Path.Combine (sd.FileName, Win.Title); + sd.Path = Win.Title; Application.Run (sd); + bool canceled = sd.Canceled; + string path = sd.Path; + string fileName = sd.FileName; + sd.Dispose (); - if (!sd.Canceled) + if (!canceled) { - if (File.Exists (sd.Path)) + if (File.Exists (path)) { if (MessageBox.Query ( "Save File", @@ -1274,7 +1281,7 @@ private bool SaveAs () ) == 1) { - return SaveFile (sd.FileName, sd.Path); + return SaveFile (fileName, path); } _saved = false; @@ -1282,7 +1289,7 @@ private bool SaveAs () return _saved; } - return SaveFile (sd.FileName, sd.Path); + return SaveFile (fileName, path); } _saved = false; diff --git a/UICatalog/Scenarios/FileDialogExamples.cs b/UICatalog/Scenarios/FileDialogExamples.cs index 3a5f269630..65333b4fc7 100644 --- a/UICatalog/Scenarios/FileDialogExamples.cs +++ b/UICatalog/Scenarios/FileDialogExamples.cs @@ -204,7 +204,14 @@ _rgOpenMode.RadioLabels [_rgOpenMode.SelectedItem] Application.Run (fd); - if (fd.Canceled) + var canceled = fd.Canceled; + var multiSelected = fd.MultiSelected; + var path = fd.Path; + + // This needs to be disposed before opening other toplevel + fd.Dispose (); + + if (canceled) { MessageBox.Query ( "Canceled", @@ -216,7 +223,7 @@ _rgOpenMode.RadioLabels [_rgOpenMode.SelectedItem] { MessageBox.Query ( "Chosen!", - "You chose:" + Environment.NewLine + string.Join (Environment.NewLine, fd.MultiSelected.Select (m => m)), + "You chose:" + Environment.NewLine + string.Join (Environment.NewLine, multiSelected.Select (m => m)), "Ok" ); } @@ -224,7 +231,7 @@ _rgOpenMode.RadioLabels [_rgOpenMode.SelectedItem] { MessageBox.Query ( "Chosen!", - "You chose:" + Environment.NewLine + fd.Path, + "You chose:" + Environment.NewLine + path, "Ok" ); } diff --git a/UICatalog/Scenarios/Generic.cs b/UICatalog/Scenarios/Generic.cs index 1c665cf305..38e1086d7e 100644 --- a/UICatalog/Scenarios/Generic.cs +++ b/UICatalog/Scenarios/Generic.cs @@ -4,36 +4,28 @@ namespace UICatalog.Scenarios; [ScenarioMetadata ("Generic", "Generic sample - A template for creating new Scenarios")] [ScenarioCategory ("Controls")] -public class MyScenario : Scenario +public sealed class MyScenario : Scenario { - public override void Init () + public override void Main () { - // The base `Scenario.Init` implementation: - // - Calls `Application.Init ()` - // - Adds a full-screen Window to Application.Top with a title - // that reads "Press to Quit". Access this Window with `this.Win`. - // - Sets the Theme & the ColorScheme property of `this.Win` to `colorScheme`. - // To override this, implement an override of `Init`. - - //base.Init (); - - // A common, alternate, implementation where `this.Win` is not used is below. This code - // leverages ConfigurationManager to borrow the color scheme settings from UICatalog: - + // Init Application.Init (); - ConfigurationManager.Themes.Theme = Theme; - ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - } - public override void Setup () - { - // Put scenario code here (in a real app, this would be the code - // that would setup the app before `Application.Run` is called`). - // With a Scenario, after UI Catalog calls `Scenario.Setup` it calls - // `Scenario.Run` which calls `Application.Run`. Example: + // Setup - Create a top-level application window and configure it. + Window appWindow = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" + }; var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" }; - Application.Top.Add (button); + button.Accept += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "Ok"); + appWindow.Add (button); + + // Run - Start the application. + Application.Run (appWindow); + appWindow.Dispose (); + + // Shutdown - Calling Application.Shutdown is required. + Application.Shutdown (); } } diff --git a/UICatalog/Scenarios/GraphViewExample.cs b/UICatalog/Scenarios/GraphViewExample.cs index 8ca960a23a..a795079154 100644 --- a/UICatalog/Scenarios/GraphViewExample.cs +++ b/UICatalog/Scenarios/GraphViewExample.cs @@ -133,7 +133,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _graphView = new GraphView { @@ -179,7 +179,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); } private void EnableDiagnostics () diff --git a/UICatalog/Scenarios/HexEditor.cs b/UICatalog/Scenarios/HexEditor.cs index 27f444da7e..1427f61c0c 100644 --- a/UICatalog/Scenarios/HexEditor.cs +++ b/UICatalog/Scenarios/HexEditor.cs @@ -74,7 +74,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _statusBar = new StatusBar ( new [] @@ -101,7 +101,7 @@ public override void Setup () ) } ); - Application.Top.Add (_statusBar); + Top.Add (_statusBar); } private void _hexView_Edited (object sender, HexViewEditEventArgs e) { _saved = false; } @@ -203,6 +203,7 @@ private void Open () _hexView.Source = LoadFile (); _hexView.DisplayStart = 0; } + d.Dispose (); } private void Paste () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); } diff --git a/UICatalog/Scenarios/HotKeys.cs b/UICatalog/Scenarios/HotKeys.cs index 1b4a248693..8201a140fe 100644 --- a/UICatalog/Scenarios/HotKeys.cs +++ b/UICatalog/Scenarios/HotKeys.cs @@ -12,21 +12,22 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - Application.Top.BorderStyle = LineStyle.RoundedDotted; - Application.Top.Title = $"{Application.QuitKey} to _Quit - Scenario: {GetName ()}"; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top.BorderStyle = LineStyle.RoundedDotted; + Top.Title = $"{Application.QuitKey} to _Quit - Scenario: {GetName ()}"; } public override void Run () { var textViewLabel = new Label { Text = "_TextView:", X = 0, Y = 0 }; - Application.Top.Add (textViewLabel); + Top.Add (textViewLabel); var textField = new TextField (){ X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 }; - Application.Top.Add (textField); + Top.Add (textField); var viewLabel = new Label { Text = "_View:", X = 0, Y = Pos.Bottom (textField) + 1 }; - Application.Top.Add (viewLabel); + Top.Add (viewLabel); var view = new View () { Title = "View (_focusable)", @@ -35,10 +36,10 @@ public override void Run () X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (view); + Top.Add (view); viewLabel = new Label { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 }; - Application.Top.Add (viewLabel); + Top.Add (viewLabel); view = new View () { @@ -47,10 +48,10 @@ public override void Run () X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (view); + Top.Add (view); var labelWithFrameLabel = new Label { Text = "_Label with Frame:", X = 0, Y = Pos.Bottom (view) + 1 }; - Application.Top.Add (labelWithFrameLabel); + Top.Add (labelWithFrameLabel); var labelWithFrameFocusable = new Label () { @@ -60,10 +61,10 @@ public override void Run () X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (labelWithFrameFocusable); + Top.Add (labelWithFrameFocusable); labelWithFrameLabel = new Label { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 }; - Application.Top.Add (labelWithFrameLabel); + Top.Add (labelWithFrameLabel); var labelWithFrame = new Label () { @@ -72,11 +73,11 @@ public override void Run () X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (labelWithFrame); + Top.Add (labelWithFrame); var buttonWithFrameLabel = new Label { Text = "_Button with Frame:", X = 0, Y = Pos.Bottom (labelWithFrame) + 1 }; - Application.Top.Add (buttonWithFrameLabel); + Top.Add (buttonWithFrameLabel); var buttonWithFrameFocusable = new Button () { @@ -86,10 +87,10 @@ public override void Run () X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (buttonWithFrameFocusable); + Top.Add (buttonWithFrameFocusable); buttonWithFrameLabel = new Label { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 }; - Application.Top.Add (buttonWithFrameLabel); + Top.Add (buttonWithFrameLabel); var buttonWithFrame = new Button () { @@ -99,12 +100,12 @@ public override void Run () CanFocus = false, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (buttonWithFrame); + Top.Add (buttonWithFrame); var checkboxWithFrameLabel = new Label { Text = "_Checkbox with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrame) + 1 }; - Application.Top.Add (checkboxWithFrameLabel); + Top.Add (checkboxWithFrameLabel); var checkboxWithFrameFocusable = new CheckBox { @@ -114,10 +115,10 @@ public override void Run () X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (checkboxWithFrameFocusable); + Top.Add (checkboxWithFrameFocusable); checkboxWithFrameLabel = new Label { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 }; - Application.Top.Add (checkboxWithFrameLabel); + Top.Add (checkboxWithFrameLabel); var checkboxWithFrame = new CheckBox { @@ -127,12 +128,12 @@ public override void Run () CanFocus = false, BorderStyle = LineStyle.Dashed, }; - Application.Top.Add (checkboxWithFrame); + Top.Add (checkboxWithFrame); var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), Text = "_Press me!" }; - Application.Top.Add (button); + Top.Add (button); - Application.Run (Application.Top); + Application.Run (Top); } } diff --git a/UICatalog/Scenarios/Images.cs b/UICatalog/Scenarios/Images.cs index 15668c56cc..038d92255a 100644 --- a/UICatalog/Scenarios/Images.cs +++ b/UICatalog/Scenarios/Images.cs @@ -66,11 +66,14 @@ public override void Setup () if (ofd.Canceled) { + ofd.Dispose (); return; } string path = ofd.FilePaths [0]; + ofd.Dispose (); + if (string.IsNullOrWhiteSpace (path)) { return; diff --git a/UICatalog/Scenarios/InteractiveTree.cs b/UICatalog/Scenarios/InteractiveTree.cs index 4818e48367..fafc34351e 100644 --- a/UICatalog/Scenarios/InteractiveTree.cs +++ b/UICatalog/Scenarios/InteractiveTree.cs @@ -23,7 +23,7 @@ public override void Setup () new MenuBarItem ("_File", new MenuItem [] { new ("_Quit", "", Quit) }) ] }; - Application.Top.Add (menu); + Top.Add (menu); _treeView = new TreeView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill (1) }; _treeView.KeyDown += TreeView_KeyPress; @@ -55,7 +55,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); } private void AddChildNode () @@ -103,6 +103,7 @@ private bool GetText (string title, string label, string initialText, out string tf.SetFocus (); Application.Run (d); + d.Dispose (); enteredText = okPressed ? tf.Text : null; diff --git a/UICatalog/Scenarios/LineCanvasExperiment.cs b/UICatalog/Scenarios/LineCanvasExperiment.cs index 86cf4bb891..651d82f569 100644 --- a/UICatalog/Scenarios/LineCanvasExperiment.cs +++ b/UICatalog/Scenarios/LineCanvasExperiment.cs @@ -8,7 +8,11 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Proof of Concept")] public class LineCanvasExperiment : Scenario { - public override void Init () { Application.Init (); } + public override void Init () + { + Application.Init (); + Top = new (); + } /// Setup the scenario. public override void Setup () @@ -18,7 +22,7 @@ public override void Setup () // new MenuItem ("_Quit", "", () => Application.RequestStop()), //}) }); - //Application.Top.Add (menu); + //Top.Add (menu); var frame1 = new FrameView { @@ -33,7 +37,7 @@ public override void Setup () //View.Diagnostics ^= DiagnosticFlags.FrameRuler; - Application.Top.Add (frame1); + Top.Add (frame1); var win1 = new Window { diff --git a/UICatalog/Scenarios/LineViewExample.cs b/UICatalog/Scenarios/LineViewExample.cs index dd5df25c83..dc386ba947 100644 --- a/UICatalog/Scenarios/LineViewExample.cs +++ b/UICatalog/Scenarios/LineViewExample.cs @@ -22,7 +22,7 @@ public override void Setup () new MenuBarItem ("_File", new MenuItem [] { new ("_Quit", "", () => Quit ()) }) ] }; - Application.Top.Add (menu); + Top.Add (menu); Win.Add (new Label { Y = 0, Text = "Regular Line" }); @@ -82,7 +82,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); } private void Quit () { Application.RequestStop (); } diff --git a/UICatalog/Scenarios/ListColumns.cs b/UICatalog/Scenarios/ListColumns.cs index 03959fd46e..1dbe19a1dd 100644 --- a/UICatalog/Scenarios/ListColumns.cs +++ b/UICatalog/Scenarios/ListColumns.cs @@ -208,7 +208,7 @@ public override void Setup () ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -235,7 +235,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); Win.Add (_listColView); @@ -294,6 +294,7 @@ private void RunListWidthDialog (string prompt, Action setter, F tf.SetFocus (); Application.Run (d); + d.Dispose (); if (accepted) { diff --git a/UICatalog/Scenarios/Localization.cs b/UICatalog/Scenarios/Localization.cs index 444f9adfba..6669639aec 100644 --- a/UICatalog/Scenarios/Localization.cs +++ b/UICatalog/Scenarios/Localization.cs @@ -93,7 +93,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); var selectLanguageLabel = new Label { @@ -200,6 +200,7 @@ public void ShowFileDialog (bool isSaveFile) } Application.Run (dialog); + dialog.Dispose (); } public void ShowWizard () @@ -209,6 +210,7 @@ public void ShowWizard () wizard.AddStep (new WizardStep { HelpText = "Wizard step 2", NextButtonText = ">>> (_N)" }); wizard.AddStep (new WizardStep { HelpText = "Wizard last step" }); Application.Run (wizard); + wizard.Dispose (); } private void LanguageComboBox_SelectChanged (object sender, ListViewItemEventArgs e) diff --git a/UICatalog/Scenarios/MenuBarScenario.cs b/UICatalog/Scenarios/MenuBarScenario.cs index b767cda613..bab9256b89 100644 --- a/UICatalog/Scenarios/MenuBarScenario.cs +++ b/UICatalog/Scenarios/MenuBarScenario.cs @@ -199,7 +199,8 @@ public static MenuBar CreateTestMenu (Func actionFn) public override void Init () { Application.Init (); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes ["Base"]; } public override void Setup () @@ -208,34 +209,34 @@ public override void Setup () MenuItem miCurrent = null; var label = new Label { X = 0, Y = 10, Text = "Last Key: " }; - Application.Top.Add (label); + Top.Add (label); _lastKey = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" }; - Application.Top.Add (_lastKey); + Top.Add (_lastKey); label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Current MenuBarItem: " }; - Application.Top.Add (label); + Top.Add (label); _currentMenuBarItem = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" }; - Application.Top.Add (_currentMenuBarItem); + Top.Add (_currentMenuBarItem); label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Current MenuItem: " }; - Application.Top.Add (label); + Top.Add (label); _currentMenuItem = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" }; - Application.Top.Add (_currentMenuItem); + Top.Add (_currentMenuItem); label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Last Action: " }; - Application.Top.Add (label); + Top.Add (label); _lastAction = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" }; - Application.Top.Add (_lastAction); + Top.Add (_lastAction); label = new Label { X = 0, Y = Pos.Bottom (label), Text = "Focused View: " }; - Application.Top.Add (label); + Top.Add (label); _focusedView = new Label { X = Pos.Right (label), Y = Pos.Top (label), Text = "" }; - Application.Top.Add (_focusedView); + Top.Add (_focusedView); MenuBar menuBar = CreateTestMenu ( s => @@ -276,21 +277,21 @@ public override void Setup () }; // There's no focus change event, so this is a bit of a hack. - menuBar.LayoutComplete += (s, e) => { _focusedView.Text = Application.Top.MostFocused?.ToString () ?? "None"; }; + menuBar.LayoutComplete += (s, e) => { _focusedView.Text = Top.MostFocused?.ToString () ?? "None"; }; var openBtn = new Button { X = Pos.Center (), Y = 4, Text = "_Open Menu", IsDefault = true }; openBtn.Accept += (s, e) => { menuBar.OpenMenu (); }; - Application.Top.Add (openBtn); + Top.Add (openBtn); var hideBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (openBtn), Text = "Toggle Menu._Visible" }; hideBtn.Accept += (s, e) => { menuBar.Visible = !menuBar.Visible; }; - Application.Top.Add (hideBtn); + Top.Add (hideBtn); var enableBtn = new Button { X = Pos.Center (), Y = Pos.Bottom (hideBtn), Text = "_Toggle Menu.Enable" }; enableBtn.Accept += (s, e) => { menuBar.Enabled = !menuBar.Enabled; }; - Application.Top.Add (enableBtn); + Top.Add (enableBtn); - Application.Top.Add (menuBar); + Top.Add (menuBar); } private void SetCurrentMenuBarItem (MenuItem mbi) { _currentMenuBarItem.Text = mbi != null ? mbi.Title : "Closed"; } diff --git a/UICatalog/Scenarios/MessageBoxes.cs b/UICatalog/Scenarios/MessageBoxes.cs index e00228aedc..06c3533a1a 100644 --- a/UICatalog/Scenarios/MessageBoxes.cs +++ b/UICatalog/Scenarios/MessageBoxes.cs @@ -188,10 +188,10 @@ void Top_LayoutComplete (object sender, EventArgs args) + styleRadioGroup.Frame.Height + ckbWrapMessage.Frame.Height + frame.GetAdornmentsThickness ().Vertical; - Application.Top.Loaded -= Top_LayoutComplete; + Top.Loaded -= Top_LayoutComplete; } - Application.Top.LayoutComplete += Top_LayoutComplete; + Top.LayoutComplete += Top_LayoutComplete; label = new Label { diff --git a/UICatalog/Scenarios/MultiColouredTable.cs b/UICatalog/Scenarios/MultiColouredTable.cs index be152973f4..7050c06393 100644 --- a/UICatalog/Scenarios/MultiColouredTable.cs +++ b/UICatalog/Scenarios/MultiColouredTable.cs @@ -29,7 +29,7 @@ public override void Setup () new MenuBarItem ("_File", new MenuItem [] { new ("_Quit", "", () => Quit ()) }) ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -41,7 +41,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); Win.Add (_tableView); @@ -117,6 +117,7 @@ private bool GetText (string title, string label, string initialText, out string tf.SetFocus (); Application.Run (d); + d.Dispose (); enteredText = okPressed ? tf.Text : null; diff --git a/UICatalog/Scenarios/Notepad.cs b/UICatalog/Scenarios/Notepad.cs index 85aa23f304..4980d20c87 100644 --- a/UICatalog/Scenarios/Notepad.cs +++ b/UICatalog/Scenarios/Notepad.cs @@ -12,14 +12,92 @@ public class Notepad : Scenario { private TabView _focusedTabView; private StatusItem _lenStatusItem; - private int _numbeOfNewTabs = 1; + private int _numNewTabs = 1; private TabView _tabView; - // Don't create a Window, just return the top-level view - public override void Init () + public override void Main () { Application.Init (); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + + Toplevel top = new (); + + var menu = new MenuBar + { + Menus = + [ + new ( + "_File", + new MenuItem [] + { + new ( + "_New", + "", + () => New (), + null, + null, + KeyCode.N + | KeyCode.CtrlMask + | KeyCode.AltMask + ), + new ("_Open", "", () => Open ()), + new ("_Save", "", () => Save ()), + new ("Save _As", "", () => SaveAs ()), + new ("_Close", "", () => Close ()), + new ("_Quit", "", () => Quit ()) + } + ), + new ( + "_About", + "", + () => MessageBox.Query ("Notepad", "About Notepad...", "Ok") + ) + ] + }; + top.Add (menu); + + _tabView = CreateNewTabView (); + + _tabView.Style.ShowBorder = true; + _tabView.ApplyStyleChanges (); + + // Start with only a single view but support splitting to show side by side + var split = new TileView (1) { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) }; + split.Tiles.ElementAt (0).ContentView.Add (_tabView); + split.LineStyle = LineStyle.None; + + top.Add (split); + + _lenStatusItem = new (KeyCode.CharMask, "Len: ", null); + + var statusBar = new StatusBar ( + new [] + { + new ( + Application.QuitKey, + $"{Application.QuitKey} to Quit", + () => Quit () + ), + + // These shortcut keys don't seem to work correctly in linux + //new StatusItem(Key.CtrlMask | Key.N, "~^O~ Open", () => Open()), + //new StatusItem(Key.CtrlMask | Key.N, "~^N~ New", () => New()), + + new (KeyCode.CtrlMask | KeyCode.S, "~^S~ Save", () => Save ()), + new (KeyCode.CtrlMask | KeyCode.W, "~^W~ Close", () => Close ()), + _lenStatusItem + } + ); + _focusedTabView = _tabView; + _tabView.SelectedTabChanged += TabView_SelectedTabChanged; + _tabView.Enter += (s, e) => _focusedTabView = _tabView; + + top.Add (statusBar); + top.Ready += (s, e) => New (); + + Application.Run (top); + top.Dispose (); + + Application.Shutdown (); } public void Save () { Save (_focusedTabView, _focusedTabView.SelectedTab); } @@ -56,95 +134,25 @@ public bool SaveAs () if (string.IsNullOrWhiteSpace (fd.Path)) { + fd.Dispose (); + return false; } if (fd.Canceled) { + fd.Dispose (); + return false; } - tab.File = new FileInfo (fd.Path); + tab.File = new (fd.Path); tab.Text = fd.FileName; tab.Save (); - return true; - } + fd.Dispose (); - public override void Setup () - { - var menu = new MenuBar - { - Menus = - [ - new MenuBarItem ( - "_File", - new MenuItem [] - { - new ( - "_New", - "", - () => New (), - null, - null, - KeyCode.N - | KeyCode.CtrlMask - | KeyCode.AltMask - ), - new ("_Open", "", () => Open ()), - new ("_Save", "", () => Save ()), - new ("Save _As", "", () => SaveAs ()), - new ("_Close", "", () => Close ()), - new ("_Quit", "", () => Quit ()) - } - ), - new MenuBarItem ( - "_About", - "", - () => MessageBox.Query ("Notepad", "About Notepad...", "Ok") - ) - ] - }; - Application.Top.Add (menu); - - _tabView = CreateNewTabView (); - - _tabView.Style.ShowBorder = true; - _tabView.ApplyStyleChanges (); - - // Start with only a single view but support splitting to show side by side - var split = new TileView (1) { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) }; - split.Tiles.ElementAt (0).ContentView.Add (_tabView); - split.LineStyle = LineStyle.None; - - Application.Top.Add (split); - - _lenStatusItem = new StatusItem (KeyCode.CharMask, "Len: ", null); - - var statusBar = new StatusBar ( - new [] - { - new ( - Application.QuitKey, - $"{Application.QuitKey} to Quit", - () => Quit () - ), - - // These shortcut keys don't seem to work correctly in linux - //new StatusItem(Key.CtrlMask | Key.N, "~^O~ Open", () => Open()), - //new StatusItem(Key.CtrlMask | Key.N, "~^N~ New", () => New()), - - new (KeyCode.CtrlMask | KeyCode.S, "~^S~ Save", () => Save ()), - new (KeyCode.CtrlMask | KeyCode.W, "~^W~ Close", () => Close ()), - _lenStatusItem - } - ); - _focusedTabView = _tabView; - _tabView.SelectedTabChanged += TabView_SelectedTabChanged; - _tabView.Enter += (s, e) => _focusedTabView = _tabView; - - Application.Top.Add (statusBar); - Application.Top.Ready += (s, e) => New (); + return true; } private void Close () { Close (_focusedTabView, _focusedTabView.SelectedTab); } @@ -240,7 +248,7 @@ private TabView CreateNewTabView () return tv; } - private void New () { Open (null, $"new {_numbeOfNewTabs++}"); } + private void New () { Open (null, $"new {_numNewTabs++}"); } private void Open () { @@ -248,19 +256,23 @@ private void Open () Application.Run (open); - if (!open.Canceled) + bool canceled = open.Canceled; + + if (!canceled) { foreach (string path in open.FilePaths) { if (string.IsNullOrEmpty (path) || !File.Exists (path)) { - return; + break; } // TODO should open in focused TabView - Open (new FileInfo (path), Path.GetFileName (path)); + Open (new (path), Path.GetFileName (path)); } } + + open.Dispose (); } /// Creates a new tab with initial text @@ -327,27 +339,27 @@ private void TabView_TabClicked (object sender, TabMouseEventArgs e) if (e.Tab == null) { - items = new MenuBarItem ( - new MenuItem [] { new ("Open", "", () => Open ()) } - ); + items = new ( + new MenuItem [] { new ("Open", "", () => Open ()) } + ); } else { var tv = (TabView)sender; var t = (OpenedFile)e.Tab; - items = new MenuBarItem ( - new MenuItem [] - { - new ("Save", "", () => Save (_focusedTabView, e.Tab)), - new ("Close", "", () => Close (tv, e.Tab)), - null, - new ("Split Up", "", () => SplitUp (tv, t)), - new ("Split Down", "", () => SplitDown (tv, t)), - new ("Split Right", "", () => SplitRight (tv, t)), - new ("Split Left", "", () => SplitLeft (tv, t)) - } - ); + items = new ( + new MenuItem [] + { + new ("Save", "", () => Save (_focusedTabView, e.Tab)), + new ("Close", "", () => Close (tv, e.Tab)), + null, + new ("Split Up", "", () => SplitUp (tv, t)), + new ("Split Down", "", () => SplitDown (tv, t)), + new ("Split Right", "", () => SplitRight (tv, t)), + new ("Split Left", "", () => SplitLeft (tv, t)) + } + ); } Rectangle screen = ((View)sender).BoundsToScreen (new (e.MouseEvent.X, e.MouseEvent.Y, 0, 0)); @@ -360,14 +372,6 @@ private void TabView_TabClicked (object sender, TabMouseEventArgs e) private class OpenedFile : Tab { - public FileInfo File { get; set; } - - /// The text of the tab the last time it was saved - /// - public string SavedText { get; set; } - - public bool UnsavedChanges => !string.Equals (SavedText, View.Text); - public OpenedFile CloneTo (TabView other) { var newTab = new OpenedFile { DisplayText = base.Text, File = File }; @@ -399,6 +403,8 @@ public View CreateTextView (FileInfo file) }; } + public FileInfo File { get; set; } + public void RegisterTextViewEvents (TabView parent) { var textView = (TextView)View; @@ -428,6 +434,12 @@ public void RegisterTextViewEvents (TabView parent) }; } + /// The text of the tab the last time it was saved + /// + public string SavedText { get; set; } + + public bool UnsavedChanges => !string.Equals (SavedText, View.Text); + internal void Save () { string newText = View.Text; diff --git a/UICatalog/Scenarios/ProgressBarStyles.cs b/UICatalog/Scenarios/ProgressBarStyles.cs index 44b2875b1b..61fee87ae7 100644 --- a/UICatalog/Scenarios/ProgressBarStyles.cs +++ b/UICatalog/Scenarios/ProgressBarStyles.cs @@ -27,6 +27,8 @@ public override void Init () ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); + Top = new (); + var editor = new AdornmentsEditor { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", BorderStyle = LineStyle.Single @@ -72,12 +74,13 @@ ColorName ChooseColor (string text, ColorName colorName) dialog.Bounds = new Rectangle (0, 0, colorPicker.Frame.Width, colorPicker.Frame.Height); - Application.Top.LayoutSubviews (); + Top.LayoutSubviews (); }; dialog.Add (colorPicker); colorPicker.ColorChanged += (s, e) => { dialog.RequestStop (); }; Application.Run (dialog); + dialog.Dispose (); ColorName retColor = colorPicker.SelectedColor; colorPicker.Dispose (); @@ -274,7 +277,7 @@ ColorName ChooseColor (string text, ColorName colorName) 300 ); - Application.Top.Unloaded += Top_Unloaded; + Top.Unloaded += Top_Unloaded; void Top_Unloaded (object sender, EventArgs args) { @@ -290,10 +293,11 @@ void Top_Unloaded (object sender, EventArgs args) _pulseTimer = null; } - Application.Top.Unloaded -= Top_Unloaded; + Top.Unloaded -= Top_Unloaded; } Application.Run (editor); + editor.Dispose (); Application.Shutdown (); } diff --git a/UICatalog/Scenarios/RunTExample.cs b/UICatalog/Scenarios/RunTExample.cs index 7f06294553..ce82b18632 100644 --- a/UICatalog/Scenarios/RunTExample.cs +++ b/UICatalog/Scenarios/RunTExample.cs @@ -6,13 +6,16 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Top Level Windows")] public class RunTExample : Scenario { - public override void Run () { Application.Run (); } - - public override void Setup () + public override void Init () { // No need to call Init if Application.Run is used + Application.Run (); + + Application.Top.Dispose (); } + public override void Run () { } + public class ExampleWindow : Window { private readonly TextField _usernameText; diff --git a/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs b/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs index 65d7b1416d..217d8838ef 100644 --- a/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs +++ b/UICatalog/Scenarios/RuneWidthGreaterThanOne.cs @@ -21,6 +21,8 @@ public override void Init () { Application.Init (); + Top = new (); + var menu = new MenuBar { Menus = @@ -85,13 +87,13 @@ public override void Init () }; _win = new Window { X = 5, Y = 5, Width = Dim.Fill (22), Height = Dim.Fill (5) }; _win.Add (_label, _text, _button, _labelR, _labelV); - Application.Top.Add (menu, _win); + Top.Add (menu, _win); WideRunes (); //NarrowRunes (); //MixedRunes (); - Application.Run (); + Application.Run (Top); } public override void Run () { } diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index dd07728035..33c15e8660 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -78,10 +78,10 @@ void Top_Loaded (object sender, EventArgs args) verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling (verticalRuler.Bounds.Height * 2 / (double)rule.Length)) [..(verticalRuler.Bounds.Height * 2)]; - Application.Top.Loaded -= Top_Loaded; + Top.Loaded -= Top_Loaded; } - Application.Top.Loaded += Top_Loaded; + Top.Loaded += Top_Loaded; var pressMeButton = new Button { X = 3, Y = 3, Text = "Press me!" }; pressMeButton.Accept += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No"); @@ -270,9 +270,9 @@ bool timer () void Top_Unloaded (object sender, EventArgs args) { pulsing = false; - Application.Top.Unloaded -= Top_Unloaded; + Top.Unloaded -= Top_Unloaded; } - Application.Top.Unloaded += Top_Unloaded; + Top.Unloaded += Top_Unloaded; } } diff --git a/UICatalog/Scenarios/SingleBackgroundWorker.cs b/UICatalog/Scenarios/SingleBackgroundWorker.cs index 0174e48622..82e9802f9f 100644 --- a/UICatalog/Scenarios/SingleBackgroundWorker.cs +++ b/UICatalog/Scenarios/SingleBackgroundWorker.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Threading; using Terminal.Gui; @@ -11,15 +12,15 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Top Level Windows")] public class SingleBackgroundWorker : Scenario { - public override void Run () + public override void Init () { - Application.Top.Dispose (); - Application.Run (); Application.Top.Dispose (); } + public override void Run () { } + public class MainApp : Toplevel { private readonly ListView _listLog; @@ -77,9 +78,9 @@ public MainApp () ); Add (statusBar); - var top = new Toplevel (); + var workerLogTop = new Toplevel () { Title = "Worker Log Top"}; - top.Add ( + workerLogTop.Add ( new Label { X = Pos.Center (), Y = 0, Text = "Worker Log" } ); @@ -91,8 +92,9 @@ public MainApp () Height = Dim.Fill (), Source = new ListWrapper (_log) }; - top.Add (_listLog); - Add (top); + workerLogTop.Add (_listLog); + Add (workerLogTop); + Title = "MainApp"; } private void RunWorker () @@ -193,24 +195,32 @@ private void RunWorker () var builderUI = new StagingUIController (_startStaging, e.Result as List); + var top = Application.Top; + top.Visible = false; + Application.Current.Visible = false; builderUI.Load (); + builderUI.Dispose (); + top.Visible = true; } _worker = null; }; _worker.RunWorkerAsync (); Application.Run (md); + md.Dispose (); } } public class StagingUIController : Window { - private readonly Toplevel _top; + private Toplevel _top; public StagingUIController (DateTime? start, List list) { - Rectangle frame = Application.Top.Frame; - _top = new Toplevel { X = frame.X, Y = frame.Y, Width = frame.Width, Height = frame.Height }; + _top = new Toplevel + { + Title = "_top", Width = Dim.Fill (), Height = Dim.Fill () + }; _top.KeyDown += (s, e) => { @@ -299,6 +309,18 @@ bool Close () _top.Add (this); } - public void Load () { Application.Run (_top); } + public void Load () { + Application.Run (_top); + _top.Dispose (); + _top = null; + } + + ///// + //protected override void Dispose (bool disposing) + //{ + // _top?.Dispose (); + // _top = null; + // base.Dispose (disposing); + //} } } diff --git a/UICatalog/Scenarios/Sliders.cs b/UICatalog/Scenarios/Sliders.cs index 88b45d88c7..5811582a08 100644 --- a/UICatalog/Scenarios/Sliders.cs +++ b/UICatalog/Scenarios/Sliders.cs @@ -477,6 +477,6 @@ public override void Setup () #endregion Config Slider Win.FocusFirst (); - Application.Top.Initialized += (s, e) => Application.Top.LayoutSubviews (); + Top.Initialized += (s, e) => Top.LayoutSubviews (); } } diff --git a/UICatalog/Scenarios/SpinnerStyles.cs b/UICatalog/Scenarios/SpinnerStyles.cs index 5f824c7e8a..7dad78f9e7 100644 --- a/UICatalog/Scenarios/SpinnerStyles.cs +++ b/UICatalog/Scenarios/SpinnerStyles.cs @@ -159,7 +159,7 @@ public override void Setup () ckbBounce.Toggled += (s, e) => { spinner.SpinBounce = (bool)!e.OldValue; }; - Application.Top.Unloaded += Top_Unloaded; + Top.Unloaded += Top_Unloaded; void SetCustom () { @@ -200,7 +200,7 @@ void Top_Unloaded (object sender, EventArgs args) spinner = null; } - Application.Top.Unloaded -= Top_Unloaded; + Top.Unloaded -= Top_Unloaded; } } diff --git a/UICatalog/Scenarios/SyntaxHighlighting.cs b/UICatalog/Scenarios/SyntaxHighlighting.cs index a438b154e6..2aa49d4b2b 100644 --- a/UICatalog/Scenarios/SyntaxHighlighting.cs +++ b/UICatalog/Scenarios/SyntaxHighlighting.cs @@ -164,7 +164,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _textView = new TextView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; @@ -183,7 +183,7 @@ public override void Setup () } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); } /// diff --git a/UICatalog/Scenarios/TabViewExample.cs b/UICatalog/Scenarios/TabViewExample.cs index 5fb78d692a..838619b29d 100644 --- a/UICatalog/Scenarios/TabViewExample.cs +++ b/UICatalog/Scenarios/TabViewExample.cs @@ -67,7 +67,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _tabView = new TabView { @@ -181,7 +181,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); } private void AddBlankTab () { _tabView.AddTab (new Tab (), false); } diff --git a/UICatalog/Scenarios/TableEditor.cs b/UICatalog/Scenarios/TableEditor.cs index 56614a71bf..cebac284ca 100644 --- a/UICatalog/Scenarios/TableEditor.cs +++ b/UICatalog/Scenarios/TableEditor.cs @@ -669,7 +669,7 @@ public override void Setup () ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -696,7 +696,7 @@ public override void Setup () ) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); Win.Add (_tableView); @@ -886,6 +886,7 @@ private void EditCurrentCell (object sender, CellActivatedEventArgs e) tf.SetFocus (); Application.Run (d); + d.Dispose (); if (okPressed) { @@ -1085,6 +1086,7 @@ Func getter tf.SetFocus (); Application.Run (d); + d.Dispose (); if (accepted) { diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs index 7babd0de57..629e567764 100644 --- a/UICatalog/Scenarios/TextFormatterDemo.cs +++ b/UICatalog/Scenarios/TextFormatterDemo.cs @@ -57,7 +57,7 @@ public override void Setup () X = 0, Y = Pos.Bottom (blockText) + 1, Text = "Unicode", - Checked = Application.Top.HotKeySpecifier == (Rune)' ' + Checked = Top.HotKeySpecifier == (Rune)' ' }; Win.Add (unicodeCheckBox); diff --git a/UICatalog/Scenarios/TextViewAutocompletePopup.cs b/UICatalog/Scenarios/TextViewAutocompletePopup.cs index e43890216d..8dbbdddf87 100644 --- a/UICatalog/Scenarios/TextViewAutocompletePopup.cs +++ b/UICatalog/Scenarios/TextViewAutocompletePopup.cs @@ -51,7 +51,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _textViewTopLeft = new TextView { Width = width, Height = _height, Text = text }; _textViewTopLeft.DrawContent += TextViewTopLeft_DrawContent; @@ -105,7 +105,7 @@ public override void Setup () _siWrap = new StatusItem (KeyCode.Null, "", null) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); Win.LayoutStarted += Win_LayoutStarted; } diff --git a/UICatalog/Scenarios/Threading.cs b/UICatalog/Scenarios/Threading.cs index a6d162dfc6..14dcb60894 100644 --- a/UICatalog/Scenarios/Threading.cs +++ b/UICatalog/Scenarios/Threading.cs @@ -118,10 +118,10 @@ public override void Setup () void Top_Loaded (object sender, EventArgs args) { _btnActionCancel.SetFocus (); - Application.Top.Loaded -= Top_Loaded; + Top.Loaded -= Top_Loaded; } - Application.Top.Loaded += Top_Loaded; + Top.Loaded += Top_Loaded; } private async void CallLoadItemsAsync () diff --git a/UICatalog/Scenarios/TileViewNesting.cs b/UICatalog/Scenarios/TileViewNesting.cs index f793d1e4b5..f35aea0d69 100644 --- a/UICatalog/Scenarios/TileViewNesting.cs +++ b/UICatalog/Scenarios/TileViewNesting.cs @@ -62,7 +62,7 @@ public override void Setup () SetupTileView (); - Application.Top.Add (menu); + Top.Add (menu); Win.Loaded += (s, e) => _loaded = true; } diff --git a/UICatalog/Scenarios/TreeUseCases.cs b/UICatalog/Scenarios/TreeUseCases.cs index d83d791a56..f306d1a91e 100644 --- a/UICatalog/Scenarios/TreeUseCases.cs +++ b/UICatalog/Scenarios/TreeUseCases.cs @@ -47,7 +47,7 @@ public override void Setup () ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -60,7 +60,7 @@ public override void Setup () } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); // Start with the most basic use case LoadSimpleNodes (); diff --git a/UICatalog/Scenarios/TreeViewFileSystem.cs b/UICatalog/Scenarios/TreeViewFileSystem.cs index 0ec589ea7c..c16758a09e 100644 --- a/UICatalog/Scenarios/TreeViewFileSystem.cs +++ b/UICatalog/Scenarios/TreeViewFileSystem.cs @@ -172,7 +172,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); _treeViewFiles = new TreeView { X = 0, Y = 0, Width = Dim.Percent (50), Height = Dim.Fill () }; _treeViewFiles.DrawLine += TreeViewFiles_DrawLine; diff --git a/UICatalog/Scenarios/Unicode.cs b/UICatalog/Scenarios/Unicode.cs index b73bc33254..00c139638c 100644 --- a/UICatalog/Scenarios/Unicode.cs +++ b/UICatalog/Scenarios/Unicode.cs @@ -60,7 +60,7 @@ public override void Setup () ) ] }; - Application.Top.Add (menu); + Top.Add (menu); var statusBar = new StatusBar ( new StatusItem [] @@ -74,7 +74,7 @@ public override void Setup () new (KeyCode.Null, "~F3~ Со_хранить", null) } ); - Application.Top.Add (statusBar); + Top.Add (statusBar); var label = new Label { X = 0, Y = 1, Text = "Label:" }; Win.Add (label); diff --git a/UICatalog/Scenarios/ViewExperiments.cs b/UICatalog/Scenarios/ViewExperiments.cs index f1303e0bfe..b8f25bb3e0 100644 --- a/UICatalog/Scenarios/ViewExperiments.cs +++ b/UICatalog/Scenarios/ViewExperiments.cs @@ -14,7 +14,8 @@ public override void Init () Application.Init (); ConfigurationManager.Themes.Theme = Theme; ConfigurationManager.Apply (); - Application.Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; + Top = new (); + Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; } public override void Setup () @@ -27,7 +28,7 @@ public override void Setup () Width = Dim.Fill (), Height = 3 }; - Application.Top.Add (containerLabel); + Top.Add (containerLabel); var view = new View { @@ -40,7 +41,7 @@ public override void Setup () Id = "DaView" }; - //Application.Top.Add (view); + //Top.Add (view); view.Margin.Thickness = new Thickness (2, 2, 2, 2); view.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"]; @@ -216,9 +217,9 @@ public override void Setup () { containerLabel.Text = $"Container.Frame: { - Application.Top.Frame + Top.Frame } .Bounds: { - Application.Top.Bounds + Top.Bounds }\nView.Frame: { view.Frame } .Bounds: { @@ -243,11 +244,11 @@ public override void Setup () ViewToEdit = view }; - Application.Top.Add (editor); + Top.Add (editor); view.X = 36; view.Y = 4; view.Width = Dim.Fill (); view.Height = Dim.Fill (); - Application.Top.Add (view); + Top.Add (view); } } diff --git a/UICatalog/Scenarios/WindowsAndFrameViews.cs b/UICatalog/Scenarios/WindowsAndFrameViews.cs index 2fd42d7abf..ba6fec117d 100644 --- a/UICatalog/Scenarios/WindowsAndFrameViews.cs +++ b/UICatalog/Scenarios/WindowsAndFrameViews.cs @@ -27,7 +27,7 @@ static int About () List listWin = new (); //Ignore the Win that UI Catalog created and create a new one - Application.Top.Remove (Win); + Top.Remove (Win); Win?.Dispose (); Win = new Window @@ -61,7 +61,7 @@ static int About () Text = "Press ME! (Y = Pos.AnchorEnd(1))" } ); - Application.Top.Add (Win); + Top.Add (Win); // add it to our list listWin.Add (Win); @@ -130,7 +130,7 @@ static int About () ); win.Add (frameView); - Application.Top.Add (win); + Top.Add (win); listWin.Add (win); } @@ -212,9 +212,9 @@ static int About () frame.Add (subFrameViewofFV); - Application.Top.Add (frame); + Top.Add (frame); listWin.Add (frame); - Application.Top.ColorScheme = Colors.ColorSchemes ["Base"]; + Top.ColorScheme = Colors.ColorSchemes ["Base"]; } } diff --git a/UICatalog/Scenarios/WizardAsView.cs b/UICatalog/Scenarios/WizardAsView.cs index e828416d4d..817cccd3bc 100644 --- a/UICatalog/Scenarios/WizardAsView.cs +++ b/UICatalog/Scenarios/WizardAsView.cs @@ -52,7 +52,8 @@ public override void Init () ) ] }; - Application.Top.Add (menu); + Top = new (); + Top.Add (menu); // No need for a Title because the border is disabled var wizard = new Wizard { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; @@ -138,8 +139,8 @@ public override void Init () lastStep.HelpText = "The wizard is complete!\n\nPress the Finish button to continue.\n\nPressing Esc will cancel."; - Application.Top.Add (wizard); - Application.Run (Application.Top); + Top.Add (wizard); + Application.Run (Top); } public override void Run () diff --git a/UICatalog/Scenarios/Wizards.cs b/UICatalog/Scenarios/Wizards.cs index 167d0f87bb..304b9ad0c0 100644 --- a/UICatalog/Scenarios/Wizards.cs +++ b/UICatalog/Scenarios/Wizards.cs @@ -81,10 +81,10 @@ public override void Setup () void Top_Loaded (object sender, EventArgs args) { frame.Height = widthEdit.Frame.Height + heightEdit.Frame.Height + titleEdit.Frame.Height + 2; - Application.Top.Loaded -= Top_Loaded; + Top.Loaded -= Top_Loaded; } - Application.Top.Loaded += Top_Loaded; + Top.Loaded += Top_Loaded; label = new Label { @@ -349,6 +349,7 @@ void Top_Loaded (object sender, EventArgs args) }; Application.Run (wizard); + wizard.Dispose (); } catch (FormatException) { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 6cb319346b..ecccd74f32 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -199,7 +199,7 @@ private static Scenario RunUICatalogTopLevel () Apply (); } - Application.Run (); + Application.Run ().Dispose (); Application.Shutdown (); return _selectedScenario!; @@ -290,11 +290,10 @@ private static void UICatalogMain (Options options) Application.Init (driverName: _forceDriver); _selectedScenario.Theme = _cachedTheme; _selectedScenario.TopLevelColorScheme = _topLevelColorScheme; - _selectedScenario.Init (); - _selectedScenario.Setup (); - _selectedScenario.Run (); + _selectedScenario.Main (); _selectedScenario.Dispose (); _selectedScenario = null; + // TODO: Throw if shutdown was not called already Application.Shutdown (); VerifyObjectsWereDisposed (); @@ -322,13 +321,12 @@ private static void UICatalogMain (Options options) Apply (); scenario.Theme = _cachedTheme; scenario.TopLevelColorScheme = _topLevelColorScheme; - scenario.Init (); - scenario.Setup (); - scenario.Run (); + scenario.Main (); scenario.Dispose (); // This call to Application.Shutdown brackets the Application.Init call // made by Scenario.Init() above + // TODO: Throw if shutdown was not called already Application.Shutdown (); VerifyObjectsWereDisposed (); @@ -464,10 +462,6 @@ public UICatalogTopLevel () _selectedScenario = null; RequestStop (); } - else - { - _selectedScenario.RequestStop (); - } } ), new ( @@ -992,6 +986,7 @@ private MenuItem [] CreateKeyBindingsMenuItems () { var dlg = new KeyBindingsDialog (); Application.Run (dlg); + dlg.Dispose (); }; menuItems.Add (null!); @@ -1069,6 +1064,7 @@ private void UnloadedHandler (object? sender, EventArgs? args) { Applied -= ConfigAppliedHandler; Unloaded -= UnloadedHandler; + Dispose (); } } diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 9105fe7bb8..2dbad7cccf 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -39,36 +39,39 @@ public void Begin_Null_Toplevel_Throws () [AutoInitShutdown] public void Begin_Sets_Application_Top_To_Console_Size () { - Assert.Equal (new Rectangle (0, 0, 80, 25), Application.Top.Frame); - Application.Begin (Application.Top); + Assert.Null (Application.Top); + Application.Begin (new ()); Assert.Equal (new Rectangle (0, 0, 80, 25), Application.Top.Frame); ((FakeDriver)Application.Driver).SetBufferSize (5, 5); Assert.Equal (new Rectangle (0, 0, 5, 5), Application.Top.Frame); } [Fact] - public void End_Should_Not_Dispose_ApplicationTop_Shutdown_Should () + public void End_And_Shutdown_Should_Not_Dispose_ApplicationTop () { Init (); - RunState rs = Application.Begin (Application.Top); + RunState rs = Application.Begin (new ()); + Assert.Equal (rs.Toplevel, Application.Top); Application.End (rs); #if DEBUG_IDISPOSABLE Assert.True (rs.WasDisposed); - Assert.False (Application.Top.WasDisposed); + Assert.False (Application.Top.WasDisposed); // Is true because the rs.Toplevel is the same as Application.Top #endif Assert.Null (rs.Toplevel); var top = Application.Top; - Shutdown (); - #if DEBUG_IDISPOSABLE + var exception = Record.Exception (() => Shutdown ()); + Assert.NotNull (exception); + Assert.False (top.WasDisposed); + top.Dispose (); Assert.True (top.WasDisposed); #endif - + Shutdown (); Assert.Null (Application.Top); } @@ -107,6 +110,7 @@ public void Init_Begin_End_Cleans_Up () Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); + topLevel.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -126,6 +130,7 @@ public void Init_DriverName_Should_Pick_Correct_Driver (Type driverType) var driver = (ConsoleDriver)Activator.CreateInstance (driverType); Application.Init (driverName: driverType.Name); Assert.NotNull (Application.Driver); + Assert.NotEqual(driver, Application.Driver); Assert.Equal (driverType, Application.Driver.GetType ()); Shutdown (); } @@ -264,7 +269,6 @@ public void Init_Unbalanced_Throws () Assert.Throws ( () => Application.InternalInit ( - () => topLevel = new TestToplevel (), new FakeDriver () ) ); @@ -276,7 +280,7 @@ public void Init_Unbalanced_Throws () // 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 (); @@ -287,7 +291,7 @@ public void Init_Unbalanced_Throws () } [Fact] - public void InitWithTopLevelFactory_Begin_End_Cleans_Up () + public void InitWithoutTopLevelFactory_Begin_End_Cleans_Up () { // Begin will cause Run() to be called, which will call Begin(). Thus will block the tests // if we don't stop @@ -295,8 +299,8 @@ public void InitWithTopLevelFactory_Begin_End_Cleans_Up () // 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 ()); + Toplevel topLevel = new (); + Application.InternalInit (new FakeDriver ()); RunState runstate = null; @@ -323,6 +327,7 @@ public void InitWithTopLevelFactory_Begin_End_Cleans_Up () Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); + topLevel.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -335,8 +340,8 @@ public void InitWithTopLevelFactory_Begin_End_Cleans_Up () public void Internal_Properties_Correct () { Assert.True (Application._initialized); - Assert.NotNull (Application.Top); - RunState rs = Application.Begin (Application.Top); + Assert.Null (Application.Top); + RunState rs = Application.Begin (new ()); Assert.Equal (Application.Top, rs.Toplevel); Assert.Null (Application.MouseGrabView); // public Assert.Null (Application.WantContinuousButtonPressedView); // public @@ -358,6 +363,7 @@ public void Invoke_Adds_Idle () Application.MainLoop.Running = true; Application.RunIteration (ref rs, ref firstIteration); Assert.Equal (1, actionCalled); + top.Dispose (); Application.Shutdown (); } @@ -365,6 +371,8 @@ public void Invoke_Adds_Idle () [AutoInitShutdown] public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top () { + var top = new Toplevel (); + var t1 = new Toplevel (); var t2 = new Toplevel (); var t3 = new Toplevel (); @@ -456,6 +464,13 @@ public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Applica Application.Run (t1); Assert.Equal (t1, Application.Top); + // top wasn't run and so never was added to toplevel's stack + Assert.NotEqual (top, Application.Top); +#if DEBUG_IDISPOSABLE + Assert.False (Application.Top.WasDisposed); + t1.Dispose (); + Assert.True (Application.Top.WasDisposed); +#endif } private void Init () @@ -497,14 +512,19 @@ private class TestToplevel : Toplevel [Fact] - public void Run_T_After_InitWithDriver_with_TopLevel_Throws () + public void Run_T_After_InitWithDriver_with_TopLevel_Does_Not_Throws () { // Setup Mock driver Init (); - // Run when already initialized with a Driver will throw (because Toplevel is not derived from TopLevel) - Assert.Throws (() => Application.Run ()); + Application.Iteration += (s, e) => Application.RequestStop (); + // Run when already initialized or not with a Driver will not throw (because Window is derived from Toplevel) + // Using another type not derived from Toplevel will throws at compile time + Application.Run (); + Assert.True (Application.Top is Window); + + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -514,14 +534,24 @@ public void Run_T_After_InitWithDriver_with_TopLevel_Throws () [Fact] - public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Throws () + public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Does_Not_Throws () { // Setup Mock driver Init (); - // Run when already initialized with a Driver will throw (because Toplevel is not derivied from TopLevel) - Assert.Throws (() => Application.Run (null, new FakeDriver ())); + Application.Iteration += (s, e) => Application.RequestStop (); + + // Run when already initialized or not with a Driver will not throw (because Window is derived from Toplevel) + // Using another type not derived from Toplevel will throws at compile time + Application.Run (null, new FakeDriver ()); + Assert.True (Application.Top is Window); + Application.Top.Dispose (); + // Run when already initialized or not with a Driver will not throw (because Dialog is derived from Toplevel) + Application.Run (null, new FakeDriver ()); + Assert.True (Application.Top is Dialog); + + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -532,18 +562,19 @@ public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Throws () [Fact] [TestRespondersDisposed] - public void Run_T_After_Init_Disposes_Application_Top () + public void Run_T_After_Init_Does_Not_Disposes_Application_Top () { Init (); - // Init created a Toplevel and assigned it to Application.Top - var initTop = Application.Top; + // Init doesn't create a Toplevel and assigned it to Application.Top + // but Begin does + var initTop = new Toplevel (); Application.Iteration += (s, a) => { Assert.NotEqual(initTop, Application.Top); #if DEBUG_IDISPOSABLE - Assert.True (initTop.WasDisposed); + Assert.False (initTop.WasDisposed); #endif Application.RequestStop (); }; @@ -551,9 +582,11 @@ public void Run_T_After_Init_Disposes_Application_Top () Application.Run (); #if DEBUG_IDISPOSABLE + Assert.False (initTop.WasDisposed); + initTop.Dispose (); Assert.True (initTop.WasDisposed); #endif - + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -574,6 +607,7 @@ public void Run_T_After_InitWithDriver_with_TestTopLevel_DoesNotThrow () // Init has been called and we're passing no driver to Run. This is ok. Application.Run (); + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -596,6 +630,7 @@ public void Run_T_After_InitNullDriver_with_TestTopLevel_DoesNotThrow () // Init has been called, selecting FakeDriver; we're passing no driver to Run. Should be fine. Application.Run (); + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -612,8 +647,6 @@ public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws () Application.Driver = null; - Application.Iteration += (s, a) => { Application.RequestStop (); }; - // Init has been called, but Driver has been set to null. Bad. Assert.Throws (() => Application.Run ()); @@ -635,6 +668,7 @@ public void Run_T_NoInit_DoesNotThrow () Application.Run (); Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ()); + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -652,6 +686,7 @@ public void Run_T_NoInit_WithDriver_DoesNotThrow () // Init has NOT been called and we're passing a valid driver to Run. This is ok. Application.Run (null, new FakeDriver ()); + Application.Top.Dispose (); Shutdown (); Assert.Null (Application.Top); @@ -676,6 +711,7 @@ public void Run_RequestStop_Stops () Application.Run (top); + top.Dispose (); Application.Shutdown (); Assert.Null (Application.Current); Assert.Null (Application.Top); @@ -700,6 +736,7 @@ public void Run_RunningFalse_Stops () Application.Run (top); + top.Dispose (); Application.Shutdown (); Assert.Null (Application.Current); Assert.Null (Application.Top); @@ -713,13 +750,14 @@ public void Run_RunningFalse_Stops () public void Run_Loaded_Ready_Unlodaded_Events () { Init (); - Toplevel top = Application.Top; + Toplevel top = new (); var count = 0; top.Loaded += (s, e) => count++; top.Ready += (s, e) => count++; top.Unloaded += (s, e) => count++; Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (top); + top.Dispose (); Application.Shutdown (); Assert.Equal (3, count); } @@ -733,7 +771,7 @@ public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty () // Don't use Dialog here as it has more layout logic. Use Window instead. Dialog d = null; - Toplevel top = Application.Top; + Toplevel top = new (); top.DrawContent += (s, a) => count++; int iteration = -1; @@ -768,7 +806,8 @@ public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty () Application.RequestStop (); } }; - Application.Run (); + Application.Run (top); + top.Dispose (); Application.Shutdown (); // 1 - First top load, 1 - Dialog load, 1 - Dialog unload, Total - 3. @@ -873,9 +912,145 @@ Colors.ColorSchemes ["Base"].Normal ); Application.End (rs); + w.Dispose (); Application.Shutdown (); } + [Fact] + public void End_Does_Not_Dispose () + { + Init (); + + var top = new Toplevel (); + + Window w = new (); + w.Ready += (s, e) => Application.RequestStop (); // Causes `End` to be called + Application.Run(w); + +#if DEBUG_IDISPOSABLE + Assert.False (w.WasDisposed); +#endif + + Assert.NotNull (w); + Assert.Equal (string.Empty, w.Title); // Valid - w has not been disposed. The user may want to run it again + Assert.NotNull (Application.Top); + Assert.Equal(w, Application.Top); + Assert.NotEqual(top, Application.Top); + Assert.Null (Application.Current); + + Application.Run(w); // Valid - w has not been disposed. + +#if DEBUG_IDISPOSABLE + Assert.False (w.WasDisposed); + var exception = Record.Exception (() => Application.Shutdown()); // Invalid - w has not been disposed. + Assert.NotNull (exception); + + w.Dispose (); + Assert.True (w.WasDisposed); + exception = Record.Exception (() => Application.Run (w)); // Invalid - w has been disposed. Run it in debug mode will throw, otherwise the user may want to run it again + Assert.NotNull (exception); + + exception = Record.Exception (() => Assert.Equal (string.Empty, w.Title)); // Invalid - w has been disposed and cannot be accessed + Assert.NotNull (exception); + exception = Record.Exception (() => w.Title = "NewTitle"); // Invalid - w has been disposed and cannot be accessed + Assert.NotNull (exception); +#endif + Application.Shutdown (); + Assert.NotNull (w); + Assert.Null (Application.Current); + Assert.NotNull (top); + Assert.Null (Application.Top); + } + + [Fact] + public void Run_Creates_Top_Without_Init () + { + var driver = new FakeDriver (); + + Assert.Null (Application.Top); + + Application.Iteration += (s, e) => + { + Assert.NotNull (Application.Top); + Application.RequestStop (); + }; + var top = Application.Run (null, driver); +#if DEBUG_IDISPOSABLE + Assert.Equal(top, Application.Top); + Assert.False (top.WasDisposed); + var exception = Record.Exception (() => Application.Shutdown ()); + Assert.NotNull (exception); + Assert.False (top.WasDisposed); +#endif + + // It's up to caller to dispose it + top.Dispose (); + +#if DEBUG_IDISPOSABLE + Assert.True (top.WasDisposed); +#endif + 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); +#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 (); + 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 (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 (); + Assert.Null (Application.Top); + } + // TODO: Add tests for Run that test errorHandler #endregion diff --git a/UnitTests/Application/KeyboardTests.cs b/UnitTests/Application/KeyboardTests.cs index d40f3f87a2..2a0f6cba0b 100644 --- a/UnitTests/Application/KeyboardTests.cs +++ b/UnitTests/Application/KeyboardTests.cs @@ -20,7 +20,7 @@ public void AlternateForwardKey_AlternateBackwardKey_Tests () { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var w1 = new Window (); var v1 = new TextField (); var v2 = new TextView (); @@ -110,6 +110,7 @@ public void AlternateForwardKey_AlternateBackwardKey_Tests () Assert.Equal (KeyCode.PageUp | KeyCode.CtrlMask, Application.AlternateBackwardKey.KeyCode); Assert.Equal (KeyCode.Q | KeyCode.CtrlMask, Application.QuitKey.KeyCode); + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -118,7 +119,7 @@ public void AlternateForwardKey_AlternateBackwardKey_Tests () [AutoInitShutdown] public void EnsuresTopOnFront_CanFocus_False_By_Keyboard () { - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window { @@ -149,35 +150,35 @@ public void EnsuresTopOnFront_CanFocus_False_By_Keyboard () Assert.True (win.HasFocus); Assert.True (win2.CanFocus); Assert.False (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); win.CanFocus = false; Assert.False (win.CanFocus); Assert.False (win.HasFocus); Assert.True (win2.CanFocus); Assert.True (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); top.NewKeyDownEvent (Key.Tab.WithCtrl); Assert.True (win2.CanFocus); Assert.False (win.HasFocus); Assert.True (win2.CanFocus); Assert.True (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); top.NewKeyDownEvent (Key.Tab.WithCtrl); Assert.False (win.CanFocus); Assert.False (win.HasFocus); Assert.True (win2.CanFocus); Assert.True (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); } [Fact] [AutoInitShutdown] public void EnsuresTopOnFront_CanFocus_True_By_Keyboard_ () { - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window { @@ -208,21 +209,21 @@ public void EnsuresTopOnFront_CanFocus_True_By_Keyboard_ () Assert.True (win.HasFocus); Assert.True (win2.CanFocus); Assert.False (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); top.NewKeyDownEvent (Key.Tab.WithCtrl); Assert.True (win.CanFocus); Assert.False (win.HasFocus); Assert.True (win2.CanFocus); Assert.True (win2.HasFocus); - Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title); top.NewKeyDownEvent (Key.Tab.WithCtrl); Assert.True (win.CanFocus); Assert.True (win.HasFocus); Assert.True (win2.CanFocus); Assert.False (win2.HasFocus); - Assert.Equal ("win", ((Window)top.Subviews [top.Subviews.Count - 1]).Title); + Assert.Equal ("win", ((Window)top.Subviews [^1]).Title); } [Fact] @@ -281,18 +282,19 @@ public void KeyUp_Event () var keyUps = 0; var output = string.Empty; + var top = new Toplevel (); - Application.Top.KeyUp += (sender, args) => - { - if (args.KeyCode != (KeyCode.CtrlMask | KeyCode.Q)) - { - output += args.AsRune; - } + top.KeyUp += (sender, args) => + { + if (args.KeyCode != (KeyCode.CtrlMask | KeyCode.Q)) + { + output += args.AsRune; + } - keyUps++; - }; + keyUps++; + }; - Application.Run (Application.Top); + Application.Run (top); // Input string should match output Assert.Equal (input, output); @@ -306,6 +308,7 @@ public void KeyUp_Event () // # of key up events should match # of iterations Assert.Equal (stackSize, iterations); + top.Dispose (); Application.Shutdown (); Assert.Null (Application.Current); Assert.Null (Application.Top); @@ -321,8 +324,9 @@ public void OnKeyDown_Application_KeyBinding () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnKeyDown (Key.A); Assert.True (invoked); @@ -364,8 +368,9 @@ public void OnKeyDown_Application_KeyBinding_Negative () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnKeyDown (Key.A.WithCtrl); Assert.False (invoked); @@ -386,7 +391,7 @@ public void OnKeyDown_Application_KeyBinding_Negative () [AutoInitShutdown] public void QuitKey_Getter_Setter () { - Toplevel top = Application.Top; + Toplevel top = new (); var isQuiting = false; top.Closing += (s, e) => diff --git a/UnitTests/Application/MainLoopTests.cs b/UnitTests/Application/MainLoopTests.cs index 043927478a..0b4b63f851 100644 --- a/UnitTests/Application/MainLoopTests.cs +++ b/UnitTests/Application/MainLoopTests.cs @@ -625,7 +625,8 @@ public async Task InvokeLeakTest () { Random r = new (); TextField tf = new (); - Application.Top.Add (tf); + var top = new Toplevel (); + top.Add (tf); const int numPasses = 5; const int numIncrements = 500; @@ -634,7 +635,7 @@ public async Task InvokeLeakTest () Task task = Task.Run (() => RunTest (r, tf, numPasses, numIncrements, pollMs)); // blocks here until the RequestStop is processed at the end of the test - Application.Run (); + Application.Run (top); await task; // Propagate exception if any occurred @@ -672,7 +673,8 @@ int pfour btnLaunch.Accept += (s, e) => action (); - Application.Top.Add (btnLaunch); + var top = new Toplevel (); + top.Add (btnLaunch); int iterations = -1; @@ -711,7 +713,7 @@ int pfour } }; - Application.Run (); + Application.Run (top); Assert.True (taskCompleted); Assert.Equal (clickMe, btn.Text); diff --git a/UnitTests/Application/MouseTests.cs b/UnitTests/Application/MouseTests.cs index 5c85641b01..d6b4cecca8 100644 --- a/UnitTests/Application/MouseTests.cs +++ b/UnitTests/Application/MouseTests.cs @@ -114,8 +114,6 @@ bool expectedClicked Width = size.Width, Height = size.Height }; - view.BeginInit(); - view.EndInit(); var mouseEvent = new MouseEvent { X = clickX, Y = clickY, Flags = MouseFlags.Button1Clicked }; var mouseEventArgs = new MouseEventEventArgs (mouseEvent); @@ -127,7 +125,10 @@ bool expectedClicked clicked = true; }; - Application.Top.Add (view); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); + Application.OnMouseEvent (mouseEventArgs); Assert.Equal (expectedClicked, clicked); } @@ -198,11 +199,12 @@ bool expectedClicked var clicked = false; - Application.Top.X = 0; - Application.Top.Y = 0; - Application.Top.Width = size.Width * 2; - Application.Top.Height = size.Height * 2; - Application.Top.BorderStyle = LineStyle.None; + var top = new Toplevel (); + top.X = 0; + top.Y = 0; + top.Width = size.Width * 2; + top.Height = size.Height * 2; + top.BorderStyle = LineStyle.None; var view = new View { X = pos.X, Y = pos.Y, Width = size.Width, Height = size.Height }; @@ -210,8 +212,8 @@ bool expectedClicked view.BorderStyle = LineStyle.Single; view.CanFocus = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + top.Add (view); + Application.Begin (top); var mouseEvent = new MouseEvent { X = clickX, Y = clickY, Flags = MouseFlags.Button1Clicked }; var mouseEventArgs = new MouseEventEventArgs (mouseEvent); @@ -238,7 +240,8 @@ public void MouseGrabView_WithNullMouseEventView () var sv = new ScrollView { Width = Dim.Fill (), Height = Dim.Fill (), ContentSize = new (100, 100) }; sv.Add (tf); - Application.Top.Add (sv); + var top = new Toplevel (); + top.Add (sv); int iterations = -1; @@ -306,7 +309,7 @@ public void MouseGrabView_WithNullMouseEventView () } }; - Application.Run (); + Application.Run (top); } [Fact] diff --git a/UnitTests/Application/RunStateTests.cs b/UnitTests/Application/RunStateTests.cs index 39ec7d8134..0e02101c5b 100644 --- a/UnitTests/Application/RunStateTests.cs +++ b/UnitTests/Application/RunStateTests.cs @@ -33,6 +33,7 @@ public void Begin_End_Cleans_Up_RunState () Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); + top.Dispose (); Shutdown (); #if DEBUG_IDISPOSABLE diff --git a/UnitTests/Application/SynchronizatonContextTests.cs b/UnitTests/Application/SynchronizatonContextTests.cs index b370c91f38..3e76355803 100644 --- a/UnitTests/Application/SynchronizatonContextTests.cs +++ b/UnitTests/Application/SynchronizatonContextTests.cs @@ -46,7 +46,7 @@ public void SynchronizationContext_Post () ); // blocks here until the RequestStop is processed at the end of the test - Application.Run (); + Application.Run ().Dispose (); Assert.True (success); } @@ -79,7 +79,7 @@ public void SynchronizationContext_Send () ); // blocks here until the RequestStop is processed at the end of the test - Application.Run (); + Application.Run ().Dispose (); Assert.True (success); } } diff --git a/UnitTests/Configuration/ConfigurationMangerTests.cs b/UnitTests/Configuration/ConfigurationMangerTests.cs index 94f17eb7ec..c238ad5fbf 100644 --- a/UnitTests/Configuration/ConfigurationMangerTests.cs +++ b/UnitTests/Configuration/ConfigurationMangerTests.cs @@ -816,9 +816,9 @@ public void TestConfigurationManagerUpdateFromJson () } [Fact] - public void UseWithoutResetAsserts () + public void UseWithoutResetDoesNotThrow () { Initialize (); - Assert.Throws (() => _ = Settings); + _ = Settings; } } diff --git a/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs index d08d3a9697..ad2d19dc60 100644 --- a/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs +++ b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs @@ -49,7 +49,7 @@ public void FakeDriver_MockKeyPresses (Type driverType) Console.MockKeyPresses = mKeys; - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { CanFocus = true }; var rText = ""; var idx = 0; @@ -72,10 +72,11 @@ public void FakeDriver_MockKeyPresses (Type driverType) } }; - Application.Run (); + Application.Run (top); Assert.Equal ("MockKeyPresses", rText); + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -87,7 +88,7 @@ public void FakeDriver_Only_Sends_Keystrokes_Through_MockKeyPresses (Type driver var driver = (ConsoleDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { CanFocus = true }; var count = 0; var wasKeyPressed = false; @@ -105,10 +106,11 @@ public void FakeDriver_Only_Sends_Keystrokes_Through_MockKeyPresses (Type driver } }; - Application.Run (); + Application.Run (top); Assert.False (wasKeyPressed); + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } diff --git a/UnitTests/Dialogs/DialogTests.cs b/UnitTests/Dialogs/DialogTests.cs index 2008b16ce0..6c7eb754a1 100644 --- a/UnitTests/Dialogs/DialogTests.cs +++ b/UnitTests/Dialogs/DialogTests.cs @@ -49,6 +49,7 @@ public void Add_Button_Works () RunIteration (ref runstate, ref first); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify dlg = new Dialog @@ -73,6 +74,7 @@ public void Add_Button_Works () RunIteration (ref runstate, ref first); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right dlg = new Dialog @@ -97,6 +99,7 @@ public void Add_Button_Works () RunIteration (ref runstate, ref first); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left dlg = new Dialog @@ -121,6 +124,7 @@ public void Add_Button_Works () RunIteration (ref runstate, ref first); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -148,7 +152,7 @@ public void ButtonAlignment_Four () d.SetBufferSize (buttonRow.Length, 3); // Default - Center - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -159,54 +163,58 @@ public void ButtonAlignment_Four () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( - title, - width, - Dialog.ButtonAlignments.Justify, - new Button { Text = btn1Text }, - new Button { Text = btn2Text }, - new Button { Text = btn3Text }, - new Button { Text = btn4Text } - ); + (runstate, dlg) = RunButtonTestDialog ( + title, + width, + Dialog.ButtonAlignments.Justify, + new Button { Text = btn1Text }, + new Button { Text = btn2Text }, + new Button { Text = btn3Text }, + new Button { Text = btn4Text } + ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( - title, - width, - Dialog.ButtonAlignments.Right, - new Button { Text = btn1Text }, - new Button { Text = btn2Text }, - new Button { Text = btn3Text }, - new Button { Text = btn4Text } - ); + (runstate, dlg) = RunButtonTestDialog ( + title, + width, + Dialog.ButtonAlignments.Right, + new Button { Text = btn1Text }, + new Button { Text = btn2Text }, + new Button { Text = btn3Text }, + new Button { Text = btn4Text } + ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( - title, - width, - Dialog.ButtonAlignments.Left, - new Button { Text = btn1Text }, - new Button { Text = btn2Text }, - new Button { Text = btn3Text }, - new Button { Text = btn4Text } - ); + (runstate, dlg) = RunButtonTestDialog ( + title, + width, + Dialog.ButtonAlignments.Left, + new Button { Text = btn1Text }, + new Button { Text = btn2Text }, + new Button { Text = btn3Text }, + new Button { Text = btn4Text } + ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -249,6 +257,7 @@ public void ButtonAlignment_Four_On_Too_Small_Width () Assert.Equal (new (width, 1), dlg.Frame.Size); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = @@ -268,7 +277,7 @@ public void ButtonAlignment_Four_On_Too_Small_Width () CM.Glyphs.VLine }"; - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -279,11 +288,12 @@ public void ButtonAlignment_Four_On_Too_Small_Width () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine}{CM.Glyphs.RightBracket} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -294,11 +304,12 @@ public void ButtonAlignment_Four_On_Too_Small_Width () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {CM.Glyphs.LeftBracket} n{CM.Glyphs.VLine}"; - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -309,6 +320,7 @@ public void ButtonAlignment_Four_On_Too_Small_Width () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -338,7 +350,7 @@ public void ButtonAlignment_Four_WideOdd () d.SetBufferSize (buttonRow.Length, 1); // Default - Center - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -349,12 +361,13 @@ public void ButtonAlignment_Four_WideOdd () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -365,12 +378,13 @@ public void ButtonAlignment_Four_WideOdd () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -381,12 +395,13 @@ public void ButtonAlignment_Four_WideOdd () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -397,6 +412,7 @@ public void ButtonAlignment_Four_WideOdd () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -428,7 +444,7 @@ public void ButtonAlignment_Four_Wider () d.SetBufferSize (width, 3); // Default - Center - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -439,12 +455,13 @@ public void ButtonAlignment_Four_Wider () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.GetColumns ()); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -455,12 +472,13 @@ public void ButtonAlignment_Four_Wider () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.GetColumns ()); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -471,12 +489,13 @@ public void ButtonAlignment_Four_Wider () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.GetColumns ()); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -487,6 +506,7 @@ public void ButtonAlignment_Four_Wider () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -507,7 +527,7 @@ public void ButtonAlignment_One () d.SetBufferSize (width, 1); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -517,13 +537,14 @@ public void ButtonAlignment_One () // Center TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -531,13 +552,14 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -545,13 +567,14 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -559,6 +582,7 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Wider buttonRow = @@ -567,7 +591,7 @@ public void ButtonAlignment_One () d.SetBufferSize (width, 1); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -575,13 +599,14 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -589,13 +614,14 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -603,13 +629,14 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -617,6 +644,7 @@ public void ButtonAlignment_One () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -642,7 +670,7 @@ public void ButtonAlignment_Three () d.SetBufferSize (buttonRow.Length, 3); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -652,12 +680,13 @@ public void ButtonAlignment_Three () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $@"{CM.Glyphs.VLine}{btn1} {btn2} {btn3}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -667,12 +696,13 @@ public void ButtonAlignment_Three () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $@"{CM.Glyphs.VLine} {btn1} {btn2} {btn3}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -682,12 +712,13 @@ public void ButtonAlignment_Three () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $@"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -697,6 +728,7 @@ public void ButtonAlignment_Three () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -720,7 +752,7 @@ public void ButtonAlignment_Two () d.SetBufferSize (buttonRow.Length, 3); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, Dialog dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Center, @@ -729,12 +761,13 @@ public void ButtonAlignment_Two () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify buttonRow = $@"{CM.Glyphs.VLine}{btn1} {btn2}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Justify, @@ -743,12 +776,13 @@ public void ButtonAlignment_Two () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right buttonRow = $@"{CM.Glyphs.VLine} {btn1} {btn2}{CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Right, @@ -757,12 +791,13 @@ public void ButtonAlignment_Two () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left buttonRow = $@"{CM.Glyphs.VLine}{btn1} {btn2} {CM.Glyphs.VLine}"; Assert.Equal (width, buttonRow.Length); - (runstate, Dialog _) = RunButtonTestDialog ( + (runstate, dlg) = RunButtonTestDialog ( title, width, Dialog.ButtonAlignments.Left, @@ -771,6 +806,7 @@ public void ButtonAlignment_Two () ); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -807,6 +843,7 @@ public void ButtonAlignment_Two_Hidden () buttonRow = $@"{CM.Glyphs.VLine} {btn2} {CM.Glyphs.VLine}"; TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Justify Assert.Equal (width, buttonRow.Length); @@ -818,6 +855,7 @@ public void ButtonAlignment_Two_Hidden () buttonRow = $@"{CM.Glyphs.VLine} {btn2}{CM.Glyphs.VLine}"; TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Right Assert.Equal (width, buttonRow.Length); @@ -828,6 +866,7 @@ public void ButtonAlignment_Two_Hidden () RunIteration (ref runstate, ref firstIteration); TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); // Left Assert.Equal (width, buttonRow.Length); @@ -839,6 +878,7 @@ public void ButtonAlignment_Two_Hidden () buttonRow = $@"{CM.Glyphs.VLine} {btn2} {CM.Glyphs.VLine}"; TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output); End (runstate); + dlg.Dispose (); } [Fact] @@ -1086,7 +1126,7 @@ public void Dialog_Opened_From_Another_Dialog () } }; - Run (); + Run ().Dispose (); Shutdown (); Assert.Equal (4, iterations); @@ -1101,6 +1141,7 @@ public void FileDialog_FileSystemWatcher () var fd = new FileDialog (); fd.Ready += (s, e) => RequestStop (); Run (fd); + fd.Dispose (); } } @@ -1157,7 +1198,8 @@ public void Location_When_Application_Top_Not_Default () [AutoInitShutdown] public void Location_When_Not_Application_Top_Not_Default () { - Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; int iterations = -1; @@ -1168,7 +1210,7 @@ public void Location_When_Not_Application_Top_Not_Default () if (iterations == 0) { var d = new Dialog { X = 5, Y = 5, Height = 3, Width = 5 }; - Begin (d); + var rs = Begin (d); Assert.Equal (new Point (5, 5), (Point)d.Frame.Location); @@ -1186,9 +1228,11 @@ public void Location_When_Not_Application_Top_Not_Default () ╚══════════════════╝", _output ); + End (rs); + d.Dispose (); d = new Dialog { X = 5, Y = 5 }; - Begin (d); + rs = Begin (d); // This is because of PostionTopLevels and EnsureVisibleBounds Assert.Equal (new (3, 2), d.Frame.Location); @@ -1224,6 +1268,8 @@ public void Location_When_Not_Application_Top_Not_Default () ╚══════════════════╝", _output ); + End (rs); + d.Dispose (); } else if (iterations > 0) { @@ -1231,9 +1277,8 @@ public void Location_When_Not_Application_Top_Not_Default () } }; - Begin (Top); ((FakeDriver)Driver).SetBufferSize (20, 10); - Run (); + Run (top); } [Fact] @@ -1331,4 +1376,104 @@ params Button [] btns return (Begin (dlg), dlg); } + + [Fact] + [AutoInitShutdown] + public void Run_Does_Not_Dispose_Dialog () + { + var top = new Toplevel (); + + Dialog dlg = new (); + + dlg.Ready += Dlg_Ready; + + Run (dlg); + +#if DEBUG_IDISPOSABLE + Assert.False (dlg.WasDisposed); + Assert.False (Top.WasDisposed); + Assert.NotEqual (top, Top); + Assert.Equal (dlg, Top); +#endif + + // dlg wasn't disposed yet and it's possible to access to his properties + Assert.False (dlg.Canceled); + Assert.NotNull (dlg); + + dlg.Canceled = true; + Assert.True (dlg.Canceled); + + dlg.Dispose (); + top.Dispose (); +#if DEBUG_IDISPOSABLE + Assert.True (dlg.WasDisposed); + Assert.True (Top.WasDisposed); + Assert.NotNull (Top); +#endif + Shutdown(); + Assert.Null (Top); + + return; + + void Dlg_Ready (object sender, EventArgs e) + { + RequestStop (); + } + } + + [Fact] + [AutoInitShutdown] + public void Can_Access_Cancel_Property_After_Run () + { + Dialog dlg = new (); + + dlg.Ready += Dlg_Ready; + + Run (dlg); + +#if DEBUG_IDISPOSABLE + Assert.False (dlg.WasDisposed); + Assert.False (Top.WasDisposed); + Assert.Equal (dlg, Top); +#endif + + Assert.True (dlg.Canceled); + + // Run it again is possible because it isn't disposed yet + Run (dlg); + + // Run another view without dispose the prior will throw an assertion +#if DEBUG_IDISPOSABLE + Dialog dlg2 = new (); + dlg2.Ready += Dlg_Ready; + var exception = Record.Exception (() => Run (dlg2)); + Assert.NotNull (exception); + + dlg.Dispose(); + // Now it's possible to tun dlg2 without throw + Run (dlg2); + + Assert.True (dlg.WasDisposed); + Assert.False (Top.WasDisposed); + Assert.Equal (dlg2, Top); + Assert.False (dlg2.WasDisposed); + + dlg2.Dispose (); + // Now an assertion will throw accessing the Canceled property + exception = Record.Exception (() => Assert.True (dlg.Canceled)); + Assert.NotNull (exception); + Assert.True (Top.WasDisposed); + Shutdown (); + Assert.True (dlg2.WasDisposed); + Assert.Null (Top); +#endif + + return; + + void Dlg_Ready (object sender, EventArgs e) + { + ((Dialog)sender).Canceled = true; + RequestStop (); + } + } } diff --git a/UnitTests/Dialogs/MessageBoxTests.cs b/UnitTests/Dialogs/MessageBoxTests.cs index dceb0e3e61..eed1530532 100644 --- a/UnitTests/Dialogs/MessageBoxTests.cs +++ b/UnitTests/Dialogs/MessageBoxTests.cs @@ -12,8 +12,6 @@ public class MessageBoxTests [AutoInitShutdown] public void KeyBindings_Enter_Causes_Focused_Button_Click () { - Application.Begin (Application.Top); - int result = -1; var iteration = 0; @@ -43,7 +41,7 @@ public void KeyBindings_Enter_Causes_Focused_Button_Click () break; } }; - Application.Run (); + Application.Run ().Dispose (); Assert.Equal (1, result); } @@ -52,8 +50,6 @@ public void KeyBindings_Enter_Causes_Focused_Button_Click () [AutoInitShutdown] public void KeyBindings_Esc_Closes () { - Application.Begin (Application.Top); - var result = 999; var iteration = 0; @@ -81,7 +77,7 @@ public void KeyBindings_Esc_Closes () break; } }; - Application.Run (); + Application.Run ().Dispose (); Assert.Equal (-1, result); } @@ -90,8 +86,6 @@ public void KeyBindings_Esc_Closes () [AutoInitShutdown] public void KeyBindings_Space_Causes_Focused_Button_Click () { - Application.Begin (Application.Top); - int result = -1; var iteration = 0; @@ -121,7 +115,7 @@ public void KeyBindings_Space_Causes_Focused_Button_Click () break; } }; - Application.Run (); + Application.Run ().Dispose (); Assert.Equal (1, result); } @@ -131,7 +125,6 @@ public void KeyBindings_Space_Causes_Focused_Button_Click () public void Location_Default () { int iterations = -1; - Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (100, 100); Application.Iteration += (s, a) => @@ -159,7 +152,7 @@ public void Location_Default () } }; - Application.Run (); + Application.Run ().Dispose (); } [Theory] @@ -179,7 +172,6 @@ int linesLength ) { int iterations = -1; - Application.Begin (Application.Top); Application.Iteration += (s, a) => { @@ -241,7 +233,7 @@ int linesLength } }; - Application.Run (); + Application.Run ().Dispose (); } [Fact] @@ -249,8 +241,8 @@ int linesLength public void Message_Long_Without_Spaces_WrapMessage_True () { int iterations = -1; - Application.Begin (Application.Top); - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var btn = @@ -325,7 +317,7 @@ public void Message_Long_Without_Spaces_WrapMessage_True () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -333,8 +325,8 @@ public void Message_Long_Without_Spaces_WrapMessage_True () public void Message_With_Spaces_WrapMessage_False () { int iterations = -1; - Application.Begin (Application.Top); - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var btn = @@ -410,7 +402,7 @@ ff ff ff ff ff ff ff } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -418,8 +410,8 @@ ff ff ff ff ff ff ff public void Message_With_Spaces_WrapMessage_True () { int iterations = -1; - Application.Begin (Application.Top); - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel(); + top.BorderStyle = LineStyle.Double; ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var btn = @@ -499,7 +491,7 @@ public void Message_With_Spaces_WrapMessage_True () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -507,8 +499,8 @@ public void Message_With_Spaces_WrapMessage_True () public void Message_Without_Spaces_WrapMessage_False () { int iterations = -1; - Application.Begin (Application.Top); - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel(); + top.BorderStyle = LineStyle.Double; ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var btn = @@ -579,7 +571,7 @@ public void Message_Without_Spaces_WrapMessage_False () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -587,7 +579,6 @@ public void Message_Without_Spaces_WrapMessage_False () public void Size_Default () { int iterations = -1; - Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (100, 100); Application.Iteration += (s, a) => @@ -613,7 +604,7 @@ public void Size_Default () } }; - Application.Run (); + Application.Run ().Dispose (); } [Fact] @@ -621,7 +612,6 @@ public void Size_Default () public void Size_JustBigEnough_Fixed_Size () { int iterations = -1; - Application.Begin (Application.Top); var btn = $"{ @@ -665,16 +655,16 @@ public void Size_JustBigEnough_Fixed_Size () } }; - Application.Run (); + Application.Run ().Dispose (); } [Fact] [AutoInitShutdown] public void Size_No_With_Button () { - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; int iterations = -1; - Application.Begin (Application.Top); var aboutMessage = new StringBuilder (); aboutMessage.AppendLine (@"0123456789012345678901234567890123456789"); @@ -728,7 +718,7 @@ public void Size_No_With_Button () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -736,7 +726,6 @@ public void Size_No_With_Button () public void Size_None_No_Buttons () { int iterations = -1; - Application.Begin (Application.Top); Application.Iteration += (s, a) => { @@ -767,7 +756,7 @@ public void Size_None_No_Buttons () } }; - Application.Run (); + Application.Run ().Dispose (); } [Theory] @@ -783,7 +772,6 @@ public void Size_None_No_Buttons () public void Size_Not_Default_Message (int height, int width, string message) { int iterations = -1; - Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (100, 100); Application.Iteration += (s, a) => @@ -821,7 +809,6 @@ public void Size_Not_Default_Message (int height, int width, string message) public void Size_Not_Default_Message_Button (int height, int width, string message) { int iterations = -1; - Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (100, 100); Application.Iteration += (s, a) => @@ -855,7 +842,6 @@ public void Size_Not_Default_Message_Button (int height, int width, string messa public void Size_Not_Default_No_Message (int height, int width) { int iterations = -1; - Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (100, 100); Application.Iteration += (s, a) => @@ -885,7 +871,6 @@ public void Size_Not_Default_No_Message (int height, int width) public void Size_Tiny_Fixed_Size () { int iterations = -1; - Application.Begin (Application.Top); Application.Iteration += (s, a) => { @@ -920,6 +905,6 @@ public void Size_Tiny_Fixed_Size () } }; - Application.Run (); + Application.Run ().Dispose (); } } diff --git a/UnitTests/Drawing/LineCanvasTests.cs b/UnitTests/Drawing/LineCanvasTests.cs index c2fb7c39ee..3d2ad403f3 100644 --- a/UnitTests/Drawing/LineCanvasTests.cs +++ b/UnitTests/Drawing/LineCanvasTests.cs @@ -1305,8 +1305,9 @@ public void Zero_Length_Intersections () private View GetCanvas (out LineCanvas canvas, int offsetX = 0, int offsetY = 0) { var v = new View { Width = 10, Height = 5, Bounds = new Rectangle (0, 0, 10, 5) }; - Application.Top.Add (v); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (v); + Application.Begin (top); LineCanvas canvasCopy = canvas = new LineCanvas (); diff --git a/UnitTests/Drawing/RulerTests.cs b/UnitTests/Drawing/RulerTests.cs index 2af387527d..6e6e9b50c1 100644 --- a/UnitTests/Drawing/RulerTests.cs +++ b/UnitTests/Drawing/RulerTests.cs @@ -48,8 +48,9 @@ public void Draw_Horizontal () // Add a frame so we can see the ruler var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (f); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (f); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (len + 5, 5); Assert.Equal (new Rectangle (0, 0, len + 5, 5), f.Frame); @@ -120,8 +121,9 @@ public void Draw_Horizontal_Start () // Add a frame so we can see the ruler var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (f); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (f); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (len + 5, 5); Assert.Equal (new Rectangle (0, 0, len + 5, 5), f.Frame); @@ -165,8 +167,9 @@ public void Draw_Vertical () // Add a frame so we can see the ruler var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (f); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (f); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (5, len + 5); Assert.Equal (new Rectangle (0, 0, 5, len + 5), f.Frame); @@ -297,8 +300,9 @@ public void Draw_Vertical_Start () // Add a frame so we can see the ruler var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (f); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (f); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (5, len + 5); Assert.Equal (new Rectangle (0, 0, 5, len + 5), f.Frame); diff --git a/UnitTests/Drawing/ThicknessTests.cs b/UnitTests/Drawing/ThicknessTests.cs index d05ef09440..a6cf839ef6 100644 --- a/UnitTests/Drawing/ThicknessTests.cs +++ b/UnitTests/Drawing/ThicknessTests.cs @@ -177,8 +177,9 @@ public void DrawTests_Ruler () // Add a frame so we can see the ruler var f = new FrameView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (f); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (f); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (45, 20); var t = new Thickness (0, 0, 0, 0); diff --git a/UnitTests/Input/EscSeqUtilsTests.cs b/UnitTests/Input/EscSeqUtilsTests.cs index c8838b7500..bf2c930e7b 100644 --- a/UnitTests/Input/EscSeqUtilsTests.cs +++ b/UnitTests/Input/EscSeqUtilsTests.cs @@ -695,8 +695,9 @@ public void DecodeEscSeq_Tests () Assert.False (_isReq); var view = new View { Width = Dim.Fill (), Height = Dim.Fill (), WantContinuousButtonPressed = true }; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnMouseEvent ( new MouseEventEventArgs ( @@ -769,7 +770,7 @@ public void DecodeEscSeq_Tests () } }; - Application.Run (); + Application.Run (top); Assert.Null (Application.WantContinuousButtonPressedView); diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index 3666fc0f5e..88d7ec9785 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -74,6 +74,7 @@ public override void After (MethodInfo methodUnderTest) if (AutoInit) { + Application.Top?.Dispose (); Application.Shutdown (); #if DEBUG_IDISPOSABLE if (Responder.Instances.Count == 0) @@ -94,8 +95,9 @@ public override void Before (MethodInfo methodUnderTest) if (AutoInit) { -#if DEBUG_IDISPOSABLE + ConfigurationManager.Reset (); +#if DEBUG_IDISPOSABLE // Clear out any lingering Responder instances from previous tests if (Responder.Instances.Count == 0) { diff --git a/UnitTests/Text/AutocompleteTests.cs b/UnitTests/Text/AutocompleteTests.cs index 61ad0d023e..e3cf22218a 100644 --- a/UnitTests/Text/AutocompleteTests.cs +++ b/UnitTests/Text/AutocompleteTests.cs @@ -20,7 +20,7 @@ public void CursorLeft_CursorRight_Mouse_Button_Pressed_Does_Not_Show_Popup () .Select (s => s.Value) .Distinct () .ToList (); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -152,7 +152,7 @@ This an long line and against TextView. public void KeyBindings_Command () { var tv = new TextView { Width = 10, Height = 2, Text = " Fortunately super feature." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); diff --git a/UnitTests/UICatalog/ScenarioTests.cs b/UnitTests/UICatalog/ScenarioTests.cs index 6a2b7803fa..630190b40a 100644 --- a/UnitTests/UICatalog/ScenarioTests.cs +++ b/UnitTests/UICatalog/ScenarioTests.cs @@ -40,7 +40,7 @@ public void Run_All_Scenarios () FakeConsole.PushMockKeyPress ((KeyCode)Application.QuitKey); // The only key we care about is the QuitKey - Application.Top.KeyDown += (sender, args) => + Application.KeyDown += (sender, args) => { _output.WriteLine ($" Keypress: {args.KeyCode}"); @@ -53,29 +53,28 @@ public void Run_All_Scenarios () uint abortTime = 500; // If the scenario doesn't close within 500ms, this will force it to quit - Func forceCloseCallback = () => - { - if (Application.Top.Running && FakeConsole.MockKeyPresses.Count == 0) - { - Application.RequestStop (); - - // See #2474 for why this is commented out - Assert.Fail ( - $"'{ - scenario.GetName () - }' failed to Quit with { - Application.QuitKey - } after { - abortTime - }ms. Force quit." - ); - } - - return false; - }; + bool ForceCloseCallback () + { + if (Application.Top.Running && FakeConsole.MockKeyPresses.Count == 0) + { + Application.RequestStop (); + + // See #2474 for why this is commented out + Assert.Fail ( + $"'{ + scenario.GetName () + }' failed to Quit with { + Application.QuitKey + } after { + abortTime + }ms. Force quit."); + } + + return false; + } //output.WriteLine ($" Add timeout to force quit after {abortTime}ms"); - _ = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), forceCloseCallback); + _ = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback); Application.Iteration += (s, a) => { @@ -87,9 +86,7 @@ public void Run_All_Scenarios () } }; - scenario.Init (); - scenario.Setup (); - scenario.Run (); + scenario.Main (); scenario.Dispose (); Application.Shutdown (); @@ -135,7 +132,7 @@ public void Run_All_Views_Tester_Scenario () Application.Init (new FakeDriver ()); - Toplevel Top = Application.Top; + Toplevel top = new Toplevel (); _viewClasses = GetAllViewClassesCollection () .OrderBy (t => t.Name) @@ -321,9 +318,9 @@ public void Run_All_Views_Tester_Scenario () _hRadioGroup.SelectedItemChanged += (s, selected) => DimPosChanged (_curView); - Top.Add (_leftPane, _settingsPane, _hostPane); + top.Add (_leftPane, _settingsPane, _hostPane); - Top.LayoutSubviews (); + top.LayoutSubviews (); _curView = CreateClass (_viewClasses.First ().Value); @@ -348,10 +345,11 @@ public void Run_All_Views_Tester_Scenario () } }; - Application.Run (); + Application.Run (top); Assert.Equal (_viewClasses.Count, iterations); + top.Dispose (); Application.Shutdown (); void DimPosChanged (View view) @@ -624,15 +622,13 @@ public void Run_Generic () } }; - Application.Top.KeyDown += (sender, args) => + Application.KeyDown += (sender, args) => { // See #2474 for why this is commented out Assert.Equal (KeyCode.CtrlMask | KeyCode.Q, args.KeyCode); }; - generic.Init (); - generic.Setup (); - generic.Run (); + generic.Main (); Assert.Equal (0, abortCount); diff --git a/UnitTests/View/Adornment/BorderTests.cs b/UnitTests/View/Adornment/BorderTests.cs index 97c3880f80..1eb51fb359 100644 --- a/UnitTests/View/Adornment/BorderTests.cs +++ b/UnitTests/View/Adornment/BorderTests.cs @@ -711,12 +711,13 @@ int expectedScreenY [AutoInitShutdown] public void HasSuperView () { - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (frame); - RunState rs = Application.Begin (Application.Top); + top.Add (frame); + RunState rs = Application.Begin (top); var firstIteration = false; ((FakeDriver)Application.Driver).SetBufferSize (5, 5); @@ -737,12 +738,13 @@ public void HasSuperView () [AutoInitShutdown] public void HasSuperView_Title () { - Application.Top.BorderStyle = LineStyle.Double; + var top = new Toplevel (); + top.BorderStyle = LineStyle.Double; var frame = new FrameView { Title = "1234", Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (frame); - RunState rs = Application.Begin (Application.Top); + top.Add (frame); + RunState rs = Application.Begin (top); var firstIteration = false; ((FakeDriver)Application.Driver).SetBufferSize (10, 4); diff --git a/UnitTests/View/DrawTests.cs b/UnitTests/View/DrawTests.cs index e29d5f6628..02b9c867ae 100644 --- a/UnitTests/View/DrawTests.cs +++ b/UnitTests/View/DrawTests.cs @@ -70,7 +70,7 @@ public void CJK_Compatibility_Ideographs_ConsoleWidth_ColumnWidth_Equal_Two () var view = new View { Text = r.ToString (), Height = Dim.Fill (), Width = Dim.Fill () }; var tf = new TextField { Text = us, Y = 1, Width = 3 }; win.Add (view, tf); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Begin (top); @@ -135,7 +135,8 @@ public void Clipping_AddRune_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_Wi }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (tv); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); // Don't use Label. It sets AutoSize = true which is not what we're testing here. var view = new View { Text = "ワイドルーン。", Height = Dim.Fill (), Width = Dim.Fill () }; @@ -143,8 +144,8 @@ public void Clipping_AddRune_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_Wi // Don't have unit tests use things that aren't absolutely critical for the test, like Dialog var dg = new Window { X = 2, Y = 2, Width = 14, Height = 3 }; dg.Add (view); - Application.Begin (Application.Top); - Application.Begin (dg); + RunState rsTop = Application.Begin (top); + RunState rsDiag = Application.Begin (dg); ((FakeDriver)Application.Driver).SetBufferSize (30, 10); const string expectedOutput = """ @@ -163,6 +164,9 @@ public void Clipping_AddRune_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_Wi Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expectedOutput, _output); Assert.Equal (new Rectangle (0, 0, 30, 10), pos); + + Application.End (rsDiag); + Application.End (rsTop); } [Fact] @@ -189,7 +193,7 @@ public void Colors_On_TextAlignment_Right_And_Bottom () VerticalTextAlignment = VerticalTextAlignment.Bottom, ColorScheme = Colors.ColorSchemes ["Base"] }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (viewRight, viewBottom); Application.Begin (top); @@ -402,7 +406,7 @@ public void Draw_Negative_Bounds_Horizontal_With_New_Lines () Height = 5 }; container.Add (content); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (container); Application.Driver.Clip = container.Frame; Application.Begin (top); @@ -517,7 +521,7 @@ public void Draw_Negative_Bounds_Horizontal_Without_New_Lines () Height = 5 }; container.Add (content); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (container); // BUGBUG: v2 - it's bogus to reference .Frame before BeginInit. And why is the clip being set anyway??? @@ -604,7 +608,7 @@ public void Draw_Negative_Bounds_Vertical () Height = 5 }; container.Add (content); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (container); Application.Driver.Clip = container.Frame; Application.Begin (top); @@ -723,7 +727,7 @@ public void Non_Bmp_ConsoleWidth_ColumnWidth_Equal_Two () var view = new Label { Text = r.ToString () }; var tf = new TextField { Text = us, Y = 1, Width = 3 }; win.Add (view, tf); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Begin (top); diff --git a/UnitTests/View/Layout/DimTests.cs b/UnitTests/View/Layout/DimTests.cs index 367a2c65de..40bcb2ecfa 100644 --- a/UnitTests/View/Layout/DimTests.cs +++ b/UnitTests/View/Layout/DimTests.cs @@ -28,7 +28,7 @@ public DimTests (ITestOutputHelper output) [AutoInitShutdown] public void Dim_Add_Operator () { - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { X = 0, Y = 0, Width = 20, Height = 0 }; var field = new TextField { X = 0, Y = Pos.Bottom (view), Width = 20 }; @@ -102,7 +102,7 @@ public void Dim_Referencing_SuperView_Does_Not_Throw () [AutoInitShutdown] public void Dim_Subtract_Operator () { - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { X = 0, Y = 0, Width = 20, Height = 0 }; var field = new TextField { X = 0, Y = Pos.Bottom (view), Width = 20 }; @@ -386,10 +386,11 @@ public void DimPercentPlusOne (int startingDistance, bool testHorizontal) }; container.Add (label); - Application.Top.Add (container); - Application.Top.BeginInit (); - Application.Top.EndInit (); - Application.Top.LayoutSubviews (); + var top = new Toplevel (); + top.Add (container); + top.BeginInit (); + top.EndInit (); + top.LayoutSubviews (); Assert.Equal (100, container.Frame.Width); Assert.Equal (100, container.Frame.Height); @@ -528,7 +529,7 @@ public void New_Works () public void Only_DimAbsolute_And_DimFactor_As_A_Different_Procedure_For_Assigning_Value_To_Width_Or_Height () { // Testing with the Button because it properly handles the Dim class. - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window { Width = 100, Height = 100 }; @@ -765,7 +766,7 @@ public void Only_DimAbsolute_And_DimFactor_As_A_Different_Procedure_For_Assignin Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); } [Fact] diff --git a/UnitTests/View/Layout/LayoutTests.cs b/UnitTests/View/Layout/LayoutTests.cs index 86c429a40b..d7c0b8d3a3 100644 --- a/UnitTests/View/Layout/LayoutTests.cs +++ b/UnitTests/View/Layout/LayoutTests.cs @@ -331,12 +331,13 @@ public void Dim_CenteredSubView_85_Percent_Width (int width) public void DimFill_SizedCorrectly () { var view = new View { Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Single }; - Application.Top.Add (view); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (32, 5); //view.SetNeedsLayout (); - Application.Top.LayoutSubviews (); + top.LayoutSubviews (); //view.SetRelativeLayout (new (0, 0, 32, 5)); Assert.Equal (32, view.Frame.Width); @@ -349,7 +350,7 @@ public void Draw_Throws_IndexOutOfRangeException_With_Negative_Bounds () { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { X = -2, Text = "view" }; top.Add (view); @@ -363,7 +364,7 @@ public void Draw_Throws_IndexOutOfRangeException_With_Negative_Bounds () try { - Application.Run (); + Application.Run (top); } catch (IndexOutOfRangeException ex) { @@ -371,6 +372,7 @@ public void Draw_Throws_IndexOutOfRangeException_With_Negative_Bounds () Assert.IsType (ex); } + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -381,7 +383,7 @@ public void Draw_Vertical_Throws_IndexOutOfRangeException_With_Negative_Bounds ( { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { Y = -2, Height = 10, TextDirection = TextDirection.TopBottom_LeftRight, Text = "view" }; top.Add (view); @@ -395,7 +397,7 @@ public void Draw_Vertical_Throws_IndexOutOfRangeException_With_Negative_Bounds ( try { - Application.Run (); + Application.Run (top); } catch (IndexOutOfRangeException ex) { @@ -403,6 +405,7 @@ public void Draw_Vertical_Throws_IndexOutOfRangeException_With_Negative_Bounds ( Assert.IsType (ex); } + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -488,7 +491,7 @@ public void { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window { X = Pos.Left (t) + 2, Y = Pos.At (2) }; @@ -506,7 +509,8 @@ public void Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -545,14 +549,16 @@ public void PosCombine_Refs_SuperView_Throws () { Application.Init (new FakeDriver ()); - var w = new Window { X = Pos.Left (Application.Top) + 2, Y = Pos.Top (Application.Top) + 2 }; + var top = new Toplevel (); + var w = new Window { X = Pos.Left (top) + 2, Y = Pos.Top (top) + 2 }; var f = new FrameView (); var v1 = new View { X = Pos.Left (w) + 2, Y = Pos.Top (w) + 2 }; var v2 = new View { X = Pos.Left (v1) + 2, Y = Pos.Top (v1) + 2 }; f.Add (v1, v2); w.Add (f); - Application.Top.Add (w); + top.Add (w); + Application.Begin (top); f.X = Pos.X (Application.Top) + Pos.X (v2) - Pos.X (v1); f.Y = Pos.Y (Application.Top) + Pos.Y (v2) - Pos.Y (v1); @@ -574,6 +580,7 @@ public void PosCombine_Refs_SuperView_Throws () Application.Iteration += (s, a) => Application.RequestStop (); Assert.Throws (() => Application.Run ()); + top.Dispose (); Application.Shutdown (); } @@ -634,8 +641,9 @@ public void TrySetHeight_ForceValidatePosDim () Assert.Equal (10, rHeight); Assert.False (v.IsInitialized); - Application.Top.Add (top); - Application.Begin (Application.Top); + var toplevel = new Toplevel (); + toplevel.Add (top); + Application.Begin (toplevel); Assert.True (v.IsInitialized); @@ -665,8 +673,9 @@ public void TrySetWidth_ForceValidatePosDim () Assert.Equal (70, rWidth); Assert.False (v.IsInitialized); - Application.Top.Add (top); - Application.Begin (Application.Top); + var toplevel = new Toplevel (); + toplevel.Add (top); + Application.Begin (toplevel); Assert.True (v.IsInitialized); v.Width = 75; diff --git a/UnitTests/View/Layout/PosTests.cs b/UnitTests/View/Layout/PosTests.cs index 644e4580e3..2e625ee376 100644 --- a/UnitTests/View/Layout/PosTests.cs +++ b/UnitTests/View/Layout/PosTests.cs @@ -43,7 +43,7 @@ public void AnchorEnd_Equal_Inside_Window () win.Add (tv); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); RunState rs = Application.Begin (top); @@ -73,7 +73,7 @@ public void AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel var menu = new MenuBar (); var status = new StatusBar (); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win, menu, status); RunState rs = Application.Begin (top); @@ -317,17 +317,18 @@ public void Internal_Tests () public void LeftTopBottomRight_Win_ShouldNotThrow () { // Setup Fake driver - (Window win, Button button) setup () + (Toplevel top, Window win, Button button) setup () { Application.Init (new FakeDriver ()); Application.Iteration += (s, a) => { Application.RequestStop (); }; var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); var button = new Button { X = Pos.Center (), Text = "button" }; win.Add (button); - return (win, button); + return (top, win, button); } RunState rs; @@ -337,14 +338,15 @@ void cleanup (RunState rs) // Cleanup Application.End (rs); + Application.Top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } // Test cases: - (Window win, Button button) app = setup (); + (Toplevel top, Window win, Button button) app = setup (); app.button.Y = Pos.Left (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -352,7 +354,7 @@ void cleanup (RunState rs) app = setup (); app.button.Y = Pos.X (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -360,7 +362,7 @@ void cleanup (RunState rs) app = setup (); app.button.Y = Pos.Top (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -368,7 +370,7 @@ void cleanup (RunState rs) app = setup (); app.button.Y = Pos.Y (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -376,7 +378,7 @@ void cleanup (RunState rs) app = setup (); app.button.Y = Pos.Bottom (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -384,7 +386,7 @@ void cleanup (RunState rs) app = setup (); app.button.Y = Pos.Right (app.win); - rs = Application.Begin (Application.Top); + rs = Application.Begin (app.top); // If Application.RunState is used then we must use Application.RunLoop with the rs parameter Application.RunLoop (rs); @@ -467,7 +469,7 @@ public void Pos_Add_Operator () { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { X = 0, Y = 0, Width = 20, Height = 20 }; var field = new TextField { X = 0, Y = 0, Width = 20 }; @@ -510,6 +512,7 @@ public void Pos_Add_Operator () Assert.Equal (20, count); + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -522,7 +525,7 @@ public void Pos_Subtract_Operator () { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { X = 0, Y = 0, Width = 20, Height = 20 }; var field = new TextField { X = 0, Y = 0, Width = 20 }; @@ -578,6 +581,7 @@ public void Pos_Subtract_Operator () Assert.Equal (0, count); + top.Dispose (); // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -589,7 +593,7 @@ public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window { X = 1, Y = 2, Width = 3, Height = 5 }; t.Add (w); @@ -602,7 +606,8 @@ public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -637,7 +642,7 @@ public void PosCombine_Will_Throws () { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window { X = Pos.Left (t) + 2, Y = Pos.Top (t) + 2 }; var f = new FrameView (); @@ -651,7 +656,8 @@ public void PosCombine_Will_Throws () f.X = Pos.X (v2) - Pos.X (v1); f.Y = Pos.Y (v2) - Pos.Y (v1); - Assert.Throws (() => Application.Run ()); + Assert.Throws (() => Application.Run (t)); + t.Dispose (); Application.Shutdown (); v2.Dispose (); @@ -676,8 +682,9 @@ public void PosPercentPlusOne (bool testHorizontal) }; container.Add (view); - Application.Top.Add (container); - Application.Top.LayoutSubviews (); + var top = new Toplevel (); + top.Add (container); + top.LayoutSubviews (); Assert.Equal (100, container.Frame.Width); Assert.Equal (100, container.Frame.Height); diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index cb4269b966..ee37f895ee 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -68,7 +68,9 @@ public void ButtonPressed_In_Margin_Or_Border_Starts_Drag (int marginThickness, testView.Border.Thickness = new (borderThickness); testView.Padding.Thickness = new (paddingThickness); - Application.Top.Add (testView); + var top = new Toplevel (); + top.Add (testView); + Application.Begin (top); Assert.Equal (new Point (4, 4), testView.Frame.Location); Application.OnMouseEvent (new (new () { X = xy, Y = xy, Flags = MouseFlags.Button1Pressed })); diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs index 7df35b0e3f..3d1e6611ce 100644 --- a/UnitTests/View/NavigationTests.cs +++ b/UnitTests/View/NavigationTests.cs @@ -57,7 +57,7 @@ public void CanFocus_Container_ToFalse_Turns_All_Subviews_ToFalse_Too () { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window (); var f = new FrameView (); @@ -84,7 +84,8 @@ public void CanFocus_Container_ToFalse_Turns_All_Subviews_ToFalse_Too () Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -93,7 +94,7 @@ public void CanFocus_Container_Toggling_All_Subviews_To_Old_Value_When_Is_True ( { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window (); var f = new FrameView (); @@ -126,7 +127,8 @@ public void CanFocus_Container_Toggling_All_Subviews_To_Old_Value_When_Is_True ( Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -166,7 +168,7 @@ public void CanFocus_Faced_With_Container_After_Run () { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window (); var f = new FrameView (); @@ -201,7 +203,8 @@ public void CanFocus_Faced_With_Container_After_Run () Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -210,7 +213,7 @@ public void CanFocus_Faced_With_Container_Before_Run () { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window (); var f = new FrameView (); @@ -238,7 +241,8 @@ public void CanFocus_Faced_With_Container_Before_Run () Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } @@ -292,8 +296,9 @@ public void CanFocus_Sets_To_False_Does_Not_Sets_HasFocus_To_True () var view = new View { CanFocus = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); Assert.True (view.CanFocus); Assert.True (view.HasFocus); @@ -315,21 +320,22 @@ public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel var view2 = new View { Id = "view2", Width = 20, Height = 2, CanFocus = true }; var win2 = new Window { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win1, win2); + Application.Begin (top); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); Assert.False (view2.HasFocus); // Only one of the most focused toplevels view can have focus - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab)); + Assert.True (top.NewKeyDownEvent (Key.Tab)); Assert.True (view1.CanFocus); Assert.False (view1.HasFocus); // Only one of the most focused toplevels view can have focus Assert.True (view2.CanFocus); Assert.True (view2.HasFocus); - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab)); + Assert.True (top.NewKeyDownEvent (Key.Tab)); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); @@ -354,21 +360,22 @@ public void CanFocus_Sets_To_False_On_Toplevel_Focus_View_On_Another_Toplevel () var view2 = new View { Id = "view2", Width = 20, Height = 2, CanFocus = true }; var win2 = new Window { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win1, win2); + Application.Begin (top); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); Assert.False (view2.HasFocus); // Only one of the most focused toplevels view can have focus - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab.WithCtrl)); + Assert.True (top.NewKeyDownEvent (Key.Tab.WithCtrl)); Assert.True (view1.CanFocus); Assert.False (view1.HasFocus); // Only one of the most focused toplevels view can have focus Assert.True (view2.CanFocus); Assert.True (view2.HasFocus); - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab.WithCtrl)); + Assert.True (top.NewKeyDownEvent (Key.Tab.WithCtrl)); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); @@ -404,22 +411,23 @@ public void CanFocus_Sets_To_False_With_Two_Views_Focus_Another_View_On_The_Same var view2 = new View { Id = "view2", Width = 20, Height = 2, CanFocus = true }; var win2 = new Window { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () }; win2.Add (view2); - Application.Top.Add (win1, win2); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win1, win2); + Application.Begin (top); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); Assert.False (view2.HasFocus); // Only one of the most focused toplevels view can have focus - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab.WithCtrl)); - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab.WithCtrl)); + Assert.True (top.NewKeyDownEvent (Key.Tab.WithCtrl)); + Assert.True (top.NewKeyDownEvent (Key.Tab.WithCtrl)); Assert.True (view1.CanFocus); Assert.False (view1.HasFocus); // Only one of the most focused toplevels view can have focus Assert.True (view2.CanFocus); Assert.True (view2.HasFocus); - Assert.True (Application.Top.NewKeyDownEvent (Key.Tab.WithCtrl)); + Assert.True (top.NewKeyDownEvent (Key.Tab.WithCtrl)); Assert.True (view1.CanFocus); Assert.True (view1.HasFocus); Assert.True (view2.CanFocus); @@ -441,7 +449,6 @@ public void Enabled_False_Sets_HasFocus_To_False () var wasClicked = false; var view = new Button { Text = "Click Me" }; view.Accept += (s, e) => wasClicked = !wasClicked; - Application.Top.Add (view); view.NewKeyDownEvent (Key.Space); Assert.True (wasClicked); @@ -473,7 +480,8 @@ public void Enabled_Sets_Also_Sets_Subviews () button.Accept += (s, e) => wasClicked = !wasClicked; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (button); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); var iterations = 0; @@ -518,7 +526,7 @@ public void Enabled_Sets_Also_Sets_Subviews () Application.RequestStop (); }; - Application.Run (); + Application.Run (top); Assert.Equal (1, iterations); } @@ -556,7 +564,7 @@ public void FocusNearestView_Ensure_Focus_Ordered () [AutoInitShutdown] public void FocusNext_Does_Not_Throws_If_A_View_Was_Removed_From_The_Collection () { - Toplevel top1 = Application.Top; + Toplevel top1 = new (); var view1 = new View { Id = "view1", Width = 10, Height = 5, CanFocus = true }; var top2 = new Toplevel { Id = "top2", Y = 1, Width = 10, Height = 5 }; @@ -644,7 +652,7 @@ void Tf_KeyPressed (object sender, Key obj) var win = new Window (); win.Add (sb, tf); - Toplevel top = Application.Top; + Toplevel top = new (); top.KeyDown += Top_KeyPress; void Top_KeyPress (object sender, Key obj) @@ -718,7 +726,7 @@ void Tf_KeyPressed (object sender, Key obj) var win = new Window (); win.Add (sb, tf); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Begin (top); @@ -746,14 +754,16 @@ public void Navigation_With_Null_Focused_View () Application.Init (new FakeDriver ()); - Application.Top.Ready += (s, e) => { Assert.Null (Application.Top.Focused); }; + var top = new Toplevel (); + top.Ready += (s, e) => { Assert.Null (top.Focused); }; // Keyboard navigation with tab Console.MockKeyPresses.Push (new ConsoleKeyInfo ('\t', ConsoleKey.Tab, false, false, false)); Application.Iteration += (s, a) => Application.RequestStop (); - Application.Run (); + Application.Run (top); + top.Dispose (); Application.Shutdown (); } @@ -761,8 +771,9 @@ public void Navigation_With_Null_Focused_View () [AutoInitShutdown] public void Remove_Does_Not_Change_Focus () { - Assert.True (Application.Top.CanFocus); - Assert.False (Application.Top.HasFocus); + var top = new Toplevel (); + Assert.True (top.CanFocus); + Assert.False (top.HasFocus); var container = new View { Width = 10, Height = 10 }; var leave = false; @@ -776,11 +787,11 @@ public void Remove_Does_Not_Change_Focus () Assert.True (child.CanFocus); Assert.False (child.HasFocus); - Application.Top.Add (container); - Application.Begin (Application.Top); + top.Add (container); + Application.Begin (top); - Assert.True (Application.Top.CanFocus); - Assert.True (Application.Top.HasFocus); + Assert.True (top.CanFocus); + Assert.True (top.HasFocus); Assert.True (container.CanFocus); Assert.True (container.HasFocus); Assert.True (child.CanFocus); @@ -789,7 +800,7 @@ public void Remove_Does_Not_Change_Focus () container.Remove (child); child.Dispose (); child = null; - Assert.True (Application.Top.HasFocus); + Assert.True (top.HasFocus); Assert.True (container.CanFocus); Assert.True (container.HasFocus); Assert.Null (child); @@ -800,7 +811,7 @@ public void Remove_Does_Not_Change_Focus () [AutoInitShutdown] public void ScreenToView_ViewToScreen_FindDeepestView_Full_Top () { - Toplevel top = Application.Current; + Toplevel top = new (); top.BorderStyle = LineStyle.Single; var view = new View @@ -1120,13 +1131,14 @@ public void SendSubviewToBack_Subviews_vs_TabIndexes () [AutoInitShutdown] public void SetFocus_View_With_Null_Superview_Does_Not_Throw_Exception () { - Assert.True (Application.Top.CanFocus); - Assert.False (Application.Top.HasFocus); + var top = new Toplevel (); + Assert.True (top.CanFocus); + Assert.False (top.HasFocus); - Exception exception = Record.Exception (Application.Top.SetFocus); + Exception exception = Record.Exception (top.SetFocus); Assert.Null (exception); - Assert.True (Application.Top.CanFocus); - Assert.True (Application.Top.HasFocus); + Assert.True (top.CanFocus); + Assert.True (top.HasFocus); } [Fact] @@ -1136,7 +1148,7 @@ public void SetHasFocus_Do_Not_Throws_If_OnLeave_Remove_Focused_Changing_To_Null var view1Leave = false; var subView1Leave = false; var subView1subView1Leave = false; - Toplevel top = Application.Top; + Toplevel top = new (); var view1 = new View { CanFocus = true }; var subView1 = new View { CanFocus = true }; var subView1subView1 = new View { CanFocus = true }; @@ -1459,6 +1471,7 @@ public void WindowDispose_CanFocusProblem () // Act RunState rs = Application.Begin (top); Application.End (rs); + top.Dispose (); Application.Shutdown (); // Assert does Not throw NullReferenceException diff --git a/UnitTests/View/SubviewTests.cs b/UnitTests/View/SubviewTests.cs index d4f730c958..3df9d73dd4 100644 --- a/UnitTests/View/SubviewTests.cs +++ b/UnitTests/View/SubviewTests.cs @@ -206,6 +206,7 @@ public void Initialized_Event_Comparing_With_Added_Event () }; Application.Run (top); + top.Dispose (); Application.Shutdown (); Assert.Equal (1, tc); @@ -301,6 +302,7 @@ public void Initialized_Event_Will_Be_Invoked_When_Added_Dynamically () }; Application.Run (t); + t.Dispose (); Application.Shutdown (); Assert.Equal (1, tc); diff --git a/UnitTests/View/Text/AutoSizeTrueTests.cs b/UnitTests/View/Text/AutoSizeTrueTests.cs index 00ec2208a0..d4f5458423 100644 --- a/UnitTests/View/Text/AutoSizeTrueTests.cs +++ b/UnitTests/View/Text/AutoSizeTrueTests.cs @@ -350,7 +350,7 @@ public void AutoSize_AnchorEnd_Better_Than_Bottom_Equal_Inside_Window () win.Add (label); - Toplevel top = Application.Top; + Toplevel top =new (); top.Add (win); RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (40, 10); @@ -399,7 +399,7 @@ public void AutoSize_AnchorEnd_Better_Than_Bottom_Equal_Inside_Window_With_MenuB var menu = new MenuBar { Menus = new MenuBarItem [] { new ("Menu", "", null) } }; var status = new StatusBar (new StatusItem [] { new (KeyCode.F1, "~F1~ Help", null) }); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win, menu, status); RunState rs = Application.Begin (top); @@ -462,7 +462,7 @@ public void AutoSize_Bottom_Equal_Inside_Window () win.Add (label); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (40, 10); @@ -511,7 +511,7 @@ public void AutoSize_Bottom_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_To var menu = new MenuBar { Menus = new MenuBarItem [] { new ("Menu", "", null) } }; var status = new StatusBar (new StatusItem [] { new (KeyCode.F1, "~F1~ Help", null) }); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win, menu, status); RunState rs = Application.Begin (top); @@ -558,7 +558,7 @@ F1 Help [AutoInitShutdown] public void AutoSize_Dim_Add_Operator_With_Text () { - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { @@ -641,7 +641,7 @@ public void AutoSize_Dim_Add_Operator_With_Text () [AutoInitShutdown] public void AutoSize_Dim_Subtract_Operator_With_Text () { - Toplevel top = Application.Top; + Toplevel top = new (); var view = new View { @@ -741,61 +741,64 @@ public void AutoSize_Dim_Subtract_Operator_With_Text () Assert.Equal (count, listLabels.Count); } - // [Fact] - // [AutoInitShutdown] - // public void AutoSize_False_Label_IsEmpty_True_Return_Null_Lines () - // { - // var text = "Label"; - // var label = new Label { - // AutoSize = false, - // Height = 1, - // Text = text, - // }; - // var win = new Window { - // Width = Dim.Fill (), - // Height = Dim.Fill () - // }; - // win.Add (label); - // Application.Top.Add (win); - // Application.Begin (Application.Top); - // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - - // Assert.Equal (5, text.Length); - // Assert.False (label.AutoSize); - // Assert.Equal (new (0, 0, 0, 1), label.Frame); - // Assert.Equal (new (3, 1), label.TextFormatter.Size); - // Assert.Equal (new List { "Lab" }, label.TextFormatter.Lines); - // Assert.Equal (new (0, 0, 10, 4), win.Frame); - // Assert.Equal (new (0, 0, 10, 4), Application.Top.Frame); - // var expected = @" + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_False_Label_IsEmpty_True_Return_Null_Lines () + //{ + // var text = "Label"; + // var label = new Label + // { + // AutoSize = false, + // Height = 1, + // Text = text, + // }; + // var win = new Window + // { + // Width = Dim.Fill (), + // Height = Dim.Fill () + // }; + // win.Add (label); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + + // Assert.Equal (5, text.Length); + // Assert.False (label.AutoSize); + // Assert.Equal (new (0, 0, 0, 1), label.Frame); + // Assert.Equal (new (3, 1), label.TextFormatter.Size); + // Assert.Equal (new List { "Lab" }, label.TextFormatter.GetLines()); + // Assert.Equal (new (0, 0, 10, 4), win.Frame); + // Assert.Equal (new (0, 0, 10, 4), Application.Top.Frame); + // var expected = @" //┌────────┐ //│Lab │ //│ │ //└────────┘ //"; - // var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 10, 4), pos); + // var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + // Assert.Equal (new (0, 0, 10, 4), pos); - // text = "0123456789"; - // Assert.Equal (10, text.Length); - // //label.Width = Dim.Fill () - text.Length; - // Application.Refresh (); + // text = "0123456789"; + // Assert.Equal (10, text.Length); + // //label.Width = Dim.Fill () - text.Length; + // Application.Refresh (); - // Assert.False (label.AutoSize); - // Assert.Equal (new (0, 0, 0, 1), label.Frame); - // Assert.Equal (new (0, 1), label.TextFormatter.Size); - // Assert.Equal (new List { string.Empty }, label.TextFormatter.Lines); - // expected = @" + // Assert.False (label.AutoSize); + // Assert.Equal (new (0, 0, 0, 1), label.Frame); + // Assert.Equal (new (0, 1), label.TextFormatter.Size); + // Assert.Equal (new List { string.Empty }, label.TextFormatter.GetLines()); + // expected = @" //┌────────┐ //│ │ //│ │ //└────────┘ //"; - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 10, 4), pos); - // } + // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + // Assert.Equal (new (0, 0, 10, 4), pos); + //} [Fact] [SetupFakeDriver] @@ -922,8 +925,9 @@ public void AutoSize_GetAutoSize_Centered () var view = new View { Text = text, TextAlignment = TextAlignment.Centered, AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Size size = view.GetAutoSize (); @@ -961,8 +965,9 @@ public void AutoSize_GetAutoSize_Horizontal () var view = new View { Text = text, AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Size size = view.GetAutoSize (); @@ -1000,8 +1005,9 @@ public void AutoSize_GetAutoSize_Left () var view = new View { Text = text, TextAlignment = TextAlignment.Left, AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Size size = view.GetAutoSize (); @@ -1039,8 +1045,9 @@ public void AutoSize_GetAutoSize_Right () var view = new View { Text = text, TextAlignment = TextAlignment.Right, AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Size size = view.GetAutoSize (); @@ -1078,8 +1085,9 @@ public void AutoSize_GetAutoSize_Vertical () var view = new View { Text = text, TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Size size = view.GetAutoSize (); @@ -1183,11 +1191,12 @@ public void AutoSize_Stays_True_Center_HotKeySpecifier () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (label.AutoSize); - RunState rs = Application.Begin (Application.Top); + RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @" @@ -1380,8 +1389,9 @@ public void AutoSize_True_Label_IsEmpty_False_Minimum_Height () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Assert.Equal (5, text.Length); @@ -1438,8 +1448,9 @@ public void AutoSize_True_Label_IsEmpty_False_Never_Return_Null_Lines () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (10, 4); Assert.Equal (5, text.Length); @@ -1555,8 +1566,9 @@ public void AutoSize_True_Setting_With_Height_Vertical () var viewX = new View { Text = "X", X = Pos.Right (label), Width = 1, Height = 1 }; var viewY = new View { Text = "Y", Y = Pos.Bottom (label), Width = 1, Height = 1 }; - Application.Top.Add (label, viewX, viewY); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label, viewX, viewY); + RunState rs = Application.Begin (top); Assert.True (label.AutoSize); label.Text = "Hello"; @@ -1611,9 +1623,10 @@ public void AutoSize_True_TextDirection_Toggle () // View is AutoSize == true var view = new View (); win.Add (view); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - RunState rs = Application.Begin (Application.Top); + RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (15, 15); Assert.Equal (new Rectangle (0, 0, 15, 15), win.Frame); @@ -1881,8 +1894,9 @@ public void AutoSize_True_View_IsEmpty_False_Minimum_Width () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (4, 10); Assert.Equal (5, text.Length); @@ -1952,8 +1966,9 @@ public void AutoSize_True_View_IsEmpty_False_Minimum_Width_Wide_Rune () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (view); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (4, 10); Assert.Equal (5, text.Length); @@ -2049,8 +2064,9 @@ public void AutoSize_True_Width_Height_SetMinWidthHeight_Narrow_Wide_Runes () Text = "Window" }; win.Add (horizontalView, verticalView); - Application.Top.Add (win); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 20); Assert.True (horizontalView.AutoSize); @@ -2135,8 +2151,9 @@ public void AutoSize_True_Width_Height_Stay_True_If_TextFormatter_Size_Fit () }; var win = new Window { Id = "win", Width = Dim.Fill (), Height = Dim.Fill (), Text = "Window" }; win.Add (horizontalView, verticalView); - Application.Top.Add (win); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + RunState rs = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (22, 22); Assert.True (horizontalView.AutoSize); @@ -2230,10 +2247,11 @@ public void DimPercentPlusOne (int startingDistance, bool testHorizontal) }; container.Add (label); - Application.Top.Add (container); - Application.Top.BeginInit (); - Application.Top.EndInit (); - Application.Top.LayoutSubviews (); + var top = new Toplevel (); + top.Add (container); + top.BeginInit (); + top.EndInit (); + top.LayoutSubviews (); Assert.Equal (100, container.Frame.Width); Assert.Equal (100, container.Frame.Height); @@ -2255,8 +2273,9 @@ public void DimPercentPlusOne (int startingDistance, bool testHorizontal) public void Excess_Text_Is_Erased_When_The_Width_Is_Reduced () { var lbl = new Label { Text = "123" }; - Application.Top.Add (lbl); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (lbl); + RunState rs = Application.Begin (top); Assert.True (lbl.AutoSize); Assert.Equal ("123 ", GetContents ()); @@ -2352,320 +2371,313 @@ public void GetCurrentWidth_TrySetWidth () top.Dispose (); } - // [Fact] - // [AutoInitShutdown] - // public void AutoSize_False_TextDirection_Toggle () - // { - // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - // // View is AutoSize == true - // var view = new View (); - // win.Add (view); - // Application.Top.Add (win); - - // var rs = Application.Begin (Application.Top); - // ((FakeDriver)Application.Driver).SetBufferSize (22, 22); - - // Assert.Equal (new (0, 0, 22, 22), win.Frame); - // Assert.Equal (new (0, 0, 22, 22), win.Margin.Frame); - // Assert.Equal (new (0, 0, 22, 22), win.Border.Frame); - // Assert.Equal (new (1, 1, 20, 20), win.Padding.Frame); - // Assert.False (view.AutoSize); - // Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection); - // Assert.Equal (Rect.Empty, view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(0)", view.Width.ToString ()); - // Assert.Equal ("Absolute(0)", view.Height.ToString ()); - // var expected = @" - //┌────────────────────┐ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.Text = "Hello World"; - // view.Width = 11; - // view.Height = 1; - // win.LayoutSubviews (); - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 11, 1), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(11)", view.Width.ToString ()); - // Assert.Equal ("Absolute(1)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│Hello World │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.AutoSize = true; - // view.Text = "Hello Worlds"; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 12, 1), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(11)", view.Width.ToString ()); - // Assert.Equal ("Absolute(1)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│Hello Worlds │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.TextDirection = TextDirection.TopBottom_LeftRight; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 11, 12), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(11)", view.Width.ToString ()); - // Assert.Equal ("Absolute(1)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│H │ - //│e │ - //│l │ - //│l │ - //│o │ - //│ │ - //│W │ - //│o │ - //│r │ - //│l │ - //│d │ - //│s │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.AutoSize = false; - // view.Height = 1; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 11, 1), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(11)", view.Width.ToString ()); - // Assert.Equal ("Absolute(1)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│HelloWorlds │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.PreserveTrailingSpaces = true; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 11, 1), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(11)", view.Width.ToString ()); - // Assert.Equal ("Absolute(1)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│Hello World │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.PreserveTrailingSpaces = false; - // var f = view.Frame; - // view.Width = f.Height; - // view.Height = f.Width; - // view.TextDirection = TextDirection.TopBottom_LeftRight; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 1, 11), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(1)", view.Width.ToString ()); - // Assert.Equal ("Absolute(11)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│H │ - //│e │ - //│l │ - //│l │ - //│o │ - //│ │ - //│W │ - //│o │ - //│r │ - //│l │ - //│d │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - - // view.AutoSize = true; - // Application.Refresh (); - - // Assert.Equal (new (0, 0, 1, 12), view.Frame); - // Assert.Equal ("Absolute(0)", view.X.ToString ()); - // Assert.Equal ("Absolute(0)", view.Y.ToString ()); - // Assert.Equal ("Absolute(1)", view.Width.ToString ()); - // Assert.Equal ("Absolute(12)", view.Height.ToString ()); - // expected = @" - //┌────────────────────┐ - //│H │ - //│e │ - //│l │ - //│l │ - //│o │ - //│ │ - //│W │ - //│o │ - //│r │ - //│l │ - //│d │ - //│s │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //│ │ - //└────────────────────┘ - //"; - - // pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - // Assert.Equal (new (0, 0, 22, 22), pos); - // Application.End (rs); - // } +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_False_TextDirection_Toggle () +// { +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; +// // View is AutoSize == true +// var view = new View (); +// win.Add (view); +// var top = new Toplevel (); +// top.Add (win); + +// var rs = Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (22, 22); + +// Assert.Equal (new (0, 0, 22, 22), win.Frame); +// Assert.Equal (new (0, 0, 22, 22), win.Margin.Frame); +// Assert.Equal (new (0, 0, 22, 22), win.Border.Frame); +// Assert.Equal (new (1, 1, 20, 20), win.Padding.Frame); +// Assert.False (view.AutoSize); +// Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection); +// Assert.Equal (Rectangle.Empty, view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(0)", view.Width.ToString ()); +// Assert.Equal ("Absolute(0)", view.Height.ToString ()); +// var expected = @" +//┌────────────────────┐ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.Text = "Hello World"; +// view.Width = 11; +// view.Height = 1; +// win.LayoutSubviews (); +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 11, 1), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(11)", view.Width.ToString ()); +// Assert.Equal ("Absolute(1)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│Hello World │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.AutoSize = true; +// view.Text = "Hello Worlds"; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 12, 1), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(11)", view.Width.ToString ()); +// Assert.Equal ("Absolute(1)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│Hello Worlds │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.TextDirection = TextDirection.TopBottom_LeftRight; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 11, 12), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(11)", view.Width.ToString ()); +// Assert.Equal ("Absolute(1)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│H │ +//│e │ +//│l │ +//│l │ +//│o │ +//│ │ +//│W │ +//│o │ +//│r │ +//│l │ +//│d │ +//│s │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.AutoSize = false; +// view.Height = 1; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 11, 1), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(11)", view.Width.ToString ()); +// Assert.Equal ("Absolute(1)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│HelloWorlds │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.PreserveTrailingSpaces = true; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 11, 1), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(11)", view.Width.ToString ()); +// Assert.Equal ("Absolute(1)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│Hello World │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.PreserveTrailingSpaces = false; +// var f = view.Frame; +// view.Width = f.Height; +// view.Height = f.Width; +// view.TextDirection = TextDirection.TopBottom_LeftRight; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 1, 11), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(1)", view.Width.ToString ()); +// Assert.Equal ("Absolute(11)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│H │ +//│e │ +//│l │ +//│l │ +//│o │ +//│ │ +//│W │ +//│o │ +//│r │ +//│l │ +//│d │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); + +// view.AutoSize = true; +// Application.Refresh (); + +// Assert.Equal (new (0, 0, 1, 12), view.Frame); +// Assert.Equal ("Absolute(0)", view.X.ToString ()); +// Assert.Equal ("Absolute(0)", view.Y.ToString ()); +// Assert.Equal ("Absolute(1)", view.Width.ToString ()); +// Assert.Equal ("Absolute(12)", view.Height.ToString ()); +// expected = @" +//┌────────────────────┐ +//│H │ +//│e │ +//│l │ +//│l │ +//│o │ +//│ │ +//│W │ +//│o │ +//│r │ +//│l │ +//│d │ +//│s │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//│ │ +//└────────────────────┘"; + +// pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// Assert.Equal (new (0, 0, 22, 22), pos); +// Application.End (rs); +// } [Fact] [AutoInitShutdown] @@ -2686,9 +2698,9 @@ public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier () verticalView.Text = text; verticalView.TextFormatter.HotKeySpecifier = (Rune)'_'; - - Application.Top.Add (horizontalView, verticalView); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (horizontalView, verticalView); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (50, 50); Assert.True (horizontalView.AutoSize); @@ -2755,9 +2767,10 @@ public void Setting_Frame_Dont_Respect_AutoSize_True_On_Layout_Absolute () TextDirection = TextDirection.TopBottom_LeftRight }; - Application.Top.Add (view1, viewTopBottom_LeftRight); + var top = new Toplevel (); + top.Add (view1, viewTopBottom_LeftRight); - RunState rs = Application.Begin (Application.Top); + RunState rs = Application.Begin (top); Assert.True (view1.AutoSize); Assert.Equal (LayoutStyle.Absolute, view1.LayoutStyle); @@ -2821,8 +2834,9 @@ public void TrySetHeight_ForceValidatePosDim () Assert.Equal (10, rHeight); Assert.False (v.IsInitialized); - Application.Top.Add (top); - Application.Begin (Application.Top); + var toplevel = new Toplevel (); + toplevel.Add (top); + Application.Begin (toplevel); Assert.True (v.IsInitialized); @@ -2852,8 +2866,9 @@ public void TrySetWidth_ForceValidatePosDim () Assert.Equal (70, rWidth); Assert.False (v.IsInitialized); - Application.Top.Add (top); - Application.Begin (Application.Top); + var toplevel = new Toplevel (); + toplevel.Add (top); + Application.Begin (toplevel); Assert.True (v.IsInitialized); v.Width = 75; @@ -2902,8 +2917,9 @@ public void View_Draw_Horizontal_Simple_TextAlignments (bool autoSize) }; var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () }; frame.Add (lblLeft, lblCenter, lblRight, lblJust); - Application.Top.Add (frame); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (frame); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6); Assert.True (lblLeft.AutoSize == autoSize); @@ -3002,8 +3018,9 @@ public void View_Draw_Vertical_Simple_TextAlignments (bool autoSize) var frame = new FrameView { Width = Dim.Fill (), Height = Dim.Fill () }; frame.Add (lblLeft, lblCenter, lblRight, lblJust); - Application.Top.Add (frame); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (frame); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (9, height + 2); Assert.True (lblLeft.AutoSize == autoSize); diff --git a/UnitTests/View/ViewKeyBindingTests.cs b/UnitTests/View/ViewKeyBindingTests.cs index 4fe5b69b4a..73d97ed6b2 100644 --- a/UnitTests/View/ViewKeyBindingTests.cs +++ b/UnitTests/View/ViewKeyBindingTests.cs @@ -15,8 +15,9 @@ public void Focus_KeyBinding () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnKeyDown (Key.A); Assert.True (invoked); @@ -51,8 +52,9 @@ public void Focus_KeyBinding_Negative () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnKeyDown (Key.Z); Assert.False (invoked); @@ -77,8 +79,9 @@ public void HotKey_KeyBinding () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); invoked = false; Application.OnKeyDown (Key.H); @@ -105,8 +108,9 @@ public void HotKey_KeyBinding_Negative () var invoked = false; view.InvokingKeyBindings += (s, e) => invoked = true; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Application.OnKeyDown (Key.Z); Assert.False (invoked); diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs index 133c1f19eb..de9de98c3e 100644 --- a/UnitTests/View/ViewTests.cs +++ b/UnitTests/View/ViewTests.cs @@ -33,8 +33,9 @@ public void Clear_Bounds_Can_Use_Driver_AddRune_Or_AddStr_Methods () Application.Driver.Clip = savedClip; e.Cancel = true; }; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var expected = @" @@ -95,8 +96,9 @@ public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods () Application.Driver.Clip = savedClip; e.Cancel = true; }; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 10); var expected = @" @@ -147,8 +149,9 @@ public void Clear_Does_Not_Spillover_Its_Parent (bool label) root.Add (v); - Application.Top.Add (root); - RunState runState = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (root); + RunState runState = Application.Begin (top); if (label) { @@ -232,7 +235,7 @@ public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Usin Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -277,7 +280,7 @@ public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Usin Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -326,7 +329,7 @@ public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_F Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -371,7 +374,7 @@ public void Correct_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using_P Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -435,8 +438,9 @@ public void DrawContentComplete_Event_Is_Always_Called () var tv = new TextView { Y = 11, Width = 10, Height = 10 }; tv.DrawContentComplete += (s, e) => tvCalled = true; - Application.Top.Add (view, tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view, tv); + Application.Begin (top); Assert.True (viewCalled); Assert.True (tvCalled); @@ -467,7 +471,7 @@ public void Frame_Set_After_Initialize_Update_NeededDisplay () frame.Width = 40; frame.Height = 8; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (frame); @@ -539,7 +543,7 @@ public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Us Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -584,7 +588,7 @@ public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Down_Right_Us Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -633,7 +637,7 @@ public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -680,7 +684,7 @@ public void Incorrect_Redraw_Bounds_NeedDisplay_On_Shrink_And_Move_Up_Left_Using Height = 2, Text = "A text with some long width\n and also with two lines." }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (label, view); RunState runState = Application.Begin (top); @@ -999,7 +1003,7 @@ public void Visible_Clear_The_View_Output () Assert.Equal (0, view.Height); var win = new Window (); win.Add (view); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); RunState rs = Application.Begin (top); @@ -1044,7 +1048,7 @@ public void Visible_Sets_Also_Sets_Subviews () var button = new Button { Text = "Click Me" }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (button); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); var iterations = 0; @@ -1087,7 +1091,7 @@ public void Visible_Sets_Also_Sets_Subviews () Application.RequestStop (); }; - Application.Run (); + Application.Run (top); Assert.Equal (1, iterations); diff --git a/UnitTests/Views/AllViewsTests.cs b/UnitTests/Views/AllViewsTests.cs index 8beb983e3a..676198e844 100644 --- a/UnitTests/Views/AllViewsTests.cs +++ b/UnitTests/Views/AllViewsTests.cs @@ -64,12 +64,13 @@ public void AllViews_Enter_Leave_Events () Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); View vType = CreateViewFromType (type, type.GetConstructor (Array.Empty ())); if (vType == null) { output.WriteLine ($"Ignoring {type} - It's a Generic"); + top.Dispose (); Application.Shutdown (); continue; @@ -104,6 +105,7 @@ public void AllViews_Enter_Leave_Events () if (!vType.CanFocus || (vType is Toplevel && ((Toplevel)vType).Modal)) { + top.Dispose (); Application.Shutdown (); continue; @@ -132,6 +134,7 @@ public void AllViews_Enter_Leave_Events () Assert.Equal (1, viewEnter); Assert.Equal (1, viewLeave); + top.Dispose (); Application.Shutdown (); } } diff --git a/UnitTests/Views/AppendAutocompleteTests.cs b/UnitTests/Views/AppendAutocompleteTests.cs index f8818795b9..f208810de1 100644 --- a/UnitTests/Views/AppendAutocompleteTests.cs +++ b/UnitTests/Views/AppendAutocompleteTests.cs @@ -227,7 +227,7 @@ private TextField GetTextFieldsInView () var tf = new TextField { Width = 10 }; var tf2 = new TextField { Y = 1, Width = 10 }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tf); top.Add (tf2); diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index 72d9e9cd34..d64214832b 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -113,9 +113,10 @@ public void AutoSize_False_With_Fixed_Width () tab.Height = btnFindNext.Height + btnFindPrevious.Height + btnCancel.Height + 4; win.Add (tabView); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (54, 11); Assert.Equal (new Rectangle (0, 0, 54, 11), win.Frame); @@ -185,12 +186,12 @@ public void AutoSize_Stays_True_AnchorEnd () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Assert.True (btn.AutoSize); Assert.True (btn.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @$" @@ -232,12 +233,12 @@ public void AutoSize_Stays_True_Center () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Assert.True (btn.AutoSize); Assert.True (btn.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @$" @@ -282,18 +283,16 @@ public void AutoSize_Stays_True_With_EmptyText () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Assert.True (btn.AutoSize); Assert.True (btn.AutoSize); - btn.Text = "Say Hello 你"; btn.Text = "Say Hello 你"; - Assert.True (btn.AutoSize); Assert.True (btn.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @$" @@ -532,8 +531,9 @@ public void HotKeyChange_Works () var clicked = false; var btn = new Button { Text = "_Test" }; btn.Accept += (s, e) => clicked = true; - Application.Top.Add (btn); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (btn); + Application.Begin (top); Assert.Equal (KeyCode.T, btn.HotKey); Assert.True (btn.NewKeyDownEvent (Key.T)); @@ -566,10 +566,9 @@ public void KeyBindingExample () Assert.Contains (Command.HotKey, btn.GetSupportedCommands ()); Assert.Contains (Command.Accept, btn.GetSupportedCommands ()); - Application.Top.Add (btn); - Application.Begin (Application.Top); - Application.Top.Add (btn); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (btn); + Application.Begin (top); // default keybinding is Space which results in keypress Application.OnKeyDown (new Key ((KeyCode)' ')); @@ -611,8 +610,9 @@ public void KeyBindings_Command () var clicked = false; var btn = new Button { Text = "_Test" }; btn.Accept += (s, e) => clicked = true; - Application.Top.Add (btn); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (btn); + Application.Begin (top); // Hot key. Both alone and with alt Assert.Equal (KeyCode.T, btn.HotKey); @@ -749,14 +749,12 @@ public void Update_Only_On_Or_After_Initialize () var btn = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Say Hello 你" }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Assert.False (btn.IsInitialized); Assert.False (btn.IsInitialized); - Application.Begin (Application.Top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.True (btn.IsInitialized); @@ -786,14 +784,12 @@ public void Update_Parameterless_Only_On_Or_After_Initialize () var btn = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Say Hello 你" }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Assert.False (btn.IsInitialized); Assert.False (btn.IsInitialized); - Application.Begin (Application.Top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.True (btn.IsInitialized); diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs index c7ce63e366..aeec6b8218 100644 --- a/UnitTests/Views/CheckBoxTests.cs +++ b/UnitTests/Views/CheckBoxTests.cs @@ -40,7 +40,7 @@ public void Title_Mirrors_Text () public void AllowNullChecked_Get_Set () { var checkBox = new CheckBox { Text = "Check this out 你" }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (checkBox); Application.Begin (top); @@ -81,11 +81,12 @@ public void AutoSize_Stays_True_AnchorEnd_With_HotKeySpecifier () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (checkBox.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @$" @@ -124,11 +125,12 @@ public void AutoSize_Stays_True_AnchorEnd_Without_HotKeySpecifier () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (checkBox.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @$" @@ -164,11 +166,12 @@ public void AutoSize_StaysVisible () var checkBox = new CheckBox { X = 1, Y = Pos.Center (), Text = "Check this out 你" }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.False (checkBox.IsInitialized); - RunState runstate = Application.Begin (Application.Top); + RunState runstate = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.True (checkBox.IsInitialized); @@ -355,9 +358,10 @@ public void TextAlignment_Centered () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.Equal (TextAlignment.Centered, checkBox.TextAlignment); @@ -416,9 +420,10 @@ public void TextAlignment_Justified () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox1, checkBox2); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 6); Assert.Equal (TextAlignment.Justified, checkBox1.TextAlignment); @@ -475,9 +480,10 @@ public void TextAlignment_Left () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.Equal (TextAlignment.Left, checkBox.TextAlignment); @@ -525,9 +531,10 @@ public void TextAlignment_Right () }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.Equal (TextAlignment.Right, checkBox.TextAlignment); diff --git a/UnitTests/Views/ColorPickerTests.cs b/UnitTests/Views/ColorPickerTests.cs index 083110a7b9..bdf05a84b6 100644 --- a/UnitTests/Views/ColorPickerTests.cs +++ b/UnitTests/Views/ColorPickerTests.cs @@ -48,8 +48,9 @@ public void MouseEvents () { var colorPicker = new ColorPicker { X = 0, Y = 0, Height = 4, Width = 32 }; Assert.Equal (ColorName.Black, colorPicker.SelectedColor); - Application.Top.Add (colorPicker); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (colorPicker); + Application.Begin (top); Assert.False (colorPicker.OnMouseEvent (new MouseEvent ())); diff --git a/UnitTests/Views/ComboBoxTests.cs b/UnitTests/Views/ComboBoxTests.cs index 1a38b80d49..88285ef89a 100644 --- a/UnitTests/Views/ComboBoxTests.cs +++ b/UnitTests/Views/ComboBoxTests.cs @@ -86,7 +86,8 @@ public void EnsureKeyEventsDoNotCauseExceptions () string [] source = Enumerable.Range (0, 15).Select (x => x.ToString ()).ToArray (); comboBox.SetSource (source); - Application.Top.Add (comboBox); + var top = new Toplevel (); + top.Add (comboBox); foreach (KeyCode key in (KeyCode [])Enum.GetValues (typeof (KeyCode))) { @@ -104,8 +105,9 @@ public void Expanded_Collapsed_Events () cb.Expanded += (s, e) => cb.SetSource (list); cb.Collapsed += (s, e) => cb.Source = null; - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.Null (cb.Source); Assert.False (cb.IsShow); @@ -133,8 +135,9 @@ public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_Cu var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = false }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.False (cb.HideDropdownListOnClick); Assert.False (cb.ReadOnly); @@ -190,8 +193,9 @@ public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_F4 var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = false }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.False (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -225,8 +229,9 @@ public void var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = false, ReadOnly = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.False (cb.HideDropdownListOnClick); Assert.True (cb.ReadOnly); @@ -282,8 +287,9 @@ public void HideDropdownListOnClick_Gets_Sets () var cb = new ComboBox { Height = 4, Width = 5 }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.False (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -382,8 +388,9 @@ public void HideDropdownListOnClick_True_Colapse_On_Click_Outside_Frame () var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.True (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -499,8 +506,9 @@ public void HideDropdownListOnClick_True_Highlight_Current_Item () var cb = new ComboBox { Width = 6, Height = 4, HideDropdownListOnClick = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.True (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -655,8 +663,9 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.True (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -716,8 +725,9 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_Cur var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.True (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -772,8 +782,9 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_F4 var cb = new ComboBox { Height = 4, Width = 5, HideDropdownListOnClick = true }; cb.SetSource (new List { "One", "Two", "Three" }); cb.OpenSelectedItem += (s, e) => selected = e.Value.ToString (); - Application.Top.Add (cb); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (cb); + Application.Begin (top); Assert.True (cb.HideDropdownListOnClick); Assert.False (cb.IsShow); @@ -805,8 +816,9 @@ public void KeyBindings_Command () List source = new () { "One", "Two", "Three" }; var cb = new ComboBox { Width = 10 }; cb.SetSource (source); - Application.Top.Add (cb); - Application.Top.FocusFirst (); + var top = new Toplevel (); + top.Add (cb); + top.FocusFirst (); Assert.Equal (-1, cb.SelectedItem); Assert.Equal (string.Empty, cb.Text); var opened = false; @@ -835,7 +847,7 @@ public void KeyBindings_Command () Assert.True (cb.NewKeyDownEvent (Key.CursorDown)); // losing focus Assert.False (cb.IsShow); Assert.False (cb.HasFocus); - Application.Top.FocusFirst (); // Gets focus again + top.FocusFirst (); // Gets focus again Assert.False (cb.IsShow); Assert.True (cb.HasFocus); cb.Expand (); @@ -866,7 +878,7 @@ public void KeyBindings_Command () Assert.True (cb.IsShow); Assert.Equal (0, cb.SelectedItem); Assert.Equal ("One", cb.Text); - Application.Begin (Application.Top); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -880,7 +892,7 @@ public void KeyBindings_Command () Assert.True (cb.IsShow); Assert.Equal (1, cb.SelectedItem); Assert.Equal ("Two", cb.Text); - Application.Begin (Application.Top); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -894,7 +906,7 @@ public void KeyBindings_Command () Assert.True (cb.IsShow); Assert.Equal (2, cb.SelectedItem); Assert.Equal ("Three", cb.Text); - Application.Begin (Application.Top); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -944,7 +956,7 @@ public void KeyBindings_Command () Assert.False (cb.IsShow); Assert.Equal (-1, cb.SelectedItem); Assert.Equal ("One", cb.Text); - Application.Top.FocusFirst (); // Gets focus again + top.FocusFirst (); // Gets focus again Assert.True (cb.HasFocus); Assert.False (cb.IsShow); Assert.Equal (-1, cb.SelectedItem); @@ -962,8 +974,9 @@ public void KeyBindings_Command () public void Source_Equal_Null_Or_Count_Equal_Zero_Sets_SelectedItem_Equal_To_Minus_One () { var cb = new ComboBox (); - Application.Top.Add (cb); - Application.Top.FocusFirst (); + var top = new Toplevel (); + top.Add (cb); + top.FocusFirst (); Assert.Null (cb.Source); Assert.Equal (-1, cb.SelectedItem); List source = new (); diff --git a/UnitTests/Views/ContextMenuTests.cs b/UnitTests/Views/ContextMenuTests.cs index c4f34a11e2..239dca482e 100644 --- a/UnitTests/Views/ContextMenuTests.cs +++ b/UnitTests/Views/ContextMenuTests.cs @@ -77,8 +77,9 @@ public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Null (Application.MouseGrabView); @@ -142,9 +143,10 @@ public void ContextMenu_On_Toplevel_With_A_MenuBar_TextField_StatusBar () ] ); - Application.Top.Add (menu, label, tf, statusBar); + var top = new Toplevel (); + top.Add (menu, label, tf, statusBar); ((FakeDriver)Application.Driver).SetBufferSize (45, 17); - Application.Begin (Application.Top); + Application.Begin (top); Assert.Equal (new Rectangle (9, 3, 20, 1), tf.Frame); Assert.True (tf.HasFocus); @@ -208,8 +210,9 @@ public void ContextMenu_On_Toplevel_With_A_MenuBar_Window_TextField_StatusBar () } ); - Application.Top.Add (menu, win, statusBar); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu, win, statusBar); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (44, 17); Assert.Equal (new Rectangle (9, 3, 20, 1), tf.Frame); @@ -297,10 +300,10 @@ public void Draw_A_ContextMenu_Over_A_Borderless_Top () [AutoInitShutdown] public void Draw_A_ContextMenu_Over_A_Dialog () { - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window (); top.Add (win); - Application.Begin (top); + RunState rsTop = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 15); Assert.Equal (new Rectangle (0, 0, 20, 15), win.Frame); @@ -328,7 +331,7 @@ public void Draw_A_ContextMenu_Over_A_Dialog () // Don't use Dialog here as it has more layout logic. Use Window instead. var dialog = new Window { X = 2, Y = 2, Width = 15, Height = 4 }; dialog.Add (new TextField { X = Pos.Center (), Width = 10, Text = "Test" }); - RunState rs = Application.Begin (dialog); + RunState rsDialog = Application.Begin (dialog); Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame); @@ -359,7 +362,7 @@ public void Draw_A_ContextMenu_Over_A_Dialog () ); var firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsDialog, ref firstIteration); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -381,7 +384,8 @@ public void Draw_A_ContextMenu_Over_A_Dialog () _output ); - Application.End (rs); + Application.End (rsDialog); + Application.End (rsTop); } [Fact] @@ -455,9 +459,11 @@ public void ForceMinimumPosToZero_True_False () Assert.Equal (new Point (-1, -2), cm.Position); + Application.Begin (new ()); + cm.Show (); Assert.Equal (new Point (-1, -2), cm.Position); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -499,7 +505,7 @@ public void Hide_Is_Invoke_At_Container_Closing () ) }; - Toplevel top = Application.Top; + Toplevel top = new (); Application.Begin (top); top.Running = true; @@ -517,8 +523,9 @@ public void Hide_Is_Invoke_At_Container_Closing () public void Key_Open_And_Close_The_ContextMenu () { var tf = new TextField (); - Application.Top.Add (tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tf); + Application.Begin (top); Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey)); Assert.True (tf.ContextMenu.MenuBar.IsMenuOpen); @@ -555,8 +562,9 @@ public void MenuItens_Changing () ) }; + Application.Begin (new ()); cm.Show (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -621,10 +629,13 @@ public void Menus_And_SubMenus_Always_Try_To_Be_On_Screen () Assert.Equal (new Point (-1, -2), cm.Position); + Toplevel top = new (); + Application.Begin (top); + cm.Show (); + Application.Refresh (); + Assert.Equal (new Point (-1, -2), cm.Position); - Toplevel top = Application.Top; - Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -864,7 +875,7 @@ public void MouseFlags_Changing () } }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (lbl); Application.Begin (top); @@ -906,8 +917,9 @@ public void Position_Changing () ) }; + Application.Begin (new ()); cm.Show (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -938,7 +950,7 @@ public void Position_Changing () public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws () { ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5); - Toplevel top = Application.Top; + Toplevel top = new (); var isMenuAllClosed = false; MenuBarItem mi = null; int iterations = -1; @@ -957,6 +969,7 @@ public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws () { var dialog1 = new Dialog (); Application.Run (dialog1); + dialog1.Dispose (); Assert.False (ContextMenu.IsShow); Assert.True (isMenuAllClosed); }; @@ -994,12 +1007,13 @@ public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws () { var dialog2 = new Dialog (); Application.Run (dialog2); + dialog2.Dispose (); Assert.False (ContextMenu.IsShow); Assert.True (isMenuAllClosed); isTopClosed = true; }; - Application.Run (); + Application.Run (top); Assert.True (isTopClosed); Assert.False (ContextMenu.IsShow); @@ -1025,9 +1039,10 @@ public void Show_Display_At_Zero_If_The_Toplevel_Height_Is_Less_Than_The_Menu_He Assert.Equal (Point.Empty, cm.Position); + Application.Begin (new ()); cm.Show (); Assert.Equal (Point.Empty, cm.Position); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -1060,9 +1075,10 @@ public void Show_Display_At_Zero_If_The_Toplevel_Width_Is_Less_Than_The_Menu_Wid Assert.Equal (Point.Empty, cm.Position); + Application.Begin (new ()); cm.Show (); Assert.Equal (Point.Empty, cm.Position); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──── @@ -1102,13 +1118,14 @@ public void Show_Display_Below_The_Bottom_Host_If_Has_Enough_Space () ) }; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Assert.Equal (new Point (10, 5), cm.Position); cm.Show (); - Application.Top.Draw (); + top.Draw (); Assert.Equal (new Point (10, 5), cm.Position); var expected = @" @@ -1166,9 +1183,10 @@ public void Show_Ensures_Display_Inside_The_Container_But_Preserves_Position () Assert.Equal (new Point (80, 25), cm.Position); + Application.Begin (new ()); cm.Show (); Assert.Equal (new Point (80, 25), cm.Position); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -1208,15 +1226,16 @@ public void Show_Ensures_Display_Inside_The_Container_Without_Overlap_The_Host ( ) }; - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame); Assert.Equal (Point.Empty, cm.Position); cm.Show (); Assert.Equal (new Point (70, 24), cm.Position); - Application.Top.Draw (); + top.Draw (); var expected = @" ┌──────┐ @@ -1239,10 +1258,10 @@ public void Show_Hide_IsShow () { ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5); + Application.Begin (new ()); cm.Show (); Assert.True (ContextMenu.IsShow); - - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -1291,10 +1310,10 @@ public void UseSubMenusSingleFrame_True_By_Mouse () UseSubMenusSingleFrame = true }; + RunState rs = Application.Begin (new ()); cm.Show (); - RunState rs = Application.Begin (Application.Top); - Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -1388,10 +1407,11 @@ public void UseSubMenusSingleFrame_False_By_Mouse () ) }; + RunState rs = Application.Begin (new ()); cm.Show (); - RunState rs = Application.Begin (Application.Top); Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre ( @" diff --git a/UnitTests/Views/DatePickerTests.cs b/UnitTests/Views/DatePickerTests.cs index 4c8008ffa8..498d521182 100644 --- a/UnitTests/Views/DatePickerTests.cs +++ b/UnitTests/Views/DatePickerTests.cs @@ -49,8 +49,9 @@ public void DatePicker_ShouldNot_SetDateOutOfRange_UsingNextMonthButton () var date = new DateTime (9999, 11, 15); var datePicker = new DatePicker (date); - Application.Top.Add (datePicker); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (datePicker); + Application.Begin (top); // Set focus to next month button datePicker.FocusNext (); @@ -72,10 +73,11 @@ public void DatePicker_ShouldNot_SetDateOutOfRange_UsingPreviousMonthButton () { var date = new DateTime (1, 2, 15); var datePicker = new DatePicker (date); + var top = new Toplevel (); // Move focus to previous month button - Application.Top.Add (datePicker); - Application.Begin (Application.Top); + top.Add (datePicker); + Application.Begin (top); // set focus to the previous month button datePicker.FocusNext (); diff --git a/UnitTests/Views/FrameViewTests.cs b/UnitTests/Views/FrameViewTests.cs index 9edd4ebbcf..31212a6b5a 100644 --- a/UnitTests/Views/FrameViewTests.cs +++ b/UnitTests/Views/FrameViewTests.cs @@ -44,8 +44,9 @@ public void Draw_Defaults () var fv = new FrameView (); Assert.Equal (string.Empty, fv.Title); Assert.Equal (string.Empty, fv.Text); - Application.Top.Add (fv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (fv); + Application.Begin (top); Assert.Equal (new Rectangle (0, 0, 0, 0), fv.Frame); TestHelpers.AssertDriverContentsWithFrameAre (@"", _output); diff --git a/UnitTests/Views/GraphViewTests.cs b/UnitTests/Views/GraphViewTests.cs index 7362e7cf18..f701ebe21c 100644 --- a/UnitTests/Views/GraphViewTests.cs +++ b/UnitTests/Views/GraphViewTests.cs @@ -1500,6 +1500,7 @@ public void ViewChangeText_RendersCorrectly (bool useFill) // create a wide window var mount = new View { Width = 100, Height = 100 }; + var top = new Toplevel (); try { @@ -1521,8 +1522,8 @@ public void ViewChangeText_RendersCorrectly (bool useFill) //putting mount into Toplevel since changing size //also change AutoSize to false - Application.Top.Add (mount); - Application.Begin (Application.Top); + top.Add (mount); + Application.Begin (top); // render view view.ColorScheme = new ColorScheme (); @@ -1541,6 +1542,7 @@ public void ViewChangeText_RendersCorrectly (bool useFill) } finally { + top.Dispose (); Application.Shutdown (); } } diff --git a/UnitTests/Views/HexViewTests.cs b/UnitTests/Views/HexViewTests.cs index eff9013e5c..dc60c17622 100644 --- a/UnitTests/Views/HexViewTests.cs +++ b/UnitTests/Views/HexViewTests.cs @@ -98,8 +98,9 @@ public void Constructors_Defaults () public void CursorPosition_Encoding_Default () { var hv = new HexView (LoadStream ()) { Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (hv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (hv); + Application.Begin (top); Assert.Equal (new Point (1, 1), hv.CursorPosition); @@ -126,8 +127,9 @@ public void CursorPosition_Encoding_Default () public void CursorPosition_Encoding_Unicode () { var hv = new HexView (LoadStream (true)) { Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (hv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (hv); + Application.Begin (top); Assert.Equal (new Point (1, 1), hv.CursorPosition); @@ -220,8 +222,9 @@ public void Exceptions_Tests () public void KeyBindings_Command () { var hv = new HexView (LoadStream ()) { Width = 20, Height = 10 }; - Application.Top.Add (hv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (hv); + Application.Begin (top); Assert.Equal (63, hv.Source.Length); Assert.Equal (1, hv.Position); @@ -348,8 +351,9 @@ public void PositionChanged_Event () var hv = new HexView (LoadStream ()) { Width = Dim.Fill (), Height = Dim.Fill () }; HexViewEventArgs hexViewEventArgs = null; hv.PositionChanged += (s, e) => hexViewEventArgs = e; - Application.Top.Add (hv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (hv); + Application.Begin (top); Assert.True (hv.NewKeyDownEvent (Key.CursorRight)); // left side must press twice Assert.True (hv.NewKeyDownEvent (Key.CursorRight)); @@ -365,8 +369,9 @@ public void PositionChanged_Event () public void Source_Sets_DisplayStart_And_Position_To_Zero_If_Greater_Than_Source_Length () { var hv = new HexView (LoadStream ()) { Width = 10, Height = 5 }; - Application.Top.Add (hv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (hv); + Application.Begin (top); Assert.True (hv.NewKeyDownEvent (Key.End)); Assert.Equal (62, hv.DisplayStart); @@ -379,7 +384,7 @@ public void Source_Sets_DisplayStart_And_Position_To_Zero_If_Greater_Than_Source hv.Source = LoadStream (); hv.Width = Dim.Fill (); hv.Height = Dim.Fill (); - Application.Top.LayoutSubviews (); + top.LayoutSubviews (); Assert.Equal (0, hv.DisplayStart); Assert.Equal (0, hv.Position - 1); diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs index 343b763e80..6a7d10df64 100644 --- a/UnitTests/Views/LabelTests.cs +++ b/UnitTests/Views/LabelTests.cs @@ -96,11 +96,12 @@ public void AutoSize_Stays_True_AnchorEnd () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (label.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @" @@ -137,11 +138,12 @@ public void AutoSize_Stays_True_Center () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (label.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @" @@ -178,7 +180,8 @@ public void AutoSize_Stays_True_With_EmptyText () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.True (label.AutoSize); @@ -186,7 +189,7 @@ public void AutoSize_Stays_True_With_EmptyText () Assert.True (label.AutoSize); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); var expected = @" @@ -226,8 +229,9 @@ public void Label_Draw_Fill_Remaining_AutoSize_True () tf2.Text = "This TextFormatter (tf2) with fill will be cleared on rewritten."; Size tf2Size = tf2.Size; - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.True (label.AutoSize); @@ -277,8 +281,9 @@ This TextFormatter (tf2) is rewritten. public void Label_Draw_Horizontal_Simple_Runes () { var label = new Label { Text = "Demo Simple Rune" }; - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.True (label.AutoSize); Assert.Equal (new Rectangle (0, 0, 16, 1), label.Frame); @@ -296,8 +301,9 @@ Demo Simple Rune public void Label_Draw_Vertical_Simple_Runes () { var label = new Label { TextDirection = TextDirection.TopBottom_LeftRight, Text = "Demo Simple Rune" }; - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.NotNull (label.Width); Assert.NotNull (label.Height); @@ -330,8 +336,9 @@ public void Label_Draw_Vertical_Simple_Runes () public void Label_Draw_Vertical_Wide_Runes () { var label = new Label { TextDirection = TextDirection.TopBottom_LeftRight, Text = "デモエムポンズ" }; - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); var expected = @" デ @@ -411,11 +418,12 @@ public void Update_Only_On_Or_After_Initialize () var label = new Label { X = Pos.Center (), Y = Pos.Center (), Text = "Say Hello 你" }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.False (label.IsInitialized); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.True (label.IsInitialized); @@ -441,11 +449,12 @@ public void Update_Parameterless_Only_On_Or_After_Initialize () var label = new Label { X = Pos.Center (), Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); Assert.False (label.IsInitialized); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.True (label.IsInitialized); @@ -471,8 +480,9 @@ public void Update_Parameterless_Only_On_Or_After_Initialize () public void Full_Border () { var label = new Label { Text = "Test", /*Width = 6, Height = 3, */BorderStyle = LineStyle.Single }; - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.Equal (new (0, 0, 6, 3), label.Frame); Assert.Equal (new (0, 0, 4, 1), label.Bounds); @@ -493,12 +503,13 @@ public void With_Top_Margin_Without_Top_Border () var label = new Label { Text = "Test", /*Width = 6, Height = 3,*/ BorderStyle = LineStyle.Single }; label.Margin.Thickness = new Thickness (0, 1, 0, 0); label.Border.Thickness = new Thickness (1, 0, 1, 1); - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.Equal (new (0, 0, 6, 3), label.Frame); Assert.Equal (new (0, 0, 4, 1), label.Bounds); - Application.Begin (Application.Top); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -514,12 +525,13 @@ public void Without_Top_Border () { var label = new Label { Text = "Test", /* Width = 6, Height = 3, */BorderStyle = LineStyle.Single }; label.Border.Thickness = new Thickness (1, 0, 1, 1); - Application.Top.Add (label); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (label); + Application.Begin (top); Assert.Equal (new (0, 0, 6, 2), label.Frame); Assert.Equal (new (0, 0, 4, 1), label.Bounds); - Application.Begin (Application.Top); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" diff --git a/UnitTests/Views/ListViewTests.cs b/UnitTests/Views/ListViewTests.cs index 8acd233af4..71193de12e 100644 --- a/UnitTests/Views/ListViewTests.cs +++ b/UnitTests/Views/ListViewTests.cs @@ -53,8 +53,9 @@ public void Ensures_Visibility_SelectedItem_On_MoveDown_And_MoveUp () var lv = new ListView { Width = Dim.Fill (), Height = Dim.Fill (), Source = new ListWrapper (source) }; var win = new Window (); win.Add (lv); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (12, 12); Application.Refresh (); @@ -300,8 +301,9 @@ public void EnsureSelectedItemVisible_SelectedItem () } var lv = new ListView { Width = 10, Height = 5, Source = new ListWrapper (source) }; - Application.Top.Add (lv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (lv); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -335,8 +337,9 @@ public void EnsureSelectedItemVisible_Top () List source = new () { "First", "Second" }; var lv = new ListView { Width = Dim.Fill (), Height = 1, Source = new ListWrapper (source) }; lv.SelectedItem = 1; - Application.Top.Add (lv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (lv); + Application.Begin (top); Assert.Equal ("Second ", GetContents (0)); Assert.Equal (new string (' ', 7), GetContents (1)); @@ -618,8 +621,9 @@ public void RowRender_Event () List source = new () { "one", "two", "three" }; var lv = new ListView { Width = Dim.Fill (), Height = Dim.Fill () }; lv.RowRender += (s, _) => rendered = true; - Application.Top.Add (lv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (lv); + Application.Begin (top); Assert.False (rendered); lv.SetSource (source); @@ -688,69 +692,76 @@ public void Render ( public IList ToList () { return new List { "One", "Two", "Three" }; } } - // No longer needed given PR #2920 - // [Fact, AutoInitShutdown] - // public void Clicking_On_Border_Is_Ignored () - // { - // var selected = ""; - // var lv = new ListView { - // Height = 5, - // Width = 7, - // BorderStyle = LineStyle.Single - // }; - // lv.SetSource (new List { "One", "Two", "Three", "Four" }); - // lv.SelectedItemChanged += (s, e) => selected = e.Value.ToString (); - // Application.Top.Add (lv); - // Application.Begin (Application.Top); - - // Assert.Equal (new Thickness (1), lv.Border.Thickness); - // Assert.Equal (-1, lv.SelectedItem); - // Assert.Equal ("", lv.Text); - // TestHelpers.AssertDriverContentsWithFrameAre (@" - //┌─────┐ - //│One │ - //│Two │ - //│Three│ - //└─────┘", output); - - // Assert.True (lv.OnMouseEvent (new MouseEvent { - // X = 0, - // Y = 0, - // Flags = MouseFlags.Button1Clicked - // })); - // Assert.Equal ("", selected); - // Assert.Equal (-1, lv.SelectedItem); - - // Assert.True (lv.OnMouseEvent (new MouseEvent { - // X = 0, - // Y = 1, - // Flags = MouseFlags.Button1Clicked - // })); - // Assert.Equal ("One", selected); - // Assert.Equal (0, lv.SelectedItem); - - // Assert.True (lv.OnMouseEvent (new MouseEvent { - // X = 0, - // Y = 2, - // Flags = MouseFlags.Button1Clicked - // })); - // Assert.Equal ("Two", selected); - // Assert.Equal (1, lv.SelectedItem); - - // Assert.True (lv.OnMouseEvent (new MouseEvent { - // X = 0, - // Y = 3, - // Flags = MouseFlags.Button1Clicked - // })); - // Assert.Equal ("Three", selected); - // Assert.Equal (2, lv.SelectedItem); - - // Assert.True (lv.OnMouseEvent (new MouseEvent { - // X = 0, - // Y = 4, - // Flags = MouseFlags.Button1Clicked - // })); - // Assert.Equal ("Three", selected); - // Assert.Equal (2, lv.SelectedItem); - // } + [Fact] + [AutoInitShutdown] + public void Clicking_On_Border_Is_Ignored () + { + var selected = ""; + var lv = new ListView + { + Height = 5, + Width = 7, + BorderStyle = LineStyle.Single + }; + lv.SetSource (new List { "One", "Two", "Three", "Four" }); + lv.SelectedItemChanged += (s, e) => selected = e.Value.ToString (); + var top = new Toplevel (); + top.Add (lv); + Application.Begin (top); + + Assert.Equal (new Thickness (1), lv.Border.Thickness); + Assert.Equal (-1, lv.SelectedItem); + Assert.Equal ("", lv.Text); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌─────┐ +│One │ +│Two │ +│Three│ +└─────┘", _output); + + Application.OnMouseEvent (new (new () + { + X = 0, + Y = 0, + Flags = MouseFlags.Button1Clicked + })); + Assert.Equal ("", selected); + Assert.Equal (-1, lv.SelectedItem); + + Application.OnMouseEvent (new (new () + { + X = 1, + Y = 1, + Flags = MouseFlags.Button1Clicked + })); + Assert.Equal ("One", selected); + Assert.Equal (0, lv.SelectedItem); + + Application.OnMouseEvent (new (new () + { + X = 1, + Y = 2, + Flags = MouseFlags.Button1Clicked + })); + Assert.Equal ("Two", selected); + Assert.Equal (1, lv.SelectedItem); + + Application.OnMouseEvent (new (new () + { + X = 1, + Y = 3, + Flags = MouseFlags.Button1Clicked + })); + Assert.Equal ("Three", selected); + Assert.Equal (2, lv.SelectedItem); + + Application.OnMouseEvent (new (new () + { + X = 1, + Y = 4, + Flags = MouseFlags.Button1Clicked + })); + Assert.Equal ("Three", selected); + Assert.Equal (2, lv.SelectedItem); + } } diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs index 6f5f6b8bd7..ddd216bd58 100644 --- a/UnitTests/Views/MenuBarTests.cs +++ b/UnitTests/Views/MenuBarTests.cs @@ -26,7 +26,7 @@ public void AllowNullChecked_Get_Set () }; //new CheckBox (); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (menu); Application.Begin (top); @@ -135,7 +135,7 @@ public void CanExecute_HotKey () ) ] }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (menu); bool CanExecuteNew () { return win == null; } @@ -230,7 +230,7 @@ public void Constructors_Defaults () [AutoInitShutdown] public void Disabled_MenuBar_Is_Never_Opened () { - Toplevel top = Application.Top; + Toplevel top = new (); var menu = new MenuBar { @@ -272,7 +272,7 @@ public void Disabled_MenuItem_Is_Never_Selected () ] }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (menu); Application.Begin (top); @@ -362,10 +362,10 @@ top.Subviews [1] [AutoInitShutdown] public void Draw_A_Menu_Over_A_Dialog () { - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window (); top.Add (win); - Application.Begin (top); + RunState rsTop = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (40, 15); Assert.Equal (new Rectangle (0, 0, 40, 15), win.Frame); @@ -467,7 +467,7 @@ void ChangeMenuTitle (string title) menu.SetNeedsDisplay (); } - RunState rs = Application.Begin (dialog); + RunState rsDialog = Application.Begin (dialog); Assert.Equal (new Rectangle (2, 2, 15, 4), dialog.Frame); @@ -494,7 +494,7 @@ void ChangeMenuTitle (string title) Assert.Equal ("File", menu.Menus [0].Title); menu.OpenMenu (); var firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsDialog, ref firstIteration); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -526,7 +526,7 @@ void ChangeMenuTitle (string title) // Need to fool MainLoop into thinking it's running Application.MainLoop.Running = true; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsDialog, ref firstIteration); Assert.Equal (items [0], menu.Menus [0].Title); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -560,14 +560,14 @@ void ChangeMenuTitle (string title) ); firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsDialog, ref firstIteration); Assert.Equal (items [i], menu.Menus [0].Title); } ((FakeDriver)Application.Driver).SetBufferSize (20, 15); menu.OpenMenu (); firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsDialog, ref firstIteration); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -589,7 +589,8 @@ void ChangeMenuTitle (string title) _output ); - Application.End (rs); + Application.End (rsDialog); + Application.End (rsTop); } [Fact] @@ -787,8 +788,9 @@ public void DrawFrame_With_Negative_Positions () Assert.Equal (new Point (-1, -1), new Point (menu.Frame.X, menu.Frame.Y)); + Application.Begin (new ()); menu.OpenMenu (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ──────┐ @@ -863,8 +865,9 @@ public void DrawFrame_With_Negative_Positions_Disabled_Border () Assert.Equal (new Point (-2, -1), new Point (menu.Frame.X, menu.Frame.Y)); + Application.Begin (new ()); menu.OpenMenu (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ne @@ -924,8 +927,9 @@ public void DrawFrame_With_Positive_Positions () Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); + Application.Begin (new ()); menu.OpenMenu (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" ┌──────┐ @@ -953,8 +957,9 @@ public void DrawFrame_With_Positive_Positions_Disabled_Border () Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); + Application.Begin (new ()); menu.OpenMenu (); - Application.Begin (Application.Top); + Application.Refresh (); var expected = @" One @@ -990,8 +995,9 @@ public void HotKey_MenuBar_OnKeyDown_OnKeyUp_ProcessKeyPressed () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.False (newAction); Assert.False (copyAction); @@ -1098,8 +1104,9 @@ .Children [0] ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.False (newAction); Assert.False (copyAction); @@ -1134,21 +1141,22 @@ public void Key_Open_And_Close_The_MenuBar () new MenuBarItem ("File", new MenuItem [] { new ("New", "", null) }) ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); - Assert.True (Application.Top.NewKeyDownEvent (menu.Key)); + Assert.True (top.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); - Assert.True (Application.Top.NewKeyDownEvent (menu.Key)); + Assert.True (top.NewKeyDownEvent (menu.Key)); Assert.False (menu.IsMenuOpen); menu.Key = Key.F10.WithShift; - Assert.False (Application.Top.NewKeyDownEvent (Key.F9)); + Assert.False (top.NewKeyDownEvent (Key.F9)); Assert.False (menu.IsMenuOpen); - Assert.True (Application.Top.NewKeyDownEvent (Key.F10.WithShift)); + Assert.True (top.NewKeyDownEvent (Key.F10.WithShift)); Assert.True (menu.IsMenuOpen); - Assert.True (Application.Top.NewKeyDownEvent (Key.F10.WithShift)); + Assert.True (top.NewKeyDownEvent (Key.F10.WithShift)); Assert.False (menu.IsMenuOpen); } @@ -1266,12 +1274,13 @@ params KeyCode [] keys miCurrent = null; }; menu.UseKeysUpDownAsKeysLeftRight = true; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); foreach (KeyCode key in keys) { - Application.Top.NewKeyDownEvent (new Key (key)); + top.NewKeyDownEvent (new Key (key)); Application.MainLoop.RunIteration (); } @@ -1313,12 +1322,13 @@ public void KeyBindings_Shortcut_Commands (string expectedAction, params KeyCode }; menu.UseKeysUpDownAsKeysLeftRight = true; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); foreach (KeyCode key in keys) { - Assert.True (Application.Top.NewKeyDownEvent (new Key (key))); + Assert.True (top.NewKeyDownEvent (new Key (key))); Application.MainLoop.RunIteration (); } @@ -1352,8 +1362,9 @@ public void Menu_With_Separator () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); menu.OpenMenu (); Application.Refresh (); @@ -1398,8 +1409,9 @@ public void Menu_With_Separator_Disabled_Border () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); menu.OpenMenu (); Application.Refresh (); @@ -1457,18 +1469,19 @@ .Children [0] ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); } @@ -1497,7 +1510,7 @@ public void MenuBar_In_Window_Without_Other_Views_With_Top_Init () ] }; win.Add (menu); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (40, 8); @@ -1605,7 +1618,7 @@ public void MenuBar_In_Window_Without_Other_Views_With_Top_Init_With_Parameterle ] }; win.Add (menu); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Iteration += (s, a) => @@ -1692,7 +1705,7 @@ public void MenuBar_In_Window_Without_Other_Views_With_Top_Init_With_Parameterle Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] @@ -1938,28 +1951,29 @@ public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKey ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); // Open first Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); // Open second Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorRight)); Assert.True (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); // Close menu Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.False (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); - Application.Top.Remove (menu); + top.Remove (menu); // Now test WITH HotKeys menu = new MenuBar @@ -1984,16 +1998,16 @@ public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKey ] }; - Application.Top.Add (menu); + top.Add (menu); // Open first Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); // Open second - Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorRight)); + Assert.True (top.Subviews [1].NewKeyDownEvent (Key.CursorRight)); Assert.True (menu.IsMenuOpen); Application.Top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); @@ -2001,7 +2015,7 @@ public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKey // Close menu Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.False (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); } @@ -2064,17 +2078,18 @@ public void MenuBar_Submenus_Alignment_Correct () var menu = new MenuBar { Menus = items }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); for (var i = 0; i < expectedMenu.Menus.Length; i++) { menu.OpenMenu (i); Assert.True (menu.IsMenuOpen); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (i), _output); } } @@ -2093,8 +2108,9 @@ public void MenuBar_With_Action_But_Without_MenuItems_Not_Throw () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); #if SUPPORT_ALT_TO_ACTIVATE_MENU Assert.True ( @@ -2120,7 +2136,8 @@ public void MenuBarItem_Children_Null_Does_Not_Throw () new MenuBarItem ("Test", "", null) ] }; - Application.Top.Add (menu); + var top = new Toplevel (); + top.Add (menu); Exception exception = Record.Exception (() => menu.NewKeyDownEvent (Key.Space)); Assert.Null (exception); @@ -2166,8 +2183,9 @@ public void MenuOpened_On_Disabled_MenuItem () mCurrent = menu._openMenu; }; menu.UseKeysUpDownAsKeysLeftRight = true; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); // open the menu Assert.True ( @@ -2295,14 +2313,15 @@ public void MenuOpening_MenuOpened_MenuClosing_Events () isMenuClosed = true; } }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); isMenuClosed = !menu.IsMenuOpen; Assert.False (isMenuClosed); - Application.Top.Draw (); + top.Draw (); var expected = @" Edit @@ -2316,7 +2335,7 @@ public void MenuOpening_MenuOpened_MenuClosing_Events () Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); Assert.False (isMenuClosed); - Application.Top.Draw (); + top.Draw (); expected = @" Edit @@ -2330,7 +2349,7 @@ public void MenuOpening_MenuOpened_MenuClosing_Events () Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.False (menu.IsMenuOpen); Assert.True (isMenuClosed); - Application.Top.Draw (); + top.Draw (); expected = @" Edit @@ -2369,9 +2388,10 @@ public void MouseEvent_Test () miCurrent = e.MenuItem; mCurrent = menu.openCurrentMenu; }; - Application.Top.Add (menu); - Application.Begin (Application.Top); - + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); + // Click on Edit Assert.True ( menu.OnMouseEvent ( @@ -2470,14 +2490,15 @@ expectedMenu.Menus [i].Children.Length > 0 var menu = new MenuBar { Menus = items }; var tf = new TextField { Y = 2, Width = 10 }; - Application.Top.Add (menu, tf); + var top = new Toplevel (); + top.Add (menu, tf); - Application.Begin (Application.Top); + Application.Begin (top); Assert.True (tf.HasFocus); Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); // Right - Edit has no sub menu; this tests that no sub menu shows @@ -2487,33 +2508,33 @@ expectedMenu.Menus [i].Children.Length > 0 Assert.Equal (1, menu._selected); Assert.Equal (-1, menu._selectedSub); Assert.Null (menu._openSubMenu); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); // Right - Format Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight)); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (2), _output); // Left - Edit Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorLeft)); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorLeft)); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); Assert.True (menu.NewKeyDownEvent (menu.Key)); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); } @@ -2564,14 +2585,15 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () }; var tf = new TextField { Y = 2, Width = 10 }; - Application.Top.Add (menu, tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu, tf); + Application.Begin (top); Assert.True (tf.HasFocus); Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); Assert.True ( @@ -2581,7 +2603,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () ); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); Assert.True ( @@ -2591,7 +2613,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () ); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (2), _output); Assert.True ( @@ -2601,7 +2623,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () ); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); Assert.True ( @@ -2611,13 +2633,13 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () ); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); Assert.True (menu.OnMouseEvent (new MouseEvent { X = 8, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); } @@ -2699,8 +2721,9 @@ public void Resizing_Close_Menus () ) ] }; - Application.Top.Add (menu); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + RunState rs = Application.Begin (top); menu.OpenMenu (); var firstIteration = false; @@ -2773,8 +2796,9 @@ public void ShortCut_Activates () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Application.OnKeyDown (Key.S.WithCtrl); Application.MainLoop.RunIteration (); @@ -2825,13 +2849,14 @@ public void UseSubMenusSingleFrame_False_By_Keyboard () } }; menu.UseKeysUpDownAsKeysLeftRight = true; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -2840,7 +2865,7 @@ public void UseSubMenusSingleFrame_False_By_Keyboard () Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.True (menu.NewKeyDownEvent (menu.Key)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2854,7 +2879,7 @@ public void UseSubMenusSingleFrame_False_By_Keyboard () pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorDown)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2869,7 +2894,7 @@ public void UseSubMenusSingleFrame_False_By_Keyboard () pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.True (Application.Top.Subviews [2].NewKeyDownEvent (Key.CursorLeft)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2883,7 +2908,7 @@ public void UseSubMenusSingleFrame_False_By_Keyboard () pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.Esc)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2927,13 +2952,14 @@ public void UseSubMenusSingleFrame_False_By_Mouse () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -2947,7 +2973,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2969,7 +2995,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -2992,7 +3018,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3011,7 +3037,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3058,14 +3084,15 @@ public void UseSubMenusSingleFrame_False_Disabled_Border () }; menu.UseKeysUpDownAsKeysLeftRight = true; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); Assert.True (menu.NewKeyDownEvent (menu.Key)); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -3076,7 +3103,7 @@ public void UseSubMenusSingleFrame_False_Disabled_Border () _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorDown)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3122,15 +3149,16 @@ public void UseSubMenusSingleFrame_True_By_Keyboard () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); menu.UseSubMenusSingleFrame = true; Assert.True (menu.UseSubMenusSingleFrame); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -3140,7 +3168,7 @@ public void UseSubMenusSingleFrame_True_By_Keyboard () Assert.Equal (new Rectangle (1, 0, 8, 1), pos); Assert.True (menu.NewKeyDownEvent (menu.Key)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3156,7 +3184,7 @@ public void UseSubMenusSingleFrame_True_By_Keyboard () Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorDown)); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.Enter)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3172,7 +3200,7 @@ public void UseSubMenusSingleFrame_True_By_Keyboard () Assert.Equal (new Rectangle (1, 0, 15, 7), pos); Assert.True (Application.Top.Subviews [2].NewKeyDownEvent (Key.Enter)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3187,7 +3215,7 @@ public void UseSubMenusSingleFrame_True_By_Keyboard () Assert.Equal (new Rectangle (1, 0, 10, 6), pos); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.Esc)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3232,15 +3260,16 @@ public void UseSubMenusSingleFrame_True_By_Mouse () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); menu.UseSubMenusSingleFrame = true; Assert.True (menu.UseSubMenusSingleFrame); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -3254,7 +3283,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3273,7 +3302,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3293,7 +3322,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3312,7 +3341,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3357,8 +3386,9 @@ public void UseSubMenusSingleFrame_True_Disabled_Border () ) ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.False (menu.UseSubMenusSingleFrame); @@ -3366,7 +3396,7 @@ public void UseSubMenusSingleFrame_True_Disabled_Border () Assert.True (menu.UseSubMenusSingleFrame); Assert.True (menu.NewKeyDownEvent (menu.Key)); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -3378,7 +3408,7 @@ public void UseSubMenusSingleFrame_True_Disabled_Border () Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.CursorDown)); Assert.True (Application.Top.Subviews [1].NewKeyDownEvent (Key.Enter)); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3427,14 +3457,15 @@ public void UseSubMenusSingleFrame_True_Without_Border () ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.Equal (Point.Empty, new Point (menu.Frame.X, menu.Frame.Y)); Assert.True (menu.UseSubMenusSingleFrame); Assert.Equal (LineStyle.None, menu.MenusBorderStyle); - Application.Top.Draw (); + top.Draw (); var expected = @" Numbers @@ -3448,7 +3479,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3465,7 +3496,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3483,7 +3514,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3500,7 +3531,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); - Application.Top.Draw (); + top.Draw (); expected = @" Numbers @@ -3521,8 +3552,9 @@ public void Visible_False_Key_Does_Not_Open_And_Close_All_Opened_Menus () new MenuBarItem ("File", new MenuItem [] { new ("New", "", null) }) ] }; - Application.Top.Add (menu); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu); + Application.Begin (top); Assert.True (menu.Visible); Assert.True (menu.NewKeyDownEvent (menu.Key)); @@ -3674,8 +3706,9 @@ public void Click_Another_View_Close_An_Open_Menu () var btnClicked = false; var btn = new Button { Y = 4, Text = "Test" }; btn.Accept += (s, e) => btnClicked = true; - Application.Top.Add (menu, btn); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (menu, btn); + Application.Begin (top); Application.OnMouseEvent (new (new () { X = 0, Y = 4, Flags = MouseFlags.Button1Clicked })); Assert.True (btnClicked); diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs index 41270d5583..87bbebe3ed 100644 --- a/UnitTests/Views/OverlappedTests.cs +++ b/UnitTests/Views/OverlappedTests.cs @@ -98,6 +98,8 @@ public void AllChildClosed_Event_Test () Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -192,6 +194,7 @@ public void Dispose_Toplevel_IsOverlappedContainer_False_With_Begin_End () RunState rs = Application.Begin (top); Application.End (rs); + top.Dispose (); Application.Shutdown (); #if DEBUG_IDISPOSABLE @@ -208,7 +211,7 @@ public void Dispose_Toplevel_IsOverlappedContainer_True_With_Begin () var overlapped = new Toplevel { IsOverlappedContainer = true }; RunState rs = Application.Begin (overlapped); Application.End (rs); - + overlapped.Dispose (); Application.Shutdown (); } @@ -333,6 +336,8 @@ public void Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -422,6 +427,8 @@ Application.OverlappedChildren [i].Id Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -505,6 +512,8 @@ public void MoveCurrent_Returns_False_If_The_Current_And_Top_Parameter_Are_Both_ Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -598,6 +607,8 @@ public void OverlappedContainer_Open_And_Close_Modal_And_Open_Not_Modal_Toplevel Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -690,6 +701,8 @@ public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_With_ Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -767,6 +780,8 @@ public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_Witho Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -843,6 +858,8 @@ public void OverlappedContainer_With_Toplevel_RequestStop_Balanced () Application.Run (overlapped); Assert.Empty (Application.OverlappedChildren); + Assert.NotNull (Application.OverlappedTop); + Assert.NotNull (Application.Top); } [Fact] @@ -853,12 +870,44 @@ public void Visible_False_Does_Not_Clear () var win1 = new Window { Width = 5, Height = 5, Visible = false }; var win2 = new Window { X = 1, Y = 1, Width = 5, Height = 5 }; ((FakeDriver)Application.Driver).SetBufferSize (10, 10); - RunState rs = Application.Begin (overlapped); - Application.Begin (win1); - Application.Begin (win2); - Assert.Equal (win2, Application.Current); + RunState rsOverlapped = Application.Begin (overlapped); + + // Need to fool MainLoop into thinking it's running + Application.MainLoop.Running = true; + + // RunIteration must be call on each iteration because + // it's using the Begin and not the Run method var firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsOverlapped, ref firstIteration); + + Assert.Equal (overlapped, rsOverlapped.Toplevel); + Assert.Equal (Application.Top, rsOverlapped.Toplevel); + Assert.Equal (Application.OverlappedTop, rsOverlapped.Toplevel); + Assert.Equal (Application.Current, rsOverlapped.Toplevel); + Assert.Equal (overlapped, Application.Current); + + RunState rsWin1 = Application.Begin (win1); + Application.RunIteration (ref rsOverlapped, ref firstIteration); + + Assert.Equal (overlapped, rsOverlapped.Toplevel); + Assert.Equal (Application.Top, rsOverlapped.Toplevel); + Assert.Equal (Application.OverlappedTop, rsOverlapped.Toplevel); + // The win1 Visible is false and cannot be set as the Current + Assert.Equal (Application.Current, rsOverlapped.Toplevel); + Assert.Equal (overlapped, Application.Current); + Assert.Equal (win1, rsWin1.Toplevel); + + RunState rsWin2 = Application.Begin (win2); + Application.RunIteration (ref rsOverlapped, ref firstIteration); + + // Here the Current and the rsOverlapped.Toplevel is now the win2 + // and not the original overlapped + Assert.Equal (win2, rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Equal (Application.Current, rsWin2.Toplevel); + Assert.Equal (win2, Application.Current); + Assert.Equal (win1, rsWin1.Toplevel); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -902,6 +951,15 @@ Colors.ColorSchemes ["Base"].Normal ); Assert.Equal (win2.Border, Application.MouseGrabView); + Application.RunIteration (ref rsOverlapped, ref firstIteration); + + Assert.Equal (win2, rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Equal (Application.Current, rsWin2.Toplevel); + Assert.Equal (win2, Application.Current); + Assert.Equal (win1, rsWin1.Toplevel); + Application.OnMouseEvent ( new MouseEventEventArgs ( new MouseEvent @@ -914,9 +972,14 @@ Colors.ColorSchemes ["Base"].Normal ) ); - // Need to fool MainLoop into thinking it's running - Application.MainLoop.Running = true; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsOverlapped, ref firstIteration); + + Assert.Equal (win2, rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Equal (Application.Current, rsWin2.Toplevel); + Assert.Equal (win2, Application.Current); + Assert.Equal (win1, rsWin1.Toplevel); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -944,6 +1007,61 @@ Colors.ColorSchemes ["Base"].Normal attributes ); + // This will end the win2 and not the overlapped + Application.End (rsOverlapped); + // rsOverlapped has been disposed and Toplevel property is null + // So we must use another valid RunState to iterate + Application.RunIteration (ref rsWin1, ref firstIteration); +#if DEBUG_IDISPOSABLE + Assert.True (rsOverlapped.WasDisposed); +#endif + Assert.Null (rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Equal (Application.Current, rsWin1.Toplevel); + Assert.Equal (win1, Application.Current); + Assert.Equal (win1, rsWin1.Toplevel); + + Application.End (rsWin1); + // rsWin1 has been disposed and Toplevel property is null + // So we must use another valid RunState to iterate + Application.RunIteration (ref rsWin2, ref firstIteration); +#if DEBUG_IDISPOSABLE + Assert.True (rsOverlapped.WasDisposed); + Assert.True (rsWin1.WasDisposed); +#endif + Assert.Null (rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Equal (Application.Current, overlapped); + Assert.Null (rsWin1.Toplevel); + // See here that the only Toplevel that needs to End is the overlapped + // which the rsWin2 now has the Toplevel set to the overlapped + Assert.Equal (overlapped, rsWin2.Toplevel); + + Application.End (rsWin2); + // There is no more RunState to iteration +#if DEBUG_IDISPOSABLE + Assert.True (rsOverlapped.WasDisposed); + Assert.True (rsWin1.WasDisposed); + Assert.True (rsWin2.WasDisposed); +#endif + Assert.Null (rsOverlapped.Toplevel); + Assert.Equal (Application.Top, overlapped); + Assert.Equal (Application.OverlappedTop, overlapped); + Assert.Null (Application.Current); + Assert.Null (rsWin1.Toplevel); + Assert.Null (rsWin2.Toplevel); + +#if DEBUG_IDISPOSABLE + Assert.False (win2.WasDisposed); + Assert.False (win1.WasDisposed); + Assert.False (overlapped.WasDisposed); +#endif + // Now dispose all them + win2.Dispose (); + win1.Dispose (); + overlapped.Dispose (); Application.Shutdown (); } diff --git a/UnitTests/Views/RadioGroupTests.cs b/UnitTests/Views/RadioGroupTests.cs index 1599a2b38c..bc7ba90bb3 100644 --- a/UnitTests/Views/RadioGroupTests.cs +++ b/UnitTests/Views/RadioGroupTests.cs @@ -171,9 +171,10 @@ public void Orientation_Width_Height_Vertical_Horizontal_Space () var rg = new RadioGroup { RadioLabels = new [] { "Test", "New Test 你" } }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (rg); - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (30, 5); Assert.Equal (Orientation.Vertical, rg.Orientation); diff --git a/UnitTests/Views/RuneCellTests.cs b/UnitTests/Views/RuneCellTests.cs index 3ce523a461..5d420444b5 100644 --- a/UnitTests/Views/RuneCellTests.cs +++ b/UnitTests/Views/RuneCellTests.cs @@ -72,8 +72,9 @@ public void RuneCell_LoadRuneCells_InheritsPreviousColorScheme () TextView tv = CreateTextView (); tv.Load (runeCells); - Application.Top.Add (tv); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + RunState rs = Application.Begin (top); Assert.True (tv.InheritsPreviousColorScheme); var expectedText = @" @@ -197,7 +198,8 @@ public void RuneCell_LoadRuneCells_Without_ColorScheme_Is_Never_Null () new RuneCell { Rune = new Rune ('t') } }; TextView tv = CreateTextView (); - Application.Top.Add (tv); + var top = new Toplevel (); + top.Add (tv); tv.Load (cells); for (var i = 0; i < tv.Lines; i++) @@ -240,8 +242,9 @@ void _textView_DrawColor (object sender, RuneCellEventArgs e) tv.Text = $"{TextModel.ToString (text [0])}\n{TextModel.ToString (text [1])}\n"; Assert.False (tv.WordWrap); - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs index eafe135df1..7ef271ac87 100644 --- a/UnitTests/Views/ScrollBarViewTests.cs +++ b/UnitTests/Views/ScrollBarViewTests.cs @@ -142,7 +142,8 @@ public void Both_Default_Draws_Correctly () var height = 40; var super = new Window { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (super); + var top = new Toplevel (); + top.Add (super); var horiz = new ScrollBarView { @@ -168,7 +169,7 @@ public void Both_Default_Draws_Correctly () }; super.Add (vert); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" @@ -287,10 +288,11 @@ public void ClearOnVisibleFalse_Gets_Sets () var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label { Text = text }; - Application.Top.Add (label); + var top = new Toplevel (); + top.Add (label); var sbv = new ScrollBarView (label, true, false) { Size = 100, ClearOnVisibleFalse = false }; - Application.Begin (Application.Top); + Application.Begin (top); Assert.True (sbv.Visible); @@ -308,7 +310,7 @@ This is a tes▼ sbv.Visible = false; Assert.False (sbv.Visible); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -324,7 +326,7 @@ This is a test sbv.Visible = true; Assert.True (sbv.Visible); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -359,85 +361,91 @@ This is a tes public void Constructor_ShowBothScrollIndicator_False_And_IsVertical_False_Refresh_Does_Not_Throws_An_Object_Null_Exception () { - // BUGBUG: v2 - Tig broke these tests; @bdisp help? - //var exception = Record.Exception (() => { - Application.Init (new FakeDriver ()); - - Toplevel top = Application.Top; - - var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - - List source = new (); - - for (var i = 0; i < 50; i++) - { - var text = $"item {i} - "; - - for (var j = 0; j < 160; j++) - { - var col = j.ToString (); - text += col.Length == 1 ? col [0] : col [1]; - } - - source.Add (text); - } - - var listView = new ListView - { - X = 0, - Y = 0, - Width = Dim.Fill (), - Height = Dim.Fill (), - Source = new ListWrapper (source) - }; - win.Add (listView); - - var newScrollBarView = new ScrollBarView (listView, false, false) { KeepContentAlwaysInViewport = true }; - win.Add (newScrollBarView); - - newScrollBarView.ChangedPosition += (s, e) => - { - listView.LeftItem = newScrollBarView.Position; - - if (listView.LeftItem != newScrollBarView.Position) - { - newScrollBarView.Position = listView.LeftItem; - } - - Assert.Equal (newScrollBarView.Position, listView.LeftItem); - listView.SetNeedsDisplay (); - }; - - listView.DrawContent += (s, e) => - { - newScrollBarView.Size = listView.MaxLength; - Assert.Equal (newScrollBarView.Size, listView.MaxLength); - newScrollBarView.Position = listView.LeftItem; - Assert.Equal (newScrollBarView.Position, listView.LeftItem); - newScrollBarView.Refresh (); - }; + var exception = Record.Exception ( + () => + { + Application.Init (new FakeDriver ()); + + Toplevel top = new (); + + var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; + + List source = new (); + + for (var i = 0; i < 50; i++) + { + var text = $"item {i} - "; + + for (var j = 0; j < 160; j++) + { + var col = j.ToString (); + text += col.Length == 1 ? col [0] : col [1]; + } + + source.Add (text); + } + + var listView = new ListView + { + X = 0, + Y = 0, + Width = Dim.Fill (), + Height = Dim.Fill (), + Source = new ListWrapper (source) + }; + win.Add (listView); + + var newScrollBarView = new ScrollBarView (listView, false, false) { KeepContentAlwaysInViewport = true }; + win.Add (newScrollBarView); + + newScrollBarView.ChangedPosition += (s, e) => + { + listView.LeftItem = newScrollBarView.Position; + + if (listView.LeftItem != newScrollBarView.Position) + { + newScrollBarView.Position = listView.LeftItem; + } + + Assert.Equal (newScrollBarView.Position, listView.LeftItem); + listView.SetNeedsDisplay (); + }; + + listView.DrawContent += (s, e) => + { + newScrollBarView.Size = listView.MaxLength; + Assert.Equal (newScrollBarView.Size, listView.MaxLength); + newScrollBarView.Position = listView.LeftItem; + Assert.Equal (newScrollBarView.Position, listView.LeftItem); + newScrollBarView.Refresh (); + }; + + top.Ready += (s, e) => + { + newScrollBarView.Position = 100; - top.Ready += (s, e) => - { - newScrollBarView.Position = 100; + Assert.Equal ( + newScrollBarView.Position, + newScrollBarView.Size + - listView.LeftItem + + (listView.LeftItem - listView.Bounds.Width)); + Assert.Equal (newScrollBarView.Position, listView.LeftItem); - //Assert.Equal (newScrollBarView.Position, newScrollBarView.Size - listView.LeftItem + (listView.LeftItem - listView.Bounds.Width)); - Assert.Equal (newScrollBarView.Position, listView.LeftItem); + Assert.Equal (92, newScrollBarView.Position); + Assert.Equal (92, listView.LeftItem); + Application.RequestStop (); + }; - //Assert.Equal (92, newScrollBarView.Position); - //Assert.Equal (92, listView.LeftItem); - Application.RequestStop (); - }; + top.Add (win); - top.Add (win); + Application.Run (top); - Application.Run (); + top.Dispose (); + Application.Shutdown (); - Application.Shutdown (); + }); - //}); - - //Assert.Null (exception); + Assert.Null (exception); } [Fact] @@ -448,7 +456,7 @@ public void () => { Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; List source = new (); @@ -507,7 +515,8 @@ public void Application.RequestStop (); }; top.Add (win); - Application.Run (); + Application.Run (top); + top.Dispose (); Application.Shutdown (); } ); @@ -522,11 +531,12 @@ public void ContentBottomRightCorner_Not_Redraw_If_Both_Size_Equal_To_Zero () var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label { Text = text }; - Application.Top.Add (label); + var top = new Toplevel (); + top.Add (label); var sbv = new ScrollBarView (label, true) { Size = 100 }; sbv.OtherScrollBarView.Size = 100; - Application.Begin (Application.Top); + Application.Begin (top); Assert.Equal (100, sbv.Size); Assert.Equal (100, sbv.OtherScrollBarView.Size); @@ -560,7 +570,7 @@ This is a tes▼ Assert.False (sbv.OtherScrollBarView.ShowScrollIndicator); Assert.False (sbv.Visible); Assert.False (sbv.OtherScrollBarView.Visible); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -582,7 +592,7 @@ This is a test Assert.True (sbv.OtherScrollBarView.ShowScrollIndicator); Assert.True (sbv.Visible); Assert.True (sbv.OtherScrollBarView.Visible); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -604,10 +614,11 @@ public void ContentBottomRightCorner_Not_Redraw_If_One_Size_Equal_To_Zero () var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label { Text = text }; - Application.Top.Add (label); + var top = new Toplevel (); + top.Add (label); var sbv = new ScrollBarView (label, true, false) { Size = 100 }; - Application.Begin (Application.Top); + Application.Begin (top); Assert.Equal (100, sbv.Size); Assert.Null (sbv.OtherScrollBarView); @@ -630,7 +641,7 @@ This is a tes▼ Assert.Equal (0, sbv.Size); Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.Visible); - Application.Top.Draw (); + top.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -670,11 +681,12 @@ public void Horizontal_Default_Draws_Correctly () var height = 3; var super = new Window { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (super); + var top = new Toplevel (); + top.Add (super); var sbv = new ScrollBarView { Id = "sbv", Size = width * 2, ShowScrollIndicator = true }; super.Add (sbv); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" @@ -722,7 +734,7 @@ public void Hosting_A_View_To_A_ScrollBarView () _scrollBar = new ScrollBarView (_hostView, true); - Application.Begin (Application.Top); + Application.Begin (_hostView.SuperView as Toplevel); Assert.True (_scrollBar.IsVertical); Assert.False (_scrollBar.OtherScrollBarView.IsVertical); @@ -820,9 +832,10 @@ public void Hosting_ShowBothScrollIndicator_Invisible () scrollBar.LayoutSubviews (); scrollBar.Refresh (); }; - Application.Top.Add (win); + var top = new Toplevel (); + top.Add (win); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (45, 20); Assert.True (scrollBar.AutoHideScrollBars); @@ -959,7 +972,7 @@ public void Hosting_Two_Vertical_ScrollBarView_Throws_ArgumentException () [AutoInitShutdown] public void Internal_Tests () { - Toplevel top = Application.Top; + Toplevel top = new (); Assert.Equal (new Rectangle (0, 0, 80, 25), top.Bounds); var view = new View { Width = Dim.Fill (), Height = Dim.Fill () }; top.Add (view); @@ -1116,10 +1129,11 @@ public void ShowScrollIndicator_False_Must_Also_Set_Visible_To_False_To_Not_Resp var label = new Label { AutoSize = false, Width = 14, Height = 5, Text = text }; var btn = new Button { X = 14, Text = "Click Me!" }; btn.Accept += (s, e) => clicked = true; - Application.Top.Add (label, btn); + var top = new Toplevel (); + top.Add (label, btn); var sbv = new ScrollBarView (label, true, false) { Size = 5 }; - Application.Begin (Application.Top); + Application.Begin (top); Assert.Equal (5, sbv.Size); Assert.Null (sbv.OtherScrollBarView); @@ -1155,7 +1169,7 @@ This is a test Assert.Equal (5, sbv.Size); Assert.False (sbv.ShowScrollIndicator); Assert.True (sbv.Visible); - Application.Top.Draw (); + top.Draw (); Assert.False (sbv.Visible); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -1193,7 +1207,8 @@ public void Vertical_Default_Draws_Correctly () var height = 40; var super = new Window { Id = "super", Width = Dim.Fill (), Height = Dim.Fill () }; - Application.Top.Add (super); + var top = new Toplevel (); + top.Add (super); var sbv = new ScrollBarView { @@ -1207,7 +1222,7 @@ public void Vertical_Default_Draws_Correctly () }; super.Add (sbv); - Application.Begin (Application.Top); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (width, height); var expected = @" @@ -1347,7 +1362,8 @@ public override void Before (MethodInfo methodUnderTest) Cols = 100 }; - Application.Top.Add (_hostView); + var top = new Toplevel (); + top.Add (_hostView); } } } diff --git a/UnitTests/Views/ScrollViewTests.cs b/UnitTests/Views/ScrollViewTests.cs index fcaab57609..591dc7f5aa 100644 --- a/UnitTests/Views/ScrollViewTests.cs +++ b/UnitTests/Views/ScrollViewTests.cs @@ -31,8 +31,9 @@ public void AutoHideScrollBars_False_ShowHorizontalScrollIndicator_ShowVerticalS sv.ShowHorizontalScrollIndicator = true; sv.ShowVerticalScrollIndicator = true; - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); Assert.Equal (new Rectangle (0, 0, 10, 10), sv.Bounds); @@ -138,8 +139,9 @@ public void AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVerticalScrollI { var sv = new ScrollView { Width = 10, Height = 10 }; - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); Assert.True (sv.AutoHideScrollBars); Assert.False (sv.ShowHorizontalScrollIndicator); @@ -186,8 +188,9 @@ public void Clear_Window_Inside_ScrollView () KeepContentAlwaysInViewport = false }; var bottomLabel = new Label { X = 15, Y = 15, Text = "At 15,15" }; - Application.Top.Add (topLabel, sv, bottomLabel); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (topLabel, sv, bottomLabel); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -445,8 +448,9 @@ public void Width = 10, Height = 10, ContentSize = new (50, 50), ContentOffset = new (25, 25) }; - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); Assert.Equal(new(-25,-25),sv.ContentOffset); Assert.Equal(new(50,50),sv.ContentSize); @@ -477,8 +481,9 @@ public void ContentSize_AutoHideScrollBars_ShowHorizontalScrollIndicator_ShowVer { var sv = new ScrollView { Width = 10, Height = 10, ContentSize = new (50, 50) }; - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); Assert.Equal (50, sv.ContentSize.Width); Assert.Equal (50, sv.ContentSize.Height); @@ -543,8 +548,9 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () scrollView.Add (view); var win = new Window { X = 1, Y = 1, Width = 20, Height = 14 }; win.Add (scrollView); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); var expected = @" ┌──────────────────┐ @@ -568,7 +574,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -592,7 +598,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -616,7 +622,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -640,7 +646,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -664,7 +670,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -688,7 +694,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -712,7 +718,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorRight)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -735,7 +741,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.End.WithCtrl)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -759,7 +765,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.True (scrollView.OnKeyDown (Key.Home.WithCtrl)); Assert.True (scrollView.OnKeyDown (Key.CursorDown)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -782,7 +788,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorDown)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -805,7 +811,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.CursorDown)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -828,7 +834,7 @@ public void DrawTextFormatter_Respects_The_Clip_Bounds () Assert.Equal (new Rectangle (1, 1, 21, 14), pos); Assert.True (scrollView.OnKeyDown (Key.End)); - Application.Top.Draw (); + top.Draw (); expected = @" ┌──────────────────┐ @@ -870,8 +876,9 @@ public void Frame_And_Labels_Does_Not_Overspill_ScrollView () sv.Add (new CustomButton ("█", $"Button {i}", 20, 3) { Y = i * 3 }); } - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -1052,8 +1059,9 @@ public void Remove_Added_View_Is_Allowed () new View { Y = 51, Width = Dim.Fill (), Height = Dim.Fill (), Id = "View2" } ); - Application.Top.Add (sv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (sv); + Application.Begin (top); Assert.Equal (4, sv.Subviews.Count); Assert.Equal (2, sv.Subviews [0].Subviews.Count); diff --git a/UnitTests/Views/SpinnerViewTests.cs b/UnitTests/Views/SpinnerViewTests.cs index 77c673b2be..577c9a1355 100644 --- a/UnitTests/Views/SpinnerViewTests.cs +++ b/UnitTests/Views/SpinnerViewTests.cs @@ -100,8 +100,9 @@ private SpinnerView GetSpinnerView () { var view = new SpinnerView (); - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Assert.Equal (1, view.Width); Assert.Equal (1, view.Height); diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index 1deb7a0be8..b2a9dfdc3a 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -62,7 +62,7 @@ public void CanExecute_ProcessHotKey () ) } ); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (statusBar); bool CanExecuteNew () { return win == null; } @@ -97,7 +97,8 @@ public void Redraw_Output () new (Application.QuitKey, $"{Application.QuitKey} to Quit!", null) } ); - Application.Top.Add (sb); + var top = new Toplevel (); + top.Add (sb); sb.OnDrawContent (sb.Bounds); @@ -120,7 +121,8 @@ public void Redraw_Output_CTRLQ () new (KeyCode.CtrlMask | KeyCode.Q, "~CTRL-Q~ Quit", null) } ); - Application.Top.Add (sb); + var top = new Toplevel (); + top.Add (sb); sb.OnDrawContent (sb.Bounds); var expected = @$" @@ -148,8 +150,6 @@ public void Run_Action_With_Key_And_Mouse () ) } ); - Application.Top.Add (sb); - var iteration = 0; Application.Iteration += (s, a) => @@ -175,7 +175,7 @@ public void Run_Action_With_Key_And_Mouse () iteration++; }; - Application.Run (); + Application.Run ().Dispose (); } [Fact] @@ -217,10 +217,12 @@ public void StatusBar_Constructor_Default () Application.RequestStop (); }; - Application.Top.Add (sb); + var top = new Toplevel (); + top.Add (sb); - Application.Run (); + Application.Run (top); + top.Dispose (); Application.Shutdown (); } diff --git a/UnitTests/Views/TabViewTests.cs b/UnitTests/Views/TabViewTests.cs index f23ff10b8b..200f9638e5 100644 --- a/UnitTests/Views/TabViewTests.cs +++ b/UnitTests/Views/TabViewTests.cs @@ -137,8 +137,9 @@ public void MouseClick_ChangesTab () tv.TabClicked += (s, e) => { clicked = e.Tab; }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); MouseEventEventArgs args; @@ -239,8 +240,9 @@ public void MouseClick_Right_Left_Arrows_ChangesTab () newChanged = e.NewTab; }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); // Click the right arrow var args = new MouseEventEventArgs ( @@ -332,8 +334,9 @@ public void MouseClick_Right_Left_Arrows_ChangesTab_With_Border () newChanged = e.NewTab; }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); // Click the right arrow var args = new MouseEventEventArgs ( @@ -402,7 +405,7 @@ public void ProcessKey_Down_Up_Right_Left_Home_End_PageDown_PageUp () Text = "Ok" }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv, btn); Application.Begin (top); diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs index b90f42b116..574ad85a83 100644 --- a/UnitTests/Views/TableViewTests.cs +++ b/UnitTests/Views/TableViewTests.cs @@ -72,8 +72,9 @@ public void CellEventsBackgroundFill () tv.Table = new DataTableSource (dt); tv.NullSymbol = string.Empty; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); tv.Draw (); @@ -417,8 +418,9 @@ public void LongColumnTest () { var tableView = new TableView (); - Application.Top.Add (tableView); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tableView); + Application.Begin (top); tableView.ColorScheme = Colors.ColorSchemes ["TopLevel"]; @@ -592,6 +594,7 @@ public void LongColumnTest () "; TestHelpers.AssertDriverContentsAre (expected, output); + top.Dispose (); Application.Shutdown (); } @@ -610,10 +613,11 @@ public void PageDown_ExcludesHeaders () tableView.Style.AlwaysShowHeaders = false; // ensure that TableView has the input focus - Application.Top.Add (tableView); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tableView); + Application.Begin (top); - Application.Top.FocusFirst (); + top.FocusFirst (); Assert.True (tableView.HasFocus); Assert.Equal (0, tableView.RowOffset); @@ -1004,8 +1008,9 @@ public void TableView_Activate () var tv = new TableView (BuildTable (1, 1)); tv.CellActivated += (s, c) => activatedValue = c.Table [c.Row, c.Col].ToString (); - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); // pressing enter should activate the first cell (selected cell) tv.NewKeyDownEvent (Key.Enter); @@ -1625,10 +1630,11 @@ public void Test_CollectionNavigator () Assert.Equal (0, tv.SelectedRow); // ensure that TableView has the input focus - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); - Application.Top.FocusFirst (); + top.FocusFirst (); Assert.True (tv.HasFocus); // already on fish diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs index 413973ac00..3418de10d8 100644 --- a/UnitTests/Views/TextFieldTests.cs +++ b/UnitTests/Views/TextFieldTests.cs @@ -18,7 +18,7 @@ public class TextFieldTests public void Accented_Letter_With_Three_Combining_Unicode_Chars () { var tf = new TextField { Width = 3, Text = "ắ" }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tf); Application.Begin (top); @@ -61,8 +61,9 @@ public void Accented_Letter_With_Three_Combining_Unicode_Chars () public void Adjust_First () { var tf = new TextField { Width = Dim.Fill (), Text = "This is a test." }; - Application.Top.Add (tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tf); + Application.Begin (top); Assert.Equal ("This is a test. ", GetContents ()); @@ -104,7 +105,7 @@ public void Cancel_TextChanging_ThenBackspace () [TextFieldTestsAutoInitShutdown] public void CanFocus_False_Wont_Focus_With_Mouse () { - Toplevel top = Application.Top; + Toplevel top = new (); var tf = new TextField { Width = Dim.Fill (), CanFocus = false, ReadOnly = true, Text = "some text" }; var fv = new FrameView @@ -431,8 +432,9 @@ public void DeleteSelectedText_InsertText_DeleteCharLeft_DeleteCharRight_Cut () tf.TextChanging += (s, e) => newText = e.NewValue; tf.TextChanged += (s, e) => oldText = e.OldValue; - Application.Top.Add (tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tf); + Application.Begin (top); Assert.Equal ("-1", tf.Text); @@ -903,8 +905,9 @@ public void ScrollOffset_Initialize () Assert.Equal (0, tf.ScrollOffset); Assert.Equal (16, tf.CursorPosition); - Application.Top.Add (tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tf); + Application.Begin (top); Assert.Equal (0, tf.ScrollOffset); Assert.Equal (16, tf.CursorPosition); @@ -917,8 +920,9 @@ public void Selected_Text_Shows () // Proves #3022 is fixed (TextField selected text does not show in v2) _textField.CursorPosition = 0; - Application.Top.Add (_textField); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (_textField); + RunState rs = Application.Begin (top); Attribute [] attributes = { @@ -1029,8 +1033,9 @@ public void MouseEvent_Handled_Prevents_RightClick () var clickCounter = 0; tf.MouseClick += (s, m) => { clickCounter++; }; - Application.Top.Add (tf); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tf); + Application.Begin (top); var mouseEvent = new MouseEvent { Flags = MouseFlags.Button1Clicked, View = tf }; @@ -1822,7 +1827,7 @@ public void public void Words_With_Accents_Incorrect_Order_Will_Result_With_Wrong_Accent_Place () { var tf = new TextField { Width = 30, Text = "Les Misérables" }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tf); Application.Begin (top); @@ -1857,7 +1862,7 @@ private TextField GetTextFieldsInView () var tf = new TextField { Width = 10 }; var tf2 = new TextField { Y = 1, Width = 10 }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tf); top.Add (tf2); diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index fdbe0e789b..2eb28a06dd 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -59,7 +59,8 @@ public void AllowsTab_Setting_To_True_Changes_TabWidth_To_Default_If_It_Is_Zero [TextViewTestsAutoInitShutdown] public void BackTab_Test_Follow_By_Tab () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -103,7 +104,7 @@ public void BackTab_Test_Follow_By_Tab () Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] @@ -142,7 +143,7 @@ public void BottomOffset_Sets_To_Zero_Adjust_TopRow () [TextViewTestsAutoInitShutdown] public void CanFocus_False_Wont_Focus_With_Mouse () { - Toplevel top = Application.Top; + Toplevel top = new (); var tv = new TextView { Width = Dim.Fill (), CanFocus = false, ReadOnly = true, Text = "some text" }; var fv = new FrameView @@ -281,8 +282,9 @@ public void ContentsChanged_Event_Fires_On_Init () Assert.Equal (expectedCol, e.Col); }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.Equal (1, eventcount); } @@ -368,8 +370,9 @@ public void ContentsChanged_Event_Fires_On_Set_Text () Assert.Equal ("abc", tv.Text); - Application.Top.Add (tv); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + RunState rs = Application.Begin (top); Assert.Equal (1, eventcount); // for Initialize expectedCol = 0; @@ -396,8 +399,9 @@ public void ContentsChanged_Event_Fires_On_Typing () Assert.Equal (expectedCol, e.Col); }; - Application.Top.Add (tv); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + RunState rs = Application.Begin (top); Assert.Equal (1, eventcount); // for Initialize expectedCol = 0; @@ -771,8 +775,9 @@ public void DeleteTextBackwards_WordWrap_False_Return_Undo () const string text = "This is the first line.\nThis is the second line.\n"; var tv = new TextView { Width = Dim.Fill (), Height = Dim.Fill (), Text = text }; string envText = tv.Text; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.False (tv.WordWrap); Assert.Equal (Point.Empty, tv.CursorPosition); @@ -841,8 +846,9 @@ public void DeleteTextBackwards_WordWrap_True_Return_Undo () const string text = "This is the first line.\nThis is the second line.\n"; var tv = new TextView { Width = Dim.Fill (), Height = Dim.Fill (), Text = text, WordWrap = true }; string envText = tv.Text; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.True (tv.WordWrap); Assert.Equal (Point.Empty, tv.CursorPosition); @@ -911,8 +917,9 @@ public void DeleteTextForwards_WordWrap_False_Return_Undo () const string text = "This is the first line.\nThis is the second line.\n"; var tv = new TextView { Width = Dim.Fill (), Height = Dim.Fill (), Text = text }; string envText = tv.Text; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.False (tv.WordWrap); Assert.Equal (Point.Empty, tv.CursorPosition); @@ -981,8 +988,9 @@ public void DeleteTextForwards_WordWrap_True_Return_Undo () const string text = "This is the first line.\nThis is the second line.\n"; var tv = new TextView { Width = Dim.Fill (), Height = Dim.Fill (), Text = text, WordWrap = true }; string envText = tv.Text; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.True (tv.WordWrap); Assert.Equal (Point.Empty, tv.CursorPosition); @@ -2265,7 +2273,7 @@ public void HistoryText_Undo_Redo_Multi_Line_DeleteCharLeft () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -2550,7 +2558,7 @@ public void HistoryText_Undo_Redo_Multi_Line_DeleteCharRight () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -2715,7 +2723,7 @@ public void HistoryText_Undo_Redo_Multi_Line_InsertText () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -3280,7 +3288,7 @@ public void HistoryText_Undo_Redo_Multi_Line_Selected_InsertText () var text = $"This is the first line.{Environment.NewLine}This is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -3460,7 +3468,7 @@ public void HistoryText_Undo_Redo_Multi_Line_Selected_InsertText_Twice_On_Same_L { var text = "One\nTwo\nThree"; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -3523,7 +3531,7 @@ public void HistoryText_Undo_Redo_Multi_Line_Selected_InsertText_Twice_On_Same_L { var text = "One\nTwo\nThree\n"; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -3585,7 +3593,7 @@ public void HistoryText_Undo_Redo_Multi_Line_Selected_InsertText_Twice_On_Same_L public void HistoryText_Undo_Redo_Multi_Line_Selected_With_Empty_Text () { var tv = new TextView { Width = 10, Height = 2 }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -3940,7 +3948,7 @@ public void HistoryText_Undo_Redo_Multi_Line_Selected_With_Empty_Text () public void HistoryText_Undo_Redo_Multi_Line_With_Empty_Text () { var tv = new TextView { Width = 10, Height = 2 }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4412,7 +4420,7 @@ public void HistoryText_Undo_Redo_Single_Line_DeleteCharLeft () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4485,7 +4493,7 @@ public void HistoryText_Undo_Redo_Single_Line_DeleteCharRight () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4558,7 +4566,7 @@ public void HistoryText_Undo_Redo_Single_Line_InsertText () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4627,7 +4635,7 @@ public void HistoryText_Undo_Redo_Single_Line_Selected_DeleteCharLeft () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4712,7 +4720,7 @@ public void HistoryText_Undo_Redo_Single_Line_Selected_DeleteCharRight () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -4797,7 +4805,7 @@ public void HistoryText_Undo_Redo_Single_Line_Selected_InsertText () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -5423,7 +5431,7 @@ public void KeyBindings_Command () { var text = "This is the first line.\nThis is the second line.\nThis is the third line."; var tv = new TextView { Width = 10, Height = 2, Text = text }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (tv); Application.Begin (top); @@ -6997,8 +7005,9 @@ public void ScrollTo_CursorPosition () public void Selected_Text_Shows () { // Proves #3022 is fixed (TextField selected text does not show in v2) - Application.Top.Add (_textView); - RunState rs = Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (_textView); + RunState rs = Application.Begin (top); _textView.CursorPosition = Point.Empty; _textView.SelectionStartColumn = 0; @@ -7107,7 +7116,8 @@ public void StringToRunes_Slipts_LF () [TextViewTestsAutoInitShutdown] public void Tab_Test_Follow_By_BackTab () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -7137,18 +7147,19 @@ public void Tab_Test_Follow_By_BackTab () Assert.Equal (leftCol, _textView.LeftColumn); } - Application.Top.Remove (_textView); + top.Remove (_textView); Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] [TextViewTestsAutoInitShutdown] public void Tab_Test_Follow_By_BackTab_With_Text () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -7178,18 +7189,19 @@ public void Tab_Test_Follow_By_BackTab_With_Text () Assert.Equal (leftCol, _textView.LeftColumn); } - Application.Top.Remove (_textView); + top.Remove (_textView); Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] [TextViewTestsAutoInitShutdown] public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -7228,18 +7240,19 @@ public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight () Assert.Equal (leftCol, _textView.LeftColumn); } - Application.Top.Remove (_textView); + top.Remove (_textView); Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] [TextViewTestsAutoInitShutdown] public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight_With_Text () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -7280,18 +7293,19 @@ public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight_With_Te Assert.Equal (leftCol, _textView.LeftColumn); } - Application.Top.Remove (_textView); + top.Remove (_textView); Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] [TextViewTestsAutoInitShutdown] public void Tab_Test_Follow_By_Home_And_Then_Follow_By_End_And_Then_Follow_By_BackTab_With_Text () { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); Application.Iteration += (s, a) => { @@ -7348,19 +7362,20 @@ public void Tab_Test_Follow_By_Home_And_Then_Follow_By_End_And_Then_Follow_By_Ba Assert.Equal ("TAB to jump between text fields.", _textView.Text); Assert.Equal (32, _textView.Text.Length); - Application.Top.Remove (_textView); + top.Remove (_textView); Application.RequestStop (); }; - Application.Run (); + Application.Run (top); } [Fact] [TextViewTestsAutoInitShutdown] public void TabWidth_Setting_To_Zero_Keeps_AllowsTab () { - Application.Top.Add (_textView); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (_textView); + Application.Begin (top); Assert.Equal (4, _textView.TabWidth); Assert.True (_textView.AllowsTab); @@ -7454,8 +7469,9 @@ public void TextView_InsertText_Newline_CRLF () var win = new Window (); win.Add (tv); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (15, 15); Application.Refresh (); @@ -7530,8 +7546,9 @@ public void TextView_InsertText_Newline_LF () var win = new Window (); win.Add (tv); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (15, 15); Application.Refresh (); @@ -7627,8 +7644,9 @@ public void UnwrappedCursorPosition_Event () Width = Dim.Fill (), Height = Dim.Fill (), Text = "This is the first line.\nThis is the second line.\n" }; tv.UnwrappedCursorPosition += (s, e) => { cp = e.Point; }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.False (tv.WordWrap); Assert.Equal (Point.Empty, tv.CursorPosition); @@ -8797,8 +8815,9 @@ public void public void WordWrap_Deleting_Backwards () { var tv = new TextView { Width = 5, Height = 2, WordWrap = true, Text = "aaaa" }; - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.Equal (Point.Empty, tv.CursorPosition); Assert.Equal (0, tv.LeftColumn); @@ -8872,10 +8891,11 @@ public void WordWrap_Deleting_Backwards () [InlineData (KeyCode.Delete)] public void WordWrap_Draw_Typed_Keys_After_Text_Is_Deleted (KeyCode del) { - Application.Top.Add (_textView); + var top = new Toplevel (); + top.Add (_textView); _textView.Text = "Line 1.\nLine 2."; _textView.WordWrap = true; - Application.Begin (Application.Top); + Application.Begin (top); Assert.True (_textView.WordWrap); @@ -8934,7 +8954,7 @@ public void WordWrap_Not_Throw_If_Width_Is_Less_Than_Zero () } [Fact] - [TextViewTestsAutoInitShutdown] + [AutoInitShutdown] public void WordWrap_ReadOnly_CursorPosition_SelectedText_Copy () { // 0123456789 @@ -8948,8 +8968,9 @@ public void WordWrap_ReadOnly_CursorPosition_SelectedText_Copy () ); tv.WordWrap = true; - Application.Top.Add (tv); - Application.Top.LayoutSubviews (); + var top = new Toplevel (); + top.Add (tv); + top.LayoutSubviews (); tv.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -8968,7 +8989,7 @@ This is tv.ReadOnly = true; tv.CursorPosition = new Point (6, 2); Assert.Equal (new Point (5, 2), tv.CursorPosition); - Application.Top.LayoutSubviews (); + top.LayoutSubviews (); tv.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -9052,7 +9073,8 @@ public void WordWrap_WrapModel_Output () ); tv.WordWrap = true; - Application.Top.Add (tv); + var top = new Toplevel (); + top.Add (tv); tv.LayoutSubviews (); tv.Draw (); diff --git a/UnitTests/Views/TileViewTests.cs b/UnitTests/Views/TileViewTests.cs index 1ad1d52aaf..93c1f7781b 100644 --- a/UnitTests/Views/TileViewTests.cs +++ b/UnitTests/Views/TileViewTests.cs @@ -1575,7 +1575,8 @@ public void TestNestedNonRoots_OnlyOneRoot_OnlyRootCanHaveBorders () Assert.True (tv.IsRootTileView ()); - Application.Top.Add (tv); + var top = new Toplevel (); + top.Add (tv); tv.BeginInit (); tv.EndInit (); tv.LayoutSubviews (); @@ -1624,7 +1625,8 @@ public void TestNestedRoots_BothRoots_BothCanHaveBorders () Assert.True (tv.IsRootTileView ()); tv.Tiles.ElementAt (1).ContentView.Add (tv2); - Application.Top.Add (tv); + var top = new Toplevel (); + top.Add (tv); tv.BeginInit (); tv.EndInit (); tv.LayoutSubviews (); @@ -2303,7 +2305,8 @@ private TileView Get5x1TilesView (bool border = true) new Label { AutoSize = false, Width = Dim.Fill (), Height = 1, Text = new string ('5', 100) } ); - Application.Top.Add (tv); + var top = new Toplevel (); + top.Add (tv); tv.BeginInit (); tv.EndInit (); tv.LayoutSubviews (); @@ -2429,7 +2432,8 @@ private TileView GetTileView (int width, int height, bool withBorder = false) container.Tiles.ElementAt (0).MinSize = 0; container.Tiles.ElementAt (1).MinSize = 0; - Application.Top.Add (container); + var top = new Toplevel (); + top.Add (container); container.ColorScheme = new ColorScheme (); container.BeginInit (); container.EndInit (); diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs index 057ff25f83..6ae1a33ec7 100644 --- a/UnitTests/Views/ToplevelTests.cs +++ b/UnitTests/Views/ToplevelTests.cs @@ -458,7 +458,7 @@ public void KeyBindings_Command () var tf2W2 = new TextField { Id = "tf2W2", X = Pos.Left (tf1W2), Width = Dim.Fill (), Text = "Text2 on Win2" }; win2.Add (lblTf1W2, tf1W2, lblTvW2, tvW2, lblTf2W2, tf2W2); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win1, win2); top.Loaded += (s, e) => isRunning = true; top.Closing += (s, e) => isRunning = false; @@ -560,7 +560,7 @@ public void KeyBindings_Command () [AutoInitShutdown] public void KeyBindings_Command_With_OverlappedTop () { - Toplevel top = Application.Top; + Toplevel top = new (); Assert.Null (Application.OverlappedTop); top.IsOverlappedContainer = true; Application.Begin (top); @@ -740,6 +740,8 @@ Application.OverlappedChildren [0] #if UNIX_KEY_BINDINGS Assert.True (Application.OverlappedChildren [0].ProcessKeyDown (new (Key.L.WithCtrl))); #endif + win2.Dispose (); + win1.Dispose (); } [Fact] @@ -780,7 +782,7 @@ void View_Added (object sender, SuperViewChangedEventArgs e) var win = new Window (); win.Add (view); Application.Init (new FakeDriver ()); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Assert.True (wasAdded); @@ -796,19 +798,19 @@ public void AlternateForwardKeyChanged_AlternateBackwardKeyChanged_QuitKeyChange Key alternateBackwardKey = KeyCode.Null; Key quitKey = KeyCode.Null; + Toplevel top = new (); var view = new View (); view.Initialized += View_Initialized; void View_Initialized (object sender, EventArgs e) { - Application.Top.AlternateForwardKeyChanged += (s, e) => alternateForwardKey = e.OldKey; - Application.Top.AlternateBackwardKeyChanged += (s, e) => alternateBackwardKey = e.OldKey; - Application.Top.QuitKeyChanged += (s, e) => quitKey = e.OldKey; + top.AlternateForwardKeyChanged += (s, e) => alternateForwardKey = e.OldKey; + top.AlternateBackwardKeyChanged += (s, e) => alternateBackwardKey = e.OldKey; + top.QuitKeyChanged += (s, e) => quitKey = e.OldKey; } var win = new Window (); win.Add (view); - Toplevel top = Application.Top; top.Add (win); Application.Begin (top); @@ -847,7 +849,7 @@ void View_Initialized (object sender, EventArgs e) public void Mouse_Drag_On_Top_With_Superview_Null () { var win = new Window (); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); int iterations = -1; Window testWindow; @@ -1003,7 +1005,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -1011,7 +1013,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () public void Mouse_Drag_On_Top_With_Superview_Not_Null () { var win = new Window { X = 3, Y = 2, Width = 10, Height = 5 }; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); int iterations = -1; @@ -1132,7 +1134,7 @@ public void Mouse_Drag_On_Top_With_Superview_Not_Null () } }; - Application.Run (); + Application.Run (top); } [Fact] @@ -1158,7 +1160,7 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End () var v = new View (); v.Enter += (s, _) => isEnter = true; v.Leave += (s, _) => isLeave = true; - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (v); Assert.False (v.CanFocus); @@ -1168,27 +1170,38 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End () Assert.Null (exception); v.CanFocus = true; - Application.Begin (top); + RunState rsTop = Application.Begin (top); + // From the v view Assert.True (isEnter); + // The Leave event is only raised on the End method + // and the top is still running Assert.False (isLeave); isEnter = false; var d = new Dialog (); - RunState rs = Application.Begin (d); + var dv = new View { CanFocus = true }; + dv.Enter += (s, _) => isEnter = true; + dv.Leave += (s, _) => isLeave = true; + d.Add (dv); + RunState rsDialog = Application.Begin (d); - Assert.False (isEnter); - Assert.True (isLeave); + // From the dv view + Assert.True (isEnter); + Assert.False (isLeave); + Assert.True (dv.HasFocus); - isLeave = false; - Application.End (rs); + isEnter = false; - Assert.True (isEnter); + Application.End (rsDialog); - Assert.False ( - isLeave - ); // Leave event cannot be trigger because it v.Enter was performed and v is focused + // From the v view + Assert.True (isEnter); + // From the dv view + Assert.True (isLeave); Assert.True (v.HasFocus); + + Application.End (rsTop); } [Fact] @@ -1196,11 +1209,11 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End () public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Toplevels () { var iterations = 0; - var steps = new int [5]; + var steps = new int [4]; var isEnterTop = false; var isLeaveTop = false; var vt = new View (); - Toplevel top = Application.Top; + Toplevel top = new (); var diag = new Dialog (); vt.Enter += (s, e) => @@ -1215,15 +1228,15 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Topleve } else { - steps [4] = iterations; + steps [3] = iterations; Assert.Equal (diag, e.View); } }; vt.Leave += (s, e) => { + // This will never be raised iterations++; - steps [1] = iterations; isLeaveTop = true; Assert.Equal (diag, e.View); }; @@ -1236,7 +1249,7 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Topleve Assert.Null (exception); vt.CanFocus = true; - Application.Begin (top); + RunState rsTop = Application.Begin (top); Assert.True (isEnterTop); Assert.False (isLeaveTop); @@ -1249,7 +1262,7 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Topleve vd.Enter += (s, e) => { iterations++; - steps [2] = iterations; + steps [1] = iterations; isEnterDiag = true; Assert.Null (e.View); }; @@ -1257,7 +1270,7 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Topleve vd.Leave += (s, e) => { iterations++; - steps [3] = iterations; + steps [2] = iterations; isLeaveDiag = true; Assert.Equal (top, e.View); }; @@ -1270,30 +1283,33 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Topleve Assert.Null (exception); vd.CanFocus = true; - RunState rs = Application.Begin (diag); + RunState rsDiag = Application.Begin (diag); Assert.True (isEnterDiag); Assert.False (isLeaveDiag); Assert.False (isEnterTop); - Assert.True (isLeaveTop); + // The Leave event is only raised on the End method + // and the top is still running + Assert.False (isLeaveTop); isEnterDiag = false; isLeaveTop = false; - Application.End (rs); + Application.End (rsDiag); Assert.False (isEnterDiag); Assert.True (isLeaveDiag); Assert.True (isEnterTop); - - Assert.False ( - isLeaveTop - ); // Leave event cannot be trigger because it v.Enter was performed and v is focused + // Leave event on top cannot be raised + // because Current is null on the End method + Assert.False (isLeaveTop); Assert.True (vt.HasFocus); + + Application.End (rsTop); + Assert.Equal (1, steps [0]); Assert.Equal (2, steps [1]); Assert.Equal (3, steps [2]); - Assert.Equal (4, steps [3]); - Assert.Equal (5, steps [^1]); + Assert.Equal (4, steps [^1]); } [Fact] @@ -1303,8 +1319,9 @@ public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null ( var tf = new TextField { Width = 5, Text = "test" }; var view = new View { Width = 10, Height = 10 }; view.Add (tf); - Application.Top.Add (view); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); Assert.True (tf.HasFocus); Application.Driver.GetCursorVisibility (out CursorVisibility cursor); @@ -1321,7 +1338,7 @@ public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null ( [AutoInitShutdown] public void IsLoaded_Application_Begin () { - Toplevel top = Application.Top; + Toplevel top = new (); Assert.False (top.IsLoaded); Application.Begin (top); @@ -1332,7 +1349,7 @@ public void IsLoaded_Application_Begin () [AutoInitShutdown] public void IsLoaded_With_Sub_Toplevel_Application_Begin_NeedDisplay () { - Toplevel top = Application.Top; + Toplevel top = new (); var subTop = new Toplevel (); var view = new View { Frame = new Rectangle (0, 0, 20, 10) }; subTop.Add (view); @@ -1380,7 +1397,7 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () }; var win = new Window { X = 3, Y = 3, Width = Dim.Fill (3), Height = Dim.Fill (3) }; scrollView.Add (win); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (scrollView); Application.Begin (top); @@ -1514,11 +1531,11 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () [AutoInitShutdown] public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Left_Right_And_Bottom () { - Toplevel top = Application.Top; + Toplevel top = new (); var window = new Window { Width = 20, Height = 3 }; - Application.Begin (top); + RunState rsTop = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (40, 10); - Application.Begin (window); + RunState rsWindow = Application.Begin (window); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 40, 10), top.Frame); Assert.Equal (new Rectangle (0, 0, 20, 3), window.Frame); @@ -1661,6 +1678,9 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); Assert.Equal (new Rectangle (19, 2, 20, 3), window.Frame); TestHelpers.AssertDriverContentsWithFrameAre (@"", _output); + + Application.End (rsWindow); + Application.End (rsTop); } [Fact] @@ -1749,15 +1769,18 @@ public void Modal_As_Top_Will_Drag_Cleanly () [AutoInitShutdown] public void Begin_With_Window_Sets_Size_Correctly () { - Toplevel top = Application.Top; - Application.Begin (top); + Toplevel top = new (); + RunState rsTop = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 20); var testWindow = new Window { X = 2, Y = 1, Width = 15, Height = 10 }; Assert.Equal (new Rectangle (2, 1, 15, 10), testWindow.Frame); - RunState rs = Application.Begin (testWindow); + RunState rsTestWindow = Application.Begin (testWindow); Assert.Equal (new Rectangle (2, 1, 15, 10), testWindow.Frame); + + Application.End (rsTestWindow); + Application.End (rsTop); } // Don't use Dialog as a Top, use a Window instead - dialog has complex layout behavior that is not needed here. @@ -1765,10 +1788,10 @@ public void Begin_With_Window_Sets_Size_Correctly () [AutoInitShutdown] public void Draw_A_Top_Subview_On_A_Window () { - Toplevel top = Application.Top; + Toplevel top = new (); var win = new Window (); top.Add (win); - Application.Begin (top); + RunState rsTop = Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 20); Assert.Equal (new Rectangle (0, 0, 20, 20), win.Frame); @@ -1816,10 +1839,10 @@ public void Draw_A_Top_Subview_On_A_Window () BorderStyle = LineStyle.Single }; Assert.Equal (testWindow, Application.Current); - Application.Current.DrawContentComplete += testWindow_DrawContentComplete; + Application.Current.DrawContentComplete += OnDrawContentComplete; top.Add (viewAddedToTop); - void testWindow_DrawContentComplete (object sender, DrawEventArgs e) + void OnDrawContentComplete (object sender, DrawEventArgs e) { Assert.Equal (new Rectangle (1, 3, 18, 16), viewAddedToTop.Frame); @@ -1834,10 +1857,10 @@ void testWindow_DrawContentComplete (object sender, DrawEventArgs e) View.Driver.AddStr ("Three"); Application.Driver.Clip = savedClip; - Application.Current.DrawContentComplete -= testWindow_DrawContentComplete; + Application.Current.DrawContentComplete -= OnDrawContentComplete; } }; - RunState rs = Application.Begin (testWindow); + RunState rsTestWindow = Application.Begin (testWindow); Assert.Equal (new Rectangle (2, 1, 15, 10), testWindow.Frame); @@ -1878,7 +1901,7 @@ void testWindow_DrawContentComplete (object sender, DrawEventArgs e) Application.Top.Draw (); var firstIteration = false; - Application.RunIteration (ref rs, ref firstIteration); + Application.RunIteration (ref rsTestWindow, ref firstIteration); TestHelpers.AssertDriverContentsWithFrameAre ( @$" @@ -1909,9 +1932,12 @@ void testWindow_DrawContentComplete (object sender, DrawEventArgs e) _output ); - Application.End (rs); + Application.End (rsTestWindow); + Application.End (rsTop); } + private void OnDrawContentComplete (object sender, DrawEventArgs e) { throw new NotImplementedException (); } + [Fact] [AutoInitShutdown] public void Activating_MenuBar_By_Alt_Key_Does_Not_Throw () @@ -1925,8 +1951,9 @@ public void Activating_MenuBar_By_Alt_Key_Does_Not_Throw () }; var topChild = new Toplevel (); topChild.Add (menu); - Application.Top.Add (topChild); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (topChild); + Application.Begin (top); Exception exception = Record.Exception (() => topChild.NewKeyDownEvent (KeyCode.AltMask)); Assert.Null (exception); @@ -1938,7 +1965,7 @@ public void Multi_Thread_Toplevels () { Application.Init (new FakeDriver ()); - Toplevel t = Application.Top; + Toplevel t = new (); var w = new Window (); t.Add (w); @@ -2063,7 +2090,8 @@ void SecondWindow (object sender, EventArgs args) testWindow.Dispose (); } - Application.Run (); + Application.Run (t); + t.Dispose (); Application.Shutdown (); } } diff --git a/UnitTests/Views/TreeTableSourceTests.cs b/UnitTests/Views/TreeTableSourceTests.cs index 68d006f35a..b6708f1b31 100644 --- a/UnitTests/Views/TreeTableSourceTests.cs +++ b/UnitTests/Views/TreeTableSourceTests.cs @@ -150,11 +150,14 @@ public void TestTreeTableSource_BasicExpanding_WithMouse () [AutoInitShutdown] public void TestTreeTableSource_CombinedWithCheckboxes () { + Toplevel top = new (); TableView tv = GetTreeTable (out TreeView treeSource); CheckBoxTableSourceWrapperByIndex checkSource; tv.Table = checkSource = new CheckBoxTableSourceWrapperByIndex (tv, tv.Table); tv.Style.GetOrCreateColumnStyle (2).MinAcceptableWidth = 1; + top.Add (tv); + Application.Begin (top); tv.Draw (); @@ -181,7 +184,7 @@ public void TestTreeTableSource_CombinedWithCheckboxes () Assert.Equal (0, tv.SelectedRow); Assert.Equal (1, tv.SelectedColumn); - Application.Top.NewKeyDownEvent (Key.CursorRight); + top.NewKeyDownEvent (Key.CursorRight); tv.Draw (); @@ -280,9 +283,10 @@ private TableView GetTreeTable (out TreeView tree) tableView.EndInit (); tableView.LayoutSubviews (); - Application.Top.Add (tableView); - Application.Top.EnsureFocus (); - Assert.Equal (tableView, Application.Top.MostFocused); + var top = new Toplevel (); + top.Add (tableView); + top.EnsureFocus (); + Assert.Equal (tableView, top.MostFocused); return tableView; } diff --git a/UnitTests/Views/TreeViewTests.cs b/UnitTests/Views/TreeViewTests.cs index 5b180870b6..6a2805d40d 100644 --- a/UnitTests/Views/TreeViewTests.cs +++ b/UnitTests/Views/TreeViewTests.cs @@ -110,8 +110,9 @@ public void DesiredCursorVisibility_MultiSelect () tv.AddObject (n1); tv.AddObject (n2); - Application.Top.Add (tv); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (tv); + Application.Begin (top); Assert.True (tv.MultiSelect); Assert.True (tv.HasFocus); diff --git a/UnitTests/Views/ViewDisposalTest.cs b/UnitTests/Views/ViewDisposalTest.cs index 30150be846..4527b040f4 100644 --- a/UnitTests/Views/ViewDisposalTest.cs +++ b/UnitTests/Views/ViewDisposalTest.cs @@ -35,7 +35,7 @@ private WeakReference DoTest () { GetSpecialParams (); var Container = new View (); - Toplevel top = Application.Top; + Toplevel top = new (); List views = GetViews (); foreach (Type view in views) diff --git a/UnitTests/Views/WindowTests.cs b/UnitTests/Views/WindowTests.cs index 83e4b0822d..60a213d598 100644 --- a/UnitTests/Views/WindowTests.cs +++ b/UnitTests/Views/WindowTests.cs @@ -20,8 +20,9 @@ public void Activating_MenuBar_By_Alt_Key_Does_Not_Throw () }; var win = new Window (); win.Add (menu); - Application.Top.Add (win); - Application.Begin (Application.Top); + var top = new Toplevel (); + top.Add (win); + Application.Begin (top); Exception exception = Record.Exception (() => win.NewKeyDownEvent (KeyCode.AltMask)); Assert.Null (exception); @@ -55,7 +56,7 @@ public void MenuBar_And_StatusBar_Inside_Window () var fv = new FrameView { Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1), Title = "Frame View" }; var win = new Window (); win.Add (menu, sb, fv); - Toplevel top = Application.Top; + Toplevel top = new (); top.Add (win); Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (20, 10);