diff --git a/Terminal.Gui/Application/Application.Driver.cs b/Terminal.Gui/Application/Application.Driver.cs
new file mode 100644
index 000000000..f15bd8053
--- /dev/null
+++ b/Terminal.Gui/Application/Application.Driver.cs
@@ -0,0 +1,29 @@
+#nullable enable
+namespace Terminal.Gui;
+
+public static partial class Application // Driver abstractions
+{
+ internal static bool _forceFakeConsole;
+
+ /// Gets the that has been selected. See also .
+ public static ConsoleDriver? Driver { get; internal set; }
+
+ ///
+ /// Gets or sets whether will be forced to output only the 16 colors defined in
+ /// . The default is , meaning 24-bit (TrueColor) colors will be output
+ /// as long as the selected supports TrueColor.
+ ///
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+ public static bool Force16Colors { get; set; }
+
+ ///
+ /// Forces the use of the specified driver (one of "fake", "ansi", "curses", "net", or "windows"). If not
+ /// specified, the driver is selected based on the platform.
+ ///
+ ///
+ /// Note, will override this configuration setting if called
+ /// with either `driver` or `driverName` specified.
+ ///
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+ public static string ForceDriver { get; set; } = string.Empty;
+}
diff --git a/Terminal.Gui/Application/Application.Initialization.cs b/Terminal.Gui/Application/Application.Initialization.cs
new file mode 100644
index 000000000..a971850e3
--- /dev/null
+++ b/Terminal.Gui/Application/Application.Initialization.cs
@@ -0,0 +1,209 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+
+namespace Terminal.Gui;
+
+public static partial class Application // Initialization (Init/Shutdown)
+{
+ /// Initializes a new instance of Application.
+ /// Call this method once per instance (or after has been called).
+ ///
+ /// This function loads the right for the platform, Creates a . and
+ /// assigns it to
+ ///
+ ///
+ /// must be called when the application is closing (typically after
+ /// has returned) to ensure resources are cleaned up and
+ /// terminal settings
+ /// restored.
+ ///
+ ///
+ /// The function combines
+ /// and
+ /// into a single
+ /// call. An application cam use without explicitly calling
+ /// .
+ ///
+ ///
+ /// The to use. If neither or
+ /// are specified the default driver for the platform will be used.
+ ///
+ ///
+ /// The short name (e.g. "net", "windows", "ansi", "fake", or "curses") of the
+ /// to use. If neither or are
+ /// specified the default driver for the platform will be used.
+ ///
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+ public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (driver, driverName); }
+
+ internal static bool _initialized;
+ internal static int _mainThreadId = -1;
+
+
+ // INTERNAL function for initializing an app with a Toplevel factory object, driver, and mainloop.
+ //
+ // Called from:
+ //
+ // Init() - When the user wants to use the default Toplevel. calledViaRunT will be false, causing all state to be reset.
+ // Run() - When the user wants to use a custom Toplevel. calledViaRunT will be true, enabling Run() to be called without calling Init first.
+ // Unit Tests - To initialize the app with a custom Toplevel, using the FakeDriver. calledViaRunT will be false, causing all state to be reset.
+ //
+ // calledViaRunT: If false (default) all state will be reset. If true the state will not be reset.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+ internal static void InternalInit (
+ ConsoleDriver driver = null,
+ string driverName = null,
+ bool calledViaRunT = false
+ )
+ {
+ if (_initialized && driver is null)
+ {
+ return;
+ }
+
+ if (_initialized)
+ {
+ throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
+ }
+
+ if (!calledViaRunT)
+ {
+ // Reset all class variables (Application is a singleton).
+ ResetState ();
+ }
+
+ // For UnitTests
+ if (driver is { })
+ {
+ Driver = driver;
+ }
+
+ // Start the process of configuration management.
+ // Note that we end up calling LoadConfigurationFromAllSources
+ // multiple times. We need to do this because some settings are only
+ // valid after a Driver is loaded. In this case we need just
+ // `Settings` so we can determine which driver to use.
+ // Don't reset, so we can inherit the theme from the previous run.
+ Load ();
+ Apply ();
+
+ // Ignore Configuration for ForceDriver if driverName is specified
+ if (!string.IsNullOrEmpty (driverName))
+ {
+ ForceDriver = driverName;
+ }
+
+ if (Driver is null)
+ {
+ PlatformID p = Environment.OSVersion.Platform;
+
+ if (string.IsNullOrEmpty (ForceDriver))
+ {
+ if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
+ {
+ Driver = new WindowsDriver ();
+ }
+ else
+ {
+ Driver = new CursesDriver ();
+ }
+ }
+ else
+ {
+ List drivers = GetDriverTypes ();
+ Type driverType = drivers.FirstOrDefault (t => t.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));
+
+ if (driverType is { })
+ {
+ Driver = (ConsoleDriver)Activator.CreateInstance (driverType);
+ }
+ else
+ {
+ throw new ArgumentException (
+ $"Invalid driver name: {ForceDriver}. Valid names are {string.Join (", ", drivers.Select (t => t.Name))}"
+ );
+ }
+ }
+ }
+
+ try
+ {
+ MainLoop = Driver.Init ();
+ }
+ catch (InvalidOperationException ex)
+ {
+ // This is a case where the driver is unable to initialize the console.
+ // This can happen if the console is already in use by another process or
+ // if running in unit tests.
+ // In this case, we want to throw a more specific exception.
+ throw new InvalidOperationException (
+ "Unable to initialize the console. This can happen if the console is already in use by another process or in unit tests.",
+ ex
+ );
+ }
+
+ Driver.SizeChanged += (s, args) => OnSizeChanging (args);
+ Driver.KeyDown += (s, args) => OnKeyDown (args);
+ Driver.KeyUp += (s, args) => OnKeyUp (args);
+ Driver.MouseEvent += (s, args) => OnMouseEvent (args);
+
+ SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ());
+
+ SupportedCultures = GetSupportedCultures ();
+ _mainThreadId = Thread.CurrentThread.ManagedThreadId;
+ _initialized = true;
+ InitializedChanged?.Invoke (null, new (in _initialized));
+ }
+
+ private static void Driver_SizeChanged (object sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
+ private static void Driver_KeyDown (object sender, Key e) { OnKeyDown (e); }
+ private static void Driver_KeyUp (object sender, Key e) { OnKeyUp (e); }
+ private static void Driver_MouseEvent (object sender, MouseEvent e) { OnMouseEvent (e); }
+
+ /// Gets of list of types that are available.
+ ///
+ [RequiresUnreferencedCode ("AOT")]
+ public static List GetDriverTypes ()
+ {
+ // use reflection to get the list of drivers
+ List driverTypes = new ();
+
+ foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
+ {
+ foreach (Type type in asm.GetTypes ())
+ {
+ if (type.IsSubclassOf (typeof (ConsoleDriver)) && !type.IsAbstract)
+ {
+ driverTypes.Add (type);
+ }
+ }
+ }
+
+ return driverTypes;
+ }
+
+ /// Shutdown an application initialized with .
+ ///
+ /// Shutdown must be called for every call to or
+ /// to ensure all resources are cleaned
+ /// up (Disposed)
+ /// and terminal settings are restored.
+ ///
+ public static void Shutdown ()
+ {
+ // TODO: Throw an exception if Init hasn't been called.
+ ResetState ();
+ PrintJsonErrors ();
+ InitializedChanged?.Invoke (null, new (in _initialized));
+ }
+
+ ///
+ /// This event is raised after the and methods have been called.
+ ///
+ ///
+ /// Intended to support unit tests that need to know when the application has been initialized.
+ ///
+ public static event EventHandler> InitializedChanged;
+}
diff --git a/Terminal.Gui/Application/ApplicationKeyboard.cs b/Terminal.Gui/Application/Application.Keyboard.cs
similarity index 99%
rename from Terminal.Gui/Application/ApplicationKeyboard.cs
rename to Terminal.Gui/Application/Application.Keyboard.cs
index be737968f..e8d698286 100644
--- a/Terminal.Gui/Application/ApplicationKeyboard.cs
+++ b/Terminal.Gui/Application/Application.Keyboard.cs
@@ -2,7 +2,7 @@
namespace Terminal.Gui;
-partial class Application
+public static partial class Application // Keyboard handling
{
private static Key _alternateForwardKey = Key.Empty; // Defined in config.json
diff --git a/Terminal.Gui/Application/ApplicationMouse.cs b/Terminal.Gui/Application/Application.Mouse.cs
similarity index 98%
rename from Terminal.Gui/Application/ApplicationMouse.cs
rename to Terminal.Gui/Application/Application.Mouse.cs
index 9f2a95339..4d3fb6129 100644
--- a/Terminal.Gui/Application/ApplicationMouse.cs
+++ b/Terminal.Gui/Application/Application.Mouse.cs
@@ -1,6 +1,6 @@
namespace Terminal.Gui;
-partial class Application
+public static partial class Application // Mouse handling
{
#region Mouse handling
@@ -272,7 +272,7 @@ partial class Application
if (view is Adornment adornmentView)
{
- view = adornmentView.Parent.SuperView;
+ view = adornmentView.Parent!.SuperView;
}
else
{
diff --git a/Terminal.Gui/Application/Application.Run.cs b/Terminal.Gui/Application/Application.Run.cs
new file mode 100644
index 000000000..34189d9fc
--- /dev/null
+++ b/Terminal.Gui/Application/Application.Run.cs
@@ -0,0 +1,863 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Terminal.Gui;
+
+public static partial class Application // Run (Begin, Run, End, Stop)
+{
+ private static Toplevel _cachedRunStateToplevel;
+
+ ///
+ /// Notify that a new was created ( was called). The token is
+ /// created in and this event will be fired before that function exits.
+ ///
+ ///
+ /// If is callers to
+ /// must also subscribe to and manually dispose of the token
+ /// when the application is done.
+ ///
+ public static event EventHandler NotifyNewRunState;
+
+ /// Notify that an existent is stopping ( was called).
+ ///
+ /// If is callers to
+ /// must also subscribe to and manually dispose of the token
+ /// when the application is done.
+ ///
+ public static event EventHandler NotifyStopRunState;
+
+ /// Building block API: Prepares the provided for execution.
+ ///
+ /// The handle that needs to be passed to the method upon
+ /// completion.
+ ///
+ /// The to prepare execution for.
+ ///
+ /// This method prepares the provided for running with the focus, it adds this to the list
+ /// of s, lays out the Subviews, focuses the first element, and draws the
+ /// in the screen. This is usually followed by executing the method, and then the
+ /// method upon termination which will undo these changes.
+ ///
+ public static RunState Begin (Toplevel toplevel)
+ {
+ ArgumentNullException.ThrowIfNull (toplevel);
+
+#if DEBUG_IDISPOSABLE
+ Debug.Assert (!toplevel.WasDisposed);
+
+ if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
+ {
+ Debug.Assert (_cachedRunStateToplevel.WasDisposed);
+ }
+#endif
+
+ if (toplevel.IsOverlappedContainer && OverlappedTop != toplevel && OverlappedTop is { })
+ {
+ throw new InvalidOperationException ("Only one Overlapped Container is allowed.");
+ }
+
+ // Ensure the mouse is ungrabbed.
+ MouseGrabView = null;
+
+ var rs = new RunState (toplevel);
+
+ // View implements ISupportInitializeNotification which is derived from ISupportInitialize
+ if (!toplevel.IsInitialized)
+ {
+ toplevel.BeginInit ();
+ toplevel.EndInit ();
+ }
+
+#if DEBUG_IDISPOSABLE
+ if (Top is { } && toplevel != Top && !_topLevels.Contains (Top))
+ {
+ // This assertion confirm if the Top was already disposed
+ Debug.Assert (Top.WasDisposed);
+ Debug.Assert (Top == _cachedRunStateToplevel);
+ }
+#endif
+
+ lock (_topLevels)
+ {
+ if (Top is { } && toplevel != Top && !_topLevels.Contains (Top))
+ {
+ // If Top was already disposed and isn't on the Toplevels Stack,
+ // clean it up here if is the same as _cachedRunStateToplevel
+ if (Top == _cachedRunStateToplevel)
+ {
+ Top = null;
+ }
+ else
+ {
+ // Probably this will never hit
+ throw new ObjectDisposedException (Top.GetType ().FullName);
+ }
+ }
+ else if (OverlappedTop is { } && toplevel != Top && _topLevels.Contains (Top))
+ {
+ Top.OnLeave (toplevel);
+ }
+
+ // BUGBUG: We should not depend on `Id` internally.
+ // BUGBUG: It is super unclear what this code does anyway.
+ if (string.IsNullOrEmpty (toplevel.Id))
+ {
+ var count = 1;
+ var id = (_topLevels.Count + count).ToString ();
+
+ while (_topLevels.Count > 0 && _topLevels.FirstOrDefault (x => x.Id == id) is { })
+ {
+ count++;
+ id = (_topLevels.Count + count).ToString ();
+ }
+
+ toplevel.Id = (_topLevels.Count + count).ToString ();
+
+ _topLevels.Push (toplevel);
+ }
+ else
+ {
+ Toplevel dup = _topLevels.FirstOrDefault (x => x.Id == toplevel.Id);
+
+ if (dup is null)
+ {
+ _topLevels.Push (toplevel);
+ }
+ }
+
+ if (_topLevels.FindDuplicates (new ToplevelEqualityComparer ()).Count > 0)
+ {
+ throw new ArgumentException ("There are duplicates Toplevel IDs");
+ }
+ }
+
+ if (Top is null || toplevel.IsOverlappedContainer)
+ {
+ Top = toplevel;
+ }
+
+ var refreshDriver = true;
+
+ if (OverlappedTop is null
+ || toplevel.IsOverlappedContainer
+ || (Current?.Modal == false && toplevel.Modal)
+ || (Current?.Modal == false && !toplevel.Modal)
+ || (Current?.Modal == true && toplevel.Modal))
+ {
+ if (toplevel.Visible)
+ {
+ Current?.OnDeactivate (toplevel);
+ Toplevel previousCurrent = Current;
+ Current = toplevel;
+ Current.OnActivate (previousCurrent);
+
+ SetCurrentOverlappedAsTop ();
+ }
+ else
+ {
+ refreshDriver = false;
+ }
+ }
+ else if ((OverlappedTop != null
+ && toplevel != OverlappedTop
+ && Current?.Modal == true
+ && !_topLevels.Peek ().Modal)
+ || (OverlappedTop is { } && toplevel != OverlappedTop && Current?.Running == false))
+ {
+ refreshDriver = false;
+ MoveCurrent (toplevel);
+ }
+ else
+ {
+ refreshDriver = false;
+ MoveCurrent (Current);
+ }
+
+ toplevel.SetRelativeLayout (Driver.Screen.Size);
+
+ toplevel.LayoutSubviews ();
+ toplevel.PositionToplevels ();
+ toplevel.FocusFirst ();
+ BringOverlappedTopToFront ();
+
+ if (refreshDriver)
+ {
+ OverlappedTop?.OnChildLoaded (toplevel);
+ toplevel.OnLoaded ();
+ toplevel.SetNeedsDisplay ();
+ toplevel.Draw ();
+ Driver.UpdateScreen ();
+
+ if (PositionCursor (toplevel))
+ {
+ Driver.UpdateCursor ();
+ }
+ }
+
+ NotifyNewRunState?.Invoke (toplevel, new (rs));
+
+ return rs;
+ }
+
+ ///
+ /// Calls on the most focused view in the view starting with .
+ ///
+ ///
+ /// Does nothing if is or if the most focused view is not visible or
+ /// enabled.
+ ///
+ /// If the most focused view is not visible within it's superview, the cursor will be hidden.
+ ///
+ ///
+ /// if a view positioned the cursor and the position is visible.
+ internal static bool PositionCursor (View view)
+ {
+ // 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;
+ }
+ }
+
+ // If the view is not visible or enabled, don't position the cursor
+ if (!mostFocused.Visible || !mostFocused.Enabled)
+ {
+ Driver.GetCursorVisibility (out CursorVisibility current);
+
+ if (current != CursorVisibility.Invisible)
+ {
+ Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
+
+ return false;
+ }
+
+ // If the view is not visible within it's superview, don't position the cursor
+ Rectangle mostFocusedViewport = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = Point.Empty });
+ Rectangle superViewViewport = mostFocused.SuperView?.ViewportToScreen (mostFocused.SuperView.Viewport with { Location = Point.Empty }) ?? Driver.Screen;
+
+ if (!superViewViewport.IntersectsWith (mostFocusedViewport))
+ {
+ return false;
+ }
+
+ Point? cursor = mostFocused.PositionCursor ();
+
+ Driver.GetCursorVisibility (out CursorVisibility currentCursorVisibility);
+
+ if (cursor is { })
+ {
+ // Convert cursor to screen coords
+ cursor = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = cursor.Value }).Location;
+
+ // If the cursor is not in a visible location in the SuperView, hide it
+ if (!superViewViewport.Contains (cursor.Value))
+ {
+ if (currentCursorVisibility != CursorVisibility.Invisible)
+ {
+ Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
+
+ return false;
+ }
+
+ // Show it
+ if (currentCursorVisibility == CursorVisibility.Invisible)
+ {
+ Driver.SetCursorVisibility (mostFocused.CursorVisibility);
+ }
+
+ return true;
+ }
+
+ if (currentCursorVisibility != CursorVisibility.Invisible)
+ {
+ Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
+
+ return false;
+ }
+
+ ///
+ /// Runs the application by creating a object and calling
+ /// .
+ ///
+ ///
+ /// Calling first is not needed as this function will initialize the application.
+ ///
+ /// must be called when the application is closing (typically after Run> has returned) to
+ /// ensure resources are cleaned up and terminal settings restored.
+ ///
+ ///
+ /// The caller is responsible for disposing the object returned by this method.
+ ///
+ ///
+ /// The created object. The caller is responsible for disposing this object.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+ public static Toplevel Run (Func errorHandler = null, ConsoleDriver driver = null) { return Run (errorHandler, driver); }
+
+ ///
+ /// Runs the application by creating a -derived object of type T and calling
+ /// .
+ ///
+ ///
+ /// Calling first is not needed as this function will initialize the application.
+ ///
+ /// must be called when the application is closing (typically after Run> has returned) to
+ /// ensure resources are cleaned up and terminal settings restored.
+ ///
+ ///
+ /// The caller is responsible for disposing the object returned by this method.
+ ///
+ ///
+ ///
+ ///
+ /// The to use. If not specified the default driver for the platform will
+ /// be used ( , , or ). Must be
+ /// if has already been called.
+ ///
+ /// The created T object. The caller is responsible for disposing this object.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+ public static T Run (Func errorHandler = null, ConsoleDriver driver = null)
+ where T : Toplevel, new ()
+ {
+ if (!_initialized)
+ {
+ // Init() has NOT been called.
+ InternalInit (driver, null, true);
+ }
+
+ var top = new T ();
+
+ Run (top, errorHandler);
+
+ return top;
+ }
+
+ /// Runs the Application using the provided view.
+ ///
+ ///
+ /// This method is used to start processing events for the main application, but it is also used to run other
+ /// modal s such as boxes.
+ ///
+ ///
+ /// To make a stop execution, call
+ /// .
+ ///
+ ///
+ /// Calling is equivalent to calling
+ /// , followed by , and then calling
+ /// .
+ ///
+ ///
+ /// Alternatively, to have a program control the main loop and process events manually, call
+ /// to set things up manually and then repeatedly call
+ /// with the wait parameter set to false. By doing this the
+ /// method will only process any pending events, timers, idle handlers and then
+ /// return control immediately.
+ ///
+ /// When using or
+ ///
+ /// will be called automatically.
+ ///
+ ///
+ /// RELEASE builds only: When is any exceptions will be
+ /// rethrown. Otherwise, if will be called. If
+ /// returns the will resume; otherwise this method will
+ /// exit.
+ ///
+ ///
+ /// The to run as a modal.
+ ///
+ /// RELEASE builds only: Handler for any unhandled exceptions (resumes when returns true,
+ /// rethrows when null).
+ ///
+ public static void Run (Toplevel view, Func errorHandler = null)
+ {
+ ArgumentNullException.ThrowIfNull (view);
+
+ if (_initialized)
+ {
+ if (Driver is null)
+ {
+ // Disposing before throwing
+ view.Dispose ();
+
+ // This code path should be impossible because Init(null, null) will select the platform default driver
+ throw new InvalidOperationException (
+ "Init() completed without a driver being set (this should be impossible); Run() cannot be called."
+ );
+ }
+ }
+ else
+ {
+ // Init() has NOT been called.
+ throw new InvalidOperationException (
+ "Init() has not been called. Only Run() or Run() can be used without calling Init()."
+ );
+ }
+
+ var resume = true;
+
+ while (resume)
+ {
+#if !DEBUG
+ try
+ {
+#endif
+ resume = false;
+ RunState runState = Begin (view);
+
+ // If EndAfterFirstIteration is true then the user must dispose of the runToken
+ // by using NotifyStopRunState event.
+ RunLoop (runState);
+
+ if (runState.Toplevel is null)
+ {
+#if DEBUG_IDISPOSABLE
+ Debug.Assert (_topLevels.Count == 0);
+#endif
+ runState.Dispose ();
+
+ return;
+ }
+
+ if (!EndAfterFirstIteration)
+ {
+ End (runState);
+ }
+#if !DEBUG
+ }
+ catch (Exception error)
+ {
+ if (errorHandler is null)
+ {
+ throw;
+ }
+
+ resume = errorHandler (error);
+ }
+#endif
+ }
+ }
+
+ /// Adds a timeout to the application.
+ ///
+ /// When time specified passes, the callback will be invoked. If the callback returns true, the timeout will be
+ /// reset, repeating the invocation. If it returns false, the timeout will stop and be removed. The returned value is a
+ /// token that can be used to stop the timeout by calling .
+ ///
+ public static object AddTimeout (TimeSpan time, Func callback) { return MainLoop?.AddTimeout (time, callback); }
+
+ /// Removes a previously scheduled timeout
+ /// The token parameter is the value returned by .
+ /// Returns
+ /// true
+ /// if the timeout is successfully removed; otherwise,
+ /// false
+ /// .
+ /// This method also returns
+ /// false
+ /// if the timeout is not found.
+ public static bool RemoveTimeout (object token) { return MainLoop?.RemoveTimeout (token) ?? false; }
+
+ /// Runs on the thread that is processing events
+ /// the action to be invoked on the main processing thread.
+ public static void Invoke (Action action)
+ {
+ MainLoop?.AddIdle (
+ () =>
+ {
+ action ();
+
+ return false;
+ }
+ );
+ }
+
+ /// Wakes up the running application that might be waiting on input.
+ public static void Wakeup () { MainLoop?.Wakeup (); }
+
+ /// 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 ();
+ View last = null;
+
+ foreach (Toplevel v in _topLevels.Reverse ())
+ {
+ if (v.Visible)
+ {
+ v.SetNeedsDisplay ();
+ v.SetSubViewNeedsDisplay ();
+ v.Draw ();
+ }
+
+ last = v;
+ }
+
+ Driver.Refresh ();
+ }
+
+ /// This event is raised on each iteration of the main loop.
+ /// See also
+ public static event EventHandler Iteration;
+
+ /// The driver for the application
+ /// The main loop.
+ internal static MainLoop MainLoop { get; private set; }
+
+ ///
+ /// Set to true to cause to be called after the first iteration. Set to false (the default) to
+ /// cause the application to continue running until Application.RequestStop () is called.
+ ///
+ public static bool EndAfterFirstIteration { get; set; }
+
+ /// Building block API: Runs the main loop for the created .
+ /// The state returned by the method.
+ public static void RunLoop (RunState state)
+ {
+ ArgumentNullException.ThrowIfNull (state);
+ ObjectDisposedException.ThrowIf (state.Toplevel is null, "state");
+
+ var firstIteration = true;
+
+ for (state.Toplevel.Running = true; state.Toplevel?.Running == true;)
+ {
+ MainLoop.Running = true;
+
+ if (EndAfterFirstIteration && !firstIteration)
+ {
+ return;
+ }
+
+ RunIteration (ref state, ref firstIteration);
+ }
+
+ MainLoop.Running = false;
+
+ // Run one last iteration to consume any outstanding input events from Driver
+ // This is important for remaining OnKeyUp events.
+ RunIteration (ref state, ref firstIteration);
+ }
+
+ /// Run one application iteration.
+ /// The state returned by .
+ ///
+ /// Set to if this is the first run loop iteration. Upon return, it
+ /// will be set to if at least one iteration happened.
+ ///
+ public static void RunIteration (ref RunState state, ref bool firstIteration)
+ {
+ if (MainLoop.Running && MainLoop.EventsPending ())
+ {
+ // Notify Toplevel it's ready
+ if (firstIteration)
+ {
+ state.Toplevel.OnReady ();
+ }
+
+ MainLoop.RunIteration ();
+ Iteration?.Invoke (null, new ());
+ EnsureModalOrVisibleAlwaysOnTop (state.Toplevel);
+
+ if (state.Toplevel != Current)
+ {
+ OverlappedTop?.OnDeactivate (state.Toplevel);
+ state.Toplevel = Current;
+ OverlappedTop?.OnActivate (state.Toplevel);
+ Top.SetSubViewNeedsDisplay ();
+ Refresh ();
+ }
+ }
+
+ firstIteration = false;
+
+ if (Current == null)
+ {
+ return;
+ }
+
+ if (state.Toplevel != Top && (Top.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded))
+ {
+ state.Toplevel.SetNeedsDisplay (state.Toplevel.Frame);
+ Top.Draw ();
+
+ 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 || OverlappedChildNeedsDisplay ())
+ {
+ state.Toplevel.SetNeedsDisplay ();
+ state.Toplevel.Draw ();
+ Driver.UpdateScreen ();
+
+ //Driver.UpdateCursor ();
+ }
+
+ if (PositionCursor (state.Toplevel))
+ {
+ 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.
+ /// The to stop.
+ ///
+ /// This will cause to return.
+ ///
+ /// Calling is equivalent to setting the
+ /// property on the currently running to false.
+ ///
+ ///
+ public static void RequestStop (Toplevel top = null)
+ {
+ if (OverlappedTop is null || top is null || (OverlappedTop is null && top is { }))
+ {
+ top = Current;
+ }
+
+ if (OverlappedTop != null
+ && top.IsOverlappedContainer
+ && top?.Running == true
+ && (Current?.Modal == false || (Current?.Modal == true && Current?.Running == false)))
+ {
+ OverlappedTop.RequestStop ();
+ }
+ else if (OverlappedTop != null
+ && top != Current
+ && Current?.Running == true
+ && Current?.Modal == true
+ && top.Modal
+ && top.Running)
+ {
+ 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);
+ }
+ else if ((OverlappedTop != null
+ && top != OverlappedTop
+ && top != Current
+ && Current?.Modal == false
+ && Current?.Running == true
+ && !top.Running)
+ || (OverlappedTop != null
+ && top != OverlappedTop
+ && top != Current
+ && Current?.Modal == false
+ && Current?.Running == false
+ && !top.Running
+ && _topLevels.ToArray () [1].Running))
+ {
+ MoveCurrent (top);
+ }
+ else if (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 (OverlappedTop != null
+ && Current == top
+ && 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);
+ }
+ }
+
+ private static void OnNotifyStopRunState (Toplevel top)
+ {
+ if (EndAfterFirstIteration)
+ {
+ NotifyStopRunState?.Invoke (top, new (top));
+ }
+ }
+
+ ///
+ /// Building block API: completes the execution of a that was started with
+ /// .
+ ///
+ /// The returned by the method.
+ public static void End (RunState runState)
+ {
+ ArgumentNullException.ThrowIfNull (runState);
+
+ if (OverlappedTop is { })
+ {
+ OverlappedTop.OnChildUnloaded (runState.Toplevel);
+ }
+ else
+ {
+ runState.Toplevel.OnUnloaded ();
+ }
+
+ // End the RunState.Toplevel
+ // First, take it off the Toplevel Stack
+ if (_topLevels.Count > 0)
+ {
+ if (_topLevels.Peek () != runState.Toplevel)
+ {
+ // If the top of the stack is not the RunState.Toplevel then
+ // this call to End is not balanced with the call to Begin that started the RunState
+ throw new ArgumentException ("End must be balanced with calls to Begin");
+ }
+
+ _topLevels.Pop ();
+ }
+
+ // 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 (OverlappedTop is { } && !runState.Toplevel.Modal && runState.Toplevel != OverlappedTop)
+ {
+ OverlappedTop.OnChildClosed (runState.Toplevel);
+ }
+
+ // Set Current and Top to the next TopLevel on the stack
+ if (_topLevels.Count == 0)
+ {
+ Current = null;
+ }
+ else
+ {
+ if (_topLevels.Count > 1 && _topLevels.Peek () == OverlappedTop && OverlappedChildren.Any (t => t.Visible) is { })
+ {
+ OverlappedMoveNext ();
+ }
+
+ Current = _topLevels.Peek ();
+
+ if (_topLevels.Count == 1 && Current == OverlappedTop)
+ {
+ OverlappedTop.OnAllChildClosed ();
+ }
+ else
+ {
+ SetCurrentOverlappedAsTop ();
+ runState.Toplevel.OnLeave (Current);
+ Current.OnEnter (runState.Toplevel);
+ }
+
+ Refresh ();
+ }
+
+ // Don't dispose runState.Toplevel. It's up to caller dispose it
+ // If it's not the same as the current in the RunIteration,
+ // it will be fixed later in the next RunIteration.
+ if (OverlappedTop is { } && !_topLevels.Contains (OverlappedTop))
+ {
+ _cachedRunStateToplevel = OverlappedTop;
+ }
+ else
+ {
+ _cachedRunStateToplevel = runState.Toplevel;
+ }
+
+ runState.Toplevel = null;
+ runState.Dispose ();
+ }
+}
diff --git a/Terminal.Gui/Application/Application.cs b/Terminal.Gui/Application/Application.cs
index 9c981b743..1561413e9 100644
--- a/Terminal.Gui/Application/Application.cs
+++ b/Terminal.Gui/Application/Application.cs
@@ -1,5 +1,5 @@
+#nullable enable
using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
@@ -18,31 +18,6 @@ namespace Terminal.Gui;
/// TODO: Flush this out.
public static partial class Application
{
- // For Unit testing - ignores UseSystemConsole
- internal static bool _forceFakeConsole;
-
- /// Gets the that has been selected. See also .
- public static ConsoleDriver Driver { get; internal set; }
-
- ///
- /// Gets or sets whether will be forced to output only the 16 colors defined in
- /// . The default is , meaning 24-bit (TrueColor) colors will be output
- /// as long as the selected supports TrueColor.
- ///
- [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
- public static bool Force16Colors { get; set; }
-
- ///
- /// Forces the use of the specified driver (one of "fake", "ansi", "curses", "net", or "windows"). If not
- /// specified, the driver is selected based on the platform.
- ///
- ///
- /// Note, will override this configuration setting if called
- /// with either `driver` or `driverName` specified.
- ///
- [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
- public static string ForceDriver { get; set; } = string.Empty;
-
/// Gets all cultures supported by the application without the invariant language.
public static List SupportedCultures { get; private set; }
@@ -68,10 +43,6 @@ public static partial class Application
.ToList ();
}
- // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
- // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
- private static Toplevel _cachedRunStateToplevel;
-
// IMPORTANT: Ensure all property/fields are reset here. See Init_ResetState_Resets_Properties unit test.
// Encapsulate all setting of initial state for Application; Having
// this in a function like this ensures we don't make mistakes in
@@ -82,9 +53,9 @@ public static partial class Application
// Shutdown is the bookend for Init. As such it needs to clean up all resources
// Init created. Apps that do any threading will need to code defensively for this.
// e.g. see Issue #537
- foreach (Toplevel t in _topLevels)
+ foreach (Toplevel? t in _topLevels)
{
- t.Running = false;
+ t!.Running = false;
}
_topLevels.Clear ();
@@ -163,1072 +134,11 @@ public static partial class Application
SynchronizationContext.SetSynchronizationContext (null);
}
- #region Initialization (Init/Shutdown)
-
- /// Initializes a new instance of Application.
- /// Call this method once per instance (or after has been called).
- ///
- /// This function loads the right for the platform, Creates a . and
- /// assigns it to
- ///
- ///
- /// must be called when the application is closing (typically after
- /// has returned) to ensure resources are cleaned up and
- /// terminal settings
- /// restored.
- ///
- ///
- /// The function combines
- /// and
- /// into a single
- /// call. An application cam use without explicitly calling
- /// .
- ///
- ///
- /// The to use. If neither or
- /// are specified the default driver for the platform will be used.
- ///
- ///
- /// The short name (e.g. "net", "windows", "ansi", "fake", or "curses") of the
- /// to use. If neither or are
- /// specified the default driver for the platform will be used.
- ///
- [RequiresUnreferencedCode ("AOT")]
- [RequiresDynamicCode ("AOT")]
- public static void Init (ConsoleDriver driver = null, string driverName = null) { InternalInit (driver, driverName); }
-
- internal static bool _initialized;
- internal static int _mainThreadId = -1;
-
- // INTERNAL function for initializing an app with a Toplevel factory object, driver, and mainloop.
- //
- // Called from:
- //
- // Init() - When the user wants to use the default Toplevel. calledViaRunT will be false, causing all state to be reset.
- // Run() - When the user wants to use a custom Toplevel. calledViaRunT will be true, enabling Run() to be called without calling Init first.
- // Unit Tests - To initialize the app with a custom Toplevel, using the FakeDriver. calledViaRunT will be false, causing all state to be reset.
- //
- // calledViaRunT: If false (default) all state will be reset. If true the state will not be reset.
- [RequiresUnreferencedCode ("AOT")]
- [RequiresDynamicCode ("AOT")]
- internal static void InternalInit (
- ConsoleDriver driver = null,
- string driverName = null,
- bool calledViaRunT = false
- )
- {
- if (_initialized && driver is null)
- {
- return;
- }
-
- if (_initialized)
- {
- throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
- }
-
- if (!calledViaRunT)
- {
- // Reset all class variables (Application is a singleton).
- ResetState ();
- }
-
- // For UnitTests
- if (driver is { })
- {
- Driver = driver;
- }
-
- // Start the process of configuration management.
- // Note that we end up calling LoadConfigurationFromAllSources
- // multiple times. We need to do this because some settings are only
- // valid after a Driver is loaded. In this case we need just
- // `Settings` so we can determine which driver to use.
- // Don't reset, so we can inherit the theme from the previous run.
- Load ();
- Apply ();
-
- // Ignore Configuration for ForceDriver if driverName is specified
- if (!string.IsNullOrEmpty (driverName))
- {
- ForceDriver = driverName;
- }
-
- if (Driver is null)
- {
- PlatformID p = Environment.OSVersion.Platform;
-
- if (string.IsNullOrEmpty (ForceDriver))
- {
- if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
- {
- Driver = new WindowsDriver ();
- }
- else
- {
- Driver = new CursesDriver ();
- }
- }
- else
- {
- List drivers = GetDriverTypes ();
- Type driverType = drivers.FirstOrDefault (t => t.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));
-
- if (driverType is { })
- {
- Driver = (ConsoleDriver)Activator.CreateInstance (driverType);
- }
- else
- {
- throw new ArgumentException (
- $"Invalid driver name: {ForceDriver}. Valid names are {string.Join (", ", drivers.Select (t => t.Name))}"
- );
- }
- }
- }
-
- try
- {
- MainLoop = Driver.Init ();
- }
- catch (InvalidOperationException ex)
- {
- // This is a case where the driver is unable to initialize the console.
- // This can happen if the console is already in use by another process or
- // if running in unit tests.
- // In this case, we want to throw a more specific exception.
- throw new InvalidOperationException (
- "Unable to initialize the console. This can happen if the console is already in use by another process or in unit tests.",
- ex
- );
- }
-
- Driver.SizeChanged += (s, args) => OnSizeChanging (args);
- Driver.KeyDown += (s, args) => OnKeyDown (args);
- Driver.KeyUp += (s, args) => OnKeyUp (args);
- Driver.MouseEvent += (s, args) => OnMouseEvent (args);
-
- SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ());
-
- SupportedCultures = GetSupportedCultures ();
- _mainThreadId = Thread.CurrentThread.ManagedThreadId;
- _initialized = true;
- InitializedChanged?.Invoke (null, new (in _initialized));
- }
-
- private static void Driver_SizeChanged (object sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
- private static void Driver_KeyDown (object sender, Key e) { OnKeyDown (e); }
- private static void Driver_KeyUp (object sender, Key e) { OnKeyUp (e); }
- private static void Driver_MouseEvent (object sender, MouseEvent e) { OnMouseEvent (e); }
-
- /// Gets of list of types that are available.
- ///
- [RequiresUnreferencedCode ("AOT")]
- public static List GetDriverTypes ()
- {
- // use reflection to get the list of drivers
- List driverTypes = new ();
-
- foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
- {
- foreach (Type type in asm.GetTypes ())
- {
- if (type.IsSubclassOf (typeof (ConsoleDriver)) && !type.IsAbstract)
- {
- driverTypes.Add (type);
- }
- }
- }
-
- return driverTypes;
- }
-
- /// Shutdown an application initialized with .
- ///
- /// Shutdown must be called for every call to or
- /// to ensure all resources are cleaned
- /// up (Disposed)
- /// and terminal settings are restored.
- ///
- public static void Shutdown ()
- {
- // TODO: Throw an exception if Init hasn't been called.
- ResetState ();
- PrintJsonErrors ();
- InitializedChanged?.Invoke (null, new (in _initialized));
- }
-
-#nullable enable
- ///
- /// This event is raised after the and methods have been called.
- ///
- ///
- /// Intended to support unit tests that need to know when the application has been initialized.
- ///
- public static event EventHandler>? InitializedChanged;
-#nullable restore
-
- #endregion Initialization (Init/Shutdown)
-
- #region Run (Begin, Run, End, Stop)
-
- ///
- /// Notify that a new was created ( was called). The token is
- /// created in and this event will be fired before that function exits.
- ///
- ///
- /// If is callers to
- /// must also subscribe to and manually dispose of the token
- /// when the application is done.
- ///
- public static event EventHandler NotifyNewRunState;
-
- /// Notify that an existent is stopping ( was called).
- ///
- /// If is callers to
- /// must also subscribe to and manually dispose of the token
- /// when the application is done.
- ///
- public static event EventHandler NotifyStopRunState;
-
- /// Building block API: Prepares the provided for execution.
- ///
- /// The handle that needs to be passed to the method upon
- /// completion.
- ///
- /// The to prepare execution for.
- ///
- /// This method prepares the provided for running with the focus, it adds this to the list
- /// of s, lays out the Subviews, focuses the first element, and draws the
- /// in the screen. This is usually followed by executing the method, and then the
- /// method upon termination which will undo these changes.
- ///
- public static RunState Begin (Toplevel toplevel)
- {
- ArgumentNullException.ThrowIfNull (toplevel);
-
-#if DEBUG_IDISPOSABLE
- Debug.Assert (!toplevel.WasDisposed);
-
- if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
- {
- Debug.Assert (_cachedRunStateToplevel.WasDisposed);
- }
-#endif
-
- if (toplevel.IsOverlappedContainer && OverlappedTop != toplevel && OverlappedTop is { })
- {
- throw new InvalidOperationException ("Only one Overlapped Container is allowed.");
- }
-
- // Ensure the mouse is ungrabbed.
- MouseGrabView = null;
-
- var rs = new RunState (toplevel);
-
- // View implements ISupportInitializeNotification which is derived from ISupportInitialize
- if (!toplevel.IsInitialized)
- {
- toplevel.BeginInit ();
- toplevel.EndInit ();
- }
-
-#if DEBUG_IDISPOSABLE
- if (Top is { } && toplevel != Top && !_topLevels.Contains (Top))
- {
- // This assertion confirm if the Top was already disposed
- Debug.Assert (Top.WasDisposed);
- Debug.Assert (Top == _cachedRunStateToplevel);
- }
-#endif
-
- lock (_topLevels)
- {
- if (Top is { } && toplevel != Top && !_topLevels.Contains (Top))
- {
- // If Top was already disposed and isn't on the Toplevels Stack,
- // clean it up here if is the same as _cachedRunStateToplevel
- if (Top == _cachedRunStateToplevel)
- {
- Top = null;
- }
- else
- {
- // Probably this will never hit
- throw new ObjectDisposedException (Top.GetType ().FullName);
- }
- }
- else if (OverlappedTop is { } && toplevel != Top && _topLevels.Contains (Top))
- {
- Top.OnLeave (toplevel);
- }
-
- // BUGBUG: We should not depend on `Id` internally.
- // BUGBUG: It is super unclear what this code does anyway.
- if (string.IsNullOrEmpty (toplevel.Id))
- {
- var count = 1;
- var id = (_topLevels.Count + count).ToString ();
-
- while (_topLevels.Count > 0 && _topLevels.FirstOrDefault (x => x.Id == id) is { })
- {
- count++;
- id = (_topLevels.Count + count).ToString ();
- }
-
- toplevel.Id = (_topLevels.Count + count).ToString ();
-
- _topLevels.Push (toplevel);
- }
- else
- {
- Toplevel dup = _topLevels.FirstOrDefault (x => x.Id == toplevel.Id);
-
- if (dup is null)
- {
- _topLevels.Push (toplevel);
- }
- }
-
- if (_topLevels.FindDuplicates (new ToplevelEqualityComparer ()).Count > 0)
- {
- throw new ArgumentException ("There are duplicates Toplevel IDs");
- }
- }
-
- if (Top is null || toplevel.IsOverlappedContainer)
- {
- Top = toplevel;
- }
-
- var refreshDriver = true;
-
- if (OverlappedTop is null
- || toplevel.IsOverlappedContainer
- || (Current?.Modal == false && toplevel.Modal)
- || (Current?.Modal == false && !toplevel.Modal)
- || (Current?.Modal == true && toplevel.Modal))
- {
- if (toplevel.Visible)
- {
- Current?.OnDeactivate (toplevel);
- Toplevel previousCurrent = Current;
- Current = toplevel;
- Current.OnActivate (previousCurrent);
-
- SetCurrentOverlappedAsTop ();
- }
- else
- {
- refreshDriver = false;
- }
- }
- else if ((OverlappedTop != null
- && toplevel != OverlappedTop
- && Current?.Modal == true
- && !_topLevels.Peek ().Modal)
- || (OverlappedTop is { } && toplevel != OverlappedTop && Current?.Running == false))
- {
- refreshDriver = false;
- MoveCurrent (toplevel);
- }
- else
- {
- refreshDriver = false;
- MoveCurrent (Current);
- }
-
- toplevel.SetRelativeLayout (Driver.Screen.Size);
-
- toplevel.LayoutSubviews ();
- toplevel.PositionToplevels ();
- toplevel.FocusFirst ();
- BringOverlappedTopToFront ();
-
- if (refreshDriver)
- {
- OverlappedTop?.OnChildLoaded (toplevel);
- toplevel.OnLoaded ();
- toplevel.SetNeedsDisplay ();
- toplevel.Draw ();
- Driver.UpdateScreen ();
-
- if (PositionCursor (toplevel))
- {
- Driver.UpdateCursor ();
- }
- }
-
- NotifyNewRunState?.Invoke (toplevel, new (rs));
-
- return rs;
- }
-
- ///
- /// Calls on the most focused view in the view starting with .
- ///
- ///
- /// Does nothing if is or if the most focused view is not visible or
- /// enabled.
- ///
- /// If the most focused view is not visible within it's superview, the cursor will be hidden.
- ///
- ///
- /// if a view positioned the cursor and the position is visible.
- internal static bool PositionCursor (View view)
- {
- // 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;
- }
- }
-
- // If the view is not visible or enabled, don't position the cursor
- if (!mostFocused.Visible || !mostFocused.Enabled)
- {
- Driver.GetCursorVisibility (out CursorVisibility current);
-
- if (current != CursorVisibility.Invisible)
- {
- Driver.SetCursorVisibility (CursorVisibility.Invisible);
- }
-
- return false;
- }
-
- // If the view is not visible within it's superview, don't position the cursor
- Rectangle mostFocusedViewport = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = Point.Empty });
- Rectangle superViewViewport = mostFocused.SuperView?.ViewportToScreen (mostFocused.SuperView.Viewport with { Location = Point.Empty }) ?? Driver.Screen;
-
- if (!superViewViewport.IntersectsWith (mostFocusedViewport))
- {
- return false;
- }
-
- Point? cursor = mostFocused.PositionCursor ();
-
- Driver.GetCursorVisibility (out CursorVisibility currentCursorVisibility);
-
- if (cursor is { })
- {
- // Convert cursor to screen coords
- cursor = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = cursor.Value }).Location;
-
- // If the cursor is not in a visible location in the SuperView, hide it
- if (!superViewViewport.Contains (cursor.Value))
- {
- if (currentCursorVisibility != CursorVisibility.Invisible)
- {
- Driver.SetCursorVisibility (CursorVisibility.Invisible);
- }
-
- return false;
- }
-
- // Show it
- if (currentCursorVisibility == CursorVisibility.Invisible)
- {
- Driver.SetCursorVisibility (mostFocused.CursorVisibility);
- }
-
- return true;
- }
-
- if (currentCursorVisibility != CursorVisibility.Invisible)
- {
- Driver.SetCursorVisibility (CursorVisibility.Invisible);
- }
-
- return false;
- }
-
- ///
- /// Runs the application by creating a object and calling
- /// .
- ///
- ///
- /// Calling first is not needed as this function will initialize the application.
- ///
- /// must be called when the application is closing (typically after Run> has returned) to
- /// ensure resources are cleaned up and terminal settings restored.
- ///
- ///
- /// The caller is responsible for disposing the object returned by this method.
- ///
- ///
- /// The created object. The caller is responsible for disposing this object.
- [RequiresUnreferencedCode ("AOT")]
- [RequiresDynamicCode ("AOT")]
- public static Toplevel Run (Func errorHandler = null, ConsoleDriver driver = null) { return Run (errorHandler, driver); }
-
- ///
- /// Runs the application by creating a -derived object of type T and calling
- /// .
- ///
- ///
- /// Calling first is not needed as this function will initialize the application.
- ///
- /// must be called when the application is closing (typically after Run> has returned) to
- /// ensure resources are cleaned up and terminal settings restored.
- ///
- ///
- /// The caller is responsible for disposing the object returned by this method.
- ///
- ///
- ///
- ///
- /// The to use. If not specified the default driver for the platform will
- /// be used ( , , or ). Must be
- /// if has already been called.
- ///
- /// The created T object. The caller is responsible for disposing this object.
- [RequiresUnreferencedCode ("AOT")]
- [RequiresDynamicCode ("AOT")]
- public static T Run (Func errorHandler = null, ConsoleDriver driver = null)
- where T : Toplevel, new()
- {
- if (!_initialized)
- {
- // Init() has NOT been called.
- InternalInit (driver, null, true);
- }
-
- var top = new T ();
-
- Run (top, errorHandler);
-
- return top;
- }
-
- /// Runs the Application using the provided view.
- ///
- ///
- /// This method is used to start processing events for the main application, but it is also used to run other
- /// modal s such as boxes.
- ///
- ///
- /// To make a stop execution, call
- /// .
- ///
- ///
- /// Calling is equivalent to calling
- /// , followed by , and then calling
- /// .
- ///
- ///
- /// Alternatively, to have a program control the main loop and process events manually, call
- /// to set things up manually and then repeatedly call
- /// with the wait parameter set to false. By doing this the
- /// method will only process any pending events, timers, idle handlers and then
- /// return control immediately.
- ///
- /// When using or
- ///
- /// will be called automatically.
- ///
- ///
- /// RELEASE builds only: When is any exceptions will be
- /// rethrown. Otherwise, if will be called. If
- /// returns the will resume; otherwise this method will
- /// exit.
- ///
- ///
- /// The to run as a modal.
- ///
- /// RELEASE builds only: Handler for any unhandled exceptions (resumes when returns true,
- /// rethrows when null).
- ///
- public static void Run (Toplevel view, Func errorHandler = null)
- {
- ArgumentNullException.ThrowIfNull (view);
-
- if (_initialized)
- {
- if (Driver is null)
- {
- // Disposing before throwing
- view.Dispose ();
-
- // This code path should be impossible because Init(null, null) will select the platform default driver
- throw new InvalidOperationException (
- "Init() completed without a driver being set (this should be impossible); Run() cannot be called."
- );
- }
- }
- else
- {
- // Init() has NOT been called.
- throw new InvalidOperationException (
- "Init() has not been called. Only Run() or Run() can be used without calling Init()."
- );
- }
-
- var resume = true;
-
- while (resume)
- {
-#if !DEBUG
- try
- {
-#endif
- resume = false;
- RunState runState = Begin (view);
-
- // If EndAfterFirstIteration is true then the user must dispose of the runToken
- // by using NotifyStopRunState event.
- RunLoop (runState);
-
- if (runState.Toplevel is null)
- {
-#if DEBUG_IDISPOSABLE
- Debug.Assert (_topLevels.Count == 0);
-#endif
- runState.Dispose ();
-
- return;
- }
-
- if (!EndAfterFirstIteration)
- {
- End (runState);
- }
-#if !DEBUG
- }
- catch (Exception error)
- {
- if (errorHandler is null)
- {
- throw;
- }
-
- resume = errorHandler (error);
- }
-#endif
- }
- }
-
- /// Adds a timeout to the application.
- ///
- /// When time specified passes, the callback will be invoked. If the callback returns true, the timeout will be
- /// reset, repeating the invocation. If it returns false, the timeout will stop and be removed. The returned value is a
- /// token that can be used to stop the timeout by calling .
- ///
- public static object AddTimeout (TimeSpan time, Func callback) { return MainLoop?.AddTimeout (time, callback); }
-
- /// Removes a previously scheduled timeout
- /// The token parameter is the value returned by .
- /// Returns
- /// true
- /// if the timeout is successfully removed; otherwise,
- /// false
- /// .
- /// This method also returns
- /// false
- /// if the timeout is not found.
- public static bool RemoveTimeout (object token) { return MainLoop?.RemoveTimeout (token) ?? false; }
-
- /// Runs on the thread that is processing events
- /// the action to be invoked on the main processing thread.
- public static void Invoke (Action action)
- {
- MainLoop?.AddIdle (
- () =>
- {
- action ();
-
- return false;
- }
- );
- }
+ // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
+ // This field is set in `End` in this case so that `Begin` correctly sets `Top`.
// TODO: Determine if this is really needed. The only code that calls WakeUp I can find
// is ProgressBarStyles, and it's not clear it needs to.
- /// Wakes up the running application that might be waiting on input.
- public static void Wakeup () { MainLoop?.Wakeup (); }
-
- /// 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 ();
- View last = null;
-
- foreach (Toplevel v in _topLevels.Reverse ())
- {
- if (v.Visible)
- {
- v.SetNeedsDisplay ();
- v.SetSubViewNeedsDisplay ();
- v.Draw ();
- }
-
- last = v;
- }
-
- Driver.Refresh ();
- }
-
- /// This event is raised on each iteration of the main loop.
- /// See also
- public static event EventHandler Iteration;
-
- /// The driver for the application
- /// The main loop.
- internal static MainLoop MainLoop { get; private set; }
-
- ///
- /// Set to true to cause to be called after the first iteration. Set to false (the default) to
- /// cause the application to continue running until Application.RequestStop () is called.
- ///
- public static bool EndAfterFirstIteration { get; set; }
-
- /// Building block API: Runs the main loop for the created .
- /// The state returned by the method.
- public static void RunLoop (RunState state)
- {
- ArgumentNullException.ThrowIfNull (state);
- ObjectDisposedException.ThrowIf (state.Toplevel is null, "state");
-
- var firstIteration = true;
-
- for (state.Toplevel.Running = true; state.Toplevel?.Running == true;)
- {
- MainLoop.Running = true;
-
- if (EndAfterFirstIteration && !firstIteration)
- {
- return;
- }
-
- RunIteration (ref state, ref firstIteration);
- }
-
- MainLoop.Running = false;
-
- // Run one last iteration to consume any outstanding input events from Driver
- // This is important for remaining OnKeyUp events.
- RunIteration (ref state, ref firstIteration);
- }
-
- /// Run one application iteration.
- /// The state returned by .
- ///
- /// Set to if this is the first run loop iteration. Upon return, it
- /// will be set to if at least one iteration happened.
- ///
- public static void RunIteration (ref RunState state, ref bool firstIteration)
- {
- if (MainLoop.Running && MainLoop.EventsPending ())
- {
- // Notify Toplevel it's ready
- if (firstIteration)
- {
- state.Toplevel.OnReady ();
- }
-
- MainLoop.RunIteration ();
- Iteration?.Invoke (null, new ());
- EnsureModalOrVisibleAlwaysOnTop (state.Toplevel);
-
- if (state.Toplevel != Current)
- {
- OverlappedTop?.OnDeactivate (state.Toplevel);
- state.Toplevel = Current;
- OverlappedTop?.OnActivate (state.Toplevel);
- Top.SetSubViewNeedsDisplay ();
- Refresh ();
- }
- }
-
- firstIteration = false;
-
- if (Current == null)
- {
- return;
- }
-
- if (state.Toplevel != Top && (Top.NeedsDisplay || Top.SubViewNeedsDisplay || Top.LayoutNeeded))
- {
- state.Toplevel.SetNeedsDisplay (state.Toplevel.Frame);
- Top.Draw ();
-
- 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 || OverlappedChildNeedsDisplay ())
- {
- state.Toplevel.SetNeedsDisplay ();
- state.Toplevel.Draw ();
- Driver.UpdateScreen ();
-
- //Driver.UpdateCursor ();
- }
-
- if (PositionCursor (state.Toplevel))
- {
- 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.
- /// The to stop.
- ///
- /// This will cause to return.
- ///
- /// Calling is equivalent to setting the
- /// property on the currently running to false.
- ///
- ///
- public static void RequestStop (Toplevel top = null)
- {
- if (OverlappedTop is null || top is null || (OverlappedTop is null && top is { }))
- {
- top = Current;
- }
-
- if (OverlappedTop != null
- && top.IsOverlappedContainer
- && top?.Running == true
- && (Current?.Modal == false || (Current?.Modal == true && Current?.Running == false)))
- {
- OverlappedTop.RequestStop ();
- }
- else if (OverlappedTop != null
- && top != Current
- && Current?.Running == true
- && Current?.Modal == true
- && top.Modal
- && top.Running)
- {
- 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);
- }
- else if ((OverlappedTop != null
- && top != OverlappedTop
- && top != Current
- && Current?.Modal == false
- && Current?.Running == true
- && !top.Running)
- || (OverlappedTop != null
- && top != OverlappedTop
- && top != Current
- && Current?.Modal == false
- && Current?.Running == false
- && !top.Running
- && _topLevels.ToArray () [1].Running))
- {
- MoveCurrent (top);
- }
- else if (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 (OverlappedTop != null
- && Current == top
- && 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);
- }
- }
-
- private static void OnNotifyStopRunState (Toplevel top)
- {
- if (EndAfterFirstIteration)
- {
- NotifyStopRunState?.Invoke (top, new (top));
- }
- }
-
- ///
- /// Building block API: completes the execution of a that was started with
- /// .
- ///
- /// The returned by the method.
- public static void End (RunState runState)
- {
- ArgumentNullException.ThrowIfNull (runState);
-
- if (OverlappedTop is { })
- {
- OverlappedTop.OnChildUnloaded (runState.Toplevel);
- }
- else
- {
- runState.Toplevel.OnUnloaded ();
- }
-
- // End the RunState.Toplevel
- // First, take it off the Toplevel Stack
- if (_topLevels.Count > 0)
- {
- if (_topLevels.Peek () != runState.Toplevel)
- {
- // If the top of the stack is not the RunState.Toplevel then
- // this call to End is not balanced with the call to Begin that started the RunState
- throw new ArgumentException ("End must be balanced with calls to Begin");
- }
-
- _topLevels.Pop ();
- }
-
- // 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 (OverlappedTop is { } && !runState.Toplevel.Modal && runState.Toplevel != OverlappedTop)
- {
- OverlappedTop.OnChildClosed (runState.Toplevel);
- }
-
- // Set Current and Top to the next TopLevel on the stack
- if (_topLevels.Count == 0)
- {
- Current = null;
- }
- else
- {
- if (_topLevels.Count > 1 && _topLevels.Peek () == OverlappedTop && OverlappedChildren.Any (t => t.Visible) is { })
- {
- OverlappedMoveNext ();
- }
-
- Current = _topLevels.Peek ();
-
- if (_topLevels.Count == 1 && Current == OverlappedTop)
- {
- OverlappedTop.OnAllChildClosed ();
- }
- else
- {
- SetCurrentOverlappedAsTop ();
- runState.Toplevel.OnLeave (Current);
- Current.OnEnter (runState.Toplevel);
- }
-
- Refresh ();
- }
-
- // Don't dispose runState.Toplevel. It's up to caller dispose it
- // If it's not the same as the current in the RunIteration,
- // it will be fixed later in the next RunIteration.
- if (OverlappedTop is { } && !_topLevels.Contains (OverlappedTop))
- {
- _cachedRunStateToplevel = OverlappedTop;
- }
- else
- {
- _cachedRunStateToplevel = runState.Toplevel;
- }
-
- runState.Toplevel = null;
- runState.Dispose ();
- }
-
- #endregion Run (Begin, Run, End)
#region Toplevel handling
@@ -1240,7 +150,7 @@ public static partial class Application
/// The object used for the application on startup ()
/// The top.
- public static Toplevel Top { get; private set; }
+ public static Toplevel? Top { get; private set; }
///
/// The current object. This is updated in enters and leaves to
@@ -1251,7 +161,7 @@ public static partial class Application
/// Only relevant in scenarios where is .
///
/// The current.
- public static Toplevel Current { get; private set; }
+ public static Toplevel? Current { get; private set; }
private static void EnsureModalOrVisibleAlwaysOnTop (Toplevel topLevel)
{
@@ -1263,7 +173,7 @@ public static partial class Application
return;
}
- foreach (Toplevel top in _topLevels.Reverse ())
+ foreach (Toplevel? top in _topLevels.Reverse ())
{
if (top.Modal && top != Current)
{
@@ -1292,7 +202,7 @@ public static partial class Application
int rx = location.X - start.Frame.X;
int ry = location.Y - start.Frame.Y;
- foreach (Toplevel t in _topLevels)
+ foreach (Toplevel? t in _topLevels)
{
if (t != Current)
{
@@ -1327,7 +237,7 @@ public static partial class Application
#nullable enable
// Only return true if the Current has changed.
- private static bool MoveCurrent (Toplevel? top)
+ private 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.
@@ -1343,9 +253,9 @@ public static partial class Application
}
var index = 0;
- Toplevel [] savedToplevels = _topLevels.ToArray ();
+ Toplevel? [] savedToplevels = _topLevels.ToArray ();
- foreach (Toplevel t in savedToplevels)
+ foreach (Toplevel? t in savedToplevels)
{
if (!t.Modal && t != Current && t != top && t != savedToplevels [index])
{
@@ -1376,7 +286,7 @@ public static partial class Application
var index = 0;
- foreach (Toplevel t in _topLevels.ToArray ())
+ foreach (Toplevel? t in _topLevels.ToArray ())
{
if (!t.Running && t != Current && index > 0)
{
@@ -1505,6 +415,7 @@ public static partial class Application
sb.AppendLine ();
}
+
return sb.ToString ();
}
}
diff --git a/Terminal.Gui/Clipboard/Clipboard.cs b/Terminal.Gui/Clipboard/Clipboard.cs
index 63c1cc40a..5dccea0a4 100644
--- a/Terminal.Gui/Clipboard/Clipboard.cs
+++ b/Terminal.Gui/Clipboard/Clipboard.cs
@@ -31,11 +31,11 @@ public static class Clipboard
{
if (IsSupported)
{
- string clipData = Application.Driver.Clipboard.GetClipboardData ();
+ string clipData = Application.Driver?.Clipboard.GetClipboardData ();
if (clipData is null)
{
- // throw new InvalidOperationException ($"{Application.Driver.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
+ // throw new InvalidOperationException ($"{Application.Driver?.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
clipData = string.Empty;
}
@@ -60,7 +60,7 @@ public static class Clipboard
value = string.Empty;
}
- Application.Driver.Clipboard.SetClipboardData (value);
+ Application.Driver?.Clipboard.SetClipboardData (value);
}
_contents = value;
@@ -74,19 +74,16 @@ public static class Clipboard
/// Returns true if the environmental dependencies are in place to interact with the OS clipboard.
///
- public static bool IsSupported => Application.Driver.Clipboard.IsSupported;
+ public static bool IsSupported => Application.Driver?.Clipboard.IsSupported ?? false;
/// Copies the _contents of the OS clipboard to if possible.
/// The _contents of the OS clipboard if successful, if not.
/// the OS clipboard was retrieved, otherwise.
public static bool TryGetClipboardData (out string result)
{
- if (IsSupported && Application.Driver.Clipboard.TryGetClipboardData (out result))
+ if (IsSupported && Application.Driver!.Clipboard.TryGetClipboardData (out result))
{
- if (_contents != result)
- {
- _contents = result;
- }
+ _contents = result;
return true;
}
@@ -101,7 +98,7 @@ public static class Clipboard
/// the OS clipboard was set, otherwise.
public static bool TrySetClipboardData (string text)
{
- if (IsSupported && Application.Driver.Clipboard.TrySetClipboardData (text))
+ if (IsSupported && Application.Driver!.Clipboard.TrySetClipboardData (text))
{
_contents = text;
@@ -155,7 +152,7 @@ internal static class ClipboardProcessRunner
using (var process = new Process
{
- StartInfo = new ProcessStartInfo
+ StartInfo = new()
{
FileName = cmd,
Arguments = arguments,
@@ -191,17 +188,9 @@ internal static class ClipboardProcessRunner
if (process.ExitCode > 0)
{
- output = $@"Process failed to run. Command line: {
- cmd
- } {
- arguments
- }.
- Output: {
- output
- }
- Error: {
- process.StandardError.ReadToEnd ()
- }";
+ output = $@"Process failed to run. Command line: {cmd} {arguments}.
+ Output: {output}
+ Error: {process.StandardError.ReadToEnd ()}";
}
return (process.ExitCode, output);
diff --git a/Terminal.Gui/Drawing/LineCanvas.cs b/Terminal.Gui/Drawing/LineCanvas.cs
index 4b5119a82..9a7365f26 100644
--- a/Terminal.Gui/Drawing/LineCanvas.cs
+++ b/Terminal.Gui/Drawing/LineCanvas.cs
@@ -336,7 +336,7 @@ public class LineCanvas : IDisposable
return Fill != null ? Fill.GetAttribute (intersects [0]!.Point) : intersects [0]!.Line.Attribute;
}
- private Cell? GetCellForIntersects (ConsoleDriver driver, IntersectionDefinition? [] intersects)
+ private Cell? GetCellForIntersects (ConsoleDriver? driver, IntersectionDefinition? [] intersects)
{
if (!intersects.Any ())
{
@@ -356,7 +356,7 @@ public class LineCanvas : IDisposable
return cell;
}
- private Rune? GetRuneForIntersects (ConsoleDriver driver, IntersectionDefinition? [] intersects)
+ private Rune? GetRuneForIntersects (ConsoleDriver? driver, IntersectionDefinition? [] intersects)
{
if (!intersects.Any ())
{
@@ -679,7 +679,7 @@ public class LineCanvas : IDisposable
internal Rune _thickV;
public IntersectionRuneResolver () { SetGlyphs (); }
- public Rune? GetRuneForIntersects (ConsoleDriver driver, IntersectionDefinition? [] intersects)
+ public Rune? GetRuneForIntersects (ConsoleDriver? driver, IntersectionDefinition? [] intersects)
{
bool useRounded = intersects.Any (
i => i?.Line.Length != 0
diff --git a/Terminal.Gui/Drawing/Ruler.cs b/Terminal.Gui/Drawing/Ruler.cs
index 348036c84..d2551101d 100644
--- a/Terminal.Gui/Drawing/Ruler.cs
+++ b/Terminal.Gui/Drawing/Ruler.cs
@@ -39,8 +39,8 @@ public class Ruler
_hTemplate.Repeat ((int)Math.Ceiling (Length + 2 / (double)_hTemplate.Length)) [start..(Length + start)];
// Top
- Application.Driver.Move (location.X, location.Y);
- Application.Driver.AddStr (hrule);
+ Application.Driver?.Move (location.X, location.Y);
+ Application.Driver?.AddStr (hrule);
}
else
{
@@ -50,8 +50,8 @@ public class Ruler
for (int r = location.Y; r < location.Y + Length; r++)
{
- Application.Driver.Move (location.X, r);
- Application.Driver.AddRune ((Rune)vrule [r - location.Y]);
+ Application.Driver?.Move (location.X, r);
+ Application.Driver?.AddRune ((Rune)vrule [r - location.Y]);
}
}
}
diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs
index 532c0af8a..ac6cc6cd6 100644
--- a/Terminal.Gui/Drawing/Thickness.cs
+++ b/Terminal.Gui/Drawing/Thickness.cs
@@ -119,20 +119,20 @@ public record struct Thickness
// Draw the Top side
if (Top > 0)
{
- Application.Driver.FillRect (rect with { Height = Math.Min (rect.Height, Top) }, topChar);
+ Application.Driver?.FillRect (rect with { Height = Math.Min (rect.Height, Top) }, topChar);
}
// Draw the Left side
// Draw the Left side
if (Left > 0)
{
- Application.Driver.FillRect (rect with { Width = Math.Min (rect.Width, Left) }, leftChar);
+ Application.Driver?.FillRect (rect with { Width = Math.Min (rect.Width, Left) }, leftChar);
}
// Draw the Right side
if (Right > 0)
{
- Application.Driver.FillRect (
+ Application.Driver?.FillRect (
rect with
{
X = Math.Max (0, rect.X + rect.Width - Right),
@@ -145,7 +145,7 @@ public record struct Thickness
// Draw the Bottom side
if (Bottom > 0)
{
- Application.Driver.FillRect (
+ Application.Driver?.FillRect (
rect with
{
Y = rect.Y + Math.Max (0, rect.Height - Bottom),
@@ -197,7 +197,11 @@ public record struct Thickness
VerticalAlignment = Alignment.End,
AutoSize = true
};
- tf.Draw (rect, Application.Driver.CurrentAttribute, Application.Driver.CurrentAttribute, rect);
+
+ if (Application.Driver?.CurrentAttribute is { })
+ {
+ tf.Draw (rect, Application.Driver!.CurrentAttribute, Application.Driver!.CurrentAttribute, rect);
+ }
}
return GetInside (rect);
diff --git a/Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs b/Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
index f5f7190e6..2fa920e70 100644
--- a/Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
+++ b/Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
@@ -106,7 +106,7 @@ public class AppendAutocomplete : AutocompleteBase
}
// draw it like it's selected, even though it's not
- Application.Driver.SetAttribute (
+ Application.Driver?.SetAttribute (
new Attribute (
ColorScheme.Normal.Foreground,
textField.ColorScheme.Focus.Background
@@ -128,7 +128,7 @@ public class AppendAutocomplete : AutocompleteBase
);
}
- Application.Driver.AddStr (fragment);
+ Application.Driver?.AddStr (fragment);
}
///
diff --git a/Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs b/Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
index 93e32b12e..4dfeb8a95 100644
--- a/Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
+++ b/Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
@@ -376,18 +376,18 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
{
if (i == SelectedIdx - ScrollOffset)
{
- Application.Driver.SetAttribute (ColorScheme.Focus);
+ Application.Driver?.SetAttribute (ColorScheme.Focus);
}
else
{
- Application.Driver.SetAttribute (ColorScheme.Normal);
+ Application.Driver?.SetAttribute (ColorScheme.Normal);
}
popup.Move (0, i);
string text = TextFormatter.ClipOrPad (toRender [i].Title, width);
- Application.Driver.AddStr (text);
+ Application.Driver?.AddStr (text);
}
}
diff --git a/Terminal.Gui/View/Layout/Dim.cs b/Terminal.Gui/View/Layout/Dim.cs
index e765414cb..7dfc6eb2e 100644
--- a/Terminal.Gui/View/Layout/Dim.cs
+++ b/Terminal.Gui/View/Layout/Dim.cs
@@ -139,7 +139,7 @@ public abstract class Dim
/// Creates a object that tracks the Height of the specified .
/// The height of the other .
/// The view that will be tracked.
- public static Dim Height (View view) { return new DimView (view, Dimension.Height); }
+ public static Dim Height (View? view) { return new DimView (view, Dimension.Height); }
/// Creates a percentage object that is a percentage of the width or height of the SuperView.
/// The percent object.
@@ -171,7 +171,7 @@ public abstract class Dim
/// Creates a object that tracks the Width of the specified .
/// The width of the other .
/// The view that will be tracked.
- public static Dim Width (View view) { return new DimView (view, Dimension.Width); }
+ public static Dim Width (View? view) { return new DimView (view, Dimension.Width); }
#endregion static Dim creation methods
diff --git a/Terminal.Gui/View/Layout/DimView.cs b/Terminal.Gui/View/Layout/DimView.cs
index 22c0d1f70..09ea96800 100644
--- a/Terminal.Gui/View/Layout/DimView.cs
+++ b/Terminal.Gui/View/Layout/DimView.cs
@@ -15,7 +15,7 @@ public class DimView : Dim
///
/// The view the dimension is anchored to.
/// Indicates which dimension is tracked.
- public DimView (View view, Dimension dimension)
+ public DimView (View? view, Dimension dimension)
{
Target = view;
Dimension = dimension;
@@ -35,7 +35,7 @@ public class DimView : Dim
///
/// Gets the View the dimension is anchored to.
///
- public View Target { get; init; }
+ public View? Target { get; init; }
///
public override string ToString ()
diff --git a/Terminal.Gui/View/Layout/Pos.cs b/Terminal.Gui/View/Layout/Pos.cs
index 2213524ae..853bfa0ab 100644
--- a/Terminal.Gui/View/Layout/Pos.cs
+++ b/Terminal.Gui/View/Layout/Pos.cs
@@ -257,22 +257,22 @@ public abstract class Pos
/// Creates a object that tracks the Top (Y) position of the specified .
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos Top (View view) { return new PosView (view, Side.Top); }
+ public static Pos Top (View? view) { return new PosView (view, Side.Top); }
/// Creates a object that tracks the Top (Y) position of the specified .
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos Y (View view) { return new PosView (view, Side.Top); }
+ public static Pos Y (View? view) { return new PosView (view, Side.Top); }
/// Creates a object that tracks the Left (X) position of the specified .
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos Left (View view) { return new PosView (view, Side.Left); }
+ public static Pos Left (View? view) { return new PosView (view, Side.Left); }
/// Creates a object that tracks the Left (X) position of the specified .
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos X (View view) { return new PosView (view, Side.Left); }
+ public static Pos X (View? view) { return new PosView (view, Side.Left); }
///
/// Creates a object that tracks the Bottom (Y+Height) coordinate of the specified
@@ -280,7 +280,7 @@ public abstract class Pos
///
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos Bottom (View view) { return new PosView (view, Side.Bottom); }
+ public static Pos Bottom (View? view) { return new PosView (view, Side.Bottom); }
///
/// Creates a object that tracks the Right (X+Width) coordinate of the specified
@@ -288,7 +288,7 @@ public abstract class Pos
///
/// The that depends on the other view.
/// The that will be tracked.
- public static Pos Right (View view) { return new PosView (view, Side.Right); }
+ public static Pos Right (View? view) { return new PosView (view, Side.Right); }
#endregion static Pos creation methods
diff --git a/Terminal.Gui/View/Layout/PosView.cs b/Terminal.Gui/View/Layout/PosView.cs
index b48613307..fdf5bf784 100644
--- a/Terminal.Gui/View/Layout/PosView.cs
+++ b/Terminal.Gui/View/Layout/PosView.cs
@@ -12,12 +12,12 @@ namespace Terminal.Gui;
///
/// The View the position is anchored to.
/// The side of the View the position is anchored to.
-public class PosView (View view, Side side) : Pos
+public class PosView (View? view, Side side) : Pos
{
///
/// Gets the View the position is anchored to.
///
- public View Target { get; } = view;
+ public View? Target { get; } = view;
///
/// Gets the side of the View the position is anchored to.
diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs
index fa0983993..637d1f0ca 100644
--- a/Terminal.Gui/View/Layout/ViewLayout.cs
+++ b/Terminal.Gui/View/Layout/ViewLayout.cs
@@ -398,7 +398,7 @@ public partial class View
/// Either (if does not have a Super View) or
/// 's SuperView. This can be used to ensure LayoutSubviews is called on the correct View.
///
- internal static View GetLocationEnsuringFullVisibility (
+ internal static View? GetLocationEnsuringFullVisibility (
View viewToMove,
int targetX,
int targetY,
@@ -408,7 +408,7 @@ public partial class View
)
{
int maxDimension;
- View superView;
+ View? superView;
statusBar = null!;
if (viewToMove?.SuperView is null || viewToMove == Application.Top || viewToMove?.SuperView == Application.Top)
diff --git a/Terminal.Gui/View/ViewDrawing.cs b/Terminal.Gui/View/ViewDrawing.cs
index 67778536f..73fa5d550 100644
--- a/Terminal.Gui/View/ViewDrawing.cs
+++ b/Terminal.Gui/View/ViewDrawing.cs
@@ -288,19 +288,19 @@ public partial class View
public void DrawHotString (string text, Attribute hotColor, Attribute normalColor)
{
Rune hotkeySpec = HotKeySpecifier == (Rune)0xffff ? (Rune)'_' : HotKeySpecifier;
- Application.Driver.SetAttribute (normalColor);
+ Application.Driver?.SetAttribute (normalColor);
foreach (Rune rune in text.EnumerateRunes ())
{
if (rune == new Rune (hotkeySpec.Value))
{
- Application.Driver.SetAttribute (hotColor);
+ Application.Driver?.SetAttribute (hotColor);
continue;
}
- Application.Driver.AddRune (rune);
- Application.Driver.SetAttribute (normalColor);
+ Application.Driver?.AddRune (rune);
+ Application.Driver?.SetAttribute (normalColor);
}
}
diff --git a/Terminal.Gui/Views/GraphView/Annotations.cs b/Terminal.Gui/Views/GraphView/Annotations.cs
index 30247d4a6..7dbc8836e 100644
--- a/Terminal.Gui/Views/GraphView/Annotations.cs
+++ b/Terminal.Gui/Views/GraphView/Annotations.cs
@@ -133,7 +133,7 @@ public class LegendAnnotation : View, IAnnotation
{
if (!IsInitialized)
{
- ColorScheme = new ColorScheme { Normal = Application.Driver.GetAttribute () };
+ ColorScheme = new ColorScheme { Normal = Application.Driver?.GetAttribute () ?? Attribute.Default};
graph.Add (this);
}
@@ -149,7 +149,7 @@ public class LegendAnnotation : View, IAnnotation
{
if (entry.Item1.Color.HasValue)
{
- Application.Driver.SetAttribute (entry.Item1.Color.Value);
+ Application.Driver?.SetAttribute (entry.Item1.Color.Value);
}
else
{
@@ -166,7 +166,7 @@ public class LegendAnnotation : View, IAnnotation
Move (1, linesDrawn);
string str = TextFormatter.ClipOrPad (entry.Item2, Viewport.Width - 1);
- Application.Driver.AddStr (str);
+ Application.Driver?.AddStr (str);
linesDrawn++;
diff --git a/Terminal.Gui/Views/GraphView/Axis.cs b/Terminal.Gui/Views/GraphView/Axis.cs
index efff79ce9..c46938890 100644
--- a/Terminal.Gui/Views/GraphView/Axis.cs
+++ b/Terminal.Gui/Views/GraphView/Axis.cs
@@ -103,7 +103,7 @@ public class HorizontalAxis : Axis
graph.Move (screenPosition, y);
// draw the tick on the axis
- Application.Driver.AddRune (Glyphs.TopTee);
+ Application.Driver?.AddRune (Glyphs.TopTee);
// and the label text
if (!string.IsNullOrWhiteSpace (text))
@@ -161,7 +161,7 @@ public class HorizontalAxis : Axis
}
graph.Move (graph.Viewport.Width / 2 - toRender.Length / 2, graph.Viewport.Height - 1);
- Application.Driver.AddStr (toRender);
+ Application.Driver?.AddStr (toRender);
}
}
@@ -222,7 +222,7 @@ public class HorizontalAxis : Axis
protected override void DrawAxisLine (GraphView graph, int x, int y)
{
graph.Move (x, y);
- Application.Driver.AddRune (Glyphs.HLine);
+ Application.Driver?.AddRune (Glyphs.HLine);
}
private IEnumerable GetLabels (GraphView graph, Rectangle viewport)
@@ -298,13 +298,13 @@ public class VerticalAxis : Axis
graph.Move (x, screenPosition);
// draw the tick on the axis
- Application.Driver.AddRune (Glyphs.RightTee);
+ Application.Driver?.AddRune (Glyphs.RightTee);
// and the label text
if (!string.IsNullOrWhiteSpace (text))
{
graph.Move (Math.Max (0, x - labelThickness), screenPosition);
- Application.Driver.AddStr (text);
+ Application.Driver?.AddStr (text);
}
}
@@ -342,7 +342,7 @@ public class VerticalAxis : Axis
for (var i = 0; i < toRender.Length; i++)
{
graph.Move (0, startDrawingAtY + i);
- Application.Driver.AddRune ((Rune)toRender [i]);
+ Application.Driver?.AddRune ((Rune)toRender [i]);
}
}
}
@@ -395,7 +395,7 @@ public class VerticalAxis : Axis
protected override void DrawAxisLine (GraphView graph, int x, int y)
{
graph.Move (x, y);
- Application.Driver.AddRune (Glyphs.VLine);
+ Application.Driver?.AddRune (Glyphs.VLine);
}
private int GetAxisYEnd (GraphView graph)
diff --git a/Terminal.Gui/Views/GraphView/Series.cs b/Terminal.Gui/Views/GraphView/Series.cs
index f0974556c..f7c02e174 100644
--- a/Terminal.Gui/Views/GraphView/Series.cs
+++ b/Terminal.Gui/Views/GraphView/Series.cs
@@ -33,7 +33,7 @@ public class ScatterSeries : ISeries
{
if (Fill.Color.HasValue)
{
- Application.Driver.SetAttribute (Fill.Color.Value);
+ Application.Driver?.SetAttribute (Fill.Color.Value);
}
foreach (PointF p in Points.Where (p => graphBounds.Contains (p)))
@@ -261,7 +261,7 @@ public class BarSeries : ISeries
if (adjusted.Color.HasValue)
{
- Application.Driver.SetAttribute (adjusted.Color.Value);
+ Application.Driver?.SetAttribute (adjusted.Color.Value);
}
graph.DrawLine (start, end, adjusted.Rune);
diff --git a/Terminal.Gui/Views/Menu/ContextMenu.cs b/Terminal.Gui/Views/Menu/ContextMenu.cs
index 8bcbc076a..f35cbdf34 100644
--- a/Terminal.Gui/Views/Menu/ContextMenu.cs
+++ b/Terminal.Gui/Views/Menu/ContextMenu.cs
@@ -144,7 +144,7 @@ public sealed class ContextMenu : IDisposable
_container = Application.Current;
_container.Closing += Container_Closing;
_container.Deactivate += Container_Deactivate;
- Rectangle frame = Application.Driver.Screen;
+ Rectangle frame = Application.Driver?.Screen ?? Rectangle.Empty;
Point position = Position;
if (Host is { })
diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs
index f0dc5174b..bb2996ba4 100644
--- a/Terminal.Gui/Views/RadioGroup.cs
+++ b/Terminal.Gui/Views/RadioGroup.cs
@@ -278,7 +278,7 @@ public class RadioGroup : View, IDesignable
if (j == hotPos && i == _cursor)
{
- Application.Driver.SetAttribute (
+ Application.Driver?.SetAttribute (
HasFocus
? ColorScheme.HotFocus
: GetHotNormalColor ()
@@ -286,11 +286,11 @@ public class RadioGroup : View, IDesignable
}
else if (j == hotPos && i != _cursor)
{
- Application.Driver.SetAttribute (GetHotNormalColor ());
+ Application.Driver?.SetAttribute (GetHotNormalColor ());
}
else if (HasFocus && i == _cursor)
{
- Application.Driver.SetAttribute (ColorScheme.Focus);
+ Application.Driver?.SetAttribute (ColorScheme.Focus);
}
if (rune == HotKeySpecifier && j + 1 < rlRunes.Length)
@@ -300,7 +300,7 @@ public class RadioGroup : View, IDesignable
if (i == _cursor)
{
- Application.Driver.SetAttribute (
+ Application.Driver?.SetAttribute (
HasFocus
? ColorScheme.HotFocus
: GetHotNormalColor ()
@@ -308,11 +308,11 @@ public class RadioGroup : View, IDesignable
}
else if (i != _cursor)
{
- Application.Driver.SetAttribute (GetHotNormalColor ());
+ Application.Driver?.SetAttribute (GetHotNormalColor ());
}
}
- Application.Driver.AddRune (rune);
+ Application.Driver?.AddRune (rune);
Driver.SetAttribute (GetNormalColor ());
}
}
diff --git a/UICatalog/Scenarios/CombiningMarks.cs b/UICatalog/Scenarios/CombiningMarks.cs
index b61ebb09f..78455eeca 100644
--- a/UICatalog/Scenarios/CombiningMarks.cs
+++ b/UICatalog/Scenarios/CombiningMarks.cs
@@ -15,20 +15,20 @@ public class CombiningMarks : Scenario
top.DrawContentComplete += (s, e) =>
{
- Application.Driver.Move (0, 0);
- Application.Driver.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
- Application.Driver.Move (0, 2);
- Application.Driver.AddStr ("\u0301\u0301\u0328<- \"\\u301\\u301\\u328]\" using AddStr.");
- Application.Driver.Move (0, 3);
- Application.Driver.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u301\\u301\\u328]\" using AddStr.");
- Application.Driver.Move (0, 4);
- Application.Driver.AddRune ('[');
- Application.Driver.AddRune ('a');
- Application.Driver.AddRune ('\u0301');
- Application.Driver.AddRune ('\u0301');
- Application.Driver.AddRune ('\u0328');
- Application.Driver.AddRune (']');
- Application.Driver.AddStr ("<- \"[a\\u301\\u301\\u328]\" using AddRune for each.");
+ Application.Driver?.Move (0, 0);
+ Application.Driver?.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
+ Application.Driver?.Move (0, 2);
+ Application.Driver?.AddStr ("\u0301\u0301\u0328<- \"\\u301\\u301\\u328]\" using AddStr.");
+ Application.Driver?.Move (0, 3);
+ Application.Driver?.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u301\\u301\\u328]\" using AddStr.");
+ Application.Driver?.Move (0, 4);
+ Application.Driver?.AddRune ('[');
+ Application.Driver?.AddRune ('a');
+ Application.Driver?.AddRune ('\u0301');
+ Application.Driver?.AddRune ('\u0301');
+ Application.Driver?.AddRune ('\u0328');
+ Application.Driver?.AddRune (']');
+ Application.Driver?.AddStr ("<- \"[a\\u301\\u301\\u328]\" using AddRune for each.");
};
Application.Run (top);
diff --git a/UICatalog/Scenarios/Images.cs b/UICatalog/Scenarios/Images.cs
index d31eae9cc..f17246742 100644
--- a/UICatalog/Scenarios/Images.cs
+++ b/UICatalog/Scenarios/Images.cs
@@ -20,9 +20,9 @@ public class Images : Scenario
Application.Init ();
var win = new Window { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName()}" };
- bool canTrueColor = Application.Driver.SupportsTrueColor;
+ bool canTrueColor = Application.Driver?.SupportsTrueColor ?? false;
- var lblDriverName = new Label { X = 0, Y = 0, Text = $"Driver is {Application.Driver.GetType ().Name}" };
+ var lblDriverName = new Label { X = 0, Y = 0, Text = $"Driver is {Application.Driver?.GetType ().Name}" };
win.Add (lblDriverName);
var cbSupportsTrueColor = new CheckBox
diff --git a/UICatalog/Scenarios/SendKeys.cs b/UICatalog/Scenarios/SendKeys.cs
index a27a80232..6dc4a3bdf 100644
--- a/UICatalog/Scenarios/SendKeys.cs
+++ b/UICatalog/Scenarios/SendKeys.cs
@@ -86,7 +86,7 @@ public class SendKeys : Scenario
? (ConsoleKey)char.ToUpper (r)
: (ConsoleKey)r;
- Application.Driver.SendKeys (
+ Application.Driver?.SendKeys (
r,
ck,
ckbShift.State == CheckState.Checked,
diff --git a/UICatalog/Scenarios/TextEffectsScenario.cs b/UICatalog/Scenarios/TextEffectsScenario.cs
index 17f6a6e5c..7d5d0e156 100644
--- a/UICatalog/Scenarios/TextEffectsScenario.cs
+++ b/UICatalog/Scenarios/TextEffectsScenario.cs
@@ -260,5 +260,5 @@ internal class GradientsView : View
}
}
- private static void SetColor (Color color) { Application.Driver.SetAttribute (new (color, color)); }
+ private static void SetColor (Color color) { Application.Driver?.SetAttribute (new (color, color)); }
}
diff --git a/UICatalog/Scenarios/TrueColors.cs b/UICatalog/Scenarios/TrueColors.cs
index 19e00187d..d08d9685a 100644
--- a/UICatalog/Scenarios/TrueColors.cs
+++ b/UICatalog/Scenarios/TrueColors.cs
@@ -19,11 +19,11 @@ public class TrueColors : Scenario
var x = 2;
var y = 1;
- bool canTrueColor = Application.Driver.SupportsTrueColor;
+ bool canTrueColor = Application.Driver?.SupportsTrueColor ?? false;
var lblDriverName = new Label
{
- X = x, Y = y++, Text = $"Current driver is {Application.Driver.GetType ().Name}"
+ X = x, Y = y++, Text = $"Current driver is {Application.Driver?.GetType ().Name}"
};
app.Add (lblDriverName);
y++;
diff --git a/UICatalog/Scenarios/VkeyPacketSimulator.cs b/UICatalog/Scenarios/VkeyPacketSimulator.cs
index 50ce09b71..975775f45 100644
--- a/UICatalog/Scenarios/VkeyPacketSimulator.cs
+++ b/UICatalog/Scenarios/VkeyPacketSimulator.cs
@@ -198,7 +198,7 @@ public class VkeyPacketSimulator : Scenario
char keyChar =
ConsoleKeyMapping.EncodeKeyCharForVKPacket (consoleKeyInfo);
- Application.Driver.SendKeys (
+ Application.Driver?.SendKeys (
keyChar,
ConsoleKey.Packet,
consoleKeyInfo.Modifiers.HasFlag (ConsoleModifiers.Shift),
diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs
index ddb4c656f..dd4184cb4 100644
--- a/UICatalog/UICatalog.cs
+++ b/UICatalog/UICatalog.cs
@@ -369,7 +369,7 @@ internal class UICatalogApp
///
public class UICatalogTopLevel : Toplevel
{
- public ListView CategoryList;
+ public ListView? CategoryList;
public MenuItem? MiForce16Colors;
public MenuItem? MiIsMenuBorderDisabled;
public MenuItem? MiIsMouseDisabled;
@@ -999,7 +999,7 @@ internal class UICatalogApp
Title = "Force _16 Colors",
Shortcut = (KeyCode)Key.F6,
Checked = Application.Force16Colors,
- CanExecute = () => Application.Driver.SupportsTrueColor
+ CanExecute = () => Application.Driver?.SupportsTrueColor ?? false
};
MiForce16Colors.CheckType |= MenuItemCheckStyle.Checked;
diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs
index a7c1fc64a..6363233a9 100644
--- a/UnitTests/Application/ApplicationTests.cs
+++ b/UnitTests/Application/ApplicationTests.cs
@@ -44,7 +44,7 @@ public class ApplicationTests
Toplevel top = new ();
Application.Begin (top);
Assert.Equal (new (0, 0, 80, 25), Application.Top.Frame);
- ((FakeDriver)Application.Driver).SetBufferSize (5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
Assert.Equal (new (0, 0, 5, 5), Application.Top.Frame);
top.Dispose ();
}
@@ -134,7 +134,7 @@ public class ApplicationTests
Application.Init (driverName: driverType.Name);
Assert.NotNull (Application.Driver);
Assert.NotEqual (driver, Application.Driver);
- Assert.Equal (driverType, Application.Driver.GetType ());
+ Assert.Equal (driverType, Application.Driver?.GetType ());
Shutdown ();
}
@@ -565,8 +565,8 @@ public class ApplicationTests
Assert.NotNull (Application.MainLoop);
// FakeDriver is always 80x25
- Assert.Equal (80, Application.Driver.Cols);
- Assert.Equal (25, Application.Driver.Rows);
+ Assert.Equal (80, Application.Driver!.Cols);
+ Assert.Equal (25, Application.Driver!.Rows);
}
private void Pre_Init_State ()
@@ -695,7 +695,7 @@ public class ApplicationTests
Application.ForceDriver = "FakeDriver";
Application.Init ();
- Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
+ Assert.Equal (typeof (FakeDriver), Application.Driver?.GetType ());
Application.Iteration += (s, a) => { Application.RequestStop (); };
@@ -737,7 +737,7 @@ public class ApplicationTests
Application.Iteration += (s, a) => { Application.RequestStop (); };
Application.Run ();
- Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
+ Assert.Equal (typeof (FakeDriver), Application.Driver?.GetType ());
Application.Top.Dispose ();
Shutdown ();
@@ -888,7 +888,7 @@ public class ApplicationTests
Width = 5, Height = 5,
Arrangement = ViewArrangement.Movable
};
- ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
RunState rs = Application.Begin (w);
// Don't use visuals to test as style of border can change over time.
diff --git a/UnitTests/Application/CursorTests.cs b/UnitTests/Application/CursorTests.cs
index 337003b0f..87999a9d2 100644
--- a/UnitTests/Application/CursorTests.cs
+++ b/UnitTests/Application/CursorTests.cs
@@ -141,7 +141,10 @@ public class CursorTests
Assert.True (view.HasFocus);
Assert.False (Application.PositionCursor (view));
- Application.Driver.GetCursorVisibility (out CursorVisibility cursor);
- Assert.Equal (CursorVisibility.Invisible, cursor);
+
+ if (Application.Driver?.GetCursorVisibility (out CursorVisibility cursor) ?? false)
+ {
+ Assert.Equal (CursorVisibility.Invisible, cursor);
+ }
}
}
diff --git a/UnitTests/Clipboard/ClipboardTests.cs b/UnitTests/Clipboard/ClipboardTests.cs
index 65c2e7707..e2c0ac11f 100644
--- a/UnitTests/Clipboard/ClipboardTests.cs
+++ b/UnitTests/Clipboard/ClipboardTests.cs
@@ -9,14 +9,14 @@ public class ClipboardTests
[Fact, AutoInitShutdown (useFakeClipboard: true, fakeClipboardAlwaysThrowsNotSupportedException: true)]
public void IClipboard_GetClipBoardData_Throws_NotSupportedException ()
{
- var iclip = Application.Driver.Clipboard;
+ var iclip = Application.Driver?.Clipboard;
Assert.Throws (() => iclip.GetClipboardData ());
}
[Fact, AutoInitShutdown (useFakeClipboard: true, fakeClipboardAlwaysThrowsNotSupportedException: true)]
public void IClipboard_SetClipBoardData_Throws_NotSupportedException ()
{
- var iclip = Application.Driver.Clipboard;
+ var iclip = Application.Driver?.Clipboard;
Assert.Throws (() => iclip.SetClipboardData ("foo"));
}
diff --git a/UnitTests/ConsoleDrivers/ClipRegionTests.cs b/UnitTests/ConsoleDrivers/ClipRegionTests.cs
index 0d27f91c1..8a90f2e4d 100644
--- a/UnitTests/ConsoleDrivers/ClipRegionTests.cs
+++ b/UnitTests/ConsoleDrivers/ClipRegionTests.cs
@@ -26,8 +26,8 @@ public class ClipRegionTests
{
var driver = (ConsoleDriver)Activator.CreateInstance (driverType);
Application.Init (driver);
- Application.Driver.Rows = 25;
- Application.Driver.Cols = 80;
+ Application.Driver!.Rows = 25;
+ Application.Driver!.Cols = 80;
driver.Move (0, 0);
driver.AddRune ('x');
@@ -94,8 +94,8 @@ public class ClipRegionTests
{
var driver = (ConsoleDriver)Activator.CreateInstance (driverType);
Application.Init (driver);
- Application.Driver.Rows = 10;
- Application.Driver.Cols = 10;
+ Application.Driver!.Rows = 10;
+ Application.Driver!.Cols = 10;
// positive
Assert.True (driver.IsValidLocation (0, 0));
diff --git a/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs
index afbf20d96..8ecc97807 100644
--- a/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs
+++ b/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs
@@ -234,7 +234,7 @@ public class ConsoleDriverTests
// {
// var win = new Window ();
// Application.Begin (win);
- // ((FakeDriver)Application.Driver).SetBufferSize (20, 8);
+ // ((FakeDriver)Application.Driver!).SetBufferSize (20, 8);
// System.Threading.Tasks.Task.Run (() => {
// System.Threading.Tasks.Task.Delay (500).Wait ();
diff --git a/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs
index de05b868f..1ea984b3d 100644
--- a/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs
+++ b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs
@@ -123,7 +123,7 @@ public class ConsoleKeyMappingTests
if (iterations == 0)
{
var keyChar = ConsoleKeyMapping.EncodeKeyCharForVKPacket (consoleKeyInfo);
- Application.Driver.SendKeys (keyChar, ConsoleKey.Packet, shift, alt, control);
+ Application.Driver?.SendKeys (keyChar, ConsoleKey.Packet, shift, alt, control);
}
};
Application.Run ();
diff --git a/UnitTests/Dialogs/MessageBoxTests.cs b/UnitTests/Dialogs/MessageBoxTests.cs
index f32f7074a..8715eea2c 100644
--- a/UnitTests/Dialogs/MessageBoxTests.cs
+++ b/UnitTests/Dialogs/MessageBoxTests.cs
@@ -125,7 +125,7 @@ public class MessageBoxTests
public void Location_Default ()
{
int iterations = -1;
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
Application.Iteration += (s, a) =>
{
@@ -243,7 +243,7 @@ public class MessageBoxTests
int iterations = -1;
var top = new Toplevel ();
top.BorderStyle = LineStyle.None;
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var btn =
$"{
@@ -319,7 +319,7 @@ public class MessageBoxTests
int iterations = -1;
var top = new Toplevel ();
top.BorderStyle = LineStyle.None;
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var btn =
$"{
@@ -396,7 +396,7 @@ ffffffffffffffffffff
int iterations = -1;
var top = new Toplevel();
top.BorderStyle = LineStyle.None;
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var btn =
$"{
@@ -477,7 +477,7 @@ ffffffffffffffffffff
int iterations = -1;
var top = new Toplevel();
top.BorderStyle = LineStyle.None;
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var btn =
$"{
@@ -547,7 +547,7 @@ ffffffffffffffffffff
public void Size_Default ()
{
int iterations = -1;
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
Application.Iteration += (s, a) =>
{
@@ -650,7 +650,7 @@ ffffffffffffffffffff
CM.Glyphs.RightBracket
}";
- ((FakeDriver)Application.Driver).SetBufferSize (40 + 4, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40 + 4, 8);
Application.Iteration += (s, a) =>
{
@@ -737,7 +737,7 @@ ffffffffffffffffffff
public void Size_Not_Default_Message (int height, int width, string message)
{
int iterations = -1;
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
Application.Iteration += (s, a) =>
{
@@ -774,7 +774,7 @@ ffffffffffffffffffff
public void Size_Not_Default_Message_Button (int height, int width, string message)
{
int iterations = -1;
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
Application.Iteration += (s, a) =>
{
@@ -807,7 +807,7 @@ ffffffffffffffffffff
public void Size_Not_Default_No_Message (int height, int width)
{
int iterations = -1;
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
Application.Iteration += (s, a) =>
{
diff --git a/UnitTests/Drawing/RulerTests.cs b/UnitTests/Drawing/RulerTests.cs
index 0fdbfd7e2..d43ea327f 100644
--- a/UnitTests/Drawing/RulerTests.cs
+++ b/UnitTests/Drawing/RulerTests.cs
@@ -29,7 +29,7 @@ public class RulerTests
[AutoInitShutdown]
public void Draw_Default ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (25, 25);
+ ((FakeDriver)Application.Driver!).SetBufferSize (25, 25);
var r = new Ruler ();
r.Draw (Point.Empty);
@@ -47,7 +47,7 @@ public class RulerTests
var top = new Toplevel ();
top.Add (f);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (len + 5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (len + 5, 5);
Assert.Equal (new (0, 0, len + 5, 5), f.Frame);
var r = new Ruler ();
@@ -121,7 +121,7 @@ public class RulerTests
var top = new Toplevel ();
top.Add (f);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (len + 5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (len + 5, 5);
Assert.Equal (new (0, 0, len + 5, 5), f.Frame);
var r = new Ruler ();
@@ -168,7 +168,7 @@ public class RulerTests
var top = new Toplevel ();
top.Add (f);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (5, len + 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, len + 5);
Assert.Equal (new (0, 0, 5, len + 5), f.Frame);
var r = new Ruler ();
@@ -302,7 +302,7 @@ public class RulerTests
var top = new Toplevel ();
top.Add (f);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (5, len + 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, len + 5);
Assert.Equal (new (0, 0, 5, len + 5), f.Frame);
var r = new Ruler ();
diff --git a/UnitTests/Drawing/ThicknessTests.cs b/UnitTests/Drawing/ThicknessTests.cs
index 8215f8148..c71135722 100644
--- a/UnitTests/Drawing/ThicknessTests.cs
+++ b/UnitTests/Drawing/ThicknessTests.cs
@@ -51,13 +51,13 @@ public class ThicknessTests (ITestOutputHelper output)
[AutoInitShutdown]
public void DrawTests ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (60, 60);
+ ((FakeDriver)Application.Driver!).SetBufferSize (60, 60);
var t = new Thickness (0, 0, 0, 0);
var r = new Rectangle (5, 5, 40, 15);
View.Diagnostics |= ViewDiagnosticFlags.Padding;
- Application.Driver.FillRect (
- new Rectangle (0, 0, Application.Driver.Cols, Application.Driver.Rows),
+ Application.Driver?.FillRect (
+ new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
(Rune)' '
);
t.Draw (r, "Test");
@@ -73,8 +73,8 @@ public class ThicknessTests (ITestOutputHelper output)
r = new Rectangle (5, 5, 40, 15);
View.Diagnostics |= ViewDiagnosticFlags.Padding;
- Application.Driver.FillRect (
- new Rectangle (0, 0, Application.Driver.Cols, Application.Driver.Rows),
+ Application.Driver?.FillRect (
+ new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
(Rune)' '
);
t.Draw (r, "Test");
@@ -104,8 +104,8 @@ public class ThicknessTests (ITestOutputHelper output)
r = new Rectangle (5, 5, 40, 15);
View.Diagnostics |= ViewDiagnosticFlags.Padding;
- Application.Driver.FillRect (
- new Rectangle (0, 0, Application.Driver.Cols, Application.Driver.Rows),
+ Application.Driver?.FillRect (
+ new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
(Rune)' '
);
t.Draw (r, "Test");
@@ -135,8 +135,8 @@ public class ThicknessTests (ITestOutputHelper output)
r = new Rectangle (5, 5, 40, 15);
View.Diagnostics |= ViewDiagnosticFlags.Padding;
- Application.Driver.FillRect (
- new Rectangle (0, 0, Application.Driver.Cols, Application.Driver.Rows),
+ Application.Driver?.FillRect (
+ new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
(Rune)' '
);
t.Draw (r, "Test");
@@ -174,7 +174,7 @@ public class ThicknessTests (ITestOutputHelper output)
top.Add (f);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (45, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (45, 20);
var t = new Thickness (0, 0, 0, 0);
var r = new Rectangle (2, 2, 40, 15);
Application.Refresh ();
diff --git a/UnitTests/FileServices/FileDialogTests.cs b/UnitTests/FileServices/FileDialogTests.cs
index 1395543ee..1488a75f0 100644
--- a/UnitTests/FileServices/FileDialogTests.cs
+++ b/UnitTests/FileServices/FileDialogTests.cs
@@ -701,14 +701,14 @@ public class FileDialogTests (ITestOutputHelper output)
private void Send (char ch, ConsoleKey ck, bool shift = false, bool alt = false, bool control = false)
{
- Application.Driver.SendKeys (ch, ck, shift, alt, control);
+ Application.Driver?.SendKeys (ch, ck, shift, alt, control);
}
private void Send (string chars)
{
foreach (char ch in chars)
{
- Application.Driver.SendKeys (ch, ConsoleKey.NoName, false, false, false);
+ Application.Driver?.SendKeys (ch, ConsoleKey.NoName, false, false, false);
}
}
diff --git a/UnitTests/Text/TextFormatterTests.cs b/UnitTests/Text/TextFormatterTests.cs
index 6746f8ad7..f821d504b 100644
--- a/UnitTests/Text/TextFormatterTests.cs
+++ b/UnitTests/Text/TextFormatterTests.cs
@@ -451,7 +451,7 @@ ssb
[SetupFakeDriver]
public void FillRemaining_True_False ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (22, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (22, 5);
Attribute [] attrs =
{
@@ -6041,7 +6041,7 @@ B")]
Text = text
};
- Application.Driver.FillRect (new Rectangle (0, 0, 7, 7), (Rune)'*');
+ Application.Driver?.FillRect (new Rectangle (0, 0, 7, 7), (Rune)'*');
tf.Draw (new Rectangle (0, 0, 7, 7), Attribute.Default, Attribute.Default);
TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
}
diff --git a/UnitTests/View/Adornment/BorderTests.cs b/UnitTests/View/Adornment/BorderTests.cs
index 387844dbe..cae90f708 100644
--- a/UnitTests/View/Adornment/BorderTests.cs
+++ b/UnitTests/View/Adornment/BorderTests.cs
@@ -95,7 +95,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (width, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, 5);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -229,7 +229,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (width, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, 4);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -363,7 +363,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (width, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, 4);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -486,7 +486,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (20, height);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, height);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -548,7 +548,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (width, 3);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, 3);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -728,7 +728,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (top);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
Application.RunIteration (ref rs, ref firstIteration);
var expected = @"
@@ -756,7 +756,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (top);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
Application.RunIteration (ref rs, ref firstIteration);
var expected = @"
@@ -779,7 +779,7 @@ public class BorderTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (3, 3);
+ ((FakeDriver)Application.Driver!).SetBufferSize (3, 3);
Application.RunIteration (ref rs, ref firstIteration);
var expected = @"
diff --git a/UnitTests/View/Adornment/MarginTests.cs b/UnitTests/View/Adornment/MarginTests.cs
index 1cfe6f0d1..736a720b1 100644
--- a/UnitTests/View/Adornment/MarginTests.cs
+++ b/UnitTests/View/Adornment/MarginTests.cs
@@ -8,7 +8,7 @@ public class MarginTests (ITestOutputHelper output)
[SetupFakeDriver]
public void Margin_Uses_SuperView_ColorScheme ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
var view = new View { Height = 3, Width = 3 };
view.Margin.Thickness = new (1);
diff --git a/UnitTests/View/Adornment/PaddingTests.cs b/UnitTests/View/Adornment/PaddingTests.cs
index 4f7bffb20..2c917572f 100644
--- a/UnitTests/View/Adornment/PaddingTests.cs
+++ b/UnitTests/View/Adornment/PaddingTests.cs
@@ -8,7 +8,7 @@ public class PaddingTests (ITestOutputHelper output)
[SetupFakeDriver]
public void Padding_Uses_Parent_ColorScheme ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (5, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
var view = new View { Height = 3, Width = 3 };
view.Padding.Thickness = new (1);
diff --git a/UnitTests/View/DrawTests.cs b/UnitTests/View/DrawTests.cs
index 46c791ab4..52b4659f8 100644
--- a/UnitTests/View/DrawTests.cs
+++ b/UnitTests/View/DrawTests.cs
@@ -22,13 +22,13 @@ public class DrawTests (ITestOutputHelper _output)
// Only valid location w/in Viewport is 0, 0 (view) - 2, 2 (screen)
view.Move (0, 0);
- Assert.Equal (new Point (2, 2), new Point (Application.Driver.Col, Application.Driver.Row));
+ Assert.Equal (new Point (2, 2), new Point (Application.Driver!.Col, Application.Driver!.Row));
view.Move (-1, -1);
- Assert.Equal (new Point (2, 2), new Point (Application.Driver.Col, Application.Driver.Row));
+ Assert.Equal (new Point (2, 2), new Point (Application.Driver!.Col, Application.Driver!.Row));
view.Move (1, 1);
- Assert.Equal (new Point (2, 2), new Point (Application.Driver.Col, Application.Driver.Row));
+ Assert.Equal (new Point (2, 2), new Point (Application.Driver!.Col, Application.Driver!.Row));
}
[Fact]
@@ -48,16 +48,16 @@ public class DrawTests (ITestOutputHelper _output)
view.Draw ();
// Only valid location w/in Viewport is 0, 0 (view) - 2, 2 (screen)
- Assert.Equal ((Rune)' ', Application.Driver.Contents [2, 2].Rune);
+ Assert.Equal ((Rune)' ', Application.Driver?.Contents [2, 2].Rune);
view.AddRune (0, 0, Rune.ReplacementChar);
- Assert.Equal (Rune.ReplacementChar, Application.Driver.Contents [2, 2].Rune);
+ Assert.Equal (Rune.ReplacementChar, Application.Driver?.Contents [2, 2].Rune);
view.AddRune (-1, -1, Rune.ReplacementChar);
- Assert.Equal ((Rune)'M', Application.Driver.Contents [1, 1].Rune);
+ Assert.Equal ((Rune)'M', Application.Driver?.Contents [1, 1].Rune);
view.AddRune (1, 1, Rune.ReplacementChar);
- Assert.Equal ((Rune)'M', Application.Driver.Contents [3, 3].Rune);
+ Assert.Equal ((Rune)'M', Application.Driver?.Contents [3, 3].Rune);
View.Diagnostics = ViewDiagnosticFlags.Off;
}
@@ -250,7 +250,7 @@ public class DrawTests (ITestOutputHelper _output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
const string expectedOutput = """
@@ -301,7 +301,7 @@ public class DrawTests (ITestOutputHelper _output)
dg.Add (view);
RunState rsTop = Application.Begin (top);
RunState rsDiag = Application.Begin (dg);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 10);
const string expectedOutput = """
@@ -354,7 +354,7 @@ public class DrawTests (ITestOutputHelper _output)
top.Add (viewRight, viewBottom);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (7, 7);
+ ((FakeDriver)Application.Driver!).SetBufferSize (7, 7);
TestHelpers.AssertDriverContentsWithFrameAre (
"""
@@ -394,7 +394,7 @@ public class DrawTests (ITestOutputHelper _output)
var view = new View { Width = 2, Height = 2, BorderStyle = LineStyle.Single };
view.BeginInit ();
view.EndInit ();
- view.SetRelativeLayout (Application.Driver.Screen.Size);
+ view.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 2, 2), view.Frame);
Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -419,7 +419,7 @@ public class DrawTests (ITestOutputHelper _output)
view.Border.Thickness = new Thickness (1, 1, 1, 0);
view.BeginInit ();
view.EndInit ();
- view.SetRelativeLayout (Application.Driver.Screen.Size);
+ view.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 2, 1), view.Frame);
Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -437,7 +437,7 @@ public class DrawTests (ITestOutputHelper _output)
view.Border.Thickness = new Thickness (0, 1, 1, 1);
view.BeginInit ();
view.EndInit ();
- view.SetRelativeLayout (Application.Driver.Screen.Size);
+ view.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 1, 2), view.Frame);
Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -462,7 +462,7 @@ public class DrawTests (ITestOutputHelper _output)
view.Border.Thickness = new Thickness (1, 1, 0, 1);
view.BeginInit ();
view.EndInit ();
- view.SetRelativeLayout (Application.Driver.Screen.Size);
+ view.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 1, 2), view.Frame);
Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -488,7 +488,7 @@ public class DrawTests (ITestOutputHelper _output)
view.BeginInit ();
view.EndInit ();
- view.SetRelativeLayout (Application.Driver.Screen.Size);
+ view.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 2, 1), view.Frame);
Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -561,7 +561,7 @@ public class DrawTests (ITestOutputHelper _output)
container.Add (content);
Toplevel top = new ();
top.Add (container);
- Application.Driver.Clip = container.Frame;
+ Application.Driver!.Clip = container.Frame;
Application.Begin (top);
TestHelpers.AssertDriverContentsWithFrameAre (
@@ -727,7 +727,7 @@ public class DrawTests (ITestOutputHelper _output)
return;
- void Top_LayoutComplete (object? sender, LayoutEventArgs e) { Application.Driver.Clip = container.Frame; }
+ void Top_LayoutComplete (object? sender, LayoutEventArgs e) { Application.Driver!.Clip = container.Frame; }
}
[Fact]
@@ -767,7 +767,7 @@ public class DrawTests (ITestOutputHelper _output)
container.Add (content);
Toplevel top = new ();
top.Add (container);
- Application.Driver.Clip = container.Frame;
+ Application.Driver!.Clip = container.Frame;
Application.Begin (top);
TestHelpers.AssertDriverContentsWithFrameAre (
@@ -889,7 +889,7 @@ public class DrawTests (ITestOutputHelper _output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
var expected = """
@@ -928,13 +928,13 @@ public class DrawTests (ITestOutputHelper _output)
view.Border.Thickness = new Thickness (1);
view.BeginInit ();
view.EndInit ();
- Assert.Equal (view.Frame, Application.Driver.Clip);
+ Assert.Equal (view.Frame, Application.Driver?.Clip);
// Act
view.SetClip ();
// Assert
- Assert.Equal (expectedClip, Application.Driver.Clip);
+ Assert.Equal (expectedClip, Application.Driver?.Clip);
view.Dispose ();
}
@@ -960,14 +960,14 @@ public class DrawTests (ITestOutputHelper _output)
view.Border.Thickness = new Thickness (1);
view.BeginInit ();
view.EndInit ();
- Assert.Equal (view.Frame, Application.Driver.Clip);
+ Assert.Equal (view.Frame, Application.Driver?.Clip);
view.Viewport = view.Viewport with { X = 1, Y = 1 };
// Act
view.SetClip ();
// Assert
- Assert.Equal (expectedClip, Application.Driver.Clip);
+ Assert.Equal (expectedClip, Application.Driver?.Clip);
view.Dispose ();
}
diff --git a/UnitTests/View/Layout/Dim.FillTests.cs b/UnitTests/View/Layout/Dim.FillTests.cs
index c4b4ebacf..cdda3088d 100644
--- a/UnitTests/View/Layout/Dim.FillTests.cs
+++ b/UnitTests/View/Layout/Dim.FillTests.cs
@@ -14,7 +14,7 @@ public class DimFillTests (ITestOutputHelper output)
var top = new Toplevel ();
top.Add (view);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (32, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (32, 5);
//view.SetNeedsLayout ();
top.LayoutSubviews ();
diff --git a/UnitTests/View/Layout/Pos.AnchorEndTests.cs b/UnitTests/View/Layout/Pos.AnchorEndTests.cs
index 4309ee858..ddd3c62af 100644
--- a/UnitTests/View/Layout/Pos.AnchorEndTests.cs
+++ b/UnitTests/View/Layout/Pos.AnchorEndTests.cs
@@ -184,7 +184,7 @@ public class PosAnchorEndTests (ITestOutputHelper output)
[SetupFakeDriver]
public void PosAnchorEnd_View_And_Button ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (20, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 5);
var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}";
diff --git a/UnitTests/View/Layout/Pos.CenterTests.cs b/UnitTests/View/Layout/Pos.CenterTests.cs
index a17b1132a..e713c07b6 100644
--- a/UnitTests/View/Layout/Pos.CenterTests.cs
+++ b/UnitTests/View/Layout/Pos.CenterTests.cs
@@ -85,7 +85,7 @@ public class PosCenterTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (20, height);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, height);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
@@ -232,7 +232,7 @@ public class PosCenterTests (ITestOutputHelper output)
RunState rs = Application.Begin (win);
var firstIteration = false;
- ((FakeDriver)Application.Driver).SetBufferSize (width, 7);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, 7);
Application.RunIteration (ref rs, ref firstIteration);
var expected = string.Empty;
diff --git a/UnitTests/View/Layout/ViewportTests.cs b/UnitTests/View/Layout/ViewportTests.cs
index f5bc9212d..f0d30f118 100644
--- a/UnitTests/View/Layout/ViewportTests.cs
+++ b/UnitTests/View/Layout/ViewportTests.cs
@@ -472,7 +472,7 @@ public class ViewportTests (ITestOutputHelper output)
//[InlineData (5, 5, false)]
//public void IsVisibleInSuperView_With_Driver (int x, int y, bool expected)
//{
- // ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+ // ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
// var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
// var top = new Toplevel ();
diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs
index 05dc30a1f..5a7019c19 100644
--- a/UnitTests/View/NavigationTests.cs
+++ b/UnitTests/View/NavigationTests.cs
@@ -669,7 +669,7 @@ public class NavigationTests (ITestOutputHelper output)
// Assert.False (tfQuiting);
// Assert.False (topQuiting);
-// Application.Driver.SendKeys ('Q', ConsoleKey.Q, false, false, true);
+// Application.Driver?.SendKeys ('Q', ConsoleKey.Q, false, false, true);
// Assert.False (sbQuiting);
// Assert.True (tfQuiting);
// Assert.False (topQuiting);
@@ -677,7 +677,7 @@ public class NavigationTests (ITestOutputHelper output)
//#if BROKE_WITH_2927
// tf.KeyPressed -= Tf_KeyPress;
// tfQuiting = false;
-// Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+// Application.Driver?.SendKeys ('q', ConsoleKey.Q, false, false, true);
// Application.MainLoop.RunIteration ();
// Assert.True (sbQuiting);
// Assert.False (tfQuiting);
@@ -685,7 +685,7 @@ public class NavigationTests (ITestOutputHelper output)
// sb.RemoveItem (0);
// sbQuiting = false;
-// Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+// Application.Driver?.SendKeys ('q', ConsoleKey.Q, false, false, true);
// Application.MainLoop.RunIteration ();
// Assert.False (sbQuiting);
// Assert.False (tfQuiting);
@@ -733,13 +733,13 @@ public class NavigationTests (ITestOutputHelper output)
// Assert.False (sbQuiting);
// Assert.False (tfQuiting);
-// Application.Driver.SendKeys ('Q', ConsoleKey.Q, false, false, true);
+// 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.Driver?.SendKeys ('Q', ConsoleKey.Q, false, false, true);
// Application.MainLoop.RunIteration ();
//#if BROKE_WITH_2927
// Assert.True (sbQuiting);
@@ -834,7 +834,7 @@ public class NavigationTests (ITestOutputHelper output)
Assert.Equal (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
Assert.Equal (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
Assert.Equal (new Rectangle (0, 0, 20, 10), top.Frame);
@@ -984,7 +984,7 @@ public class NavigationTests (ITestOutputHelper output)
Assert.NotEqual (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
Assert.Equal (new Rectangle (3, 2, 20, 10), top.Frame);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 20);
Assert.Equal (new Rectangle (0, 0, 30, 20), new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows));
Assert.NotEqual (new Rectangle (0, 0, View.Driver.Cols, View.Driver.Rows), top.Frame);
Assert.Equal (new Rectangle (3, 2, 20, 10), top.Frame);
diff --git a/UnitTests/View/TextTests.cs b/UnitTests/View/TextTests.cs
index 3bd6cfb23..f0cb43091 100644
--- a/UnitTests/View/TextTests.cs
+++ b/UnitTests/View/TextTests.cs
@@ -148,7 +148,7 @@ Y
top.Add (win);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (15, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
Assert.Equal (new (0, 0, 15, 15), win.Frame);
Assert.Equal (new (0, 0, 15, 15), win.Margin.Frame);
@@ -416,7 +416,7 @@ Y
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (4, 10);
Assert.Equal (5, text.Length);
@@ -489,7 +489,7 @@ Y
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (4, 10);
Assert.Equal (5, text.Length);
Assert.Equal (new (0, 0, 2, 5), view.Frame);
@@ -584,7 +584,7 @@ Y
var top = new Toplevel ();
top.Add (win);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 20);
Assert.Equal (new (0, 0, 11, 2), horizontalView.Frame);
Assert.Equal (new (0, 3, 2, 11), verticalView.Frame);
@@ -672,7 +672,7 @@ Y
var top = new Toplevel ();
top.Add (win);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (22, 22);
+ ((FakeDriver)Application.Driver!).SetBufferSize (22, 22);
Assert.Equal (new (text.GetColumns (), 1), horizontalView.TextFormatter.Size);
Assert.Equal (new (2, 8), verticalView.TextFormatter.Size);
@@ -769,7 +769,7 @@ Y
for (var i = 0; i < 4; i++)
{
- text += Application.Driver.Contents [0, i].Rune;
+ text += Application.Driver?.Contents [0, i].Rune;
}
return text;
@@ -804,7 +804,7 @@ Y
var top = new Toplevel ();
top.Add (horizontalView, verticalView);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (50, 50);
+ ((FakeDriver)Application.Driver!).SetBufferSize (50, 50);
Assert.Equal (new (0, 0, 12, 1), horizontalView.Frame);
Assert.Equal (new (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
@@ -900,7 +900,7 @@ Y
var top = new Toplevel ();
top.Add (frame);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width + 2, 6);
if (autoSize)
{
@@ -1028,7 +1028,7 @@ Y
var top = new Toplevel ();
top.Add (frame);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (9, height + 2);
+ ((FakeDriver)Application.Driver!).SetBufferSize (9, height + 2);
if (autoSize)
{
@@ -1272,7 +1272,7 @@ Y
[SetupFakeDriver]
public void Narrow_Wide_Runes ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (32, 32);
+ ((FakeDriver)Application.Driver!).SetBufferSize (32, 32);
var top = new View { Width = 32, Height = 32 };
var text = $"First line{Environment.NewLine}Second line";
diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs
index 4044507f1..d545cdc1d 100644
--- a/UnitTests/View/ViewTests.cs
+++ b/UnitTests/View/ViewTests.cs
@@ -14,26 +14,26 @@ public class ViewTests (ITestOutputHelper output)
view.DrawContent += (s, e) =>
{
- Rectangle savedClip = Application.Driver.Clip;
- Application.Driver.Clip = new (1, 1, view.Viewport.Width, view.Viewport.Height);
+ Rectangle savedClip = Application.Driver!.Clip;
+ Application.Driver!.Clip = new (1, 1, view.Viewport.Width, view.Viewport.Height);
for (var row = 0; row < view.Viewport.Height; row++)
{
- Application.Driver.Move (1, row + 1);
+ Application.Driver?.Move (1, row + 1);
for (var col = 0; col < view.Viewport.Width; col++)
{
- Application.Driver.AddStr ($"{col}");
+ Application.Driver?.AddStr ($"{col}");
}
}
- Application.Driver.Clip = savedClip;
+ Application.Driver!.Clip = savedClip;
e.Cancel = true;
};
var top = new Toplevel ();
top.Add (view);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var expected = @"
┌──────────────────┐
@@ -78,26 +78,26 @@ public class ViewTests (ITestOutputHelper output)
view.DrawContent += (s, e) =>
{
- Rectangle savedClip = Application.Driver.Clip;
- Application.Driver.Clip = new (1, 1, view.Viewport.Width, view.Viewport.Height);
+ Rectangle savedClip = Application.Driver!.Clip;
+ Application.Driver!.Clip = new (1, 1, view.Viewport.Width, view.Viewport.Height);
for (var row = 0; row < view.Viewport.Height; row++)
{
- Application.Driver.Move (1, row + 1);
+ Application.Driver?.Move (1, row + 1);
for (var col = 0; col < view.Viewport.Width; col++)
{
- Application.Driver.AddStr ($"{col}");
+ Application.Driver?.AddStr ($"{col}");
}
}
- Application.Driver.Clip = savedClip;
+ Application.Driver!.Clip = savedClip;
e.Cancel = true;
};
var top = new Toplevel ();
top.Add (view);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
var expected = @"
┌──────────────────┐
@@ -1016,7 +1016,7 @@ At 0,0
view.Height = Dim.Auto ();
Assert.Equal ("Testing visibility.".Length, view.Frame.Width);
Assert.True (view.Visible);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1107,9 +1107,9 @@ At 0,0
Cell [,] contents = ((FakeDriver)Application.Driver).Contents;
var runesCount = 0;
- for (var i = 0; i < Application.Driver.Rows; i++)
+ for (var i = 0; i < Application.Driver!.Rows; i++)
{
- for (var j = 0; j < Application.Driver.Cols; j++)
+ for (var j = 0; j < Application.Driver!.Cols; j++)
{
if (contents [i, j].Rune != (Rune)' ')
{
diff --git a/UnitTests/Views/AppendAutocompleteTests.cs b/UnitTests/Views/AppendAutocompleteTests.cs
index fab9ca750..eaabc43a6 100644
--- a/UnitTests/Views/AppendAutocompleteTests.cs
+++ b/UnitTests/Views/AppendAutocompleteTests.cs
@@ -11,14 +11,14 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting ("fish");
// f is typed and suggestion is "fish"
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
// When cancelling autocomplete
- Application.Driver.SendKeys ('e', ConsoleKey.Escape, false, false, false);
+ Application.Driver?.SendKeys ('e', ConsoleKey.Escape, false, false, false);
// Suggestion should disappear
tf.Draw ();
@@ -29,7 +29,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
Assert.Same (tf, Application.Top.Focused);
// But can tab away
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
Assert.NotSame (tf, Application.Top.Focused);
Application.Top.Dispose ();
}
@@ -41,14 +41,14 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting ("fish");
// f is typed and suggestion is "fish"
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
// When cancelling autocomplete
- Application.Driver.SendKeys ('\0', ConsoleKey.Escape, false, false, false);
+ Application.Driver?.SendKeys ('\0', ConsoleKey.Escape, false, false, false);
// Suggestion should disappear
tf.Draw ();
@@ -56,7 +56,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
Assert.Equal ("f", tf.Text);
// Should reappear when you press next letter
- Application.Driver.SendKeys ('i', ConsoleKey.I, false, false, false);
+ Application.Driver?.SendKeys ('i', ConsoleKey.I, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -73,14 +73,14 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting ("fish", "friend");
// f is typed and suggestion is "fish"
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
// When cycling autocomplete
- Application.Driver.SendKeys (' ', cycleKey, false, false, false);
+ Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
tf.Draw ();
tf.PositionCursor ();
@@ -88,7 +88,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
Assert.Equal ("f", tf.Text);
// Should be able to cycle in circles endlessly
- Application.Driver.SendKeys (' ', cycleKey, false, false, false);
+ Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -103,15 +103,15 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting ("fish");
// f is typed and suggestion is "fish"
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
// add a space then go back 1
- Application.Driver.SendKeys (' ', ConsoleKey.Spacebar, false, false, false);
- Application.Driver.SendKeys ('<', ConsoleKey.LeftArrow, false, false, false);
+ Application.Driver?.SendKeys (' ', ConsoleKey.Spacebar, false, false, false);
+ Application.Driver?.SendKeys ('<', ConsoleKey.LeftArrow, false, false, false);
tf.Draw ();
TestHelpers.AssertDriverContentsAre ("f", output);
@@ -126,14 +126,14 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting ("fish");
// f is typed and suggestion is "fish"
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
// x is typed and suggestion should disappear
- Application.Driver.SendKeys ('x', ConsoleKey.X, false, false, false);
+ Application.Driver?.SendKeys ('x', ConsoleKey.X, false, false, false);
tf.Draw ();
TestHelpers.AssertDriverContentsAre ("fx", output);
Assert.Equal ("fx", tf.Text);
@@ -166,7 +166,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
Assert.Equal ("my f", tf.Text);
// When tab completing the case of the whole suggestion should be applied
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
tf.Draw ();
TestHelpers.AssertDriverContentsAre ("my FISH", output);
Assert.Equal ("my FISH", tf.Text);
@@ -194,7 +194,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TestHelpers.AssertDriverContentsAre ("fish", output);
Assert.Equal ("f", tf.Text);
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
tf.Draw ();
TestHelpers.AssertDriverContentsAre ("fish", output);
@@ -204,7 +204,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
Assert.Same (tf, Application.Top.Focused);
// Second tab should move focus (nothing to autocomplete)
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
Assert.NotSame (tf, Application.Top.Focused);
Application.Top.Dispose ();
}
@@ -219,7 +219,7 @@ public class AppendAutocompleteTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInViewSuggesting (overspillUsing);
// f is typed we should only see 'f' up to size of View (10)
- Application.Driver.SendKeys ('f', ConsoleKey.F, false, false, false);
+ Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
tf.Draw ();
tf.PositionCursor ();
TestHelpers.AssertDriverContentsAre (expectRender, output);
diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs
index 4ef86d387..d5bc04e07 100644
--- a/UnitTests/Views/ButtonTests.cs
+++ b/UnitTests/Views/ButtonTests.cs
@@ -224,7 +224,7 @@ public class ButtonTests (ITestOutputHelper output)
Assert.Equal ('_', btn.HotKeySpecifier.Value);
Assert.True (btn.CanFocus);
- Application.Driver.ClearContents ();
+ Application.Driver?.ClearContents ();
btn.Draw ();
expected = @$"
@@ -563,7 +563,7 @@ public class ButtonTests (ITestOutputHelper output)
Assert.False (btn.IsInitialized);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.True (btn.IsInitialized);
Assert.Equal ("Say Hello 你", btn.Text);
@@ -597,7 +597,7 @@ public class ButtonTests (ITestOutputHelper output)
Assert.False (btn.IsInitialized);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.True (btn.IsInitialized);
Assert.Equal ("Say Hello 你", btn.Text);
diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs
index c7739272d..da41ec55a 100644
--- a/UnitTests/Views/CheckBoxTests.cs
+++ b/UnitTests/Views/CheckBoxTests.cs
@@ -254,7 +254,7 @@ public class CheckBoxTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.Equal (Alignment.Center, checkBox.TextAlignment);
Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
@@ -314,7 +314,7 @@ public class CheckBoxTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 6);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 6);
Assert.Equal (Alignment.Fill, checkBox1.TextAlignment);
Assert.Equal (new (1, 1, 25, 1), checkBox1.Frame);
@@ -372,7 +372,7 @@ public class CheckBoxTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.Equal (Alignment.Start, checkBox.TextAlignment);
Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
@@ -423,7 +423,7 @@ public class CheckBoxTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.Equal (Alignment.End, checkBox.TextAlignment);
Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
diff --git a/UnitTests/Views/ContextMenuTests.cs b/UnitTests/Views/ContextMenuTests.cs
index 6d42add38..efeb709fb 100644
--- a/UnitTests/Views/ContextMenuTests.cs
+++ b/UnitTests/Views/ContextMenuTests.cs
@@ -117,9 +117,9 @@ public class ContextMenuTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_A_ContextMenu_Over_A_Borderless_Top ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
- Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver.Clip);
+ Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip);
TestHelpers.AssertDriverContentsWithFrameAre ("", output);
var top = new Toplevel { X = 2, Y = 2, Width = 15, Height = 4 };
@@ -167,7 +167,7 @@ public class ContextMenuTests (ITestOutputHelper output)
var win = new Window ();
top.Add (win);
RunState rsTop = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
Assert.Equal (new Rectangle (0, 0, 20, 15), win.Frame);
@@ -252,9 +252,9 @@ public class ContextMenuTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_A_ContextMenu_Over_A_Top_Dialog ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
- Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver.Clip);
+ Assert.Equal (new Rectangle (0, 0, 20, 15), Application.Driver?.Clip);
TestHelpers.AssertDriverContentsWithFrameAre ("", output);
// Don't use Dialog here as it has more layout logic. Use Window instead.
@@ -542,7 +542,7 @@ public class ContextMenuTests (ITestOutputHelper output)
output
);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
cm.Position = new Point (41, -2);
cm.Show ();
Application.Refresh ();
@@ -677,7 +677,7 @@ public class ContextMenuTests (ITestOutputHelper output)
output
);
- ((FakeDriver)Application.Driver).SetBufferSize (18, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
cm.Position = new Point (19, 10);
cm.Show ();
Application.Refresh ();
@@ -891,7 +891,7 @@ public class ContextMenuTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Show_Display_At_Zero_If_The_Toplevel_Height_Is_Less_Than_The_Menu_Height ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (80, 3);
+ ((FakeDriver)Application.Driver!).SetBufferSize (80, 3);
var cm = new ContextMenu
{
@@ -929,7 +929,7 @@ public class ContextMenuTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Show_Display_At_Zero_If_The_Toplevel_Width_Is_Less_Than_The_Menu_Width ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (5, 25);
+ ((FakeDriver)Application.Driver!).SetBufferSize (5, 25);
var cm = new ContextMenu
{
diff --git a/UnitTests/Views/FrameViewTests.cs b/UnitTests/Views/FrameViewTests.cs
index 056b45747..88a5c786c 100644
--- a/UnitTests/Views/FrameViewTests.cs
+++ b/UnitTests/Views/FrameViewTests.cs
@@ -37,7 +37,7 @@ public class FrameViewTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_Defaults ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
var fv = new FrameView ();
Assert.Equal (string.Empty, fv.Title);
Assert.Equal (string.Empty, fv.Text);
diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs
index 24a19c77d..78ed678a8 100644
--- a/UnitTests/Views/LabelTests.cs
+++ b/UnitTests/Views/LabelTests.cs
@@ -97,7 +97,7 @@ public class LabelTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
var expected = @"
┌────────────────────────────┐
@@ -137,7 +137,7 @@ public class LabelTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
var expected = @"
┌────────────────────────────┐
@@ -179,7 +179,7 @@ public class LabelTests (ITestOutputHelper output)
label.Text = "Say Hello 你";
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
var expected = @"
┌────────────────────────────┐
@@ -414,7 +414,7 @@ e
Assert.False (label.IsInitialized);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.True (label.IsInitialized);
Assert.Equal ("Say Hello 你", label.Text);
@@ -446,7 +446,7 @@ e
Assert.False (label.IsInitialized);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.True (label.IsInitialized);
Assert.Equal ("Say Hello 你", label.Text);
@@ -473,7 +473,7 @@ e
var label = new Label { BorderStyle = LineStyle.Single, Text = "Test" };
label.BeginInit ();
label.EndInit ();
- label.SetRelativeLayout (Application.Driver.Screen.Size);
+ label.SetRelativeLayout (Application.Driver!.Screen.Size);
Assert.Equal (new (0, 0, 4, 1), label.Viewport);
Assert.Equal (new (0, 0, 6, 3), label.Frame);
@@ -881,7 +881,7 @@ e
Toplevel top = new ();
top.Add (win);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
Assert.Equal (29, label.Text.Length);
Assert.Equal (new (0, 0, 40, 10), top.Frame);
@@ -931,7 +931,7 @@ e
Toplevel top = new ();
top.Add (win);
RunState rs = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
Assert.Equal (new (0, 0, 40, 10), top.Frame);
Assert.Equal (new (0, 0, 40, 10), win.Frame);
@@ -1071,7 +1071,7 @@ e
{
if (k.KeyCode == KeyCode.Enter)
{
- ((FakeDriver)Application.Driver).SetBufferSize (22, count + 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (22, count + 4);
Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expecteds [count], output);
Assert.Equal (new (0, 0, 22, count + 4), pos);
@@ -1135,7 +1135,7 @@ e
[SetupFakeDriver]
public void Label_Height_Zero_Stays_Zero ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
var text = "Label";
var label = new Label
@@ -1223,7 +1223,7 @@ e
{
if (k.KeyCode == KeyCode.Enter)
{
- ((FakeDriver)Application.Driver).SetBufferSize (22, count + 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (22, count + 4);
Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expecteds [count], output);
Assert.Equal (new (0, 0, 22, count + 4), pos);
@@ -1299,7 +1299,7 @@ e
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
Assert.Equal (5, text.Length);
Assert.Equal (new (0, 0, 5, 1), label.Frame);
@@ -1358,7 +1358,7 @@ e
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
Assert.Equal (5, text.Length);
Assert.Equal (new (0, 0, 5, 1), label.Frame);
diff --git a/UnitTests/Views/ListViewTests.cs b/UnitTests/Views/ListViewTests.cs
index 2682fb677..049c5f7e1 100644
--- a/UnitTests/Views/ListViewTests.cs
+++ b/UnitTests/Views/ListViewTests.cs
@@ -55,7 +55,7 @@ public class ListViewTests (ITestOutputHelper output)
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (12, 12);
+ ((FakeDriver)Application.Driver!).SetBufferSize (12, 12);
Application.Refresh ();
Assert.Equal (-1, lv.SelectedItem);
@@ -357,7 +357,7 @@ Item 6",
for (var i = 0; i < 7; i++)
{
- item += Application.Driver.Contents [line, i].Rune;
+ item += Application.Driver?.Contents [line, i].Rune;
}
return item;
diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs
index f7804dd42..35d08beff 100644
--- a/UnitTests/Views/MenuBarTests.cs
+++ b/UnitTests/Views/MenuBarTests.cs
@@ -366,7 +366,7 @@ public class MenuBarTests (ITestOutputHelper output)
var win = new Window ();
top.Add (win);
RunState rsTop = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 15);
Assert.Equal (new (0, 0, 40, 15), win.Frame);
@@ -556,7 +556,7 @@ public class MenuBarTests (ITestOutputHelper output)
Assert.Equal (items [i], menu.Menus [0].Title);
}
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
menu.OpenMenu ();
firstIteration = false;
Application.RunIteration (ref rsDialog, ref firstIteration);
@@ -590,9 +590,9 @@ public class MenuBarTests (ITestOutputHelper output)
[AutoInitShutdown]
public void Draw_A_Menu_Over_A_Top_Dialog ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (40, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 15);
- Assert.Equal (new (0, 0, 40, 15), Application.Driver.Clip);
+ Assert.Equal (new (0, 0, 40, 15), Application.Driver?.Clip);
TestHelpers.AssertDriverContentsWithFrameAre (@"", output);
List items = new ()
@@ -734,7 +734,7 @@ public class MenuBarTests (ITestOutputHelper output)
Assert.Equal (items [i], menu.Menus [0].Title);
}
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
menu.OpenMenu ();
firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
@@ -805,7 +805,7 @@ public class MenuBarTests (ITestOutputHelper output)
menu.CloseAllMenus ();
menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
- ((FakeDriver)Application.Driver).SetBufferSize (7, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (7, 5);
menu.OpenMenu ();
Application.Refresh ();
@@ -821,7 +821,7 @@ public class MenuBarTests (ITestOutputHelper output)
menu.CloseAllMenus ();
menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
- ((FakeDriver)Application.Driver).SetBufferSize (7, 3);
+ ((FakeDriver)Application.Driver!).SetBufferSize (7, 3);
menu.OpenMenu ();
Application.Refresh ();
@@ -878,7 +878,7 @@ wo
menu.CloseAllMenus ();
menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
- ((FakeDriver)Application.Driver).SetBufferSize (3, 2);
+ ((FakeDriver)Application.Driver!).SetBufferSize (3, 2);
menu.OpenMenu ();
Application.Refresh ();
@@ -891,7 +891,7 @@ wo
menu.CloseAllMenus ();
menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
- ((FakeDriver)Application.Driver).SetBufferSize (3, 1);
+ ((FakeDriver)Application.Driver!).SetBufferSize (3, 1);
menu.OpenMenu ();
Application.Refresh ();
@@ -1519,7 +1519,7 @@ wo
Toplevel top = new ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1630,7 +1630,7 @@ wo
Application.Iteration += (s, a) =>
{
- ((FakeDriver)Application.Driver).SetBufferSize (40, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1741,7 +1741,7 @@ wo
]
};
win.Add (menu);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
Application.Begin (win);
TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1827,7 +1827,7 @@ wo
[AutoInitShutdown]
public void MenuBar_In_Window_Without_Other_Views_Without_Top_Init_With_Run_T ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (40, 8);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
Application.Iteration += (s, a) =>
{
@@ -2758,7 +2758,7 @@ Edit
output
);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs
index 9c7202d68..5ca0fc566 100644
--- a/UnitTests/Views/OverlappedTests.cs
+++ b/UnitTests/Views/OverlappedTests.cs
@@ -881,7 +881,7 @@ public class OverlappedTests
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);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
RunState rsOverlapped = Application.Begin (overlapped);
// Need to fool MainLoop into thinking it's running
diff --git a/UnitTests/Views/RadioGroupTests.cs b/UnitTests/Views/RadioGroupTests.cs
index 75aab7b18..4c828f2c1 100644
--- a/UnitTests/Views/RadioGroupTests.cs
+++ b/UnitTests/Views/RadioGroupTests.cs
@@ -219,7 +219,7 @@ public class RadioGroupTests (ITestOutputHelper output)
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
Assert.Equal (Orientation.Vertical, rg.Orientation);
Assert.Equal (2, rg.RadioLabels.Length);
diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs
index f3f9f7c24..15c463d78 100644
--- a/UnitTests/Views/ScrollBarViewTests.cs
+++ b/UnitTests/Views/ScrollBarViewTests.cs
@@ -173,7 +173,7 @@ public class ScrollBarViewTests
super.Add (vert);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (width, height);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, height);
var expected = @"
┌─┐
@@ -703,7 +703,7 @@ This is a test
var sbv = new ScrollBarView { Id = "sbv", Size = width * 2, ShowScrollIndicator = true };
super.Add (sbv);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (width, height);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, height);
var expected = @"
┌──────────────────────────────────────┐
@@ -829,7 +829,7 @@ This is a test
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (45, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (45, 20);
Assert.True (scrollBar.AutoHideScrollBars);
Assert.False (scrollBar.ShowScrollIndicator);
@@ -867,7 +867,7 @@ This is a test
Assert.Equal (new Rectangle (0, 0, 45, 20), pos);
textView.WordWrap = true;
- ((FakeDriver)Application.Driver).SetBufferSize (26, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (26, 20);
Application.Refresh ();
Assert.True (textView.WordWrap);
@@ -904,7 +904,7 @@ This is a test
pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
Assert.Equal (new Rectangle (0, 0, 26, 20), pos);
- ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
Application.Refresh ();
Assert.True (textView.WordWrap);
@@ -1229,7 +1229,7 @@ This is a test ",
super.Add (sbv);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (width, height);
+ ((FakeDriver)Application.Driver!).SetBufferSize (width, height);
var expected = @"
┌─┐
diff --git a/UnitTests/Views/ScrollViewTests.cs b/UnitTests/Views/ScrollViewTests.cs
index ceab4e63a..c4d14c235 100644
--- a/UnitTests/Views/ScrollViewTests.cs
+++ b/UnitTests/Views/ScrollViewTests.cs
@@ -362,7 +362,7 @@ public class ScrollViewTests (ITestOutputHelper output)
[SetupFakeDriver]
public void ContentBottomRightCorner_Draw ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (30, 30);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 30);
var top = new View { Width = 30, Height = 30, ColorScheme = new() { Normal = Attribute.Default } };
diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs
index 515e3f8bd..6740120f6 100644
--- a/UnitTests/Views/TableViewTests.cs
+++ b/UnitTests/Views/TableViewTests.cs
@@ -2196,7 +2196,7 @@ public class TableViewTests (ITestOutputHelper output)
[SetupFakeDriver]
public void TestEnumerableDataSource_BasicTypes ()
{
- ((FakeDriver)Application.Driver).SetBufferSize(100,100);
+ ((FakeDriver)Application.Driver!).SetBufferSize(100,100);
var tv = new TableView ();
tv.ColorScheme = Colors.ColorSchemes ["TopLevel"];
tv.Viewport = new (0, 0, 50, 6);
diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs
index e50617933..ed3a35775 100644
--- a/UnitTests/Views/TextFieldTests.cs
+++ b/UnitTests/Views/TextFieldTests.cs
@@ -67,7 +67,7 @@ public class TextFieldTests (ITestOutputHelper output)
for (var i = 0; i < 16; i++)
{
- item += Application.Driver.Contents [0, i].Rune;
+ item += Application.Driver?.Contents [0, i].Rune;
}
return item;
@@ -164,7 +164,7 @@ public class TextFieldTests (ITestOutputHelper output)
// Caption has no effect when focused
tf.Caption = caption;
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
Assert.False (tf.HasFocus);
tf.Draw ();
@@ -184,7 +184,7 @@ public class TextFieldTests (ITestOutputHelper output)
TextField tf = GetTextFieldsInView ();
tf.Caption = caption;
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
Assert.False (tf.HasFocus);
tf.Draw ();
@@ -205,7 +205,7 @@ public class TextFieldTests (ITestOutputHelper output)
TestHelpers.AssertDriverContentsAre ("", output);
tf.Caption = "Enter txt";
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
// Caption should appear when not focused and no text
Assert.False (tf.HasFocus);
@@ -234,7 +234,7 @@ public class TextFieldTests (ITestOutputHelper output)
tf.Draw ();
TestHelpers.AssertDriverContentsAre ("", output);
- Application.Driver.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
+ Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
Assert.False (tf.HasFocus);
tf.Draw ();
@@ -347,7 +347,7 @@ public class TextFieldTests (ITestOutputHelper output)
Assert.Equal (
"TextField with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!",
- Application.Driver.Clipboard.GetClipboardData ()
+ Application.Driver?.Clipboard.GetClipboardData ()
);
Assert.Equal (string.Empty, _textField.Text);
_textField.Paste ();
@@ -374,7 +374,7 @@ public class TextFieldTests (ITestOutputHelper output)
Assert.Equal (32, _textField.CursorPosition);
_textField.SelectAll ();
_textField.Cut ();
- Assert.Equal ("TAB to jump between text fields.", Application.Driver.Clipboard.GetClipboardData ());
+ Assert.Equal ("TAB to jump between text fields.", Application.Driver?.Clipboard.GetClipboardData ());
Assert.Equal (string.Empty, _textField.Text);
Assert.Equal (0, _textField.CursorPosition);
_textField.Paste ();
diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs
index f260dd162..f9ff520dd 100644
--- a/UnitTests/Views/TextViewTests.cs
+++ b/UnitTests/Views/TextViewTests.cs
@@ -609,7 +609,7 @@ public class TextViewTests
Assert.Equal (
"TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!",
- Application.Driver.Clipboard.GetClipboardData ()
+ Application.Driver?.Clipboard.GetClipboardData ()
);
Assert.Equal (string.Empty, _textView.Text);
_textView.Paste ();
@@ -1018,7 +1018,7 @@ This is the second line.
tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledRight });
Assert.Equal (Math.Min (i + 1, 11), tv.LeftColumn);
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility);
Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
}
@@ -1028,7 +1028,7 @@ This is the second line.
Assert.Equal (i - 1, tv.LeftColumn);
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility);
if (i - 1 == 0)
{
@@ -1070,7 +1070,7 @@ This is the second line.
tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledDown });
Application.PositionCursor (top);
Assert.Equal (i + 1, tv.TopRow);
- Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility);
Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
}
@@ -1081,7 +1081,7 @@ This is the second line.
Assert.Equal (i - 1, tv.TopRow);
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility cursorVisibility);
if (i - 1 == 0)
{
@@ -6697,7 +6697,7 @@ TAB to jump between text field",
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (15, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
Application.Refresh ();
//this passes
@@ -6774,7 +6774,7 @@ TAB to jump between text field",
var top = new Toplevel ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (15, 15);
+ ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
Application.Refresh ();
//this passes
@@ -6899,8 +6899,8 @@ This is the second line.
_output
);
- ((FakeDriver)Application.Driver).SetBufferSize (6, 25);
- tv.SetRelativeLayout (Application.Driver.Screen.Size);
+ ((FakeDriver)Application.Driver!).SetBufferSize (6, 25);
+ tv.SetRelativeLayout (Application.Driver!.Screen.Size);
tv.Draw ();
Assert.Equal (new Point (4, 2), tv.CursorPosition);
Assert.Equal (new Point (12, 0), cp);
diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs
index abbfdeb59..c19c72bb1 100644
--- a/UnitTests/Views/ToplevelTests.cs
+++ b/UnitTests/Views/ToplevelTests.cs
@@ -44,8 +44,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
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);
+ 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));
@@ -54,8 +54,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
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);
+ 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));
@@ -64,8 +64,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
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);
+ 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));
@@ -74,8 +74,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
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);
+ 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));
@@ -84,8 +84,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
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);
+ 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));
@@ -675,7 +675,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
if (iterations == 0)
{
- ((FakeDriver)Application.Driver).SetBufferSize (15, 7);
+ ((FakeDriver)Application.Driver!).SetBufferSize (15, 7);
// Don't use MessageBox here; it's too complicated for this unit test; just use Window
testWindow = new ()
@@ -794,7 +794,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
if (iterations == 0)
{
- ((FakeDriver)Application.Driver).SetBufferSize (30, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (30, 10);
}
else if (iterations == 1)
{
@@ -896,10 +896,10 @@ public partial class ToplevelTests (ITestOutputHelper output)
top.BeginInit ();
top.EndInit ();
- Exception exception = Record.Exception (() => ((FakeDriver)Application.Driver).SetBufferSize (0, 10));
+ Exception exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (0, 10));
Assert.Null (exception);
- exception = Record.Exception (() => ((FakeDriver)Application.Driver).SetBufferSize (10, 0));
+ exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (10, 0));
Assert.Null (exception);
}
@@ -1085,13 +1085,13 @@ public partial class ToplevelTests (ITestOutputHelper output)
Assert.True (tf.HasFocus);
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out CursorVisibility cursor);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility cursor);
Assert.Equal (CursorVisibility.Default, cursor);
view.Enabled = false;
Assert.False (tf.HasFocus);
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out cursor);
+ Application.Driver!.GetCursorVisibility (out cursor);
Assert.Equal (CursorVisibility.Invisible, cursor);
top.Dispose ();
}
@@ -1209,7 +1209,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
Toplevel top = new ();
var window = new Window { Width = 20, Height = 3, Arrangement = ViewArrangement.Movable };
RunState rsTop = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
RunState rsWindow = Application.Begin (window);
Application.Refresh ();
Assert.Equal (new (0, 0, 40, 10), top.Frame);
@@ -1232,7 +1232,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
Assert.Equal (new (0, 0, 20, 3), window.Frame);
// Changes Top size to same size as Dialog more menu and scroll bar
- ((FakeDriver)Application.Driver).SetBufferSize (20, 3);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 3);
Application.OnMouseEvent (
new ()
@@ -1245,7 +1245,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
Assert.Equal (new (0, 0, 20, 3), window.Frame);
// Changes Top size smaller than Dialog size
- ((FakeDriver)Application.Driver).SetBufferSize (19, 2);
+ ((FakeDriver)Application.Driver!).SetBufferSize (19, 2);
Application.OnMouseEvent (
new ()
@@ -1338,7 +1338,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
{
Toplevel top = new ();
RunState rsTop = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 20);
var testWindow = new Window { X = 2, Y = 1, Width = 15, Height = 10 };
Assert.Equal (new (2, 1, 15, 10), testWindow.Frame);
@@ -1360,7 +1360,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
var win = new Window ();
top.Add (win);
RunState rsTop = Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 20);
Assert.Equal (new (0, 0, 20, 20), win.Frame);
@@ -1389,8 +1389,8 @@ public partial class ToplevelTests (ITestOutputHelper output)
{
Assert.Equal (new (1, 3, 18, 16), viewAddedToTop.Frame);
- Rectangle savedClip = Application.Driver.Clip;
- Application.Driver.Clip = top.Frame;
+ Rectangle savedClip = Application.Driver!.Clip;
+ Application.Driver!.Clip = top.Frame;
viewAddedToTop.Draw ();
top.Move (2, 15);
View.Driver.AddStr ("One");
@@ -1398,7 +1398,7 @@ public partial class ToplevelTests (ITestOutputHelper output)
View.Driver.AddStr ("Two");
top.Move (2, 17);
View.Driver.AddStr ("Three");
- Application.Driver.Clip = savedClip;
+ Application.Driver!.Clip = savedClip;
Application.Current.DrawContentComplete -= OnDrawContentComplete;
}
diff --git a/UnitTests/Views/TreeTableSourceTests.cs b/UnitTests/Views/TreeTableSourceTests.cs
index 0b54be84d..39e18327b 100644
--- a/UnitTests/Views/TreeTableSourceTests.cs
+++ b/UnitTests/Views/TreeTableSourceTests.cs
@@ -29,7 +29,7 @@ public class TreeTableSourceTests : IDisposable
[SetupFakeDriver]
public void TestTreeTableSource_BasicExpanding_WithKeyboard ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
TableView tv = GetTreeTable (out _);
tv.Style.GetOrCreateColumnStyle (1).MinAcceptableWidth = 1;
@@ -88,7 +88,7 @@ public class TreeTableSourceTests : IDisposable
[SetupFakeDriver]
public void TestTreeTableSource_BasicExpanding_WithMouse ()
{
- ((FakeDriver)Application.Driver).SetBufferSize (100, 100);
+ ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
TableView tv = GetTreeTable (out _);
diff --git a/UnitTests/Views/TreeViewTests.cs b/UnitTests/Views/TreeViewTests.cs
index 11d85acdb..a770d1d9d 100644
--- a/UnitTests/Views/TreeViewTests.cs
+++ b/UnitTests/Views/TreeViewTests.cs
@@ -114,7 +114,7 @@ public class TreeViewTests
tv.SelectAll ();
tv.CursorVisibility = CursorVisibility.Default;
Application.PositionCursor (top);
- Application.Driver.GetCursorVisibility (out CursorVisibility visibility);
+ Application.Driver!.GetCursorVisibility (out CursorVisibility visibility);
Assert.Equal (CursorVisibility.Default, tv.CursorVisibility);
Assert.Equal (CursorVisibility.Default, visibility);
top.Dispose ();
diff --git a/UnitTests/Views/WindowTests.cs b/UnitTests/Views/WindowTests.cs
index 24ea77876..6df5361e3 100644
--- a/UnitTests/Views/WindowTests.cs
+++ b/UnitTests/Views/WindowTests.cs
@@ -53,7 +53,7 @@ public class WindowTests
Toplevel top = new ();
top.Add (win);
Application.Begin (top);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -70,7 +70,7 @@ public class WindowTests
_output
);
- ((FakeDriver)Application.Driver).SetBufferSize (40, 20);
+ ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -97,7 +97,7 @@ public class WindowTests
_output
);
- ((FakeDriver)Application.Driver).SetBufferSize (20, 10);
+ ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
TestHelpers.AssertDriverContentsWithFrameAre (
@"