|
@@ -1,5 +1,5 @@
|
|
|
//
|
|
|
-// Core.cs: The core engine for gui.cs
|
|
|
+// Core.cs: The core engine for Terminal.Gui (Application, Responder, & View)
|
|
|
//
|
|
|
// Authors:
|
|
|
// Miguel de Icaza ([email protected])
|
|
@@ -21,7 +21,6 @@ using NStack;
|
|
|
using System.ComponentModel;
|
|
|
|
|
|
namespace Terminal.Gui {
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// Responder base class implemented by objects that want to participate on keyboard and mouse input.
|
|
|
/// </summary>
|
|
@@ -1482,529 +1481,6 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Toplevel views can be modally executed.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// <para>
|
|
|
- /// Toplevels can be modally executing views, and they return control
|
|
|
- /// to the caller when the "Running" property is set to false, or
|
|
|
- /// by calling <see cref="M:Terminal.Gui.Application.RequestStop()"/>
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// There will be a toplevel created for you on the first time use
|
|
|
- /// and can be accessed from the property <see cref="P:Terminal.Gui.Application.Top"/>,
|
|
|
- /// but new toplevels can be created and ran on top of it. To run, create the
|
|
|
- /// toplevel and then invoke <see cref="M:Terminal.Gui.Application.Run"/> with the
|
|
|
- /// new toplevel.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// TopLevels can also opt-in to more sophisticated initialization
|
|
|
- /// by implementing <see cref="ISupportInitialize"/>. When they do
|
|
|
- /// so, the <see cref="ISupportInitialize.BeginInit"/> and
|
|
|
- /// <see cref="ISupportInitialize.EndInit"/> methods will be called
|
|
|
- /// before running the view.
|
|
|
- /// If first-run-only initialization is preferred, the <see cref="ISupportInitializeNotification"/>
|
|
|
- /// can be implemented too, in which case the <see cref="ISupportInitialize"/>
|
|
|
- /// methods will only be called if <see cref="ISupportInitializeNotification.IsInitialized"/>
|
|
|
- /// is <see langword="false"/>. This allows proper View inheritance hierarchies
|
|
|
- /// to override base class layout code optimally by doing so only on first run,
|
|
|
- /// instead of on every run.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public class Toplevel : View {
|
|
|
- /// <summary>
|
|
|
- /// Gets or sets whether the Mainloop for this <see cref="Toplevel"/> is running or not. Setting
|
|
|
- /// this property to false will cause the MainLoop to exit.
|
|
|
- /// </summary>
|
|
|
- public bool Running { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Fired once the Toplevel's MainLoop has started it's first iteration.
|
|
|
- /// Subscribe to this event to perform tasks when the <see cref="Toplevel"/> has been laid out and focus has been set.
|
|
|
- /// changes. A Ready event handler is a good place to finalize initialization after calling `<see cref="Application.Run()"/>(topLevel)`.
|
|
|
- /// </summary>
|
|
|
- public event EventHandler Ready;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Called from Application.RunLoop after the <see cref="Toplevel"/> has entered it's first iteration of the loop.
|
|
|
- /// </summary>
|
|
|
- internal virtual void OnReady ()
|
|
|
- {
|
|
|
- Ready?.Invoke (this, EventArgs.Empty);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Toplevel"/> class with the specified absolute layout.
|
|
|
- /// </summary>
|
|
|
- /// <param name="frame">Frame.</param>
|
|
|
- public Toplevel (Rect frame) : base (frame)
|
|
|
- {
|
|
|
- Initialize ();
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Toplevel"/> class with Computed layout, defaulting to <see langword="async"/> full screen.
|
|
|
- /// </summary>
|
|
|
- public Toplevel () : base ()
|
|
|
- {
|
|
|
- Initialize ();
|
|
|
- Width = Dim.Fill ();
|
|
|
- Height = Dim.Fill ();
|
|
|
- }
|
|
|
-
|
|
|
- void Initialize ()
|
|
|
- {
|
|
|
- ColorScheme = Colors.Base;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Convenience factory method that creates a new toplevel with the current terminal dimensions.
|
|
|
- /// </summary>
|
|
|
- /// <returns>The create.</returns>
|
|
|
- public static Toplevel Create ()
|
|
|
- {
|
|
|
- return new Toplevel (new Rect (0, 0, Driver.Cols, Driver.Rows));
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Gets or sets a value indicating whether this <see cref="Toplevel"/> can focus.
|
|
|
- /// </summary>
|
|
|
- /// <value><c>true</c> if can focus; otherwise, <c>false</c>.</value>
|
|
|
- public override bool CanFocus {
|
|
|
- get => true;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Determines whether the <see cref="Toplevel"/> is modal or not.
|
|
|
- /// Causes <see cref="ProcessKey(KeyEvent)"/> to propagate keys upwards
|
|
|
- /// by default unless set to <see langword="true"/>.
|
|
|
- /// </summary>
|
|
|
- public bool Modal { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Check id current toplevel has menu bar
|
|
|
- /// </summary>
|
|
|
- public MenuBar MenuBar { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Check id current toplevel has status bar
|
|
|
- /// </summary>
|
|
|
- public StatusBar StatusBar { get; set; }
|
|
|
-
|
|
|
- ///<inheritdoc cref="ProcessKey"/>
|
|
|
- public override bool ProcessKey (KeyEvent keyEvent)
|
|
|
- {
|
|
|
- if (base.ProcessKey (keyEvent))
|
|
|
- return true;
|
|
|
-
|
|
|
- switch (keyEvent.Key) {
|
|
|
- case Key.ControlQ:
|
|
|
- // FIXED: stop current execution of this container
|
|
|
- Application.RequestStop ();
|
|
|
- break;
|
|
|
- case Key.ControlZ:
|
|
|
- Driver.Suspend ();
|
|
|
- return true;
|
|
|
-
|
|
|
-#if false
|
|
|
- case Key.F5:
|
|
|
- Application.DebugDrawBounds = !Application.DebugDrawBounds;
|
|
|
- SetNeedsDisplay ();
|
|
|
- return true;
|
|
|
-#endif
|
|
|
- case Key.Tab:
|
|
|
- case Key.CursorRight:
|
|
|
- case Key.CursorDown:
|
|
|
- case Key.ControlI: // Unix
|
|
|
- var old = Focused;
|
|
|
- if (!FocusNext ())
|
|
|
- FocusNext ();
|
|
|
- if (old != Focused) {
|
|
|
- old?.SetNeedsDisplay ();
|
|
|
- Focused?.SetNeedsDisplay ();
|
|
|
- }
|
|
|
- return true;
|
|
|
- case Key.CursorLeft:
|
|
|
- case Key.CursorUp:
|
|
|
- case Key.BackTab:
|
|
|
- old = Focused;
|
|
|
- if (!FocusPrev ())
|
|
|
- FocusPrev ();
|
|
|
- if (old != Focused) {
|
|
|
- old?.SetNeedsDisplay ();
|
|
|
- Focused?.SetNeedsDisplay ();
|
|
|
- }
|
|
|
- return true;
|
|
|
-
|
|
|
- case Key.ControlL:
|
|
|
- Application.Refresh ();
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- ///<inheritdoc cref="Add"/>
|
|
|
- public override void Add (View view)
|
|
|
- {
|
|
|
- if (this == Application.Top) {
|
|
|
- if (view is MenuBar)
|
|
|
- MenuBar = view as MenuBar;
|
|
|
- if (view is StatusBar)
|
|
|
- StatusBar = view as StatusBar;
|
|
|
- }
|
|
|
- base.Add (view);
|
|
|
- }
|
|
|
-
|
|
|
- ///<inheritdoc cref="Remove"/>
|
|
|
- public override void Remove (View view)
|
|
|
- {
|
|
|
- if (this == Application.Top) {
|
|
|
- if (view is MenuBar)
|
|
|
- MenuBar = null;
|
|
|
- if (view is StatusBar)
|
|
|
- StatusBar = null;
|
|
|
- }
|
|
|
- base.Remove (view);
|
|
|
- }
|
|
|
-
|
|
|
- ///<inheritdoc cref="RemoveAll"/>
|
|
|
- public override void RemoveAll ()
|
|
|
- {
|
|
|
- if (this == Application.Top) {
|
|
|
- MenuBar = null;
|
|
|
- StatusBar = null;
|
|
|
- }
|
|
|
- base.RemoveAll ();
|
|
|
- }
|
|
|
-
|
|
|
- internal void EnsureVisibleBounds (Toplevel top, int x, int y, out int nx, out int ny)
|
|
|
- {
|
|
|
- nx = Math.Max (x, 0);
|
|
|
- nx = nx + top.Frame.Width > Driver.Cols ? Math.Max (Driver.Cols - top.Frame.Width, 0) : nx;
|
|
|
- bool m, s;
|
|
|
- if (SuperView == null || SuperView.GetType() != typeof(Toplevel))
|
|
|
- m = Application.Top.MenuBar != null;
|
|
|
- else
|
|
|
- m = ((Toplevel)SuperView).MenuBar != null;
|
|
|
- int l = m ? 1 : 0;
|
|
|
- ny = Math.Max (y, l);
|
|
|
- if (SuperView == null || SuperView.GetType() != typeof(Toplevel))
|
|
|
- s = Application.Top.StatusBar != null;
|
|
|
- else
|
|
|
- s = ((Toplevel)SuperView).StatusBar != null;
|
|
|
- l = s ? Driver.Rows - 1 : Driver.Rows;
|
|
|
- ny = Math.Min (ny, l);
|
|
|
- ny = ny + top.Frame.Height > l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
|
|
|
- }
|
|
|
-
|
|
|
- internal void PositionToplevels ()
|
|
|
- {
|
|
|
- if (this != Application.Top) {
|
|
|
- EnsureVisibleBounds (this, Frame.X, Frame.Y, out int nx, out int ny);
|
|
|
- if ((nx != Frame.X || ny != Frame.Y) && LayoutStyle != LayoutStyle.Computed) {
|
|
|
- X = nx;
|
|
|
- Y = ny;
|
|
|
- }
|
|
|
- } else {
|
|
|
- foreach (var top in Subviews) {
|
|
|
- if (top is Toplevel) {
|
|
|
- EnsureVisibleBounds ((Toplevel)top, top.Frame.X, top.Frame.Y, out int nx, out int ny);
|
|
|
- if ((nx != top.Frame.X || ny != top.Frame.Y) && top.LayoutStyle != LayoutStyle.Computed) {
|
|
|
- top.X = nx;
|
|
|
- top.Y = ny;
|
|
|
- }
|
|
|
- if (StatusBar != null) {
|
|
|
- if (ny + top.Frame.Height > Driver.Rows - 1) {
|
|
|
- if (top.Height is Dim.DimFill)
|
|
|
- top.Height = Dim.Fill () - 1;
|
|
|
- }
|
|
|
- if (StatusBar.Frame.Y != Driver.Rows - 1) {
|
|
|
- StatusBar.Y = Driver.Rows - 1;
|
|
|
- SetNeedsDisplay ();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ///<inheritdoc cref="Redraw"/>
|
|
|
- public override void Redraw (Rect region)
|
|
|
- {
|
|
|
- Application.CurrentView = this;
|
|
|
-
|
|
|
- if (IsCurrentTop) {
|
|
|
- if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
|
|
|
- Driver.SetAttribute (Colors.TopLevel.Normal);
|
|
|
- Clear (region);
|
|
|
- Driver.SetAttribute (Colors.Base.Normal);
|
|
|
- }
|
|
|
- foreach (var view in Subviews) {
|
|
|
- if (view.Frame.IntersectsWith (region)) {
|
|
|
- view.SetNeedsLayout ();
|
|
|
- view.SetNeedsDisplay (view.Bounds);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ClearNeedsDisplay ();
|
|
|
- }
|
|
|
-
|
|
|
- base.Redraw (base.Bounds);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// This method is invoked by Application.Begin as part of the Application.Run after
|
|
|
- /// the views have been laid out, and before the views are drawn for the first time.
|
|
|
- /// </summary>
|
|
|
- public virtual void WillPresent ()
|
|
|
- {
|
|
|
- FocusFirst ();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// A <see cref="Toplevel"/> <see cref="View"/> that draws a frame around its region and has a "ContentView" subview where the contents are added.
|
|
|
- /// </summary>
|
|
|
- public class Window : Toplevel, IEnumerable {
|
|
|
- View contentView;
|
|
|
- ustring title;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// The title to be displayed for this window.
|
|
|
- /// </summary>
|
|
|
- /// <value>The title.</value>
|
|
|
- public ustring Title {
|
|
|
- get => title;
|
|
|
- set {
|
|
|
- title = value;
|
|
|
- SetNeedsDisplay ();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- class ContentView : View {
|
|
|
- public ContentView (Rect frame) : base (frame) { }
|
|
|
- public ContentView () : base () { }
|
|
|
-#if false
|
|
|
- public override void Redraw (Rect region)
|
|
|
- {
|
|
|
- Driver.SetAttribute (ColorScheme.Focus);
|
|
|
-
|
|
|
- for (int y = 0; y < Frame.Height; y++) {
|
|
|
- Move (0, y);
|
|
|
- for (int x = 0; x < Frame.Width; x++) {
|
|
|
-
|
|
|
- Driver.AddRune ('x');
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Gui.Window"/> class with an optional title and a set frame.
|
|
|
- /// </summary>
|
|
|
- /// <param name="frame">Frame.</param>
|
|
|
- /// <param name="title">Title.</param>
|
|
|
- public Window (Rect frame, ustring title = null) : this (frame, title, padding: 0)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Window"/> class with an optional title.
|
|
|
- /// </summary>
|
|
|
- /// <param name="title">Title.</param>
|
|
|
- public Window (ustring title = null) : this (title, padding: 0)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- int padding;
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Window"/> with
|
|
|
- /// the specified frame for its location, with the specified border
|
|
|
- /// an optional title.
|
|
|
- /// </summary>
|
|
|
- /// <param name="frame">Frame.</param>
|
|
|
- /// <param name="padding">Number of characters to use for padding of the drawn frame.</param>
|
|
|
- /// <param name="title">Title.</param>
|
|
|
- public Window (Rect frame, ustring title = null, int padding = 0) : base (frame)
|
|
|
- {
|
|
|
- this.Title = title;
|
|
|
- int wb = 2 * (1 + padding);
|
|
|
- this.padding = padding;
|
|
|
- var cFrame = new Rect (1 + padding, 1 + padding, frame.Width - wb, frame.Height - wb);
|
|
|
- contentView = new ContentView (cFrame);
|
|
|
- base.Add (contentView);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of the <see cref="Window"/> with
|
|
|
- /// the specified frame for its location, with the specified border
|
|
|
- /// an optional title.
|
|
|
- /// </summary>
|
|
|
- /// <param name="padding">Number of characters to use for padding of the drawn frame.</param>
|
|
|
- /// <param name="title">Title.</param>
|
|
|
- public Window (ustring title = null, int padding = 0) : base ()
|
|
|
- {
|
|
|
- this.Title = title;
|
|
|
- int wb = 1 + padding;
|
|
|
- this.padding = padding;
|
|
|
- contentView = new ContentView () {
|
|
|
- X = wb,
|
|
|
- Y = wb,
|
|
|
- Width = Dim.Fill (wb),
|
|
|
- Height = Dim.Fill (wb)
|
|
|
- };
|
|
|
- base.Add (contentView);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Enumerates the various <see cref="View"/>s in the embedded <see cref="ContentView"/>.
|
|
|
- /// </summary>
|
|
|
- /// <returns>The enumerator.</returns>
|
|
|
- public new IEnumerator GetEnumerator ()
|
|
|
- {
|
|
|
- return contentView.GetEnumerator ();
|
|
|
- }
|
|
|
-
|
|
|
- void DrawFrame (bool fill = true)
|
|
|
- {
|
|
|
- DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), padding, fill: fill);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Add the specified view to the <see cref="ContentView"/>.
|
|
|
- /// </summary>
|
|
|
- /// <param name="view">View to add to the window.</param>
|
|
|
- public override void Add (View view)
|
|
|
- {
|
|
|
- contentView.Add (view);
|
|
|
- if (view.CanFocus)
|
|
|
- CanFocus = true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Removes a widget from this container.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// </remarks>
|
|
|
- public override void Remove (View view)
|
|
|
- {
|
|
|
- if (view == null)
|
|
|
- return;
|
|
|
-
|
|
|
- SetNeedsDisplay ();
|
|
|
- var touched = view.Frame;
|
|
|
- contentView.Remove (view);
|
|
|
-
|
|
|
- if (contentView.InternalSubviews.Count < 1)
|
|
|
- this.CanFocus = false;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Removes all widgets from this container.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// </remarks>
|
|
|
- public override void RemoveAll ()
|
|
|
- {
|
|
|
- contentView.RemoveAll ();
|
|
|
- }
|
|
|
-
|
|
|
- ///<inheritdoc cref="Redraw"/>
|
|
|
- public override void Redraw (Rect bounds)
|
|
|
- {
|
|
|
- Application.CurrentView = this;
|
|
|
-
|
|
|
- if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
|
|
|
- DrawFrameWindow ();
|
|
|
- }
|
|
|
- contentView.Redraw (contentView.Bounds);
|
|
|
- ClearNeedsDisplay ();
|
|
|
- DrawFrameWindow (false);
|
|
|
-
|
|
|
- void DrawFrameWindow (bool fill = true)
|
|
|
- {
|
|
|
- Driver.SetAttribute (ColorScheme.Normal);
|
|
|
- DrawFrame (fill);
|
|
|
- if (HasFocus)
|
|
|
- Driver.SetAttribute (ColorScheme.HotNormal);
|
|
|
- var width = Frame.Width - (padding + 2) * 2;
|
|
|
- if (Title != null && width > 4) {
|
|
|
- Move (1 + padding, padding);
|
|
|
- Driver.AddRune (' ');
|
|
|
- var str = Title.Length >= width ? Title [0, width - 2] : Title;
|
|
|
- Driver.AddStr (str);
|
|
|
- Driver.AddRune (' ');
|
|
|
- }
|
|
|
- Driver.SetAttribute (ColorScheme.Normal);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- // FIXED:It does not look like the event is raised on clicked-drag
|
|
|
- // need to figure that out.
|
|
|
- //
|
|
|
- internal static Point? dragPosition;
|
|
|
- Point start;
|
|
|
- ///<inheritdoc cref="MouseEvent(Gui.MouseEvent)"/>
|
|
|
- public override bool MouseEvent (MouseEvent mouseEvent)
|
|
|
- {
|
|
|
- // FIXED:The code is currently disabled, because the
|
|
|
- // Driver.UncookMouse does not seem to have an effect if there is
|
|
|
- // a pending mouse event activated.
|
|
|
-
|
|
|
- int nx, ny;
|
|
|
- if ((mouseEvent.Flags == (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition) ||
|
|
|
- mouseEvent.Flags == MouseFlags.Button3Pressed)) {
|
|
|
- if (dragPosition.HasValue) {
|
|
|
- if (SuperView == null) {
|
|
|
- Application.Top.SetNeedsDisplay (Frame);
|
|
|
- Application.Top.Redraw (Frame);
|
|
|
- } else {
|
|
|
- SuperView.SetNeedsDisplay (Frame);
|
|
|
- }
|
|
|
- EnsureVisibleBounds (this, mouseEvent.X + mouseEvent.OfX - start.X,
|
|
|
- mouseEvent.Y + mouseEvent.OfY, out nx, out ny);
|
|
|
-
|
|
|
- dragPosition = new Point (nx, ny);
|
|
|
- Frame = new Rect (nx, ny, Frame.Width, Frame.Height);
|
|
|
- X = nx;
|
|
|
- Y = ny;
|
|
|
- //Demo.ml2.Text = $"{dx},{dy}";
|
|
|
-
|
|
|
- // FIXED: optimize, only SetNeedsDisplay on the before/after regions.
|
|
|
- SetNeedsDisplay ();
|
|
|
- return true;
|
|
|
- } else {
|
|
|
- // Only start grabbing if the user clicks on the title bar.
|
|
|
- if (mouseEvent.Y == 0) {
|
|
|
- start = new Point (mouseEvent.X, mouseEvent.Y);
|
|
|
- dragPosition = new Point ();
|
|
|
- nx = mouseEvent.X - mouseEvent.OfX;
|
|
|
- ny = mouseEvent.Y - mouseEvent.OfY;
|
|
|
- dragPosition = new Point (nx, ny);
|
|
|
- Application.GrabMouse (this);
|
|
|
- }
|
|
|
-
|
|
|
- //Demo.ml2.Text = $"Starting at {dragPosition}";
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (mouseEvent.Flags == MouseFlags.Button1Released && dragPosition.HasValue) {
|
|
|
- Application.UngrabMouse ();
|
|
|
- Driver.UncookMouse ();
|
|
|
- dragPosition = null;
|
|
|
- }
|
|
|
-
|
|
|
- //Demo.ml.Text = me.ToString ();
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// The application driver for Terminal.Gui.
|
|
|
/// </summary>
|