From b71789223583d3e9c20e8f2eabffec9929ac7724 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 17 Sep 2024 17:20:19 -0600 Subject: [PATCH] Removed OverlappedTop. Updated unit tess. Fixed bad code paths. --- .../Application/Application.Keyboard.cs | 42 +- Terminal.Gui/Application/Application.Mouse.cs | 21 +- Terminal.Gui/Application/Application.Run.cs | 344 +---- .../Application/Application.Screen.cs | 6 +- .../Application/Application.Toplevel.cs | 42 - Terminal.Gui/Application/Application.cs | 1 - .../Application/ApplicationNavigation.cs | 7 +- .../Application/ApplicationOverlapped.cs | 444 ------ Terminal.Gui/View/Adornment/Border.cs | 10 +- Terminal.Gui/View/View.Navigation.cs | 6 +- Terminal.Gui/Views/Menu/ContextMenu.cs | 2 +- Terminal.Gui/Views/Menu/Menu.cs | 13 +- Terminal.Gui/Views/Menu/MenuBar.cs | 30 +- Terminal.Gui/Views/Slider.cs | 2 +- Terminal.Gui/Views/TileView.cs | 1 - Terminal.Gui/Views/Toplevel.cs | 113 +- Terminal.Gui/Views/ToplevelOverlapped.cs | 8 - .../Scenarios/BackgroundWorkerCollection.cs | 540 ------- UICatalog/Scenarios/SingleBackgroundWorker.cs | 2 +- .../Application.NavigationTests.cs | 26 +- UnitTests/Application/ApplicationTests.cs | 162 +- UnitTests/Application/CursorTests.cs | 28 +- UnitTests/Application/KeyboardTests.cs | 5 - UnitTests/Application/RunStateTests.cs | 2 - UnitTests/Dialogs/DialogTests.cs | 159 +- UnitTests/Dialogs/MessageBoxTests.cs | 14 +- UnitTests/TestHelpers.cs | 12 +- UnitTests/View/Layout/Pos.AnchorEndTests.cs | 54 +- UnitTests/View/Layout/Pos.CombineTests.cs | 2 +- UnitTests/View/Layout/ToScreenTests.cs | 2 - UnitTests/View/Navigation/CanFocusTests.cs | 276 +--- UnitTests/View/Navigation/NavigationTests.cs | 183 +-- UnitTests/Views/ColorPickerTests.cs | 56 +- UnitTests/Views/ComboBoxTests.cs | 8 +- UnitTests/Views/ContextMenuTests.cs | 26 +- UnitTests/Views/LabelTests.cs | 20 +- UnitTests/Views/OverlappedTests.cs | 1300 ----------------- UnitTests/Views/RadioGroupTests.cs | 24 +- UnitTests/Views/ShortcutTests.cs | 6 +- UnitTests/Views/TableViewTests.cs | 52 +- UnitTests/Views/TextViewTests.cs | 14 +- UnitTests/Views/ToplevelTests.cs | 456 +----- UnitTests/Views/TreeViewTests.cs | 2 +- 43 files changed, 400 insertions(+), 4123 deletions(-) delete mode 100644 Terminal.Gui/Application/ApplicationOverlapped.cs delete mode 100644 Terminal.Gui/Views/ToplevelOverlapped.cs delete mode 100644 UICatalog/Scenarios/BackgroundWorkerCollection.cs delete mode 100644 UnitTests/Views/OverlappedTests.cs diff --git a/Terminal.Gui/Application/Application.Keyboard.cs b/Terminal.Gui/Application/Application.Keyboard.cs index 95d6923b2..0e92961a5 100644 --- a/Terminal.Gui/Application/Application.Keyboard.cs +++ b/Terminal.Gui/Application/Application.Keyboard.cs @@ -95,7 +95,7 @@ public static partial class Application // Keyboard handling return true; } - if (Current is null) + if (Top is null) { foreach (Toplevel topLevel in TopLevels.ToList ()) { @@ -112,7 +112,7 @@ public static partial class Application // Keyboard handling } else { - if (Current.NewKeyDownEvent (keyEvent)) + if (Top.NewKeyDownEvent (keyEvent)) { return true; } @@ -285,15 +285,7 @@ public static partial class Application // Keyboard handling Command.Quit, static () => { - if (ApplicationOverlapped.OverlappedTop is { }) - { - RequestStop (Current!); - } - else - { - RequestStop (); - } - + RequestStop (); return true; } ); @@ -318,35 +310,11 @@ public static partial class Application // Keyboard handling AddCommand ( Command.NextTabGroup, - static () => - { - // TODO: This OverlapppedTop tomfoolery goes away in addressing #2491 - if (ApplicationOverlapped.OverlappedTop is { }) - { - ApplicationOverlapped.OverlappedMoveNext (); - - return true; - } - - return Navigation?.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup); - } - ); + static () => Navigation?.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup)); AddCommand ( Command.PreviousTabGroup, - static () => - { - // TODO: This OverlapppedTop tomfoolery goes away in addressing #2491 - if (ApplicationOverlapped.OverlappedTop is { }) - { - ApplicationOverlapped.OverlappedMovePrevious (); - - return true; - } - - return Navigation?.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup); - } - ); + static () => Navigation?.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup)); AddCommand ( Command.Refresh, diff --git a/Terminal.Gui/Application/Application.Mouse.cs b/Terminal.Gui/Application/Application.Mouse.cs index 2b16686d3..9da49e652 100644 --- a/Terminal.Gui/Application/Application.Mouse.cs +++ b/Terminal.Gui/Application/Application.Mouse.cs @@ -139,7 +139,7 @@ public static partial class Application // Mouse handling return; } - var view = View.FindDeepestView (Current, mouseEvent.Position); + var view = View.FindDeepestView (Top, mouseEvent.Position); if (view is { }) { @@ -208,23 +208,6 @@ public static partial class Application // Mouse handling _ => null }; - if (view is not Adornment - && (view is null || view == ApplicationOverlapped.OverlappedTop) - && Current is { Modal: false } - && ApplicationOverlapped.OverlappedTop != null - && mouseEvent.Flags is not MouseFlags.ReportMousePosition and not 0) - { - // This occurs when there are multiple overlapped "tops" - // E.g. "Mdi" - in the Background Worker Scenario - View? top = ApplicationOverlapped.FindDeepestTop (Top!, mouseEvent.Position); - view = View.FindDeepestView (top, mouseEvent.Position); - - if (view is { } && view != ApplicationOverlapped.OverlappedTop && top != Current && top is { }) - { - ApplicationOverlapped.MoveCurrent ((Toplevel)top); - } - } - // May be null before the prior condition or the condition may set it as null. // So, the checking must be outside the prior condition. if (view is null) @@ -310,8 +293,6 @@ public static partial class Application // Mouse handling View = view }; } - - ApplicationOverlapped.BringOverlappedTopToFront (); } #endregion Mouse handling diff --git a/Terminal.Gui/Application/Application.Run.cs b/Terminal.Gui/Application/Application.Run.cs index 5099788fd..97ba63350 100644 --- a/Terminal.Gui/Application/Application.Run.cs +++ b/Terminal.Gui/Application/Application.Run.cs @@ -54,11 +54,6 @@ public static partial class Application // Run (Begin, Run, End, Stop) } #endif - if (toplevel.IsOverlappedContainer && ApplicationOverlapped.OverlappedTop != toplevel && ApplicationOverlapped.OverlappedTop is { }) - { - throw new InvalidOperationException ("Only one Overlapped Container is allowed."); - } - // Ensure the mouse is ungrabbed. MouseGrabView = null; @@ -96,11 +91,6 @@ public static partial class Application // Run (Begin, Run, End, Stop) throw new ObjectDisposedException (Top.GetType ().FullName); } } - else if (ApplicationOverlapped.OverlappedTop is { } && toplevel != Top && TopLevels.Contains (Top!)) - { - // BUGBUG: Don't call OnLeave/OnEnter directly! Set HasFocus to false and let the system handle it. - //Top!.OnLeave (toplevel); - } // BUGBUG: We should not depend on `Id` internally. // BUGBUG: It is super unclear what this code does anyway. @@ -135,79 +125,46 @@ public static partial class Application // Run (Begin, Run, End, Stop) } } - if (Top is null || toplevel.IsOverlappedContainer) + if (Top is null) { Top = toplevel; } - var refreshDriver = true; - - if (ApplicationOverlapped.OverlappedTop is null - || toplevel.IsOverlappedContainer - || (Current?.Modal == false && toplevel.Modal) - || (Current?.Modal == false && !toplevel.Modal) - || (Current?.Modal == true && toplevel.Modal)) + if ((Top?.Modal == false && toplevel.Modal) + || (Top?.Modal == false && !toplevel.Modal) + || (Top?.Modal == true && toplevel.Modal)) { if (toplevel.Visible) { - if (Current is { HasFocus: true }) + if (Top is { HasFocus: true }) { - Current.HasFocus = false; + Top.HasFocus = false; } - Current?.OnDeactivate (toplevel); - Toplevel previousCurrent = Current!; + Top?.OnDeactivate (toplevel); + Toplevel previousCurrent = Top!; - Current = toplevel; - Current.OnActivate (previousCurrent); - - ApplicationOverlapped.SetCurrentOverlappedAsTop (); + Top = toplevel; + Top.OnActivate (previousCurrent); } - else - { - refreshDriver = false; - } - } - else if ((toplevel != ApplicationOverlapped.OverlappedTop - && Current?.Modal == true - && !TopLevels.Peek ().Modal) - || (toplevel != ApplicationOverlapped.OverlappedTop && Current?.Running == false)) - { - refreshDriver = false; - ApplicationOverlapped.MoveCurrent (toplevel); - } - else - { - refreshDriver = false; - ApplicationOverlapped.MoveCurrent (Current!); } toplevel.SetRelativeLayout (Driver!.Screen.Size); - toplevel.LayoutSubviews (); - toplevel.PositionToplevels (); - // TODO: Should this use FindDeepestFocusableView instead? // Try to set initial focus to any TabStop if (!toplevel.HasFocus) { toplevel.SetFocus (); } - ApplicationOverlapped.BringOverlappedTopToFront (); + toplevel.OnLoaded (); - if (refreshDriver) + Refresh (); + + if (PositionCursor ()) { - ApplicationOverlapped.OverlappedTop?.OnChildLoaded (toplevel); - toplevel.OnLoaded (); - toplevel.SetNeedsDisplay (); - toplevel.Draw (); - Driver.UpdateScreen (); - - if (PositionCursor (toplevel)) - { - Driver.UpdateCursor (); - } + Driver.UpdateCursor (); } NotifyNewRunState?.Invoke (toplevel, new (rs)); @@ -226,25 +183,13 @@ public static partial class Application // Run (Begin, Run, End, Stop) /// /// /// if a view positioned the cursor and the position is visible. - internal static bool PositionCursor (View view) + internal static bool PositionCursor () { // Find the most focused view and position the cursor there. - View? mostFocused = view?.MostFocused; - - if (mostFocused is null) - { - if (view is { HasFocus: true }) - { - mostFocused = view; - } - else - { - return false; - } - } + View? mostFocused = Navigation?.GetFocused (); // If the view is not visible or enabled, don't position the cursor - if (!mostFocused.Visible || !mostFocused.Enabled) + if (mostFocused is null || !mostFocused.Visible || !mostFocused.Enabled) { Driver!.GetCursorVisibility (out CursorVisibility current); @@ -510,11 +455,12 @@ public static partial class Application // Run (Begin, Run, End, Stop) /// Triggers a refresh of the entire display. public static void Refresh () { - // TODO: Figure out how to remove this call to ClearContents. Refresh should just repaint damaged areas, not clear - Driver!.ClearContents (); - foreach (Toplevel v in TopLevels.Reverse ()) { + if (v.LayoutNeeded) + { + v.LayoutSubviews (); + } if (v.Visible) { v.SetNeedsDisplay (); @@ -523,7 +469,7 @@ public static partial class Application // Run (Begin, Run, End, Stop) } } - Driver.Refresh (); + Driver!.Refresh (); } /// This event is raised on each iteration of the main loop. @@ -586,80 +532,22 @@ public static partial class Application // Run (Begin, Run, End, Stop) MainLoop.RunIteration (); Iteration?.Invoke (null, new ()); - EnsureModalOrVisibleAlwaysOnTop (state.Toplevel); - - // TODO: Overlapped - Move elsewhere - if (state.Toplevel != Current) - { - ApplicationOverlapped.OverlappedTop?.OnDeactivate (state.Toplevel); - state.Toplevel = Current; - ApplicationOverlapped.OverlappedTop?.OnActivate (state.Toplevel!); - Top!.SetSubViewNeedsDisplay (); - Refresh (); - } } firstIteration = false; - if (Current == null) + if (Top is null) { return; } - if (state.Toplevel != Top && (Top!.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded)) - { - state.Toplevel!.SetNeedsDisplay (state.Toplevel.Frame); - Top.Draw (); + Refresh (); - foreach (Toplevel top in TopLevels.Reverse ()) - { - if (top != Top && top != state.Toplevel) - { - top.SetNeedsDisplay (); - top.SetSubViewNeedsDisplay (); - top.Draw (); - } - } - } - - if (TopLevels.Count == 1 - && state.Toplevel == Top - && (Driver!.Cols != state.Toplevel!.Frame.Width - || Driver!.Rows != state.Toplevel.Frame.Height) - && (state.Toplevel.NeedsDisplay - || state.Toplevel.SubViewNeedsDisplay - || state.Toplevel.LayoutNeeded)) - { - Driver.ClearContents (); - } - - if (state.Toplevel!.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded || ApplicationOverlapped.OverlappedChildNeedsDisplay ()) - { - state.Toplevel.SetNeedsDisplay (); - state.Toplevel.Draw (); - Driver!.UpdateScreen (); - - //Driver.UpdateCursor (); - } - - if (PositionCursor (state.Toplevel)) + if (PositionCursor ()) { Driver!.UpdateCursor (); } - // else - { - //if (PositionCursor (state.Toplevel)) - //{ - // Driver.Refresh (); - //} - //Driver.UpdateCursor (); - } - - if (state.Toplevel != Top && !state.Toplevel.Modal && (Top!.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded)) - { - Top.Draw (); - } } /// Stops the provided , causing or the if provided. @@ -673,112 +561,26 @@ public static partial class Application // Run (Begin, Run, End, Stop) /// public static void RequestStop (Toplevel? top = null) { - if (ApplicationOverlapped.OverlappedTop is null || top is null) + if (top is null) { - top = Current; + top = Top; } - if (ApplicationOverlapped.OverlappedTop != null - && top!.IsOverlappedContainer - && top?.Running == true - && (Current?.Modal == false || Current is { Modal: true, Running: false })) + if (!top!.Running) { - ApplicationOverlapped.OverlappedTop.RequestStop (); + return; } - else if (ApplicationOverlapped.OverlappedTop != null - && top != Current - && Current is { Running: true, Modal: true } - && top!.Modal - && top.Running) + + var ev = new ToplevelClosingEventArgs (top); + top.OnClosing (ev); + + if (ev.Cancel) { - var ev = new ToplevelClosingEventArgs (Current); - Current.OnClosing (ev); - - if (ev.Cancel) - { - return; - } - - ev = new (top); - top.OnClosing (ev); - - if (ev.Cancel) - { - return; - } - - Current.Running = false; - OnNotifyStopRunState (Current); - top.Running = false; - OnNotifyStopRunState (top); + return; } - else if ((ApplicationOverlapped.OverlappedTop != null - && top != ApplicationOverlapped.OverlappedTop - && top != Current - && Current is { Modal: false, Running: true } - && !top!.Running) - || (ApplicationOverlapped.OverlappedTop != null - && top != ApplicationOverlapped.OverlappedTop - && top != Current - && Current is { Modal: false, Running: false } - && !top!.Running - && TopLevels.ToArray () [1].Running)) - { - ApplicationOverlapped.MoveCurrent (top); - } - else if (ApplicationOverlapped.OverlappedTop != null - && Current != top - && Current?.Running == true - && !top!.Running - && Current?.Modal == true - && top.Modal) - { - // The Current and the top are both modal so needed to set the Current.Running to false too. - Current.Running = false; - OnNotifyStopRunState (Current); - } - else if (ApplicationOverlapped.OverlappedTop != null - && Current == top - && ApplicationOverlapped.OverlappedTop?.Running == true - && Current?.Running == true - && top!.Running - && Current?.Modal == true - && top!.Modal) - { - // The OverlappedTop was requested to stop inside a modal Toplevel which is the Current and top, - // both are the same, so needed to set the Current.Running to false too. - Current.Running = false; - OnNotifyStopRunState (Current); - } - else - { - Toplevel currentTop; - if (top == Current || (Current?.Modal == true && !top!.Modal)) - { - currentTop = Current!; - } - else - { - currentTop = top!; - } - - if (!currentTop.Running) - { - return; - } - - var ev = new ToplevelClosingEventArgs (currentTop); - currentTop.OnClosing (ev); - - if (ev.Cancel) - { - return; - } - - currentTop.Running = false; - OnNotifyStopRunState (currentTop); - } + top.Running = false; + OnNotifyStopRunState (top); } private static void OnNotifyStopRunState (Toplevel top) @@ -798,14 +600,7 @@ public static partial class Application // Run (Begin, Run, End, Stop) { ArgumentNullException.ThrowIfNull (runState); - if (ApplicationOverlapped.OverlappedTop is { }) - { - ApplicationOverlapped.OverlappedTop.OnChildUnloaded (runState.Toplevel); - } - else - { - runState.Toplevel.OnUnloaded (); - } + runState.Toplevel.OnUnloaded (); // End the RunState.Toplevel // First, take it off the Toplevel Stack @@ -824,65 +619,26 @@ public static partial class Application // Run (Begin, Run, End, Stop) // Notify that it is closing runState.Toplevel?.OnClosed (runState.Toplevel); - // If there is a OverlappedTop that is not the RunState.Toplevel then RunState.Toplevel - // is a child of MidTop, and we should notify the OverlappedTop that it is closing - if (ApplicationOverlapped.OverlappedTop is { } && !runState.Toplevel!.Modal && runState.Toplevel != ApplicationOverlapped.OverlappedTop) + if (TopLevels.Count > 0) { - ApplicationOverlapped.OverlappedTop.OnChildClosed (runState.Toplevel); + Top = TopLevels.Peek (); } - // Set Current and Top to the next TopLevel on the stack - if (TopLevels.Count == 0) + // BUGBUG: We should not call OnEnter/OnLeave directly; they should only be called by SetHasFocus + if (runState.Toplevel is { HasFocus: true }) { - if (Current is { HasFocus: true }) - { - Current.HasFocus = false; - } - Current = null; - } - else - { - if (TopLevels.Count > 1 && TopLevels.Peek () == ApplicationOverlapped.OverlappedTop && ApplicationOverlapped.OverlappedChildren?.Any (t => t.Visible) != null) - { - ApplicationOverlapped.OverlappedMoveNext (); - } - - Current = TopLevels.Peek (); - - if (TopLevels.Count == 1 && Current == ApplicationOverlapped.OverlappedTop) - { - ApplicationOverlapped.OverlappedTop.OnAllChildClosed (); - } - else - { - ApplicationOverlapped.SetCurrentOverlappedAsTop (); - // BUGBUG: We should not call OnEnter/OnLeave directly; they should only be called by SetHasFocus - if (runState.Toplevel is { HasFocus: true }) - { - runState.Toplevel.HasFocus = false; - } - - if (Current is { HasFocus: false }) - { - Current.SetFocus (); - } - } - - Refresh (); + runState.Toplevel.HasFocus = false; } - // 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 (ApplicationOverlapped.OverlappedTop is { } && !TopLevels.Contains (ApplicationOverlapped.OverlappedTop)) + if (Top is { HasFocus: false }) { - _cachedRunStateToplevel = ApplicationOverlapped.OverlappedTop; - } - else - { - _cachedRunStateToplevel = runState.Toplevel; + Top.SetFocus (); } + //Refresh (); + + _cachedRunStateToplevel = runState.Toplevel; + runState.Toplevel = null; runState.Dispose (); } diff --git a/Terminal.Gui/Application/Application.Screen.cs b/Terminal.Gui/Application/Application.Screen.cs index a3d56da06..141e1a7e0 100644 --- a/Terminal.Gui/Application/Application.Screen.cs +++ b/Terminal.Gui/Application/Application.Screen.cs @@ -37,13 +37,9 @@ public static partial class Application // Screen related stuff { t.SetRelativeLayout (args.Size.Value); t.LayoutSubviews (); - t.PositionToplevels (); + //t.PositionToplevels (); t.OnSizeChanging (new (args.Size)); - if (PositionCursor (t)) - { - Driver?.UpdateCursor (); - } } Refresh (); diff --git a/Terminal.Gui/Application/Application.Toplevel.cs b/Terminal.Gui/Application/Application.Toplevel.cs index a1844b2d0..edb6714bb 100644 --- a/Terminal.Gui/Application/Application.Toplevel.cs +++ b/Terminal.Gui/Application/Application.Toplevel.cs @@ -11,46 +11,4 @@ public static partial class Application // Toplevel handling /// The object used for the application on startup () /// The top. public static Toplevel? Top { get; internal set; } - - // TODO: Determine why this can't just return _topLevels.Peek()? - /// - /// The current object. This is updated in enters and leaves to - /// point to the current - /// . - /// - /// - /// This will only be distinct from in scenarios where is . - /// - /// The current. - public static Toplevel? Current { get; internal set; } - - /// - /// If is not already Current and visible, finds the last Modal Toplevel in the stack and makes it Current. - /// - private static void EnsureModalOrVisibleAlwaysOnTop (Toplevel topLevel) - { - if (!topLevel.Running - || (topLevel == Current && topLevel.Visible) - || ApplicationOverlapped.OverlappedTop == null - || TopLevels.Peek ().Modal) - { - return; - } - - foreach (Toplevel top in TopLevels.Reverse ()) - { - if (top.Modal && top != Current) - { - ApplicationOverlapped.MoveCurrent (top); - - return; - } - } - - if (!topLevel.Visible && topLevel == Current) - { - ApplicationOverlapped.OverlappedMoveNext (); - } - } - } diff --git a/Terminal.Gui/Application/Application.cs b/Terminal.Gui/Application/Application.cs index d37ba3513..a2b62583e 100644 --- a/Terminal.Gui/Application/Application.cs +++ b/Terminal.Gui/Application/Application.cs @@ -149,7 +149,6 @@ public static partial class Application } TopLevels.Clear (); - Current = null; #if DEBUG_IDISPOSABLE // Don't dispose the Top. It's up to caller dispose it diff --git a/Terminal.Gui/Application/ApplicationNavigation.cs b/Terminal.Gui/Application/ApplicationNavigation.cs index 088629140..cc1df9a7e 100644 --- a/Terminal.Gui/Application/ApplicationNavigation.cs +++ b/Terminal.Gui/Application/ApplicationNavigation.cs @@ -85,6 +85,11 @@ public class ApplicationNavigation _focused = value; + //if (_focused is { } && Application.PositionCursor ()) + //{ + // Application.Driver?.UpdateCursor (); + //} + FocusedChanged?.Invoke (null, EventArgs.Empty); } @@ -105,6 +110,6 @@ public class ApplicationNavigation /// public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior) { - return Application.Current is { } && Application.Current.AdvanceFocus (direction, behavior); + return Application.Top is { } && Application.Top.AdvanceFocus (direction, behavior); } } diff --git a/Terminal.Gui/Application/ApplicationOverlapped.cs b/Terminal.Gui/Application/ApplicationOverlapped.cs deleted file mode 100644 index 328897580..000000000 --- a/Terminal.Gui/Application/ApplicationOverlapped.cs +++ /dev/null @@ -1,444 +0,0 @@ -#nullable enable -using System.Diagnostics; -using System.Reflection; - -namespace Terminal.Gui; - -/// -/// Helper class for managing overlapped views in the application. -/// -public static class ApplicationOverlapped -{ - - /// - /// Gets or sets if is in overlapped mode within a Toplevel container. - /// - /// - /// - public static bool IsOverlapped (Toplevel? top) - { - return ApplicationOverlapped.OverlappedTop is { } && ApplicationOverlapped.OverlappedTop != top && !top!.Modal; - } - - /// - /// Gets the list of the Overlapped children which are not modal from the - /// . - /// - public static List? OverlappedChildren - { - get - { - if (OverlappedTop is { }) - { - List overlappedChildren = new (); - - lock (Application.TopLevels) - { - foreach (Toplevel top in Application.TopLevels) - { - if (top != OverlappedTop && !top.Modal) - { - overlappedChildren.Add (top); - } - } - } - - return overlappedChildren; - } - - return null; - } - } - - /// - /// The object used for the application on startup which - /// is true. - /// - public static Toplevel? OverlappedTop - { - get - { - if (Application.Top is { IsOverlappedContainer: true }) - { - return Application.Top; - } - - return null; - } - } - - /// Brings the superview of the most focused overlapped view is on front. - public static void BringOverlappedTopToFront () - { - if (OverlappedTop is { }) - { - return; - } - - View? top = FindTopFromView (Application.Top?.MostFocused); - - if (top is Toplevel && Application.Top?.Subviews.Count > 1 && Application.Top.Subviews [^1] != top) - { - Application.Top.MoveSubviewToStart (top); - } - } - - /// Gets the current visible Toplevel overlapped child that matches the arguments pattern. - /// The type. - /// The strings to exclude. - /// The matched view. - public static Toplevel? GetTopOverlappedChild (Type? type = null, string []? exclude = null) - { - if (OverlappedChildren is null || OverlappedTop is null) - { - return null; - } - - foreach (Toplevel top in OverlappedChildren) - { - if (type is { } && top.GetType () == type && exclude?.Contains (top.Data?.ToString ()) == false) - { - return top; - } - - if ((type is { } && top.GetType () != type) || exclude?.Contains (top.Data?.ToString ()) == true) - { - continue; - } - - return top; - } - - return null; - } - - - /// - /// Sets the focus to the next view in the specified direction within the provided list of views. - /// If the end of the list is reached, the focus wraps around to the first view in the list. - /// The method considers the current focused view (`Application.Current`) and attempts to move the focus - /// to the next view in the specified direction. If the focus cannot be set to the next view, it wraps around - /// to the first view in the list. - /// - /// - /// - internal static void SetFocusToNextViewWithWrap (IEnumerable? viewsInTabIndexes, NavigationDirection direction) - { - if (viewsInTabIndexes is null) - { - return; - } - - // This code-path only executes in obtuse IsOverlappedContainer scenarios. - Debug.Assert (Application.Current!.IsOverlappedContainer); - - bool foundCurrentView = false; - bool focusSet = false; - IEnumerable indexes = viewsInTabIndexes as View [] ?? viewsInTabIndexes.ToArray (); - int viewCount = indexes.Count (); - int currentIndex = 0; - - foreach (View view in indexes) - { - if (view == Application.Current) - { - foundCurrentView = true; - } - else if (foundCurrentView && !focusSet) - { - // One of the views is Current, but view is not. Attempt to Advance... - Application.Current!.SuperView?.AdvanceFocus (direction, null); - // QUESTION: AdvanceFocus returns false AND sets Focused to null if no view was found to advance to. Should't we only set focusProcessed if it returned true? - focusSet = true; - - if (Application.Current.SuperView?.Focused != Application.Current) - { - return; - } - - // Either AdvanceFocus didn't set focus or the view it set focus to is not current... - // continue... - } - - currentIndex++; - - if (foundCurrentView && !focusSet && currentIndex == viewCount) - { - // One of the views is Current AND AdvanceFocus didn't set focus AND we are at the last view in the list... - // This means we should wrap around to the first view in the list. - indexes.First ().SetFocus (); - } - } - } - - /// - /// Move to the next Overlapped child from the and set it as the if - /// it is not already. - /// - /// - /// - public static bool MoveToOverlappedChild (Toplevel? top) - { - ArgumentNullException.ThrowIfNull (top); - - if (top.Visible && OverlappedTop is { } && Application.Current?.Modal == false) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (top, 0, new ToplevelEqualityComparer ()); - Application.Current = top; - } - - return true; - } - - return false; - } - - /// Move to the next Overlapped child from the . - public static void OverlappedMoveNext () - { - if (OverlappedTop is { } && !Application.Current!.Modal) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveNext (); - var isOverlapped = false; - - while (Application.TopLevels.Peek () == OverlappedTop || !Application.TopLevels.Peek ().Visible) - { - if (!isOverlapped && Application.TopLevels.Peek () == OverlappedTop) - { - isOverlapped = true; - } - else if (isOverlapped && Application.TopLevels.Peek () == OverlappedTop) - { - MoveCurrent (Application.Top!); - - break; - } - - Application.TopLevels.MoveNext (); - } - - Application.Current = Application.TopLevels.Peek (); - } - } - } - - /// Move to the previous Overlapped child from the . - public static void OverlappedMovePrevious () - { - if (OverlappedTop is { } && !Application.Current!.Modal) - { - lock (Application.TopLevels) - { - Application.TopLevels.MovePrevious (); - var isOverlapped = false; - - while (Application.TopLevels.Peek () == OverlappedTop || !Application.TopLevels.Peek ().Visible) - { - if (!isOverlapped && Application.TopLevels.Peek () == OverlappedTop) - { - isOverlapped = true; - } - else if (isOverlapped && Application.TopLevels.Peek () == OverlappedTop) - { - MoveCurrent (Application.Top!); - - break; - } - - Application.TopLevels.MovePrevious (); - } - - Application.Current = Application.TopLevels.Peek (); - } - } - } - - internal static bool OverlappedChildNeedsDisplay () - { - if (OverlappedTop is null) - { - return false; - } - - lock (Application.TopLevels) - { - foreach (Toplevel top in Application.TopLevels) - { - if (top != Application.Current && top.Visible && (top.NeedsDisplay || top.SubViewNeedsDisplay || top.LayoutNeeded)) - { - OverlappedTop.SetSubViewNeedsDisplay (); - - return true; - } - } - } - - return false; - } - - internal static bool SetCurrentOverlappedAsTop () - { - if (OverlappedTop is null && Application.Current != Application.Top && Application.Current?.SuperView is null && Application.Current?.Modal == false) - { - Application.Top = Application.Current; - - return true; - } - - return false; - } - - /// - /// Finds the first Toplevel in the stack that is Visible and who's Frame contains the . - /// - /// - /// - /// - internal static Toplevel? FindDeepestTop (Toplevel start, in Point location) - { - if (!start.Frame.Contains (location)) - { - return null; - } - - lock (Application.TopLevels) - { - if (Application.TopLevels is not { Count: > 0 }) - { - return start; - } - - int rx = location.X - start.Frame.X; - int ry = location.Y - start.Frame.Y; - - foreach (Toplevel t in Application.TopLevels) - { - if (t == Application.Current) - { - continue; - } - - if (t != start && t.Visible && t.Frame.Contains (rx, ry)) - { - start = t; - - break; - } - } - } - - return start; - } - - /// - /// Given , returns the first Superview up the chain that is . - /// - internal static View? FindTopFromView (View? view) - { - if (view is null) - { - return null; - } - - View top = view.SuperView is { } && view.SuperView != Application.Top - ? view.SuperView - : view; - - while (top?.SuperView is { } && top?.SuperView != Application.Top) - { - top = top!.SuperView; - } - - return top; - } - - /// - /// If the is not the then is moved to the top of - /// the Toplevel stack and made Current. - /// - /// - /// - internal static bool MoveCurrent (Toplevel top) - { - // The Current is modal and the top is not modal Toplevel then - // the Current must be moved above the first not modal Toplevel. - if (OverlappedTop is { } - && top != OverlappedTop - && top != Application.Current - && Application.Current?.Modal == true - && !Application.TopLevels.Peek ().Modal) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (Application.Current, 0, new ToplevelEqualityComparer ()); - } - - var index = 0; - Toplevel [] savedToplevels = Application.TopLevels.ToArray (); - - foreach (Toplevel t in savedToplevels) - { - if (!t!.Modal && t != Application.Current && t != top && t != savedToplevels [index]) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (top, index, new ToplevelEqualityComparer ()); - } - } - - index++; - } - - return false; - } - - // The Current and the top are both not running Toplevel then - // the top must be moved above the first not running Toplevel. - if (OverlappedTop is { } - && top != OverlappedTop - && top != Application.Current - && Application.Current?.Running == false - && top?.Running == false) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (Application.Current, 0, new ToplevelEqualityComparer ()); - } - - var index = 0; - - foreach (Toplevel t in Application.TopLevels.ToArray ()) - { - if (!t.Running && t != Application.Current && index > 0) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (top, index - 1, new ToplevelEqualityComparer ()); - } - } - - index++; - } - - return false; - } - - if ((OverlappedTop is { } && top?.Modal == true && Application.TopLevels.Peek () != top) - || (OverlappedTop is { } && Application.Current != OverlappedTop && Application.Current?.Modal == false && top == OverlappedTop) - || (OverlappedTop is { } && Application.Current?.Modal == false && top != Application.Current) - || (OverlappedTop is { } && Application.Current?.Modal == true && top == OverlappedTop)) - { - lock (Application.TopLevels) - { - Application.TopLevels.MoveTo (top!, 0, new ToplevelEqualityComparer ()); - Application.Current = top; - } - } - - return true; - } -} diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index 397c7b742..181526158 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -290,7 +290,6 @@ public class Border : Adornment if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) { Parent!.SetFocus (); - ApplicationOverlapped.BringOverlappedTopToFront (); if (!Parent!.Arrangement.HasFlag (ViewArrangement.Movable) && !Parent!.Arrangement.HasFlag (ViewArrangement.BottomResizable) @@ -580,6 +579,7 @@ public class Border : Adornment break; } + Application.Refresh (); return true; } @@ -1260,6 +1260,8 @@ public class Border : Adornment } } + Application.Refresh (); + return true; }); @@ -1282,6 +1284,8 @@ public class Border : Adornment Parent!.Height = Parent.Height! + 1; } + Application.Refresh (); + return true; }); @@ -1307,6 +1311,8 @@ public class Border : Adornment } } + Application.Refresh (); + return true; }); @@ -1329,6 +1335,8 @@ public class Border : Adornment Parent!.Width = Parent.Width! + 1; } + Application.Refresh (); + return true; }); diff --git a/Terminal.Gui/View/View.Navigation.cs b/Terminal.Gui/View/View.Navigation.cs index e1b652cbb..5a507b343 100644 --- a/Terminal.Gui/View/View.Navigation.cs +++ b/Terminal.Gui/View/View.Navigation.cs @@ -245,7 +245,7 @@ public partial class View // Focus and cross-view navigation management (TabStop } /// Returns a value indicating if this View is currently on Top (Active) - public bool IsCurrentTop => Application.Current == this; + public bool IsCurrentTop => Application.Top == this; /// /// Returns the most focused Subview down the subview-hierarchy. @@ -609,12 +609,12 @@ public partial class View // Focus and cross-view navigation management (TabStop newFocusedView = superViewOrParent; } - if (Application.Navigation is { } && Application.Current is { }) + if (Application.Navigation is { } && Application.Top is { }) { // Temporarily ensure this view can't get focus bool prevCanFocus = _canFocus; _canFocus = false; - bool restoredFocus = Application.Current!.RestoreFocus (); + bool restoredFocus = Application.Top!.RestoreFocus (); _canFocus = prevCanFocus; if (restoredFocus) diff --git a/Terminal.Gui/Views/Menu/ContextMenu.cs b/Terminal.Gui/Views/Menu/ContextMenu.cs index 8751ada92..a963036dc 100644 --- a/Terminal.Gui/Views/Menu/ContextMenu.cs +++ b/Terminal.Gui/Views/Menu/ContextMenu.cs @@ -177,7 +177,7 @@ public sealed class ContextMenu : IDisposable } MenuItems = menuItems; - _container = Application.Current; + _container = Application.Top; _container!.Closing += Container_Closing; _container.Deactivate += Container_Deactivate; _container.Disposing += Container_Disposing; diff --git a/Terminal.Gui/Views/Menu/Menu.cs b/Terminal.Gui/Views/Menu/Menu.cs index d251a382a..f90107941 100644 --- a/Terminal.Gui/Views/Menu/Menu.cs +++ b/Terminal.Gui/Views/Menu/Menu.cs @@ -144,10 +144,10 @@ internal sealed class Menu : View public Menu () { - if (Application.Current is { }) + if (Application.Top is { }) { - Application.Current.DrawContentComplete += Current_DrawContentComplete; - Application.Current.SizeChanging += Current_TerminalResized; + Application.Top.DrawContentComplete += Current_DrawContentComplete; + Application.Top.SizeChanging += Current_TerminalResized; } Application.MouseEvent += Application_RootMouseEvent; @@ -607,6 +607,7 @@ internal sealed class Menu : View Application.UngrabMouse (); _host.CloseAllMenus (); + Application.Driver!.ClearContents (); Application.Refresh (); _host.Run (action); @@ -952,10 +953,10 @@ internal sealed class Menu : View { RemoveKeyBindingsHotKey (_barItems); - if (Application.Current is { }) + if (Application.Top is { }) { - Application.Current.DrawContentComplete -= Current_DrawContentComplete; - Application.Current.SizeChanging -= Current_TerminalResized; + Application.Top.DrawContentComplete -= Current_DrawContentComplete; + Application.Top.SizeChanging -= Current_TerminalResized; } Application.MouseEvent -= Application_RootMouseEvent; diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs index cbe3efd20..a0f79725e 100644 --- a/Terminal.Gui/Views/Menu/MenuBar.cs +++ b/Terminal.Gui/Views/Menu/MenuBar.cs @@ -402,7 +402,7 @@ public class MenuBar : View, IDesignable _selected = 0; SetNeedsDisplay (); - _previousFocused = (SuperView is null ? Application.Current?.Focused : SuperView.Focused)!; + _previousFocused = (SuperView is null ? Application.Top?.Focused : SuperView.Focused)!; OpenMenu (_selected); if (!SelectEnabledItem ( @@ -463,7 +463,7 @@ public class MenuBar : View, IDesignable if (_openMenu is null) { - _previousFocused = (SuperView is null ? Application.Current?.Focused ?? null : SuperView.Focused)!; + _previousFocused = (SuperView is null ? Application.Top?.Focused ?? null : SuperView.Focused)!; } OpenMenu (idx, sIdx, subMenu); @@ -540,10 +540,10 @@ public class MenuBar : View, IDesignable private void CloseOtherOpenedMenuBar () { - if (Application.Current is { }) + if (Application.Top is { }) { // Close others menu bar opened - Menu? menu = Application.Current.Subviews.FirstOrDefault (v => v is Menu m && m.Host != this && m.Host.IsMenuOpen) as Menu; + Menu? menu = Application.Top.Subviews.FirstOrDefault (v => v is Menu m && m.Host != this && m.Host.IsMenuOpen) as Menu; menu?.Host.CleanUp (); } } @@ -579,7 +579,7 @@ public class MenuBar : View, IDesignable case false: if (_openMenu is { }) { - Application.Current?.Remove (_openMenu); + Application.Top?.Remove (_openMenu); } SetNeedsDisplay (); @@ -614,7 +614,7 @@ public class MenuBar : View, IDesignable if (OpenCurrentMenu is { }) { - Application.Current?.Remove (OpenCurrentMenu); + Application.Top?.Remove (OpenCurrentMenu); OpenCurrentMenu.Dispose (); OpenCurrentMenu = null; } @@ -662,7 +662,7 @@ public class MenuBar : View, IDesignable } Rectangle superViewFrame = SuperView?.Frame ?? Application.Screen; - View? sv = SuperView ?? Application.Current; + View? sv = SuperView ?? Application.Top; if (sv is null) { @@ -789,7 +789,7 @@ public class MenuBar : View, IDesignable { case null: // Open a submenu below a MenuBar - _lastFocused ??= SuperView is null ? Application.Current?.MostFocused : SuperView.MostFocused; + _lastFocused ??= SuperView is null ? Application.Top?.MostFocused : SuperView.MostFocused; if (_openSubMenu is { } && !CloseMenu (false, true)) { @@ -798,7 +798,7 @@ public class MenuBar : View, IDesignable if (_openMenu is { }) { - Application.Current?.Remove (_openMenu); + Application.Top?.Remove (_openMenu); _openMenu.Dispose (); _openMenu = null; } @@ -818,7 +818,7 @@ public class MenuBar : View, IDesignable locationOffset = GetScreenOffset (); } - if (SuperView is { } && SuperView != Application.Current) + if (SuperView is { } && SuperView != Application.Top) { locationOffset.X += SuperView.Border.Thickness.Left; locationOffset.Y += SuperView.Border.Thickness.Top; @@ -835,9 +835,9 @@ public class MenuBar : View, IDesignable OpenCurrentMenu = _openMenu; OpenCurrentMenu._previousSubFocused = _openMenu; - if (Application.Current is { }) + if (Application.Top is { }) { - Application.Current.Add (_openMenu); + Application.Top.Add (_openMenu); } else { @@ -902,7 +902,7 @@ public class MenuBar : View, IDesignable OpenCurrentMenu._previousSubFocused = last._previousSubFocused; _openSubMenu.Add (OpenCurrentMenu); - Application.Current?.Add (OpenCurrentMenu); + Application.Top?.Add (OpenCurrentMenu); if (!OpenCurrentMenu.IsInitialized) { @@ -985,7 +985,7 @@ public class MenuBar : View, IDesignable { foreach (Menu item in _openSubMenu) { - Application.Current!.Remove (item); + Application.Top!.Remove (item); item.Dispose (); } } @@ -1224,7 +1224,7 @@ public class MenuBar : View, IDesignable if (_openSubMenu is { }) { menu = _openSubMenu [i]; - Application.Current!.Remove (menu); + Application.Top!.Remove (menu); _openSubMenu.Remove (menu); if (Application.MouseGrabView == menu) diff --git a/Terminal.Gui/Views/Slider.cs b/Terminal.Gui/Views/Slider.cs index b96d96a4a..47dd76d45 100644 --- a/Terminal.Gui/Views/Slider.cs +++ b/Terminal.Gui/Views/Slider.cs @@ -848,7 +848,7 @@ public class Slider : View, IOrientation if (IsInitialized) { - normalAttr = ColorScheme?.Normal ?? Application.Current.ColorScheme.Normal; + normalAttr = ColorScheme?.Normal ?? Application.Top.ColorScheme.Normal; setAttr = Style.SetChar.Attribute ?? ColorScheme!.HotNormal; } diff --git a/Terminal.Gui/Views/TileView.cs b/Terminal.Gui/Views/TileView.cs index 698f67d43..b6e57dd90 100644 --- a/Terminal.Gui/Views/TileView.cs +++ b/Terminal.Gui/Views/TileView.cs @@ -916,7 +916,6 @@ public class TileView : View { // Start a Drag SetFocus (); - ApplicationOverlapped.BringOverlappedTopToFront (); if (mouseEvent.Flags == MouseFlags.Button1Pressed) { diff --git a/Terminal.Gui/Views/Toplevel.cs b/Terminal.Gui/Views/Toplevel.cs index a97bef473..07f4878cb 100644 --- a/Terminal.Gui/Views/Toplevel.cs +++ b/Terminal.Gui/Views/Toplevel.cs @@ -175,55 +175,7 @@ public partial class Toplevel : View /// public virtual void RequestStop () { - if (IsOverlappedContainer - && Running - && (Application.Current == this - || Application.Current?.Modal == false - || (Application.Current?.Modal == true && Application.Current?.Running == false))) - { - foreach (Toplevel child in ApplicationOverlapped.OverlappedChildren!) - { - var ev = new ToplevelClosingEventArgs (this); - - if (child.OnClosing (ev)) - { - return; - } - - child.Running = false; - Application.RequestStop (child); - } - - Running = false; - Application.RequestStop (this); - } - else if (IsOverlappedContainer && Running && Application.Current?.Modal == true && Application.Current?.Running == true) - { - var ev = new ToplevelClosingEventArgs (Application.Current); - - if (OnClosing (ev)) - { - return; - } - - Application.RequestStop (Application.Current); - } - else if (!IsOverlappedContainer && Running && (!Modal || (Modal && Application.Current != this))) - { - var ev = new ToplevelClosingEventArgs (this); - - if (OnClosing (ev)) - { - return; - } - - Running = false; - Application.RequestStop (this); - } - else - { - Application.RequestStop (Application.Current); - } + Application.RequestStop (Application.Top); } /// @@ -246,11 +198,6 @@ public partial class Toplevel : View internal virtual void OnChildClosed (Toplevel top) { - if (IsOverlappedContainer) - { - SetSubViewNeedsDisplay (); - } - ChildClosed?.Invoke (this, new (top)); } @@ -311,26 +258,8 @@ public partial class Toplevel : View Clear (); //LayoutSubviews (); - PositionToplevels (); - - if (this == ApplicationOverlapped.OverlappedTop) - { - // This enables correct draw behavior when switching between overlapped subviews - foreach (Toplevel top in ApplicationOverlapped.OverlappedChildren!.AsEnumerable ().Reverse ()) - { - if (top.Frame.IntersectsWith (Viewport)) - { - if (top != this && !top.IsCurrentTop && !OutsideTopFrame (top) && top.Visible) - { - top.SetNeedsLayout (); - top.SetNeedsDisplay (top.Viewport); - top.Draw (); - top.OnRenderLineCanvas (); - } - } - } - } - + //PositionToplevels (); + // BUGBUG: This appears to be a hack to get ScrollBarViews to render correctly. foreach (View view in Subviews) { @@ -353,35 +282,6 @@ public partial class Toplevel : View // TODO: Make cancelable? internal virtual void OnSizeChanging (SizeChangedEventArgs size) { SizeChanging?.Invoke (this, size); } - /// - public override Point? PositionCursor () - { - if (!IsOverlappedContainer) - { - return null; - } - - // This code path only happens when the Toplevel is an Overlapped container - - if (Focused is null) - { - // TODO: this is an Overlapped hack - foreach (Toplevel top in ApplicationOverlapped.OverlappedChildren!) - { - if (top != this && top.Visible) - { - top.SetFocus (); - - return null; - } - } - } - - Point? cursor2 = base.PositionCursor (); - - return null; - } - /// /// Adjusts the location and size of within this Toplevel. Virtual method enabling /// implementation of specific positions for inherited views. @@ -416,8 +316,10 @@ public partial class Toplevel : View maxWidth -= superView.GetAdornmentsThickness ().Left + superView.GetAdornmentsThickness ().Right; } - if ((superView != top || top?.SuperView is { } || (top != Application.Top && top!.Modal) || (top?.SuperView is null && ApplicationOverlapped.IsOverlapped (top))) + // BUGBUG: The && true is a temp hack + if ((superView != top || top?.SuperView is { } || (top != Application.Top && top!.Modal) || (top == Application.Top && top?.SuperView is null)) && (top!.Frame.X + top.Frame.Width > maxWidth || ny > top.Frame.Y)) + { if (top?.X is null or PosAbsolute && top?.Frame.X != nx) { @@ -470,6 +372,9 @@ public partial class Toplevel : View // TODO: v2 - Not sure this is needed anymore. internal void PositionToplevels () { + return; + + PositionToplevel (this); foreach (View top in Subviews) diff --git a/Terminal.Gui/Views/ToplevelOverlapped.cs b/Terminal.Gui/Views/ToplevelOverlapped.cs deleted file mode 100644 index 28513c4ce..000000000 --- a/Terminal.Gui/Views/ToplevelOverlapped.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Terminal.Gui; - -public partial class Toplevel -{ - /// Gets or sets if this Toplevel is a container for overlapped children. - public bool IsOverlappedContainer { get; set; } -} - diff --git a/UICatalog/Scenarios/BackgroundWorkerCollection.cs b/UICatalog/Scenarios/BackgroundWorkerCollection.cs deleted file mode 100644 index 3522f059e..000000000 --- a/UICatalog/Scenarios/BackgroundWorkerCollection.cs +++ /dev/null @@ -1,540 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Threading; -using Terminal.Gui; - -namespace UICatalog.Scenarios; - -[ScenarioMetadata ("BackgroundWorker Collection", "A persisting multi Toplevel BackgroundWorker threading")] -[ScenarioCategory ("Threading")] -[ScenarioCategory ("Overlapped")] -[ScenarioCategory ("Runnable")] -[ScenarioCategory ("Dialogs")] -[ScenarioCategory ("Controls")] -public class BackgroundWorkerCollection : Scenario -{ - public override void Main () - { - Application.Run ().Dispose (); - -#if DEBUG_IDISPOSABLE - if (ApplicationOverlapped.OverlappedChildren is { }) - { - Debug.Assert (ApplicationOverlapped.OverlappedChildren?.Count == 0); - Debug.Assert (Application.Top == ApplicationOverlapped.OverlappedTop); - } -#endif - - Application.Shutdown (); - } - - private class OverlappedMain : Toplevel - { - private readonly MenuBar _menu; - private WorkerApp _workerApp; - - public OverlappedMain () - { - Arrangement = ViewArrangement.Movable; - Data = "OverlappedMain"; - - IsOverlappedContainer = true; - - _workerApp = new WorkerApp { Visible = false }; - _workerApp.Border.Thickness = new (0, 1, 0, 0); - _workerApp.Border.LineStyle = LineStyle.Dashed; - - _menu = new MenuBar - { - Menus = - [ - new MenuBarItem ( - "_Options", - new MenuItem [] - { - new ( - "_Run Worker", - "", - () => _workerApp.RunWorker (), - null, - null, - KeyCode.CtrlMask | KeyCode.R - ), - new ( - "_Cancel Worker", - "", - () => _workerApp.CancelWorker (), - null, - null, - KeyCode.CtrlMask | KeyCode.C - ), - null, - new ( - "_Quit", - "", - () => Quit (), - null, - null, - Application.QuitKey - ) - } - ), - new MenuBarItem ("_View", new MenuItem [] { }), - new MenuBarItem ("_Window", new MenuItem [] { }) - ] - }; - ; - _menu.MenuOpening += Menu_MenuOpening; - Add (_menu); - var statusBar = new StatusBar ( - new [] - { - new Shortcut (Application.QuitKey, $"Quit", Quit), - new Shortcut ( - Key.R.WithCtrl, - "Run Worker", - () => _workerApp.RunWorker () - ), - new Shortcut ( - Key.C.WithCtrl, - "Cancel Worker", - () => _workerApp.CancelWorker () - ) - } - ); - Add (statusBar); - Ready += OverlappedMain_Ready; - Activate += OverlappedMain_Activate; - Deactivate += OverlappedMain_Deactivate; - } - - private void OverlappedMain_Ready (object sender, EventArgs e) - { - if (_workerApp?.Running == false) - { - Application.Run (_workerApp); - } - } - - private void Menu_MenuOpening (object sender, MenuOpeningEventArgs menu) - { - if (menu.CurrentMenu.Title == "_Window") - { - menu.NewMenuBarItem = OpenedWindows (); - } - else if (menu.CurrentMenu.Title == "_View") - { - menu.NewMenuBarItem = View (); - } - } - - private MenuBarItem OpenedWindows () - { - var index = 1; - List menuItems = new (); - List sortedChildren = ApplicationOverlapped.OverlappedChildren; - sortedChildren.Sort (new ToplevelComparer ()); - - foreach (Toplevel top in sortedChildren) - { - if (top.Data.ToString () == "WorkerApp" && !top.Visible) - { - continue; - } - - var item = new MenuItem (); - item.Title = top is Window ? $"{index} {((Window)top).Title}" : $"{index} {top.Data}"; - index++; - item.CheckType |= MenuItemCheckStyle.Checked; - string topTitle = top is Window ? ((Window)top).Title : top.Data.ToString (); - string itemTitle = item.Title.Substring (index.ToString ().Length + 1); - - if (top == ApplicationOverlapped.GetTopOverlappedChild () && topTitle == itemTitle) - { - item.Checked = true; - } - else - { - item.Checked = false; - } - - item.Action += () => { ApplicationOverlapped.MoveToOverlappedChild (top); }; - menuItems.Add (item); - } - - if (menuItems.Count == 0) - { - return new MenuBarItem ("_Window", "", null); - } - - return new MenuBarItem ("_Window", new List { menuItems.ToArray () }); - } - - private void OverlappedMain_Activate (object sender, ToplevelEventArgs top) - { - _workerApp?.WriteLog ($"{(top.Toplevel is null ? ((Toplevel)sender).Data : top.Toplevel.Data)} activate."); - } - - private void OverlappedMain_Deactivate (object sender, ToplevelEventArgs top) - { - _workerApp?.WriteLog ($"{top.Toplevel.Data} deactivate."); - } - - private void Quit () { RequestStop (); } - - private MenuBarItem View () - { - List menuItems = new (); - var item = new MenuItem { Title = "WorkerApp", CheckType = MenuItemCheckStyle.Checked }; - Toplevel top = ApplicationOverlapped.OverlappedChildren?.Find (x => x.Data.ToString () == "WorkerApp"); - - if (top != null) - { - item.Checked = top.Visible; - } - - item.Action += () => - { - Toplevel top = ApplicationOverlapped.OverlappedChildren.Find (x => x.Data.ToString () == "WorkerApp"); - item.Checked = top.Visible = (bool)!item.Checked; - - if (top.Visible) - { - ApplicationOverlapped.MoveToOverlappedChild (top); - } - else - { - ApplicationOverlapped.OverlappedTop!.SetNeedsDisplay (); - } - }; - menuItems.Add (item); - - return new 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 - { - public Staging (DateTime? startStaging, bool completed = false) - { - StartStaging = startStaging; - Completed = completed; - } - - public bool Completed { get; } - public DateTime? StartStaging { get; } - } - - private class StagingUIController : Window - { - private readonly Button _close; - private readonly Label _label; - private readonly ListView _listView; - private readonly Button _start; - - public StagingUIController (Staging staging, ObservableCollection list) : this () - { - Staging = staging; - _label.Text = "Work list:"; - _listView.Enabled = true; - _listView.SetSource (list); - _start.Visible = false; - Id = ""; - } - - public StagingUIController () - { - Arrangement = ViewArrangement.Movable; - - X = Pos.Center (); - Y = Pos.Center (); - Width = Dim.Percent (85); - Height = Dim.Percent (85); - - ColorScheme = Colors.ColorSchemes ["Dialog"]; - - Title = "Run Worker"; - - _label = new Label - { - X = Pos.Center (), - Y = 1, - ColorScheme = Colors.ColorSchemes ["Dialog"], - Text = "Press start to do the work or close to quit." - }; - Add (_label); - - _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 }; - - _start.Accept += (s, e) => - { - Staging = new Staging (DateTime.Now); - RequestStop (); - }; - Add (_start); - - _close = new Button { Text = "Close" }; - _close.Accept += OnReportClosed; - Add (_close); - - KeyDown += (s, e) => - { - if (e == Application.QuitKey) - { - OnReportClosed (this, EventArgs.Empty); - } - }; - - LayoutStarted += StagingUIController_LayoutStarted; - Disposing += StagingUIController_Disposing; - } - - private void StagingUIController_Disposing (object sender, EventArgs e) - { - LayoutStarted -= StagingUIController_LayoutStarted; - Disposing -= StagingUIController_Disposing; - } - - private void StagingUIController_LayoutStarted (object sender, LayoutEventArgs e) - { - int btnsWidth = _start.Frame.Width + _close.Frame.Width + 2 - 1; - int shiftLeft = Math.Max ((Viewport.Width - btnsWidth) / 2 - 2, 0); - - shiftLeft += _close.Frame.Width + 1; - _close.X = Pos.AnchorEnd (shiftLeft); - _close.Y = Pos.AnchorEnd (1); - - shiftLeft += _start.Frame.Width + 1; - _start.X = Pos.AnchorEnd (shiftLeft); - _start.Y = Pos.AnchorEnd (1); - } - - public Staging Staging { get; private set; } - public event Action ReportClosed; - - private void OnReportClosed (object sender, EventArgs e) - { - if (Staging?.StartStaging != null) - { - ReportClosed?.Invoke (this); - } - - RequestStop (); - } - } - - private class WorkerApp : Toplevel - { - private readonly ListView _listLog; - private readonly ObservableCollection _log = []; - private List _stagingsUi; - private Dictionary _stagingWorkers; - - public WorkerApp () - { - Arrangement = ViewArrangement.Movable; - - Data = "WorkerApp"; - Title = "Worker collection Log"; - - Width = Dim.Percent (80); - Height = Dim.Percent (50); - - ColorScheme = Colors.ColorSchemes ["Base"]; - - _listLog = new ListView - { - X = 0, - 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 = ApplicationOverlapped.OverlappedChildren!.Find (x => x.Data.ToString () == "WorkerApp"); - - if (e.RequestingTop == this && Visible && top == this) - { - Visible = false; - e.Cancel = true; - - ApplicationOverlapped.OverlappedMoveNext (); - } - } - - public void CancelWorker () - { - if (_stagingWorkers == null || _stagingWorkers.Count == 0) - { - WriteLog ($"Worker is not running at {DateTime.Now}!"); - - return; - } - - foreach (KeyValuePair sw in _stagingWorkers) - { - Staging key = sw.Key; - BackgroundWorker value = sw.Value; - - if (!key.Completed) - { - value.CancelAsync (); - } - - WriteLog ( - $"Worker {key.StartStaging}.{key.StartStaging:fff} is canceling at {DateTime.Now}!" - ); - - _stagingWorkers.Remove (sw.Key); - } - } - - public void RunWorker () - { - var stagingUI = new StagingUIController { Modal = true }; - - Staging staging = null; - var worker = new BackgroundWorker { WorkerSupportsCancellation = true }; - - worker.DoWork += (s, e) => - { - List stageResult = new (); - - for (var i = 0; i < 500; i++) - { - stageResult.Add ( - $"Worker {i} started at {DateTime.Now}" - ); - e.Result = stageResult; - Thread.Sleep (1); - - if (worker.CancellationPending) - { - e.Cancel = true; - - return; - } - } - }; - - worker.RunWorkerCompleted += (s, e) => - { - if (e.Error != null) - { - // Failed - WriteLog ( - $"Exception occurred {e.Error.Message} on Worker {staging.StartStaging}.{staging.StartStaging:fff} at {DateTime.Now}" - ); - } - else if (e.Cancelled) - { - // Canceled - WriteLog ( - $"Worker {staging.StartStaging}.{staging.StartStaging:fff} was canceled at {DateTime.Now}!" - ); - } - else - { - // Passed - WriteLog ( - $"Worker {staging.StartStaging}.{staging.StartStaging:fff} was completed at {DateTime.Now}." - ); - Application.Refresh (); - - var stagingUI = new StagingUIController (staging, e.Result as ObservableCollection) - { - Modal = false, - Title = - $"Worker started at {staging.StartStaging}.{staging.StartStaging:fff}", - Data = $"{staging.StartStaging}.{staging.StartStaging:fff}" - }; - - stagingUI.ReportClosed += StagingUI_ReportClosed; - - if (_stagingsUi == null) - { - _stagingsUi = new List (); - } - - _stagingsUi.Add (stagingUI); - _stagingWorkers.Remove (staging); -#if DEBUG_IDISPOSABLE - if (ApplicationOverlapped.OverlappedTop is null) - { - stagingUI.Dispose (); - return; - } -#endif - Application.Run (stagingUI); - } - }; - - Application.Run (stagingUI); - - 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) - { - _stagingWorkers = new Dictionary (); - } - - _stagingWorkers.Add (staging, worker); - worker.RunWorkerAsync (); - } - else - { - stagingUI.Dispose (); - } - } - - public void WriteLog (string msg) - { - _log.Add (msg); - _listLog.MoveDown (); - } - - 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/SingleBackgroundWorker.cs b/UICatalog/Scenarios/SingleBackgroundWorker.cs index 51ee6881e..ae756645e 100644 --- a/UICatalog/Scenarios/SingleBackgroundWorker.cs +++ b/UICatalog/Scenarios/SingleBackgroundWorker.cs @@ -177,7 +177,7 @@ public class SingleBackgroundWorker : Scenario new StagingUIController (_startStaging, e.Result as ObservableCollection); Toplevel top = Application.Top; top.Visible = false; - Application.Current.Visible = false; + Application.Top.Visible = false; builderUI.Load (); builderUI.Dispose (); top.Visible = true; diff --git a/UnitTests/Application/Application.NavigationTests.cs b/UnitTests/Application/Application.NavigationTests.cs index 325d9471e..2f5768ace 100644 --- a/UnitTests/Application/Application.NavigationTests.cs +++ b/UnitTests/Application/Application.NavigationTests.cs @@ -89,7 +89,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output) { Application.Navigation = new (); - Application.Current = new() + Application.Top = new() { Id = "top", CanFocus = true @@ -106,16 +106,17 @@ public class ApplicationNavigationTests (ITestOutputHelper output) Id = "subView2", CanFocus = true }; - Application.Current.Add (subView1, subView2); - Assert.False (Application.Current.HasFocus); + Application.Top.Add (subView1, subView2); + Assert.False (Application.Top.HasFocus); - Application.Current.SetFocus (); + Application.Top.SetFocus (); Assert.True (subView1.HasFocus); Assert.Equal (subView1, Application.Navigation.GetFocused ()); Application.Navigation.AdvanceFocus (NavigationDirection.Forward, null); Assert.Equal (subView2, Application.Navigation.GetFocused ()); + Application.Top.Dispose (); Application.ResetState (); } @@ -124,7 +125,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output) { Application.Navigation = new (); - Application.Current = new() + Application.Top = new() { Id = "top", CanFocus = true @@ -136,22 +137,23 @@ public class ApplicationNavigationTests (ITestOutputHelper output) CanFocus = true }; - Application.Current.Add (subView1); - Assert.False (Application.Current.HasFocus); + Application.Top.Add (subView1); + Assert.False (Application.Top.HasFocus); - Application.Current.SetFocus (); + Application.Top.SetFocus (); Assert.True (subView1.HasFocus); Assert.Equal (subView1, Application.Navigation.GetFocused ()); subView1.HasFocus = false; Assert.False (subView1.HasFocus); - Assert.True (Application.Current.HasFocus); - Assert.Equal (Application.Current, Application.Navigation.GetFocused ()); + Assert.True (Application.Top.HasFocus); + Assert.Equal (Application.Top, Application.Navigation.GetFocused ()); - Application.Current.HasFocus = false; - Assert.False (Application.Current.HasFocus); + Application.Top.HasFocus = false; + Assert.False (Application.Top.HasFocus); Assert.Null (Application.Navigation.GetFocused ()); + Application.Top.Dispose (); Application.ResetState (); } } diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 623d4a31f..bfd5bd2bc 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -221,12 +221,10 @@ public class ApplicationTests Assert.Equal (rs, runstate); Assert.Equal (topLevel, Application.Top); - Assert.Equal (topLevel, Application.Current); Application.NotifyNewRunState -= newRunStateFn; Application.End (runstate); - Assert.Null (Application.Current); Assert.NotNull (Application.Top); Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); @@ -291,7 +289,6 @@ public class ApplicationTests // Public Properties Assert.Null (Application.Top); - Assert.Null (Application.Current); Assert.Null (Application.MouseGrabView); Assert.Null (Application.WantContinuousButtonPressedView); @@ -307,8 +304,6 @@ public class ApplicationTests Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey); Assert.Equal (Key.F6, Application.NextTabGroupKey); Assert.Equal (Key.Esc, Application.QuitKey); - Assert.Null (ApplicationOverlapped.OverlappedChildren); - Assert.Null (ApplicationOverlapped.OverlappedTop); // Internal properties Assert.False (Application.IsInitialized); @@ -489,12 +484,10 @@ public class ApplicationTests Assert.Equal (rs, runstate); Assert.Equal (topLevel, Application.Top); - Assert.Equal (topLevel, Application.Current); Application.NotifyNewRunState -= newRunStateFn; Application.End (runstate); - Assert.Null (Application.Current); Assert.NotNull (Application.Top); Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); @@ -526,7 +519,6 @@ public class ApplicationTests Assert.Equal (Application.Top, rs.Toplevel); Assert.Null (Application.MouseGrabView); // public Assert.Null (Application.WantContinuousButtonPressedView); // public - Assert.False (ApplicationOverlapped.MoveToOverlappedChild (Application.Top!)); Application.Top.Dispose (); } @@ -576,113 +568,6 @@ public class ApplicationTests } } - [Fact] - [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 (); - - // Don't use Dialog here as it has more layout logic. Use Window instead. - var d = new Dialog (); - var t4 = new Toplevel (); - - // t1, t2, t3, d, t4 - var iterations = 5; - - t1.Ready += (s, e) => - { - Assert.Equal (t1, Application.Top); - Application.Run (t2); - }; - - t2.Ready += (s, e) => - { - Assert.Equal (t2, Application.Top); - Application.Run (t3); - }; - - t3.Ready += (s, e) => - { - Assert.Equal (t3, Application.Top); - Application.Run (d); - }; - - d.Ready += (s, e) => - { - Assert.Equal (t3, Application.Top); - Application.Run (t4); - }; - - t4.Ready += (s, e) => - { - Assert.Equal (t4, Application.Top); - t4.RequestStop (); - d.RequestStop (); - t3.RequestStop (); - t2.RequestStop (); - }; - - // Now this will close the OverlappedContainer when all OverlappedChildren was closed - t2.Closed += (s, _) => { t1.RequestStop (); }; - - Application.Iteration += (s, a) => - { - if (iterations == 5) - { - // The Current still is t4 because Current.Running is false. - Assert.Equal (t4, Application.Current); - Assert.False (Application.Current.Running); - Assert.Equal (t4, Application.Top); - } - else if (iterations == 4) - { - // The Current is d and Current.Running is false. - Assert.Equal (d, Application.Current); - Assert.False (Application.Current.Running); - Assert.Equal (t4, Application.Top); - } - else if (iterations == 3) - { - // The Current is t3 and Current.Running is false. - Assert.Equal (t3, Application.Current); - Assert.False (Application.Current.Running); - Assert.Equal (t3, Application.Top); - } - else if (iterations == 2) - { - // The Current is t2 and Current.Running is false. - Assert.Equal (t2, Application.Current); - Assert.False (Application.Current.Running); - Assert.Equal (t2, Application.Top); - } - else - { - // The Current is t1. - Assert.Equal (t1, Application.Current); - Assert.False (Application.Current.Running); - Assert.Equal (t1, Application.Top); - } - - iterations--; - }; - - 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 () { Application.Init (new FakeDriver ()); @@ -691,33 +576,8 @@ public class ApplicationTests Assert.NotNull (SynchronizationContext.Current); } - private void Post_Init_State () - { - Assert.NotNull (Application.Driver); - Assert.NotNull (Application.Top); - Assert.NotNull (Application.Current); - Assert.NotNull (Application.MainLoop); - - // FakeDriver is always 80x25 - Assert.Equal (80, Application.Driver!.Cols); - Assert.Equal (25, Application.Driver!.Rows); - } - - private void Pre_Init_State () - { - Assert.Null (Application.Driver); - Assert.Null (Application.Top); - Assert.Null (Application.Current); - Assert.Null (Application.MainLoop); - } - private void Shutdown () { Application.Shutdown (); } - private class TestToplevel : Toplevel - { - public TestToplevel () { IsOverlappedContainer = false; } - } - #region RunTests [Fact] @@ -787,7 +647,7 @@ public class ApplicationTests Application.RequestStop (); }; - Application.Run (); + Application.Run (); #if DEBUG_IDISPOSABLE Assert.False (initTop.WasDisposed); @@ -812,7 +672,7 @@ public class ApplicationTests Application.Iteration += (s, a) => { Application.RequestStop (); }; // Init has been called and we're passing no driver to Run. This is ok. - Application.Run (); + Application.Run (); Application.Top.Dispose (); Shutdown (); @@ -834,7 +694,7 @@ public class ApplicationTests Application.Iteration += (s, a) => { Application.RequestStop (); }; // Init has been called, selecting FakeDriver; we're passing no driver to Run. Should be fine. - Application.Run (); + Application.Run (); Application.Top.Dispose (); Shutdown (); @@ -853,7 +713,7 @@ public class ApplicationTests Application.Driver = null; // Init has been called, but Driver has been set to null. Bad. - Assert.Throws (() => Application.Run ()); + Assert.Throws (() => Application.Run ()); Shutdown (); @@ -870,7 +730,7 @@ public class ApplicationTests Application.Iteration += (s, a) => { Application.RequestStop (); }; - Application.Run (); + Application.Run (); Assert.Equal (typeof (FakeDriver), Application.Driver?.GetType ()); Application.Top.Dispose (); @@ -888,7 +748,7 @@ public class ApplicationTests Application.Iteration += (s, a) => { Application.RequestStop (); }; // Init has NOT been called and we're passing a valid driver to Run. This is ok. - Application.Run (null, new FakeDriver ()); + Application.Run (null, new FakeDriver ()); Application.Top.Dispose (); Shutdown (); @@ -908,7 +768,6 @@ public class ApplicationTests var top = new Toplevel (); RunState rs = Application.Begin (top); Assert.NotNull (rs); - Assert.Equal (top, Application.Current); Application.Iteration += (s, a) => { Application.RequestStop (); }; @@ -916,7 +775,6 @@ public class ApplicationTests top.Dispose (); Application.Shutdown (); - Assert.Null (Application.Current); Assert.Null (Application.Top); Assert.Null (Application.MainLoop); Assert.Null (Application.Driver); @@ -932,7 +790,6 @@ public class ApplicationTests var top = new Toplevel (); RunState rs = Application.Begin (top); Assert.NotNull (rs); - Assert.Equal (top, Application.Current); Application.Iteration += (s, a) => { top.Running = false; }; @@ -940,7 +797,6 @@ public class ApplicationTests top.Dispose (); Application.Shutdown (); - Assert.Null (Application.Current); Assert.Null (Application.Top); Assert.Null (Application.MainLoop); Assert.Null (Application.Driver); @@ -948,7 +804,7 @@ public class ApplicationTests [Fact] [TestRespondersDisposed] - public void Run_Loaded_Ready_Unlodaded_Events () + public void Run_Loaded_Ready_Unloaded_Events () { Init (); Toplevel top = new (); @@ -964,7 +820,7 @@ public class ApplicationTests } // TODO: All Toplevel layout tests should be moved to ToplevelTests.cs - [Fact (Skip = "#2491 - Changing focus should cause NeedsDispay = true, so bogus test?")] + [Fact (Skip = "#2491 - Changing focus should cause NeedsDisplay = true, so bogus test?")] public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty () { Init (); @@ -1061,7 +917,6 @@ public class ApplicationTests 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. @@ -1085,7 +940,6 @@ public class ApplicationTests #endif Application.Shutdown (); Assert.NotNull (w); - Assert.Null (Application.Current); Assert.NotNull (top); Assert.Null (Application.Top); } diff --git a/UnitTests/Application/CursorTests.cs b/UnitTests/Application/CursorTests.cs index 87999a9d2..7454e1501 100644 --- a/UnitTests/Application/CursorTests.cs +++ b/UnitTests/Application/CursorTests.cs @@ -31,7 +31,10 @@ public class CursorTests [SetupFakeDriver] public void PositionCursor_No_Focus_Returns_False () { - Assert.False (Application.PositionCursor (null)); + Application.Navigation = new (); + Application.Navigation.SetFocused (null); + + Assert.False (Application.PositionCursor ()); TestView view = new () { @@ -40,13 +43,14 @@ public class CursorTests Height = 1, }; view.TestLocation = new Point (0, 0); - Assert.False (Application.PositionCursor (view)); + Assert.False (Application.PositionCursor ()); } [Fact] [SetupFakeDriver] public void PositionCursor_No_Position_Returns_False () { + Application.Navigation = new (); TestView view = new () { CanFocus = false, @@ -55,14 +59,15 @@ public class CursorTests }; view.CanFocus = true; - view.SetFocus(); - Assert.False (Application.PositionCursor (view)); + view.SetFocus (); + Assert.False (Application.PositionCursor ()); } [Fact] [SetupFakeDriver] public void PositionCursor_No_IntersectSuperView_Returns_False () { + Application.Navigation = new (); View superView = new () { Width = 1, @@ -73,7 +78,7 @@ public class CursorTests { CanFocus = false, X = 1, - Y =1, + Y = 1, Width = 1, Height = 1, }; @@ -82,13 +87,14 @@ public class CursorTests view.CanFocus = true; view.SetFocus (); view.TestLocation = new Point (0, 0); - Assert.False (Application.PositionCursor (view)); + Assert.False (Application.PositionCursor ()); } [Fact] [SetupFakeDriver] public void PositionCursor_Position_OutSide_SuperView_Returns_False () { + Application.Navigation = new (); View superView = new () { Width = 1, @@ -108,13 +114,14 @@ public class CursorTests view.CanFocus = true; view.SetFocus (); view.TestLocation = new Point (1, 1); - Assert.False (Application.PositionCursor (view)); + Assert.False (Application.PositionCursor ()); } [Fact] [SetupFakeDriver] public void PositionCursor_Focused_With_Position_Returns_True () { + Application.Navigation = new (); TestView view = new () { CanFocus = false, @@ -124,23 +131,24 @@ public class CursorTests view.CanFocus = true; view.SetFocus (); view.TestLocation = new Point (0, 0); - Assert.True (Application.PositionCursor (view)); + Assert.True (Application.PositionCursor ()); } [Fact] [SetupFakeDriver] public void PositionCursor_Defaults_Invisible () { + Application.Navigation = new (); View view = new () { CanFocus = true, Width = 1, Height = 1, }; - view.SetFocus(); + view.SetFocus (); Assert.True (view.HasFocus); - Assert.False (Application.PositionCursor (view)); + Assert.False (Application.PositionCursor ()); if (Application.Driver?.GetCursorVisibility (out CursorVisibility cursor) ?? false) { diff --git a/UnitTests/Application/KeyboardTests.cs b/UnitTests/Application/KeyboardTests.cs index 77fe4821e..09b1bf7a3 100644 --- a/UnitTests/Application/KeyboardTests.cs +++ b/UnitTests/Application/KeyboardTests.cs @@ -349,7 +349,6 @@ public class KeyboardTests top.Dispose (); Application.Shutdown (); - Assert.Null (Application.Current); Assert.Null (Application.Top); Assert.Null (Application.MainLoop); Assert.Null (Application.Driver); @@ -395,7 +394,6 @@ public class KeyboardTests top.Add (view1, view2); Application.Top = top; - Application.Current = top; view1.SetFocus (); Assert.True (view1.HasFocus); Assert.True (subView1.HasFocus); @@ -484,7 +482,6 @@ public class KeyboardTests var view2 = new View { Id = "view2", CanFocus = true }; top.Add (view1, view2); Application.Top = top; - Application.Current = top; view1.SetFocus (); // Act @@ -537,7 +534,6 @@ public class KeyboardTests top.Add (view1, view2); Application.Top = top; - Application.Current = top; view1.SetFocus (); Assert.True (view1.HasFocus); Assert.True (subView1.HasFocus); @@ -563,7 +559,6 @@ public class KeyboardTests var view2 = new View { Id = "view2", CanFocus = true }; top.Add (view1, view2); Application.Top = top; - Application.Current = top; view1.SetFocus (); // Act diff --git a/UnitTests/Application/RunStateTests.cs b/UnitTests/Application/RunStateTests.cs index 0e02101c5..ff34ab5d4 100644 --- a/UnitTests/Application/RunStateTests.cs +++ b/UnitTests/Application/RunStateTests.cs @@ -25,10 +25,8 @@ public class RunStateTests var top = new Toplevel (); RunState rs = Application.Begin (top); Assert.NotNull (rs); - Assert.Equal (top, Application.Current); Application.End (rs); - Assert.Null (Application.Current); Assert.NotNull (Application.Top); Assert.NotNull (Application.MainLoop); Assert.NotNull (Application.Driver); diff --git a/UnitTests/Dialogs/DialogTests.cs b/UnitTests/Dialogs/DialogTests.cs index 582cf659a..771ff11c8 100644 --- a/UnitTests/Dialogs/DialogTests.cs +++ b/UnitTests/Dialogs/DialogTests.cs @@ -1103,7 +1103,7 @@ public class DialogTests _output ); - Assert.True (Current.NewKeyDownEvent (Key.Enter)); + Assert.True (Top!.NewKeyDownEvent (Key.Enter)); } else if (iterations == 3) { @@ -1199,104 +1199,85 @@ public class DialogTests d.Dispose (); } - [Fact] - [AutoInitShutdown] - public void Location_When_Not_Application_Top_Not_Default () - { - var top = new Toplevel (); - top.BorderStyle = LineStyle.Double; +// [Fact] +// [AutoInitShutdown] +// public void Location_When_Not_Application_Top_Not_Default () +// { +// var top = new Toplevel (); +// top.BorderStyle = LineStyle.Double; - int iterations = -1; +// int iterations = -1; - // Override CM - Window.DefaultBorderStyle = LineStyle.Single; - Dialog.DefaultButtonAlignment = Alignment.Center; - Dialog.DefaultBorderStyle = LineStyle.Single; +// // Override CM +// Window.DefaultBorderStyle = LineStyle.Single; +// Dialog.DefaultButtonAlignment = Alignment.Center; +// Dialog.DefaultBorderStyle = LineStyle.Single; +// Dialog.DefaultShadow = ShadowStyle.None; - Iteration += (s, a) => - { - iterations++; +// Iteration += (s, a) => +// { +// iterations++; - if (iterations == 0) - { - var d = new Dialog { X = 5, Y = 5, Height = 3, Width = 5 }; - RunState rs = Begin (d); +// if (iterations == 0) +// { +// var d = new Dialog { X = 5, Y = 5, Height = 3, Width = 5 }; +// RunState rs = Begin (d); - Assert.Equal (new (5, 5), d.Frame.Location); +// Assert.Equal (new (5, 5), d.Frame.Location); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -╔══════════════════╗ -║ ║ -║ ║ -║ ║ -║ ║ -║ ┌───┐ ║ -║ │ │ ║ -║ └───┘ ║ -║ ║ -╚══════════════════╝", - _output - ); - End (rs); - d.Dispose (); +// TestHelpers.AssertDriverContentsWithFrameAre ( +// @" +//╔══════════════════╗ +//║ ║ +//║ ║ +//║ ║ +//║ ║ +//║ ┌───┐ ║ +//║ │ │ ║ +//║ └───┘ ║ +//║ ║ +//╚══════════════════╝", +// _output +// ); +// End (rs); +// d.Dispose (); - d = new () - { - X = 5, Y = 5, - Width = Dim.Percent (85), - Height = Dim.Percent (85) +// d = new () +// { +// X = 5, Y = 5, +// Width = Dim.Percent (85), +// Height = Dim.Percent (85) - }; - rs = Begin (d); +// }; +// rs = Begin (d); - // This is because of PostionTopLevels and EnsureVisibleBounds - Assert.Equal (new (3, 2), d.Frame.Location); +// TestHelpers.AssertDriverContentsWithFrameAre ( +// @" +//╔══════════════════╗ +//║ ║ +//║ ║ +//║ ║ +//║ ║ +//║ ┌────────────── +//║ │ +//║ │ +//║ │ +//╚════│ ", +// _output +// ); +// End (rs); +// d.Dispose (); +// } +// else if (iterations > 0) +// { +// RequestStop (); +// } +// }; - // #3127: Before - // Assert.Equal (new (17, 8), d.Frame.Size); - // TestHelpers.AssertDriverContentsWithFrameAre (@" - //╔══════════════════╗ - //║ ║ - //║ ┌───────────────┐ - //║ │ │ - //║ │ │ - //║ │ │ - //║ │ │ - //║ │ │ - //║ │ │ - //╚══└───────────────┘", _output); - - // #3127: After: Because Toplevel is now Width/Height = Dim.Filll - Assert.Equal (new (15, 6), d.Frame.Size); - - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -╔══════════════════╗ -║ ║ -║ ┌─────────────┐ ║ -║ │ │ ║ -║ │ │ ║ -║ │ │ ║ -║ │ │ ║ -║ └─────────────┘ ║ -║ ║ -╚══════════════════╝", - _output - ); - End (rs); - d.Dispose (); - } - else if (iterations > 0) - { - RequestStop (); - } - }; - - ((FakeDriver)Driver).SetBufferSize (20, 10); - Run (top); - top.Dispose (); - } +// ((FakeDriver)Driver).SetBufferSize (20, 10); +// Run (top); +// top.Dispose (); +// } [Fact] [AutoInitShutdown] diff --git a/UnitTests/Dialogs/MessageBoxTests.cs b/UnitTests/Dialogs/MessageBoxTests.cs index c4e501f80..bc200e859 100644 --- a/UnitTests/Dialogs/MessageBoxTests.cs +++ b/UnitTests/Dialogs/MessageBoxTests.cs @@ -152,7 +152,7 @@ public class MessageBoxTests } else if (iterations == 1) { - mbFrame = Application.Current.Frame; + mbFrame = Application.Top!.Frame; Application.RequestStop (); } }; @@ -338,8 +338,8 @@ public class MessageBoxTests { Application.Refresh (); - Assert.IsType (Application.Current); - Assert.Equal (new (height, width), Application.Current.Frame.Size); + Assert.IsType (Application.Top); + Assert.Equal (new (height, width), Application.Top.Frame.Size); Application.RequestStop (); } @@ -375,8 +375,8 @@ public class MessageBoxTests { Application.Refresh (); - Assert.IsType (Application.Current); - Assert.Equal (new (height, width), Application.Current.Frame.Size); + Assert.IsType (Application.Top); + Assert.Equal (new (height, width), Application.Top.Frame.Size); Application.RequestStop (); } @@ -408,8 +408,8 @@ public class MessageBoxTests { Application.Refresh (); - Assert.IsType (Application.Current); - Assert.Equal (new (height, width), Application.Current.Frame.Size); + Assert.IsType (Application.Top); + Assert.Equal (new (height, width), Application.Top.Frame.Size); Application.RequestStop (); } diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index 70e977a29..0942427d7 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -240,7 +240,7 @@ public class SetupFakeDriverAttribute : BeforeAfterTestAttribute public override void Before (MethodInfo methodUnderTest) { Debug.WriteLine ($"Before: {methodUnderTest.Name}"); - Application.ResetState (); + Application.ResetState (ignoreDisposed: true); Assert.Null (Application.Driver); Application.Driver = new FakeDriver { Rows = 25, Cols = 25 }; base.Before (methodUnderTest); @@ -750,11 +750,11 @@ internal partial class TestHelpers string replaced = toReplace; replaced = Environment.NewLine.Length switch - { - 2 when !replaced.Contains ("\r\n") => replaced.Replace ("\n", Environment.NewLine), - 1 => replaced.Replace ("\r\n", Environment.NewLine), - var _ => replaced - }; + { + 2 when !replaced.Contains ("\r\n") => replaced.Replace ("\n", Environment.NewLine), + 1 => replaced.Replace ("\r\n", Environment.NewLine), + var _ => replaced + }; return replaced; } diff --git a/UnitTests/View/Layout/Pos.AnchorEndTests.cs b/UnitTests/View/Layout/Pos.AnchorEndTests.cs index b5dd8eb34..990147405 100644 --- a/UnitTests/View/Layout/Pos.AnchorEndTests.cs +++ b/UnitTests/View/Layout/Pos.AnchorEndTests.cs @@ -254,39 +254,39 @@ public class PosAnchorEndTests (ITestOutputHelper output) top.Dispose (); } - // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved - // TODO: A new test that calls SetRelativeLayout directly is needed. - [Fact] - [AutoInitShutdown] - public void PosAnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel () - { - var viewWidth = 10; - var viewHeight = 1; + //// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved + //// TODO: A new test that calls SetRelativeLayout directly is needed. + //[Fact] + //[AutoInitShutdown] + //public void PosAnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel () + //{ + // var viewWidth = 10; + // var viewHeight = 1; - var tv = new TextView - { - X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight - }; + // var tv = new TextView + // { + // X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight + // }; - var win = new Window (); + // var win = new Window (); - win.Add (tv); + // win.Add (tv); - var menu = new MenuBar (); - var status = new StatusBar (); - Toplevel top = new (); - top.Add (win, menu, status); - RunState rs = Application.Begin (top); + // var menu = new MenuBar (); + // var status = new StatusBar (); + // Toplevel top = new (); + // top.Add (win, menu, status); + // RunState rs = Application.Begin (top); - Assert.Equal (new (0, 0, 80, 25), top.Frame); - Assert.Equal (new (0, 0, 80, 1), menu.Frame); - Assert.Equal (new (0, 24, 80, 1), status.Frame); - Assert.Equal (new (0, 1, 80, 23), win.Frame); - Assert.Equal (new (68, 20, 10, 1), tv.Frame); + // Assert.Equal (new (0, 0, 80, 25), top.Frame); + // Assert.Equal (new (0, 0, 80, 1), menu.Frame); + // Assert.Equal (new (0, 24, 80, 1), status.Frame); + // Assert.Equal (new (0, 1, 80, 23), win.Frame); + // Assert.Equal (new (68, 20, 10, 1), tv.Frame); - Application.End (rs); - top.Dispose (); - } + // Application.End (rs); + // top.Dispose (); + //} [Fact] public void PosAnchorEnd_Calculate_ReturnsExpectedValue () diff --git a/UnitTests/View/Layout/Pos.CombineTests.cs b/UnitTests/View/Layout/Pos.CombineTests.cs index 2dc576438..5f6ebc290 100644 --- a/UnitTests/View/Layout/Pos.CombineTests.cs +++ b/UnitTests/View/Layout/Pos.CombineTests.cs @@ -136,7 +136,7 @@ public class PosCombineTests (ITestOutputHelper output) Assert.Throws (() => Application.Run ()); top.Dispose (); - Application.Shutdown (); + Application.ResetState (ignoreDisposed: true); } } diff --git a/UnitTests/View/Layout/ToScreenTests.cs b/UnitTests/View/Layout/ToScreenTests.cs index 96cd3a326..f78f0fe20 100644 --- a/UnitTests/View/Layout/ToScreenTests.cs +++ b/UnitTests/View/Layout/ToScreenTests.cs @@ -961,7 +961,6 @@ public class ToScreenTests (ITestOutputHelper output) Application.Begin (top); - Assert.Equal (Application.Current, top); Assert.Equal (new (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows)); Assert.Equal (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame); Assert.Equal (new (0, 0, 80, 25), top.Frame); @@ -1117,7 +1116,6 @@ public class ToScreenTests (ITestOutputHelper output) Application.Begin (top); - Assert.Equal (Application.Current, top); Assert.Equal (new (0, 0, 80, 25), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows)); Assert.NotEqual (new (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame); Assert.Equal (new (3, 2, 20, 10), top.Frame); diff --git a/UnitTests/View/Navigation/CanFocusTests.cs b/UnitTests/View/Navigation/CanFocusTests.cs index ae22d3891..006a84dd4 100644 --- a/UnitTests/View/Navigation/CanFocusTests.cs +++ b/UnitTests/View/Navigation/CanFocusTests.cs @@ -325,10 +325,10 @@ public class CanFocusTests () : TestsAllViews Label label = new () { Text = "label" }; View view = new () { Text = "view", CanFocus = true }; Application.Navigation = new (); - Application.Current = new (); - Application.Current.Add (label, view); + Application.Top = new (); + Application.Top.Add (label, view); - Application.Current.SetFocus (); + Application.Top.SetFocus (); Assert.Equal (view, Application.Navigation.GetFocused ()); Assert.False (label.CanFocus); Assert.False (label.HasFocus); @@ -358,278 +358,10 @@ public class CanFocusTests () : TestsAllViews Assert.True (label.HasFocus); Assert.False (view.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); Application.ResetState (); } -#if V2_NEW_FOCUS_IMPL // Bogus test - depends on auto CanFocus behavior - - [Fact] - public void CanFocus_Container_ToFalse_Turns_All_Subviews_ToFalse_Too () - { - Application.Init (new FakeDriver ()); - - Toplevel t = new (); - - var w = new Window (); - var f = new FrameView (); - var v1 = new View { CanFocus = true }; - var v2 = new View { CanFocus = true }; - f.Add (v1, v2); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => - { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v1.CanFocus); - Assert.True (v2.CanFocus); - - w.CanFocus = false; - Assert.False (w.CanFocus); - Assert.False (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - }; - - Application.Iteration += (s, a) => Application.RequestStop (); - - Application.Run (t); - t.Dispose (); - Application.Shutdown (); - } -#endif - -#if V2_NEW_FOCUS_IMPL // Bogus test - depends on auto CanFocus behavior - - [Fact] - public void CanFocus_Container_Toggling_All_Subviews_To_Old_Value_When_Is_True () - { - Application.Init (new FakeDriver ()); - - Toplevel t = new (); - - var w = new Window (); - var f = new FrameView (); - var v1 = new View (); - var v2 = new View { CanFocus = true }; - f.Add (v1, v2); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => - { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.True (v2.CanFocus); - - w.CanFocus = false; - Assert.False (w.CanFocus); - Assert.False (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.False (v2.CanFocus); - - w.CanFocus = true; - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.False (v1.CanFocus); - Assert.True (v2.CanFocus); - }; - - Application.Iteration += (s, a) => Application.RequestStop (); - - Application.Run (t); - t.Dispose (); - Application.Shutdown (); - } -#endif -#if V2_NEW_FOCUS_IMPL // Bogus test - depends on auto CanFocus behavior - [Fact] - public void CanFocus_Faced_With_Container_After_Run () - { - Application.Init (new FakeDriver ()); - - Toplevel t = new (); - - var w = new Window (); - var f = new FrameView (); - var v = new View { CanFocus = true }; - f.Add (v); - w.Add (f); - t.Add (w); - - t.Ready += (s, e) => - { - Assert.True (t.CanFocus); - Assert.True (w.CanFocus); - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - - f.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - v.CanFocus = false; - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - Assert.Throws (() => v.CanFocus = true); - Assert.False (f.CanFocus); - Assert.False (v.CanFocus); - - f.CanFocus = true; - Assert.True (f.CanFocus); - Assert.True (v.CanFocus); - }; - - Application.Iteration += (s, a) => Application.RequestStop (); - - Application.Run (t); - t.Dispose (); - Application.Shutdown (); - } -#endif -#if V2_NEW_FOCUS_IMPL - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel () - { - var view1 = new View { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - var win1 = new Window { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1); - 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); - 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.OnKeyDown (Key.F6)); - 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.OnKeyDown (Key.F6)); - 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 - - view1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.True (view2.CanFocus); - Assert.True (view2.HasFocus); - Assert.Equal (win2, Application.Current.GetFocused ()); - Assert.Equal (view2, Application.Current.GetMostFocused ()); - top.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_On_Toplevel_Focus_View_On_Another_Toplevel () - { - var view1 = new View { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - var win1 = new Window { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1); - 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); - 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.OnKeyDown (Key.F6)); - 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.OnKeyDown (Key.F6)); - 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 - - win1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.False (win1.CanFocus); - Assert.False (win1.HasFocus); - Assert.True (view2.CanFocus); - Assert.True (view2.HasFocus); - Assert.Equal (win2, Application.Current.GetFocused ()); - Assert.Equal (view2, Application.Current.GetMostFocused ()); - top.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void CanFocus_Sets_To_False_With_Two_Views_Focus_Another_View_On_The_Same_Toplevel () - { - var view1 = new View { Id = "view1", Width = 10, Height = 1, CanFocus = true }; - - var view12 = new View - { - Id = "view12", - Y = 5, - Width = 10, - Height = 1, - CanFocus = true - }; - var win1 = new Window { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - win1.Add (view1, view12); - 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); - 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.OnKeyDown (Key.F6)); // move to win2 - 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.OnKeyDown (Key.F6)); - 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 - - view1.CanFocus = false; - Assert.False (view1.CanFocus); - Assert.False (view1.HasFocus); - Assert.True (view2.CanFocus); - Assert.False (view2.HasFocus); - Assert.Equal (win1, Application.Current.GetFocused ()); - Assert.Equal (view12, Application.Current.GetMostFocused ()); - top.Dispose (); - } -#endif - [Fact (Skip = "Causes crash on Ubuntu in Github Action. Bogus test anyway.")] public void WindowDispose_CanFocusProblem () { diff --git a/UnitTests/View/Navigation/NavigationTests.cs b/UnitTests/View/Navigation/NavigationTests.cs index 306e7739e..763219d76 100644 --- a/UnitTests/View/Navigation/NavigationTests.cs +++ b/UnitTests/View/Navigation/NavigationTests.cs @@ -28,7 +28,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews Toplevel top = new (); - Application.Current = top; + Application.Top = top; Application.Navigation = new ApplicationNavigation (); View otherView = new () @@ -115,7 +115,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews } Toplevel top = new (); - Application.Current = top; + Application.Top = top; Application.Navigation = new ApplicationNavigation (); View otherView = new () @@ -144,8 +144,8 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews Assert.False (view.HasFocus); Assert.False (otherView.HasFocus); - Application.Current.SetFocus (); - Assert.True (Application.Current!.HasFocus); + Application.Top.SetFocus (); + Assert.True (Application.Top!.HasFocus); Assert.True (top.HasFocus); // Start with the focus on our test view @@ -275,7 +275,7 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews Toplevel top = new (); - Application.Current = top; + Application.Top = top; Application.Navigation = new ApplicationNavigation (); View otherView = new () @@ -373,134 +373,6 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews Assert.Equal (subview2, view.MostFocused); } - // [Fact] - // [AutoInitShutdown] - // public void HotKey_Will_Invoke_KeyPressed_Only_For_The_MostFocused_With_Top_KeyPress_Event () - // { - // var sbQuiting = false; - // var tfQuiting = false; - // var topQuiting = false; - - // var sb = new StatusBar ( - // new Shortcut [] - // { - // new ( - // KeyCode.CtrlMask | KeyCode.Q, - // "Quit", - // () => sbQuiting = true - // ) - // } - // ); - // var tf = new TextField (); - // tf.KeyDown += Tf_KeyPressed; - - // void Tf_KeyPressed (object sender, Key obj) - // { - // if (obj.KeyCode == (KeyCode.Q | KeyCode.CtrlMask)) - // { - // obj.Handled = tfQuiting = true; - // } - // } - - // var win = new Window (); - // win.Add (sb, tf); - // Toplevel top = new (); - // top.KeyDown += Top_KeyPress; - - // void Top_KeyPress (object sender, Key obj) - // { - // if (obj.KeyCode == (KeyCode.Q | KeyCode.CtrlMask)) - // { - // obj.Handled = topQuiting = true; - // } - // } - - // top.Add (win); - // Application.Begin (top); - - // Assert.False (sbQuiting); - // Assert.False (tfQuiting); - // Assert.False (topQuiting); - - // Application.Driver?.SendKeys ('Q', ConsoleKey.Q, false, false, true); - // Assert.False (sbQuiting); - // Assert.True (tfQuiting); - // Assert.False (topQuiting); - - //#if BROKE_WITH_2927 - // tf.KeyPressed -= Tf_KeyPress; - // tfQuiting = false; - // Application.Driver?.SendKeys ('q', ConsoleKey.Q, false, false, true); - // Application.MainLoop.RunIteration (); - // Assert.True (sbQuiting); - // Assert.False (tfQuiting); - // Assert.False (topQuiting); - - // sb.RemoveItem (0); - // sbQuiting = false; - // Application.Driver?.SendKeys ('q', ConsoleKey.Q, false, false, true); - // Application.MainLoop.RunIteration (); - // Assert.False (sbQuiting); - // Assert.False (tfQuiting); - - //// This test is now invalid because `win` is focused, so it will receive the keypress - // Assert.True (topQuiting); - //#endif - // top.Dispose (); - // } - - // [Fact] - // [AutoInitShutdown] - // public void HotKey_Will_Invoke_KeyPressed_Only_For_The_MostFocused_Without_Top_KeyPress_Event () - // { - // var sbQuiting = false; - // var tfQuiting = false; - - // var sb = new StatusBar ( - // new Shortcut [] - // { - // new ( - // KeyCode.CtrlMask | KeyCode.Q, - // "~^Q~ Quit", - // () => sbQuiting = true - // ) - // } - // ); - // var tf = new TextField (); - // tf.KeyDown += Tf_KeyPressed; - - // void Tf_KeyPressed (object sender, Key obj) - // { - // if (obj.KeyCode == (KeyCode.Q | KeyCode.CtrlMask)) - // { - // obj.Handled = tfQuiting = true; - // } - // } - - // var win = new Window (); - // win.Add (sb, tf); - // Toplevel top = new (); - // top.Add (win); - // Application.Begin (top); - - // Assert.False (sbQuiting); - // Assert.False (tfQuiting); - - // Application.Driver?.SendKeys ('Q', ConsoleKey.Q, false, false, true); - // Assert.False (sbQuiting); - // Assert.True (tfQuiting); - - // tf.KeyDown -= Tf_KeyPressed; - // tfQuiting = false; - // Application.Driver?.SendKeys ('Q', ConsoleKey.Q, false, false, true); - // Application.MainLoop.RunIteration (); - //#if BROKE_WITH_2927 - // Assert.True (sbQuiting); - // Assert.False (tfQuiting); - //#endif - // top.Dispose (); - // } - [Fact] [SetupFakeDriver] public void Navigation_With_Null_Focused_View () @@ -542,49 +414,4 @@ public class NavigationTests (ITestOutputHelper _output) : TestsAllViews Assert.False (view2.HasFocus); win1.Dispose (); } - - -#if V2_NEW_FOCUS_IMPL // bogus test - Depends on auto setting of CanFocus - [Fact] - [AutoInitShutdown] - public void Remove_Does_Not_Change_Focus () - { - var top = new Toplevel (); - Assert.True (top.CanFocus); - Assert.False (top.HasFocus); - - var container = new View { Width = 10, Height = 10 }; - var leave = false; - container.Leave += (s, e) => leave = true; - Assert.False (container.CanFocus); - var child = new View { Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true }; - container.Add (child); - - Assert.True (container.CanFocus); - Assert.False (container.HasFocus); - Assert.True (child.CanFocus); - Assert.False (child.HasFocus); - - top.Add (container); - Application.Begin (top); - - Assert.True (top.CanFocus); - Assert.True (top.HasFocus); - Assert.True (container.CanFocus); - Assert.True (container.HasFocus); - Assert.True (child.CanFocus); - Assert.True (child.HasFocus); - - container.Remove (child); - child.Dispose (); - child = null; - Assert.True (top.HasFocus); - Assert.True (container.CanFocus); - Assert.True (container.HasFocus); - Assert.Null (child); - Assert.False (leave); - top.Dispose (); - } -#endif - } diff --git a/UnitTests/Views/ColorPickerTests.cs b/UnitTests/Views/ColorPickerTests.cs index 57a87733d..167872ea3 100644 --- a/UnitTests/Views/ColorPickerTests.cs +++ b/UnitTests/Views/ColorPickerTests.cs @@ -91,7 +91,7 @@ public class ColorPickerTests Assert.Equal (19, r.TrianglePosition); Assert.Equal ("#FF0000", hex.Text); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] @@ -144,7 +144,7 @@ public class ColorPickerTests Assert.Equal (4, r.TrianglePosition); Assert.Equal ("#1E0000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } @@ -198,7 +198,7 @@ public class ColorPickerTests Assert.Equal (expectedBTriangle, b.TrianglePosition); Assert.Equal (expectedHex, hex.Text); - Application.Current.Dispose (); + Application.Top.Dispose (); } public static IEnumerable ColorPickerTestData_WithTextFields () @@ -257,7 +257,7 @@ public class ColorPickerTests Assert.Equal (expectedBValue.ToString (), bTextField.Text); Assert.Equal (expectedHex, hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -291,7 +291,7 @@ public class ColorPickerTests Assert.Equal (2, b.TrianglePosition); Assert.Equal ("#FF0000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -325,7 +325,7 @@ public class ColorPickerTests Assert.Equal (2, b.TrianglePosition); Assert.Equal ("#FF0000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -336,7 +336,7 @@ public class ColorPickerTests View otherView = new View () { CanFocus = true }; - Application.Current?.Add (otherView); // thi sets focus to otherView + Application.Top?.Add (otherView); // thi sets focus to otherView Assert.True (otherView.HasFocus); cp.SetFocus (); @@ -384,7 +384,7 @@ public class ColorPickerTests Assert.Equal ("0", bTextField.Text); Assert.Equal ("#800000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -422,7 +422,7 @@ public class ColorPickerTests Assert.Equal (2, b.TrianglePosition); Assert.Equal ("#000000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -471,7 +471,7 @@ public class ColorPickerTests Assert.IsAssignableFrom (cp.Focused); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } [Fact] @@ -516,7 +516,7 @@ public class ColorPickerTests Assert.Equal (19, v.TrianglePosition); Assert.Equal ("#FF0000", hex.Text); - Application.Current?.Dispose (); + Application.Top!.Dispose (); } [Fact] @@ -552,7 +552,7 @@ public class ColorPickerTests Assert.Equal ("0", bTextField.Text); Assert.Equal ("#800000", hex.Text); - Application.Current?.Dispose (); + Application.Top?.Dispose (); } enum ColorPickerPart @@ -694,8 +694,8 @@ public class ColorPickerTests { var cp = GetColorPicker (ColorModel.RGB, true, true); Application.Navigation = new (); - Application.Current = new (); - Application.Current.Add (cp); + Application.Top = new (); + Application.Top.Add (cp); cp.Draw (); @@ -732,8 +732,8 @@ public class ColorPickerTests Assert.Equal ("#7FFFD4", hex.Text); - Application.Current?.Dispose (); - Application.ResetState (); + Application.Top?.Dispose (); + Application.ResetState (ignoreDisposed: true); } [Fact] @@ -742,8 +742,8 @@ public class ColorPickerTests { var cp = GetColorPicker (ColorModel.RGB, true, true); Application.Navigation = new (); - Application.Current = new (); - Application.Current.Add (cp); + Application.Top = new (); + Application.Top.Add (cp); cp.Draw (); @@ -786,8 +786,8 @@ public class ColorPickerTests Assert.Equal ("#7FFFD4", hex.Text); Assert.Equal ("Aquamarine", name.Text); - Application.Current?.Dispose (); - Application.ResetState (); + Application.Top?.Dispose (); + Application.ResetState (ignoreDisposed: true); } /// @@ -800,8 +800,8 @@ public class ColorPickerTests { var cp = GetColorPicker (ColorModel.RGB, true, true); Application.Navigation = new (); - Application.Current = new (); - Application.Current.Add (cp); + Application.Top = new (); + Application.Top.Add (cp); cp.Draw (); @@ -844,8 +844,8 @@ public class ColorPickerTests Assert.Equal ("#7FFFD4", hex.Text); Assert.Equal ("Aquamarine", name.Text); - Application.Current?.Dispose (); - Application.ResetState (); + Application.Top?.Dispose (); + Application.ResetState (ignoreDisposed: true); } [Fact] @@ -863,11 +863,11 @@ public class ColorPickerTests cp.Style.ShowColorName = showName; cp.ApplyStyleChanges (); - Application.Current = new Toplevel () { Width = 20, Height = 5 }; - Application.Current.Add (cp); + Application.Top = new Toplevel () { Width = 20, Height = 5 }; + Application.Top.Add (cp); - Application.Current.LayoutSubviews (); - Application.Current.SetFocus (); + Application.Top.LayoutSubviews (); + Application.Top.SetFocus (); return cp; } diff --git a/UnitTests/Views/ComboBoxTests.cs b/UnitTests/Views/ComboBoxTests.cs index 366c9d42a..a2ebdecf8 100644 --- a/UnitTests/Views/ComboBoxTests.cs +++ b/UnitTests/Views/ComboBoxTests.cs @@ -903,7 +903,7 @@ One Assert.True (cb.IsShow); Assert.Equal (1, cb.SelectedItem); Assert.Equal ("Two", cb.Text); -// Application.Begin (top); + // Application.Begin (top); cb.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -990,7 +990,7 @@ Three Application.Navigation = new (); var cb = new ComboBox (); var top = new Toplevel (); - Application.Current = top; + Application.Top = top; top.Add (cb); top.FocusDeepest (NavigationDirection.Forward, null); @@ -1028,6 +1028,8 @@ Three Assert.Equal (0, cb.Source.Count); Assert.Equal (-1, cb.SelectedItem); Assert.Equal ("", cb.Text); - Application.ResetState (); + + Application.Top.Dispose (); + Application.ResetState (ignoreDisposed: true); } } diff --git a/UnitTests/Views/ContextMenuTests.cs b/UnitTests/Views/ContextMenuTests.cs index 0872e2de9..37e230037 100644 --- a/UnitTests/Views/ContextMenuTests.cs +++ b/UnitTests/Views/ContextMenuTests.cs @@ -855,7 +855,9 @@ public class ContextMenuTests (ITestOutputHelper output) mi.Action = () => { - var dialog1 = new Dialog (); + Assert.True (ContextMenu.IsShow); + + var dialog1 = new Dialog () { Id = "dialog1" }; Application.Run (dialog1); dialog1.Dispose (); Assert.False (ContextMenu.IsShow); @@ -893,7 +895,7 @@ public class ContextMenuTests (ITestOutputHelper output) top.Closing += (_, _) => { - var dialog2 = new Dialog (); + var dialog2 = new Dialog () { Id = "dialog2" }; Application.Run (dialog2); dialog2.Dispose (); Assert.False (ContextMenu.IsShow); @@ -1706,8 +1708,8 @@ public class ContextMenuTests (ITestOutputHelper output) Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift)); Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.WithAlt)); Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.NoShift)); - Assert.Single (Application.Current!.Subviews); - View [] menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); + Assert.Single (Application.Top!.Subviews); + View [] menus = Application.Top!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.WithAlt)); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.NoShift)); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt)); @@ -1795,14 +1797,14 @@ public class ContextMenuTests (ITestOutputHelper output) Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt)); Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt)); Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt)); - View [] menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray (); + View [] menus = Application.Top!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray (); Assert.Empty (menus); Assert.Null (cm.MenuBar); Assert.True (Application.OnKeyDown (Key.F.WithAlt)); Assert.True (menuBar.IsMenuOpen); - Assert.Equal (2, Application.Current!.Subviews.Count); - menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray (); + Assert.Equal (2, Application.Top!.Subviews.Count); + menus = Application.Top!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray (); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.WithAlt)); Assert.True (Application.OnKeyDown (Key.N.WithAlt)); Assert.False (menuBar.IsMenuOpen); @@ -1831,8 +1833,8 @@ public class ContextMenuTests (ITestOutputHelper output) Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.E.NoShift)); Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt)); Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift)); - Assert.Equal (3, Application.Current!.Subviews.Count); - menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); + Assert.Equal (3, Application.Top!.Subviews.Count); + menus = Application.Top!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.WithAlt)); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.NoShift)); Assert.True (menus [1].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt)); @@ -1846,8 +1848,8 @@ public class ContextMenuTests (ITestOutputHelper output) cm.Show (menuItems); Assert.True (cm.MenuBar.IsMenuOpen); - Assert.Equal (3, Application.Current!.Subviews.Count); - menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); + Assert.Equal (3, Application.Top!.Subviews.Count); + menus = Application.Top!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray (); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.WithAlt)); Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.NoShift)); Assert.False (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt)); @@ -1862,7 +1864,7 @@ public class ContextMenuTests (ITestOutputHelper output) Application.MainLoop!.RunIteration (); Assert.True (renameFile); - Assert.Single (Application.Current!.Subviews); + Assert.Single (Application.Top!.Subviews); Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt)); Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.NoShift)); Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt)); diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs index 0ccf17d3a..f73a48db2 100644 --- a/UnitTests/Views/LabelTests.cs +++ b/UnitTests/Views/LabelTests.cs @@ -1322,11 +1322,11 @@ e Label label = new () { Text = "label" }; View view = new () { Text = "view", CanFocus = true }; Application.Navigation = new (); - Application.Current = new (); - Application.Current.Add (label, view); + Application.Top = new (); + Application.Top.Add (label, view); - Application.Current.SetFocus (); - Assert.Equal (view, Application.Current.MostFocused); + Application.Top.SetFocus (); + Assert.Equal (view, Application.Top.MostFocused); Assert.False (label.CanFocus); Assert.False (label.HasFocus); Assert.True (view.CanFocus); @@ -1351,7 +1351,7 @@ e Assert.False (label.HasFocus); Assert.True (view.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); Application.ResetState (); } @@ -1374,15 +1374,15 @@ e Height = 1, CanFocus = true }; - Application.Current = new () + Application.Top = new () { Width = 10, Height = 10 }; - Application.Current.Add (label, view); + Application.Top.Add (label, view); - Application.Current.SetFocus (); - Assert.Equal (view, Application.Current.MostFocused); + Application.Top.SetFocus (); + Assert.Equal (view, Application.Top.MostFocused); Assert.False (label.CanFocus); Assert.False (label.HasFocus); Assert.True (view.CanFocus); @@ -1408,7 +1408,7 @@ e Assert.False (label.HasFocus); Assert.True (view.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); Application.ResetState (); } } diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs deleted file mode 100644 index 5c42a5fe2..000000000 --- a/UnitTests/Views/OverlappedTests.cs +++ /dev/null @@ -1,1300 +0,0 @@ -#nullable enable -using System.Threading; -using JetBrains.Annotations; -using Xunit.Abstractions; - -namespace Terminal.Gui.ViewsTests; - -public class OverlappedTests -{ - private readonly ITestOutputHelper _output; - - public OverlappedTests (ITestOutputHelper output) - { - _output = output; -#if DEBUG_IDISPOSABLE - Responder.Instances.Clear (); - RunState.Instances.Clear (); -#endif - } - - [Fact] - [AutoInitShutdown] - public void AllChildClosed_Event_Test () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - - // OverlappedChild = c1, c2, c3 - var iterations = 3; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - c3.RequestStop (); - c2.RequestStop (); - c1.RequestStop (); - }; - - // Now this will close the OverlappedContainer when all OverlappedChildren was closed - overlapped.AllChildClosed += (s, e) => { overlapped.RequestStop (); }; - - Application.Iteration += (s, a) => - { - if (iterations == 3) - { - // The Current still is c3 because Current.Running is false. - Assert.True (Application.Current == c3); - Assert.False (Application.Current.Running); - - // But the Children order were reorder by Running = false - Assert.True (ApplicationOverlapped.OverlappedChildren! [0] == c3); - Assert.True (ApplicationOverlapped.OverlappedChildren [1] == c2); - Assert.True (ApplicationOverlapped.OverlappedChildren [^1] == c1); - } - else if (iterations == 2) - { - // The Current is c2 and Current.Running is false. - Assert.True (Application.Current == c2); - Assert.False (Application.Current.Running); - Assert.True (ApplicationOverlapped.OverlappedChildren ![0] == c2); - Assert.True (ApplicationOverlapped.OverlappedChildren [^1] == c1); - } - else if (iterations == 1) - { - // The Current is c1 and Current.Running is false. - Assert.True (Application.Current == c1); - Assert.False (Application.Current.Running); - Assert.True (ApplicationOverlapped.OverlappedChildren! [^1] == c1); - } - else - { - // The Current is overlapped. - Assert.True (Application.Current == overlapped); - Assert.False (Application.Current.Running); - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void Application_RequestStop_With_Params_On_A_Not_OverlappedContainer_Always_Use_Application_Current () - { - var top1 = new Toplevel (); - var top2 = new Toplevel (); - var top3 = new Window (); - var top4 = new Window (); - var d = new Dialog (); - - // top1, top2, top3, d1 = 4 - var iterations = 4; - - top1.Ready += (s, e) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - Application.Run (top2); - }; - - top2.Ready += (s, e) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - Application.Run (top3); - }; - - top3.Ready += (s, e) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - Application.Run (top4); - }; - - top4.Ready += (s, e) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - Application.Run (d); - }; - - d.Ready += (s, e) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - - // This will close the d because on a not OverlappedContainer the Application.Current it always used. - Application.RequestStop (top1); - Assert.True (Application.Current == d); - }; - - d.Closed += (s, e) => Application.RequestStop (top1); - - Application.Iteration += (s, a) => - { - Assert.Null (ApplicationOverlapped.OverlappedChildren); - - if (iterations == 4) - { - Assert.True (Application.Current == d); - } - else if (iterations == 3) - { - Assert.True (Application.Current == top4); - } - else if (iterations == 2) - { - Assert.True (Application.Current == top3); - } - else if (iterations == 1) - { - Assert.True (Application.Current == top2); - } - else - { - Assert.True (Application.Current == top1); - } - - Application.RequestStop (top1); - iterations--; - }; - - Application.Run (top1); - - Assert.Null (ApplicationOverlapped.OverlappedChildren); - top1.Dispose (); - } - - [Fact] - [TestRespondersDisposed] - public void Dispose_Toplevel_IsOverlappedContainer_False_With_Begin_End () - { - Application.Init (new FakeDriver ()); - - var top = new Toplevel (); - RunState rs = Application.Begin (top); - - Application.End (rs); - top.Dispose (); - Application.Shutdown (); - -#if DEBUG_IDISPOSABLE - Assert.Empty (Responder.Instances); -#endif - } - - [Fact] - [TestRespondersDisposed] - public void Dispose_Toplevel_IsOverlappedContainer_True_With_Begin () - { - Application.Init (new FakeDriver ()); - - var overlapped = new Toplevel { IsOverlappedContainer = true }; - RunState rs = Application.Begin (overlapped); - Application.End (rs); - overlapped.Dispose (); - Application.Shutdown (); - } - - [Fact] - [AutoInitShutdown] - public void IsOverlappedChild_Testing () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d = new Dialog (); - - Application.Iteration += (s, a) => - { - Assert.False (ApplicationOverlapped.IsOverlapped(overlapped)); - Assert.True (ApplicationOverlapped.IsOverlapped(c1)); - Assert.True (ApplicationOverlapped.IsOverlapped(c2)); - Assert.True (ApplicationOverlapped.IsOverlapped(c3)); - Assert.False (ApplicationOverlapped.IsOverlapped(d)); - - overlapped.RequestStop (); - }; - - Application.Run (overlapped); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void - Modal_Toplevel_Can_Open_Another_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d1 = new Dialog (); - var d2 = new Dialog (); - - // OverlappedChild = c1, c2, c3 = 3 - // d1, d2 = 2 - var iterations = 5; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d1); - }; - - d1.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d2); - }; - - d2.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Assert.True (Application.Current == d2); - Assert.True (Application.Current.Running); - - // Trying to close the Dialog1 - d1.RequestStop (); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - d1.Closed += (s, e) => - { - Assert.True (Application.Current == d1); - Assert.False (Application.Current.Running); - overlapped.RequestStop (); - }; - - Application.Iteration += (s, a) => - { - if (iterations == 5) - { - // The Dialog2 still is the current top and we can't request stop to OverlappedContainer - // because Dialog2 and Dialog1 must be closed first. - // Dialog2 will be closed in this iteration. - Assert.True (Application.Current == d2); - Assert.False (Application.Current.Running); - Assert.False (d1.Running); - } - else if (iterations == 4) - { - // Dialog1 will be closed in this iteration. - Assert.True (Application.Current == d1); - Assert.False (Application.Current.Running); - } - else - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - for (var i = 0; i < iterations; i++) - { - Assert.Equal ((iterations - i + 1).ToString (), ApplicationOverlapped.OverlappedChildren [i].Id); - } - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void - Modal_Toplevel_Can_Open_Another_Not_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d1 = new Dialog (); - var c4 = new Toplevel (); - - // OverlappedChild = c1, c2, c3, c4 = 4 - // d1 = 1 - var iterations = 5; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d1); - }; - - d1.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c4); - }; - - c4.Ready += (s, e) => - { - Assert.Equal (4, ApplicationOverlapped.OverlappedChildren!.Count); - - // Trying to close the Dialog1 - d1.RequestStop (); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - d1.Closed += (s, e) => { overlapped.RequestStop (); }; - - Application.Iteration += (s, a) => - { - if (iterations == 5) - { - // The Dialog2 still is the current top and we can't request stop to OverlappedContainer - // because Dialog2 and Dialog1 must be closed first. - // Using request stop here will call the Dialog again without need - Assert.True (Application.Current == d1); - Assert.False (Application.Current.Running); - Assert.True (c4.Running); - } - else - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - for (var i = 0; i < iterations; i++) - { - Assert.Equal ( - (iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (), - ApplicationOverlapped.OverlappedChildren [i].Id - ); - } - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void MoveCurrent_Returns_False_If_The_Current_And_Top_Parameter_Are_Both_With_Running_Set_To_False () - { - Overlapped? overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - - // OverlappedChild = c1, c2, c3 - var iterations = 3; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - c3.RequestStop (); - c1.RequestStop (); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - c1.Closed += (s, e) => { overlapped.RequestStop (); }; - - Application.Iteration += (s, a) => - { - if (iterations == 3) - { - // The Current still is c3 because Current.Running is false. - Assert.True (Application.Current == c3); - Assert.False (Application.Current.Running); - - // But the Children order were reorder by Running = false - Assert.True (ApplicationOverlapped.OverlappedChildren! [0] == c3); - Assert.True (ApplicationOverlapped.OverlappedChildren [1] == c1); - Assert.True (ApplicationOverlapped.OverlappedChildren [^1] == c2); - } - else if (iterations == 2) - { - // The Current is c1 and Current.Running is false. - Assert.True (Application.Current == c1); - Assert.False (Application.Current.Running); - Assert.True (ApplicationOverlapped.OverlappedChildren! [0] == c1); - Assert.True (ApplicationOverlapped.OverlappedChildren [^1] == c2); - } - else if (iterations == 1) - { - // The Current is c2 and Current.Running is false. - Assert.True (Application.Current == c2); - Assert.False (Application.Current.Running); - Assert.True (ApplicationOverlapped.OverlappedChildren! [^1] == c2); - } - else - { - // The Current is overlapped. - Assert.True (Application.Current == overlapped); - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - public void MoveToOverlappedChild_Throw_NullReferenceException_Passing_Null_Parameter () - { - Assert.Throws (delegate { ApplicationOverlapped.MoveToOverlappedChild (null); }); - } - - [Fact] - [AutoInitShutdown] - public void OverlappedContainer_Open_And_Close_Modal_And_Open_Not_Modal_Toplevels_Randomly () - { - var overlapped = new Overlapped (); - var logger = new Toplevel (); - - var iterations = 1; // The logger - var running = true; - var stageCompleted = true; - var allStageClosed = false; - var overlappedRequestStop = false; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (logger); - }; - - logger.Ready += (s, e) => Assert.Single (ApplicationOverlapped.OverlappedChildren!); - - Application.Iteration += (s, a) => - { - if (stageCompleted && running) - { - stageCompleted = false; - var stage = new Window { Modal = true }; - - stage.Ready += (s, e) => - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - stage.RequestStop (); - }; - - stage.Closed += (_, _) => - { - if (iterations == 11) - { - allStageClosed = true; - } - - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - if (running) - { - stageCompleted = true; - - var rpt = new Window (); - - rpt.Ready += (s, e) => - { - iterations++; - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren.Count); - }; - - Application.Run (rpt); - } - }; - - Application.Run (stage); - } - else if (iterations == 11 && running) - { - running = false; - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - } - else if (!overlappedRequestStop && running && !allStageClosed) - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - } - else if (!overlappedRequestStop && !running && allStageClosed) - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - overlappedRequestStop = true; - overlapped?.RequestStop (); - } - else - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - } - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void OverlappedContainer_Throws_If_More_Than_One () - { - var overlapped = new Overlapped (); - var overlapped2 = new Overlapped (); - - overlapped.Ready += (s, e) => - { - Assert.Throws (() => Application.Run (overlapped2)); - overlapped.RequestStop (); - }; - - Application.Run (overlapped); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_With_Params () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d = new Dialog (); - - // OverlappedChild = c1, c2, c3 - // d1 = 1 - var iterations = 4; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d); - }; - - // Also easy because the Overlapped Container handles all at once - d.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - - // This will not close the OverlappedContainer because d is a modal Toplevel - Application.RequestStop (overlapped); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - d.Closed += (s, e) => Application.RequestStop (overlapped); - - Application.Iteration += (s, a) => - { - if (iterations == 4) - { - // The Dialog was not closed before and will be closed now. - Assert.True (Application.Current == d); - Assert.False (d.Running); - } - else - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - for (var i = 0; i < iterations; i++) - { - Assert.Equal ((iterations - i + 1).ToString (), ApplicationOverlapped.OverlappedChildren [i].Id); - } - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void OverlappedContainer_With_Application_RequestStop_OverlappedTop_Without_Params () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d = new Dialog (); - - // OverlappedChild = c1, c2, c3 = 3 - // d1 = 1 - var iterations = 4; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d); - }; - - //More harder because it's sequential. - d.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - - // Close the Dialog - Application.RequestStop (); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - d.Closed += (s, e) => Application.RequestStop (overlapped); - - Application.Iteration += (s, a) => - { - if (iterations == 4) - { - // The Dialog still is the current top and we can't request stop to OverlappedContainer - // because we are not using parameter calls. - Assert.True (Application.Current == d); - Assert.False (d.Running); - } - else - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - for (var i = 0; i < iterations; i++) - { - Assert.Equal ((iterations - i + 1).ToString (), ApplicationOverlapped.OverlappedChildren [i].Id); - } - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void OverlappedContainer_With_Toplevel_RequestStop_Balanced () - { - var overlapped = new Overlapped (); - var c1 = new Toplevel (); - var c2 = new Window (); - var c3 = new Window (); - var d = new Dialog (); - - // OverlappedChild = c1, c2, c3 - // d1 = 1 - var iterations = 4; - - overlapped.Ready += (s, e) => - { - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c1); - }; - - c1.Ready += (s, e) => - { - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - Application.Run (c2); - }; - - c2.Ready += (s, e) => - { - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (c3); - }; - - c3.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - Application.Run (d); - }; - - // More easy because the Overlapped Container handles all at once - d.Ready += (s, e) => - { - Assert.Equal (3, ApplicationOverlapped.OverlappedChildren!.Count); - - // This will not close the OverlappedContainer because d is a modal Toplevel and will be closed. - overlapped.RequestStop (); - }; - - // Now this will close the OverlappedContainer propagating through the OverlappedChildren. - d.Closed += (s, e) => { overlapped.RequestStop (); }; - - Application.Iteration += (s, a) => - { - if (iterations == 4) - { - // The Dialog was not closed before and will be closed now. - Assert.True (Application.Current == d); - Assert.False (d.Running); - } - else - { - Assert.Equal (iterations, ApplicationOverlapped.OverlappedChildren!.Count); - - for (var i = 0; i < iterations; i++) - { - Assert.Equal ((iterations - i + 1).ToString (), ApplicationOverlapped.OverlappedChildren [i].Id); - } - } - - iterations--; - }; - - Application.Run (overlapped); - - Assert.Empty (ApplicationOverlapped.OverlappedChildren!); - Assert.NotNull (ApplicationOverlapped.OverlappedTop); - Assert.NotNull (Application.Top); - overlapped.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void Visible_False_Does_Not_Clear () - { - var overlapped = new Overlapped (); - 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 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 rsOverlapped, ref firstIteration); - - Assert.Equal (overlapped, rsOverlapped.Toplevel); - Assert.Equal (Application.Top, rsOverlapped.Toplevel); - Assert.Equal (ApplicationOverlapped.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 (ApplicationOverlapped.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 (ApplicationOverlapped.OverlappedTop, overlapped); - Assert.Equal (Application.Current, rsWin2.Toplevel); - Assert.Equal (win2, Application.Current); - Assert.Equal (win1, rsWin1.Toplevel); - - // Tests that rely on visuals are too fragile. If border style changes they break. - // Instead we should just rely on the test above. - - Application.OnMouseEvent (new MouseEvent { Position = new (1, 1), Flags = MouseFlags.Button1Pressed }); - Assert.Equal (win2.Border, Application.MouseGrabView); - - Application.RunIteration (ref rsOverlapped, ref firstIteration); - - Assert.Equal (win2, rsOverlapped.Toplevel); - Assert.Equal (Application.Top, overlapped); - Assert.Equal (ApplicationOverlapped.OverlappedTop, overlapped); - Assert.Equal (Application.Current, rsWin2.Toplevel); - Assert.Equal (win2, Application.Current); - Assert.Equal (win1, rsWin1.Toplevel); - - Application.OnMouseEvent (new MouseEvent - { - Position = new (2, 2), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition - }); - - Application.RunIteration (ref rsOverlapped, ref firstIteration); - - Assert.Equal (win2, rsOverlapped.Toplevel); - Assert.Equal (Application.Top, overlapped); - Assert.Equal (ApplicationOverlapped.OverlappedTop, overlapped); - Assert.Equal (Application.Current, rsWin2.Toplevel); - Assert.Equal (win2, Application.Current); - Assert.Equal (win1, rsWin1.Toplevel); - - // Tests that rely on visuals are too fragile. If border style changes they break. - // Instead we should just rely on the test above. - - // 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 (ApplicationOverlapped.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 (ApplicationOverlapped.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 (ApplicationOverlapped.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 (); - } - - private class Overlapped : Toplevel - { - public Overlapped () { IsOverlappedContainer = true; } - } - - [Fact (Skip = "#2491: This test is really bogus. It does things like Runnable = false and is overly convolulted. Replace.")] - [AutoInitShutdown] - public void KeyBindings_Command_With_OverlappedTop () - { - Toplevel top = new (); - Assert.Null (ApplicationOverlapped.OverlappedTop); - top.IsOverlappedContainer = true; - Application.Begin (top); - Assert.Equal (Application.Top, ApplicationOverlapped.OverlappedTop); - - var isRunning = true; - - var win1 = new Window { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () }; - var lblTf1W1 = new Label { Text = "Enter text in TextField on Win1:" }; - var tf1W1 = new TextField { Id="tf1W1", X = Pos.Right (lblTf1W1) + 1, Width = Dim.Fill (), Text = "Text1 on Win1" }; - var lblTvW1 = new Label { Y = Pos.Bottom (lblTf1W1) + 1, Text = "Enter text in TextView on Win1:" }; - - var tvW1 = new TextView - { - Id = "tvW1", - X = Pos.Left (tf1W1), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win1" - }; - var lblTf2W1 = new Label { Y = Pos.Bottom (lblTvW1) + 1, Text = "Enter text in TextField on Win1:" }; - var tf2W1 = new TextField { Id = "tf2W1", X = Pos.Left (tf1W1), Width = Dim.Fill (), Text = "Text2 on Win1" }; - win1.Add (lblTf1W1, tf1W1, lblTvW1, tvW1, lblTf2W1, tf2W1); - - var win2 = new Window { Id = "win2", Width = Dim.Percent (50), Height = Dim.Fill () }; - var lblTf1W2 = new Label { Text = "Enter text in TextField on Win2:" }; - var tf1W2 = new TextField { Id = "tf1W2", X = Pos.Right (lblTf1W2) + 1, Width = Dim.Fill (), Text = "Text1 on Win2" }; - var lblTvW2 = new Label { Y = Pos.Bottom (lblTf1W2) + 1, Text = "Enter text in TextView on Win2:" }; - - var tvW2 = new TextView - { - Id = "tvW2", - X = Pos.Left (tf1W2), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win2" - }; - var lblTf2W2 = new Label { Y = Pos.Bottom (lblTvW2) + 1, Text = "Enter text in TextField on Win2:" }; - 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); - - win1.Closing += (s, e) => isRunning = false; - Assert.Null (top.Focused); - Assert.Equal (top, Application.Current); - Assert.True (top.IsCurrentTop); - Assert.Equal (top, ApplicationOverlapped.OverlappedTop); - - Application.Begin (win1); - - Assert.Equal (new (0, 0, 40, 25), win1.Frame); - Assert.NotEqual (top, Application.Current); - Assert.False (top.IsCurrentTop); - Assert.Equal (win1, Application.Current); - Assert.True (win1.IsCurrentTop); - Assert.True (ApplicationOverlapped.IsOverlapped(win1)); - Assert.Null (top.Focused); - Assert.Null (top.MostFocused); - Assert.Equal (tf1W1, win1.MostFocused); - Assert.True (ApplicationOverlapped.IsOverlapped(win1)); - Assert.Single (ApplicationOverlapped.OverlappedChildren!); - - Application.Begin (win2); - - Assert.Equal (new (0, 0, 40, 25), win2.Frame); - Assert.NotEqual (top, Application.Current); - Assert.False (top.IsCurrentTop); - Assert.Equal (win2, Application.Current); - Assert.True (win2.IsCurrentTop); - Assert.True (ApplicationOverlapped.IsOverlapped(win2)); - Assert.Null (top.Focused); - Assert.Null (top.MostFocused); - Assert.Equal (tf1W2, win2.MostFocused); - Assert.Equal (2, ApplicationOverlapped.OverlappedChildren!.Count); - - ApplicationOverlapped.MoveToOverlappedChild (win1); - Assert.Equal (win1, Application.Current); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - win1.Running = true; - Assert.True (Application.OnKeyDown (Application.QuitKey)); - Assert.False (isRunning); - Assert.False (win1.Running); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - - // win1 has been closed. It can no longer be focused or acted upon. - // win2 should now have focus - Assert.Equal (win2, Application.Current); - Assert.True (win2.IsCurrentTop); - - Assert.Equal (Environment.OSVersion.Platform == PlatformID.Unix, Application.OnKeyDown (Key.Z.WithCtrl)); // suspend - - Assert.True (Application.OnKeyDown (Key.F5)); // refresh - - Assert.True (win1.IsCurrentTop); - Assert.Equal (tvW1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.Tab)); - Assert.Equal ($"\tFirst line Win1{Environment.NewLine}Second line Win1", tvW1.Text); - - Assert.True (Application.OnKeyDown (Key.Tab.WithShift)); - Assert.Equal ($"First line Win1{Environment.NewLine}Second line Win1", tvW1.Text); - - Assert.True (Application.OnKeyDown (Key.F6)); // move to win2 - Assert.Equal (win2, ApplicationOverlapped.OverlappedChildren [0]); - - Assert.True (Application.OnKeyDown (Key.F6.WithShift)); // move back to win1 - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - - Assert.Equal (tvW1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.Tab)); // text view eats tab - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - - tvW1.AllowsTab = false; - Assert.True (Application.OnKeyDown (Key.Tab)); // text view eats tab - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - - Assert.True (Application.OnKeyDown (Key.CursorRight)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.CursorDown)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf1W1, win1.MostFocused); -#if UNIX_KEY_BINDINGS - Assert.True (ApplicationOverlapped.OverlappedChildren [0].ProcessKeyDown (new (Key.I.WithCtrl))); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); -#endif - Assert.True (Application.OnKeyDown (Key.Tab)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.CursorLeft)); // The view to the left of tvW1 is tf2W1, but tvW1 is still focused and eats cursor keys - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.CursorUp)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.Tab)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - - Assert.True (Application.OnKeyDown (Key.F6)); // Move to win2 - Assert.Equal (win2, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf1W2, win2.MostFocused); - tf2W2.SetFocus (); - Assert.True (tf2W2.HasFocus); - - Assert.True (Application.OnKeyDown (Key.F6.WithShift)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Application.NextTabGroupKey)); - Assert.Equal (win2, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W2, win2.MostFocused); - Assert.True (Application.OnKeyDown (Application.PrevTabGroupKey)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.CursorDown)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf1W1, win1.MostFocused); -#if UNIX_KEY_BINDINGS - Assert.True (Application.OnKeyDown (new (Key.B.WithCtrl))); -#else - Assert.True (Application.OnKeyDown (Key.CursorLeft)); -#endif - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf1W1, win1.MostFocused); - Assert.True (Application.OnKeyDown (Key.CursorDown)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - Assert.Equal (Point.Empty, tvW1.CursorPosition); - - Assert.True (Application.OnKeyDown (Key.End.WithCtrl)); - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tvW1, win1.MostFocused); - Assert.Equal (new (16, 1), tvW1.CursorPosition); // Last position of the text -#if UNIX_KEY_BINDINGS - Assert.True (Application.OnKeyDown (new (Key.F.WithCtrl))); -#else - Assert.True (Application.OnKeyDown (Key.CursorRight)); // should move to next view w/ in Group (tf2W1) -#endif - Assert.Equal (win1, ApplicationOverlapped.OverlappedChildren [0]); - Assert.Equal (tf2W1, win1.MostFocused); - -#if UNIX_KEY_BINDINGS - Assert.True (ApplicationOverlapped.OverlappedChildren [0].ProcessKeyDown (new (Key.L.WithCtrl))); -#endif - win2.Dispose (); - win1.Dispose (); - top.Dispose (); - } - - - [Fact] - public void SetFocusToNextViewWithWrap_ShouldFocusNextView () - { - // Arrange - var superView = new TestToplevel () { Id = "superView", IsOverlappedContainer = true }; - - var view1 = new TestView () { Id = "view1" }; - var view2 = new TestView () { Id = "view2" }; - var view3 = new TestView () { Id = "view3" }; ; - superView.Add (view1, view2, view3); - - var current = new TestToplevel () { Id = "current", IsOverlappedContainer = true }; - - superView.Add (current); - superView.BeginInit (); - superView.EndInit (); - current.SetFocus (); - - Application.Current = current; - Assert.True (current.HasFocus); - Assert.Equal (superView.Focused, current); - Assert.Equal (superView.MostFocused, current); - - // Act - ApplicationOverlapped.SetFocusToNextViewWithWrap (Application.Current!.SuperView!.Subviews, NavigationDirection.Forward); - - // Assert - Assert.True (view1.HasFocus); - } - - [Fact] - public void SetFocusToNextViewWithWrap_ShouldNotChangeFocusIfViewsIsNull () - { - // Arrange - var currentView = new TestToplevel (); - Application.Current = currentView; - - // Act - ApplicationOverlapped.SetFocusToNextViewWithWrap (null, NavigationDirection.Forward); - - // Assert - Assert.Equal (currentView, Application.Current); - } - - [Fact] - public void SetFocusToNextViewWithWrap_ShouldNotChangeFocusIfCurrentViewNotFound () - { - // Arrange - var view1 = new TestToplevel (); - var view2 = new TestToplevel (); - var view3 = new TestToplevel (); - - var views = new List { view1, view2, view3 }; - - var currentView = new TestToplevel () { IsOverlappedContainer = true }; // Current view is not in the list - Application.Current = currentView; - - // Act - ApplicationOverlapped.SetFocusToNextViewWithWrap (views, NavigationDirection.Forward); - - // Assert - Assert.False (view1.IsFocused); - Assert.False (view2.IsFocused); - Assert.False (view3.IsFocused); - } - - private class TestToplevel : Toplevel - { - public bool IsFocused { get; private set; } - - protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew) - { - IsFocused = newHasFocus; - } - } - - private class TestView : View - { - public TestView () - { - CanFocus = true; - } - public bool IsFocused { get; private set; } - - protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew) - { - IsFocused = newHasFocus; - } - } -} diff --git a/UnitTests/Views/RadioGroupTests.cs b/UnitTests/Views/RadioGroupTests.cs index 2442eb98f..26fe93071 100644 --- a/UnitTests/Views/RadioGroupTests.cs +++ b/UnitTests/Views/RadioGroupTests.cs @@ -50,15 +50,15 @@ public class RadioGroupTests (ITestOutputHelper output) public void Initialize_SelectedItem_With_Minus_One () { var rg = new RadioGroup { RadioLabels = new [] { "Test" }, SelectedItem = -1 }; - Application.Current = new Toplevel (); - Application.Current.Add (rg); + Application.Top = new Toplevel (); + Application.Top.Add (rg); rg.SetFocus (); Assert.Equal (-1, rg.SelectedItem); Assert.True (Application.OnKeyDown (Key.Space)); Assert.Equal (0, rg.SelectedItem); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] @@ -80,11 +80,11 @@ public class RadioGroupTests (ITestOutputHelper output) { Application.Navigation = new (); var rg = new RadioGroup { RadioLabels = new [] { "Test", "New Test" } }; - Application.Current = new Toplevel (); - Application.Current.Add (rg); - rg.SetFocus(); - Assert.Equal(Orientation.Vertical, rg.Orientation); - Assert.Equal(0, rg.SelectedItem); + Application.Top = new Toplevel (); + Application.Top.Add (rg); + rg.SetFocus (); + Assert.Equal (Orientation.Vertical, rg.Orientation); + Assert.Equal (0, rg.SelectedItem); Assert.False (Application.OnKeyDown (Key.CursorUp)); // Should not change (should focus prev view if there was one, which there isn't) Assert.Equal (0, rg.SelectedItem); Assert.True (Application.OnKeyDown (Key.CursorDown)); @@ -101,15 +101,15 @@ public class RadioGroupTests (ITestOutputHelper output) Assert.Equal (1, rg.SelectedItem); Assert.True (Application.OnKeyDown (Key.Space)); Assert.Equal (1, rg.SelectedItem); - Application.ResetState(); + Application.ResetState (ignoreDisposed: true); } [Fact] public void HotKeys_Select_RadioLabels () { var rg = new RadioGroup { RadioLabels = new [] { "_Left", "_Right", "Cen_tered", "_Justified" } }; - Application.Current = new Toplevel (); - Application.Current.Add (rg); + Application.Top = new Toplevel (); + Application.Top.Add (rg); rg.SetFocus (); Assert.NotEmpty (rg.KeyBindings.GetCommands (KeyCode.L)); @@ -155,7 +155,7 @@ public class RadioGroupTests (ITestOutputHelper output) Assert.True (superView.NewKeyDownEvent (Key.R.WithAlt)); Assert.Equal (1, rg.SelectedItem); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] diff --git a/UnitTests/Views/ShortcutTests.cs b/UnitTests/Views/ShortcutTests.cs index 1d6ac98ce..dee6e1405 100644 --- a/UnitTests/Views/ShortcutTests.cs +++ b/UnitTests/Views/ShortcutTests.cs @@ -601,11 +601,11 @@ public class ShortcutTests [Fact] public void ColorScheme_SetColorScheme_Does_Not_Fault_3664 () { - Application.Current = new (); + Application.Top = new (); Application.Navigation = new (); Shortcut shortcut = new Shortcut (); - Application.Current.ColorScheme = null; + Application.Top.ColorScheme = null; Assert.Null (shortcut.ColorScheme); @@ -613,7 +613,7 @@ public class ShortcutTests Assert.NotNull (shortcut.ColorScheme); - Application.Current.Dispose (); + Application.Top.Dispose (); Application.ResetState (); } diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs index 33e3ba6f3..78166ea8e 100644 --- a/UnitTests/Views/TableViewTests.cs +++ b/UnitTests/Views/TableViewTests.cs @@ -3202,19 +3202,19 @@ A B C // Pressing left should move us to the first column without changing focus Application.OnKeyDown (Key.CursorLeft); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top!.MostFocused); Assert.True (tableView.HasFocus); // Because we are now on the leftmost cell a further left press should move focus Application.OnKeyDown (Key.CursorLeft); - Assert.NotSame (tableView, Application.Current.MostFocused); + Assert.NotSame (tableView, Application.Top.MostFocused); Assert.False (tableView.HasFocus); - Assert.Same (tf1, Application.Current.MostFocused); + Assert.Same (tf1, Application.Top.MostFocused); Assert.True (tf1.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] @@ -3227,19 +3227,19 @@ A B C // First press should move us up Application.OnKeyDown (Key.CursorUp); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top!.MostFocused); Assert.True (tableView.HasFocus); // Because we are now on the top row a further press should move focus Application.OnKeyDown (Key.CursorUp); - Assert.NotSame (tableView, Application.Current.MostFocused); + Assert.NotSame (tableView, Application.Top.MostFocused); Assert.False (tableView.HasFocus); - Assert.Same (tf1, Application.Current.MostFocused); + Assert.Same (tf1, Application.Top.MostFocused); Assert.True (tf1.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] public void CanTabOutOfTableViewUsingCursor_Right () @@ -3251,19 +3251,19 @@ A B C // First press should move us to the rightmost column without changing focus Application.OnKeyDown (Key.CursorRight); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top!.MostFocused); Assert.True (tableView.HasFocus); // Because we are now on the rightmost cell, a further right press should move focus Application.OnKeyDown (Key.CursorRight); - Assert.NotSame (tableView, Application.Current.MostFocused); + Assert.NotSame (tableView, Application.Top.MostFocused); Assert.False (tableView.HasFocus); - Assert.Same (tf2, Application.Current.MostFocused); + Assert.Same (tf2, Application.Top.MostFocused); Assert.True (tf2.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); } [Fact] @@ -3276,19 +3276,19 @@ A B C // First press should move us to the bottommost row without changing focus Application.OnKeyDown (Key.CursorDown); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top!.MostFocused); Assert.True (tableView.HasFocus); // Because we are now on the bottommost cell, a further down press should move focus Application.OnKeyDown (Key.CursorDown); - Assert.NotSame (tableView, Application.Current.MostFocused); + Assert.NotSame (tableView, Application.Top.MostFocused); Assert.False (tableView.HasFocus); - Assert.Same (tf2, Application.Current.MostFocused); + Assert.Same (tf2, Application.Top.MostFocused); Assert.True (tf2.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); } @@ -3302,7 +3302,7 @@ A B C // Pressing shift-left should give us a multi selection Application.OnKeyDown (Key.CursorLeft.WithShift); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top!.MostFocused); Assert.True (tableView.HasFocus); Assert.Equal (2, tableView.GetAllSelectedCells ().Count ()); @@ -3313,19 +3313,19 @@ A B C // Selection 'clears' just to the single cell and we remain focused Assert.Single (tableView.GetAllSelectedCells ()); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top.MostFocused); Assert.True (tableView.HasFocus); // A further left will switch focus Application.OnKeyDown (Key.CursorLeft); - Assert.NotSame (tableView, Application.Current.MostFocused); + Assert.NotSame (tableView, Application.Top.MostFocused); Assert.False (tableView.HasFocus); - Assert.Same (tf1, Application.Current.MostFocused); + Assert.Same (tf1, Application.Top.MostFocused); Assert.True (tf1.HasFocus); - Application.Current.Dispose (); + Application.Top.Dispose (); } /// @@ -3343,16 +3343,16 @@ A B C tableView.EndInit (); Application.Navigation = new (); - Application.Current = new (); + Application.Top = new (); tf1 = new TextField (); tf2 = new TextField (); - Application.Current.Add (tf1); - Application.Current.Add (tableView); - Application.Current.Add (tf2); + Application.Top.Add (tf1); + Application.Top.Add (tableView); + Application.Top.Add (tf2); tableView.SetFocus (); - Assert.Same (tableView, Application.Current.MostFocused); + Assert.Same (tableView, Application.Top.MostFocused); Assert.True (tableView.HasFocus); diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index 5f5662c29..3915f71ef 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -1009,14 +1009,14 @@ This is the second line. Assert.Equal (0, tv.LeftColumn); Assert.Equal (Point.Empty, tv.CursorPosition); - Application.PositionCursor (top); + Application.PositionCursor (); Assert.Equal (CursorVisibility.Default, tv.CursorVisibility); for (var i = 0; i < 12; i++) { tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledRight }); Assert.Equal (Math.Min (i + 1, 11), tv.LeftColumn); - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility); Assert.Equal (CursorVisibility.Invisible, cursorVisibility); } @@ -1026,7 +1026,7 @@ This is the second line. tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledLeft }); Assert.Equal (i - 1, tv.LeftColumn); - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility); if (i - 1 == 0) @@ -1061,13 +1061,13 @@ This is the second line. Application.Begin (top); Assert.Equal (0, tv.TopRow); - Application.PositionCursor (top); + Application.PositionCursor (); Assert.Equal (CursorVisibility.Default, tv.CursorVisibility); for (var i = 0; i < 12; i++) { tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledDown }); - Application.PositionCursor (top); + Application.PositionCursor (); Assert.Equal (i + 1, tv.TopRow); Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility); Assert.Equal (CursorVisibility.Invisible, cursorVisibility); @@ -1076,10 +1076,10 @@ This is the second line. for (var i = 12; i > 0; i--) { tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledUp }); - Application.PositionCursor (top); + Application.PositionCursor (); Assert.Equal (i - 1, tv.TopRow); - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility); if (i - 1 == 0) diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs index ad758d752..28542349d 100644 --- a/UnitTests/Views/ToplevelTests.cs +++ b/UnitTests/Views/ToplevelTests.cs @@ -16,8 +16,6 @@ public partial class ToplevelTests (ITestOutputHelper output) Assert.False (top.Modal); Assert.Null (top.MenuBar); Assert.Null (top.StatusBar); - Assert.False (top.IsOverlappedContainer); - Assert.False (ApplicationOverlapped.IsOverlapped (top)); } [Fact] @@ -27,183 +25,6 @@ public partial class ToplevelTests (ITestOutputHelper output) Assert.Equal (ViewArrangement.Fixed, top.Arrangement); } -#if BROKE_IN_2927 - // BUGBUG: The name of this test does not match what it does. - [Fact] - [AutoInitShutdown] - public void Application_Top_GetLocationThatFits_To_Driver_Rows_And_Cols () - { - var iterations = 0; - - Application.Iteration += (s, a) => - { - switch (iterations) - { - case 0: - Assert.False (Application.Top.AutoSize); - Assert.Equal ("Top1", Application.Top.Text); - Assert.Equal (0, Application.Top.Frame.X); - Assert.Equal (0, Application.Top.Frame.Y); - Assert.Equal (Application.Driver!.Cols, Application.Top.Frame.Width); - Assert.Equal (Application.Driver!.Rows, Application.Top.Frame.Height); - - Application.OnKeyPressed (new (Key.CtrlMask | Key.R)); - - break; - case 1: - Assert.Equal ("Top2", Application.Top.Text); - Assert.Equal (0, Application.Top.Frame.X); - Assert.Equal (0, Application.Top.Frame.Y); - Assert.Equal (Application.Driver!.Cols, Application.Top.Frame.Width); - Assert.Equal (Application.Driver!.Rows, Application.Top.Frame.Height); - - Application.OnKeyPressed (new (Key.CtrlMask | Key.C)); - - break; - case 3: - Assert.Equal ("Top1", Application.Top.Text); - Assert.Equal (0, Application.Top.Frame.X); - Assert.Equal (0, Application.Top.Frame.Y); - Assert.Equal (Application.Driver!.Cols, Application.Top.Frame.Width); - Assert.Equal (Application.Driver!.Rows, Application.Top.Frame.Height); - - Application.OnKeyPressed (new (Key.CtrlMask | Key.R)); - - break; - case 4: - Assert.Equal ("Top2", Application.Top.Text); - Assert.Equal (0, Application.Top.Frame.X); - Assert.Equal (0, Application.Top.Frame.Y); - Assert.Equal (Application.Driver!.Cols, Application.Top.Frame.Width); - Assert.Equal (Application.Driver!.Rows, Application.Top.Frame.Height); - - Application.OnKeyPressed (new (Key.CtrlMask | Key.C)); - - break; - case 6: - Assert.Equal ("Top1", Application.Top.Text); - Assert.Equal (0, Application.Top.Frame.X); - Assert.Equal (0, Application.Top.Frame.Y); - Assert.Equal (Application.Driver!.Cols, Application.Top.Frame.Width); - Assert.Equal (Application.Driver!.Rows, Application.Top.Frame.Height); - - Application.OnKeyPressed (new (Key.CtrlMask | Key.Q)); - - break; - } - - iterations++; - }; - - Application.Run (Top1 ()); - - Toplevel Top1 () - { - var top = Application.Top; - top.Text = "Top1"; - - var menu = new MenuBar ( - new MenuBarItem [] - { - new MenuBarItem ( - "_Options", - new MenuItem [] - { - new MenuItem ( - "_Run Top2", - "", - () => Application.Run (Top2 ()), - null, - null, - Key.CtrlMask | Key.R - ), - new MenuItem ( - "_Quit", - "", - () => Application - .RequestStop (), - null, - null, - Key.CtrlMask | Key.Q - ) - } - ) - } - ); - top.Add (menu); - - var statusBar = new StatusBar ( - new [] - { - new StatusItem ( - Key.CtrlMask | Key.R, - "~^R~ Run Top2", - () => Application.Run (Top2 ()) - ), - new StatusItem ( - Application.QuitKey, - $"{Application.QuitKey} to Quit", - () => Application.RequestStop () - ) - } - ); - top.Add (statusBar); - - var t1 = new Toplevel (); - top.Add (t1); - - return top; - } - - Toplevel Top2 () - { - var top = new Toplevel (Application.Top.Frame); - top.Text = "Top2"; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - - var menu = new MenuBar ( - new MenuBarItem [] - { - new MenuBarItem ( - "_Stage", - new MenuItem [] - { - new MenuItem ( - "_Close", - "", - () => Application - .RequestStop (), - null, - null, - Key.CtrlMask | Key.C - ) - } - ) - } - ); - top.Add (menu); - - var statusBar = new StatusBar ( - new [] - { - new StatusItem ( - Key.CtrlMask | Key.C, - "~^C~ Close", - () => Application.RequestStop () - ), - } - ); - top.Add (statusBar); - - win.Add ( - new ListView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () } - ); - top.Add (win); - - return top; - } - } -#endif [Fact] [AutoInitShutdown] public void Internal_Tests () @@ -394,7 +215,7 @@ public partial class ToplevelTests (ITestOutputHelper output) Assert.NotNull (sb); top.PositionToplevels (); - Assert.Equal (new (0, 1, 60, 15), win.Frame); + //Assert.Equal (new (0, 1, 60, 15), win.Frame); //Assert.Null (Toplevel._dragPosition); win.NewMouseEvent (new () { Position = new (6, 0), Flags = MouseFlags.Button1Pressed }); @@ -639,7 +460,7 @@ public partial class ToplevelTests (ITestOutputHelper output) } else if (iterations == 1) { - Assert.Equal (new (2, 2), Application.Current.Frame.Location); + Assert.Equal (new (2, 2), Application.Top!.Frame.Location); } else if (iterations == 2) { @@ -648,12 +469,12 @@ public partial class ToplevelTests (ITestOutputHelper output) // Grab the mouse Application.OnMouseEvent (new () { Position = new (3, 2), Flags = MouseFlags.Button1Pressed }); - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (2, 2, 10, 3), Application.Current.Frame); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); + Assert.Equal (new (2, 2, 10, 3), Application.Top.Frame); } else if (iterations == 3) { - Assert.Equal (Application.Current.Border, Application.MouseGrabView); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); // Drag to left Application.OnMouseEvent ( @@ -664,19 +485,19 @@ public partial class ToplevelTests (ITestOutputHelper output) }); Application.Refresh (); - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (1, 2, 10, 3), Application.Current.Frame); + Assert.Equal (Application.Top.Border, Application.MouseGrabView); + Assert.Equal (new (1, 2, 10, 3), Application.Top.Frame); } else if (iterations == 4) { - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (1, 2), Application.Current.Frame.Location); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); + Assert.Equal (new (1, 2), Application.Top.Frame.Location); - Assert.Equal (Application.Current.Border, Application.MouseGrabView); + Assert.Equal (Application.Top.Border, Application.MouseGrabView); } else if (iterations == 5) { - Assert.Equal (Application.Current.Border, Application.MouseGrabView); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); // Drag up Application.OnMouseEvent ( @@ -686,20 +507,20 @@ public partial class ToplevelTests (ITestOutputHelper output) }); Application.Refresh (); - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (1, 1, 10, 3), Application.Current.Frame); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); + Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame); } else if (iterations == 6) { - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (1, 1), Application.Current.Frame.Location); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); + Assert.Equal (new (1, 1), Application.Top.Frame.Location); - Assert.Equal (Application.Current.Border, Application.MouseGrabView); - Assert.Equal (new (1, 1, 10, 3), Application.Current.Frame); + Assert.Equal (Application.Top.Border, Application.MouseGrabView); + Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame); } else if (iterations == 7) { - Assert.Equal (Application.Current.Border, Application.MouseGrabView); + Assert.Equal (Application.Top!.Border, Application.MouseGrabView); // Ungrab the mouse Application.OnMouseEvent (new () { Position = new (2, 1), Flags = MouseFlags.Button1Released }); @@ -851,229 +672,6 @@ public partial class ToplevelTests (ITestOutputHelper output) Assert.Null (exception); } -#if V2_NEW_FOCUS_IMPL - [Fact] - [AutoInitShutdown] - public void OnEnter_OnLeave_Triggered_On_Application_Begin_End () - { - var viewEnterInvoked = false; - var viewLeaveInvoked = false; - var v = new View (); - v.Enter += (s, _) => viewEnterInvoked = true; - v.Leave += (s, _) => viewLeaveInvoked = true; - Toplevel top = new (); - top.Add (v); - - Assert.False (v.CanFocus); - Exception exception = Record.Exception (() => top.OnEnter (top)); - Assert.Null (exception); - exception = Record.Exception (() => top.OnLeave (top)); - Assert.Null (exception); - - v.CanFocus = true; - RunState rsTop = Application.Begin (top); - - Assert.True (top.HasFocus); - Assert.True (v.HasFocus); - - // From the v view - Assert.True (viewEnterInvoked); - - // The Leave event is only raised on the End method - // and the top is still running - Assert.False (viewLeaveInvoked); - - Assert.False (viewLeaveInvoked); - Application.End (rsTop); - - Assert.True (viewLeaveInvoked); - - top.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_Modal () - { - var viewEnterInvoked = false; - var viewLeaveInvoked = false; - var v = new View (); - v.Enter += (s, _) => viewEnterInvoked = true; - v.Leave += (s, _) => viewLeaveInvoked = true; - Toplevel top = new (); - top.Add (v); - - Assert.False (v.CanFocus); - Exception exception = Record.Exception (() => top.OnEnter (top)); - Assert.Null (exception); - exception = Record.Exception (() => top.OnLeave (top)); - Assert.Null (exception); - - v.CanFocus = true; - RunState rsTop = Application.Begin (top); - - // From the v view - Assert.True (viewEnterInvoked); - - // The Leave event is only raised on the End method - // and the top is still running - Assert.False (viewLeaveInvoked); - - var dlgEnterInvoked = false; - var dlgLeaveInvoked = false; - - var d = new Dialog (); - var dv = new View { CanFocus = true }; - dv.Enter += (s, _) => dlgEnterInvoked = true; - dv.Leave += (s, _) => dlgLeaveInvoked = true; - d.Add (dv); - - RunState rsDialog = Application.Begin (d); - - // From the dv view - Assert.True (dlgEnterInvoked); - Assert.False (dlgLeaveInvoked); - Assert.True (dv.HasFocus); - - Assert.True (viewLeaveInvoked); - - viewEnterInvoked = false; - viewLeaveInvoked = false; - - Application.End (rsDialog); - d.Dispose (); - - // From the v view - Assert.True (viewEnterInvoked); - - // From the dv view - Assert.True (dlgEnterInvoked); - Assert.True (dlgLeaveInvoked); - - Assert.True (v.HasFocus); - - Assert.False (viewLeaveInvoked); - Application.End (rsTop); - - Assert.True (viewLeaveInvoked); - - top.Dispose (); - } - - [Fact (Skip = "2491: This is a bogus test that is impossible to figure out. Replace with something simpler.")] - [AutoInitShutdown] - public void OnEnter_OnLeave_Triggered_On_Application_Begin_End_With_More_Toplevels () - { - var iterations = 0; - var steps = new int [4]; - var isEnterTop = false; - var isLeaveTop = false; - var subViewofTop = new View (); - Toplevel top = new (); - - var dlg = new Dialog (); - - subViewofTop.Enter += (s, e) => - { - iterations++; - isEnterTop = true; - - if (iterations == 1) - { - steps [0] = iterations; - Assert.Null (e.Leaving); - } - else - { - steps [3] = iterations; - Assert.Equal (dlg, e.Leaving); - } - }; - - subViewofTop.Leave += (s, e) => - { - // This will never be raised - iterations++; - isLeaveTop = true; - //Assert.Equal (dlg, e.Leaving); - }; - top.Add (subViewofTop); - - Assert.False (subViewofTop.CanFocus); - Exception exception = Record.Exception (() => top.OnEnter (top)); - Assert.Null (exception); - exception = Record.Exception (() => top.OnLeave (top)); - Assert.Null (exception); - - subViewofTop.CanFocus = true; - RunState rsTop = Application.Begin (top); - - Assert.True (isEnterTop); - Assert.False (isLeaveTop); - - isEnterTop = false; - var isEnterDiag = false; - var isLeaveDiag = false; - var subviewOfDlg = new View (); - - subviewOfDlg.Enter += (s, e) => - { - iterations++; - steps [1] = iterations; - isEnterDiag = true; - Assert.Null (e.Leaving); - }; - - subviewOfDlg.Leave += (s, e) => - { - iterations++; - steps [2] = iterations; - isLeaveDiag = true; - Assert.Equal (top, e.Entering); - }; - dlg.Add (subviewOfDlg); - - Assert.False (subviewOfDlg.CanFocus); - exception = Record.Exception (() => dlg.OnEnter (dlg)); - Assert.Null (exception); - exception = Record.Exception (() => dlg.OnLeave (dlg)); - Assert.Null (exception); - - subviewOfDlg.CanFocus = true; - RunState rsDiag = Application.Begin (dlg); - - Assert.True (isEnterDiag); - Assert.False (isLeaveDiag); - Assert.False (isEnterTop); - - // 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 (rsDiag); - dlg.Dispose (); - - Assert.False (isEnterDiag); - Assert.True (isLeaveDiag); - Assert.True (isEnterTop); - - // Leave event on top cannot be raised - // because Current is null on the End method - Assert.False (isLeaveTop); - Assert.True (subViewofTop.HasFocus); - - Application.End (rsTop); - - Assert.Equal (1, steps [0]); - Assert.Equal (2, steps [1]); - Assert.Equal (3, steps [2]); - Assert.Equal (4, steps [^1]); - top.Dispose (); - } -#endif - [Fact] [AutoInitShutdown] public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null () @@ -1086,13 +684,13 @@ public partial class ToplevelTests (ITestOutputHelper output) Application.Begin (top); Assert.True (tf.HasFocus); - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out CursorVisibility cursor); Assert.Equal (CursorVisibility.Default, cursor); view.Enabled = false; Assert.False (tf.HasFocus); - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out cursor); Assert.Equal (CursorVisibility.Invisible, cursor); top.Dispose (); @@ -1383,16 +981,15 @@ public partial class ToplevelTests (ITestOutputHelper output) Height = 16, BorderStyle = LineStyle.Single }; - Assert.Equal (testWindow, Application.Current); - Application.Current.DrawContentComplete += OnDrawContentComplete; + Assert.Equal (testWindow, Application.Top); + Application.Top!.DrawContentComplete += OnDrawContentComplete; top.Add (viewAddedToTop); void OnDrawContentComplete (object sender, DrawEventArgs e) { Assert.Equal (new (1, 3, 18, 16), viewAddedToTop.Frame); - Rectangle savedClip = Application.Driver!.Clip; - Application.Driver!.Clip = top.Frame; + viewAddedToTop.SetNeedsDisplay(); viewAddedToTop.Draw (); top.Move (2, 15); View.Driver.AddStr ("One"); @@ -1400,9 +997,8 @@ public partial class ToplevelTests (ITestOutputHelper output) View.Driver.AddStr ("Two"); top.Move (2, 17); View.Driver.AddStr ("Three"); - Application.Driver!.Clip = savedClip; - Application.Current.DrawContentComplete -= OnDrawContentComplete; + Application.Top!.DrawContentComplete -= OnDrawContentComplete; } }; RunState rsTestWindow = Application.Begin (testWindow); @@ -1410,10 +1006,8 @@ public partial class ToplevelTests (ITestOutputHelper output) Assert.Equal (new (2, 1, 15, 10), testWindow.Frame); Application.OnMouseEvent (new () { Position = new (5, 2), Flags = MouseFlags.Button1Clicked }); - Application.Top.Draw (); - var firstIteration = false; - Application.RunIteration (ref rsTestWindow, ref firstIteration); + Application.Refresh(); TestHelpers.AssertDriverContentsWithFrameAre ( @$" diff --git a/UnitTests/Views/TreeViewTests.cs b/UnitTests/Views/TreeViewTests.cs index 240c18a26..e7714a740 100644 --- a/UnitTests/Views/TreeViewTests.cs +++ b/UnitTests/Views/TreeViewTests.cs @@ -113,7 +113,7 @@ public class TreeViewTests tv.SelectAll (); tv.CursorVisibility = CursorVisibility.Default; - Application.PositionCursor (top); + Application.PositionCursor (); Application.Driver!.GetCursorVisibility (out CursorVisibility visibility); Assert.Equal (CursorVisibility.Default, tv.CursorVisibility); Assert.Equal (CursorVisibility.Default, visibility);