mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-29 01:07:58 +01:00
Merge pull request #2187 from tig/fixes_2185
Fixes #2185. PR #2176 broke Run<T>
This commit is contained in:
@@ -5,53 +5,68 @@
|
||||
|
||||
using Terminal.Gui;
|
||||
|
||||
// Initialize the console
|
||||
Application.Init();
|
||||
Application.Run<ExampleWindow> ();
|
||||
|
||||
// Creates the top-level window with border and title
|
||||
var win = new Window("Example App (Ctrl+Q to quit)");
|
||||
System.Console.WriteLine ($"Username: {((ExampleWindow)Application.Top).usernameText.Text}");
|
||||
|
||||
// Create input components and labels
|
||||
// Before the application exits, reset Terminal.Gui for clean shutdown
|
||||
Application.Shutdown ();
|
||||
|
||||
var usernameLabel = new Label("Username:");
|
||||
var usernameText = new TextField("")
|
||||
{
|
||||
// Position text field adjacent to label
|
||||
X = Pos.Right(usernameLabel) + 1,
|
||||
// Defines a top-level window with border and title
|
||||
public class ExampleWindow : Window {
|
||||
public TextField usernameText;
|
||||
|
||||
public ExampleWindow ()
|
||||
{
|
||||
Title = "Example App (Ctrl+Q to quit)";
|
||||
|
||||
// Fill remaining horizontal space with a margin of 1
|
||||
Width = Dim.Fill(1),
|
||||
};
|
||||
// Create input components and labels
|
||||
var usernameLabel = new Label () {
|
||||
Text = "Username:"
|
||||
};
|
||||
|
||||
var passwordLabel = new Label(0,2,"Password:");
|
||||
var passwordText = new TextField("")
|
||||
{
|
||||
Secret = true,
|
||||
// align with the text box above
|
||||
X = Pos.Left(usernameText),
|
||||
Y = 2,
|
||||
Width = Dim.Fill(1),
|
||||
};
|
||||
usernameText = new TextField ("") {
|
||||
// Position text field adjacent to the label
|
||||
X = Pos.Right (usernameLabel) + 1,
|
||||
|
||||
// Create login button
|
||||
var btnLogin = new Button("Login")
|
||||
{
|
||||
Y = 4,
|
||||
// center the login button horizontally
|
||||
X = Pos.Center(),
|
||||
IsDefault = true,
|
||||
};
|
||||
// Fill remaining horizontal space
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
// When login button is clicked display a message popup
|
||||
btnLogin.Clicked += () => MessageBox.Query("Logging In", "Login Successful", "Ok");
|
||||
var passwordLabel = new Label () {
|
||||
Text = "Password:",
|
||||
X = Pos.Left (usernameLabel),
|
||||
Y = Pos.Bottom (usernameLabel) + 1
|
||||
};
|
||||
|
||||
// Add all the views to the window
|
||||
win.Add(
|
||||
usernameLabel, usernameText, passwordLabel, passwordText,btnLogin
|
||||
);
|
||||
var passwordText = new TextField ("") {
|
||||
Secret = true,
|
||||
// align with the text box above
|
||||
X = Pos.Left (usernameText),
|
||||
Y = Pos.Top (passwordLabel),
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
// Show the application
|
||||
Application.Run(win);
|
||||
// Create login button
|
||||
var btnLogin = new Button () {
|
||||
Text = "Login",
|
||||
Y = Pos.Bottom(passwordLabel) + 1,
|
||||
// center the login button horizontally
|
||||
X = Pos.Center (),
|
||||
IsDefault = true,
|
||||
};
|
||||
|
||||
// After the application exits, release and reset console for clean shutdown
|
||||
Application.Shutdown();
|
||||
// When login button is clicked display a message popup
|
||||
btnLogin.Clicked += () => {
|
||||
if (usernameText.Text == "admin" && passwordText.Text == "password") {
|
||||
MessageBox.Query ("Logging In", "Login Successful", "Ok");
|
||||
Application.RequestStop ();
|
||||
} else {
|
||||
MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
|
||||
}
|
||||
};
|
||||
|
||||
// Add the views to the Window
|
||||
Add (usernameLabel, usernameText, passwordLabel, passwordText, btnLogin);
|
||||
}
|
||||
}
|
||||
95
README.md
95
README.md
@@ -68,56 +68,71 @@ The following example shows a basic Terminal.Gui application written in C#:
|
||||
|
||||
using Terminal.Gui;
|
||||
|
||||
// Initialize the console
|
||||
Application.Init();
|
||||
Application.Run<ExampleWindow> ();
|
||||
|
||||
// Creates the top-level window with border and title
|
||||
var win = new Window("Example App (Ctrl+Q to quit)");
|
||||
System.Console.WriteLine ($"Username: {((ExampleWindow)Application.Top).usernameText.Text}");
|
||||
|
||||
// Create input components and labels
|
||||
// Before the application exits, reset Terminal.Gui for clean shutdown
|
||||
Application.Shutdown ();
|
||||
|
||||
var usernameLabel = new Label("Username:");
|
||||
var usernameText = new TextField("")
|
||||
{
|
||||
// Position text field adjacent to label
|
||||
X = Pos.Right(usernameLabel) + 1,
|
||||
// Defines a top-level window with border and title
|
||||
public class ExampleWindow : Window {
|
||||
public TextField usernameText;
|
||||
|
||||
public ExampleWindow ()
|
||||
{
|
||||
Title = "Example App (Ctrl+Q to quit)";
|
||||
|
||||
// Fill remaining horizontal space with a margin of 1
|
||||
Width = Dim.Fill(1),
|
||||
};
|
||||
// Create input components and labels
|
||||
var usernameLabel = new Label () {
|
||||
Text = "Username:"
|
||||
};
|
||||
|
||||
var passwordLabel = new Label(0,2,"Password:");
|
||||
var passwordText = new TextField("")
|
||||
{
|
||||
Secret = true,
|
||||
// align with the text box above
|
||||
X = Pos.Left(usernameText),
|
||||
Y = 2,
|
||||
Width = Dim.Fill(1),
|
||||
};
|
||||
usernameText = new TextField ("") {
|
||||
// Position text field adjacent to the label
|
||||
X = Pos.Right (usernameLabel) + 1,
|
||||
|
||||
// Create login button
|
||||
var btnLogin = new Button("Login")
|
||||
{
|
||||
Y = 4,
|
||||
// center the login button horizontally
|
||||
X = Pos.Center(),
|
||||
IsDefault = true,
|
||||
};
|
||||
// Fill remaining horizontal space
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
// When login button is clicked display a message popup
|
||||
btnLogin.Clicked += () => MessageBox.Query("Logging In", "Login Successful", "Ok");
|
||||
var passwordLabel = new Label () {
|
||||
Text = "Password:",
|
||||
X = Pos.Left (usernameLabel),
|
||||
Y = Pos.Bottom (usernameLabel) + 1
|
||||
};
|
||||
|
||||
// Add all the views to the window
|
||||
win.Add(
|
||||
usernameLabel, usernameText, passwordLabel, passwordText,btnLogin
|
||||
);
|
||||
var passwordText = new TextField ("") {
|
||||
Secret = true,
|
||||
// align with the text box above
|
||||
X = Pos.Left (usernameText),
|
||||
Y = Pos.Top (passwordLabel),
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
// Show the application
|
||||
Application.Run(win);
|
||||
// Create login button
|
||||
var btnLogin = new Button () {
|
||||
Text = "Login",
|
||||
Y = Pos.Bottom(passwordLabel) + 1,
|
||||
// center the login button horizontally
|
||||
X = Pos.Center (),
|
||||
IsDefault = true,
|
||||
};
|
||||
|
||||
// After the application exits, release and reset console for clean shutdown
|
||||
Application.Shutdown();
|
||||
// When login button is clicked display a message popup
|
||||
btnLogin.Clicked += () => {
|
||||
if (usernameText.Text == "admin" && passwordText.Text == "password") {
|
||||
MessageBox.Query ("Logging In", "Login Successful", "Ok");
|
||||
Application.RequestStop ();
|
||||
} else {
|
||||
MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
|
||||
}
|
||||
};
|
||||
|
||||
// Add the views to the Window
|
||||
Add (usernameLabel, usernameText, passwordLabel, passwordText, btnLogin);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When run the application looks as follows:
|
||||
|
||||
@@ -1451,16 +1451,20 @@ namespace Terminal.Gui {
|
||||
{
|
||||
TerminalResized = terminalResized;
|
||||
|
||||
var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
|
||||
cols = winSize.Width;
|
||||
rows = winSize.Height;
|
||||
try {
|
||||
var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
|
||||
cols = winSize.Width;
|
||||
rows = winSize.Height;
|
||||
|
||||
WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
|
||||
WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
|
||||
|
||||
ResizeScreen ();
|
||||
UpdateOffScreen ();
|
||||
ResizeScreen ();
|
||||
UpdateOffScreen ();
|
||||
|
||||
CreateColors ();
|
||||
CreateColors ();
|
||||
} catch (Win32Exception e) {
|
||||
throw new InvalidOperationException ("The Windows Console output window is not available.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ResizeScreen ()
|
||||
|
||||
@@ -309,6 +309,9 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
public static bool UseSystemConsole;
|
||||
|
||||
// For Unit testing - ignores UseSystemConsole
|
||||
internal static bool ForceFakeConsole;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="Terminal.Gui"/> Application.
|
||||
/// </summary>
|
||||
@@ -329,29 +332,28 @@ namespace Terminal.Gui {
|
||||
/// into a single call. An applciation cam use <see cref="Run{T}(Func{Exception, bool}, ConsoleDriver, IMainLoopDriver)"/>
|
||||
/// without explicitly calling <see cref="Init(ConsoleDriver, IMainLoopDriver)"/>.
|
||||
/// </para>
|
||||
/// <param name="driver">The <see cref="ConsoleDriver"/> to use. If not specified the default driver for the
|
||||
/// <param name="driver">
|
||||
/// The <see cref="ConsoleDriver"/> to use. If not specified the default driver for the
|
||||
/// platform will be used (see <see cref="WindowsDriver"/>, <see cref="CursesDriver"/>, and <see cref="NetDriver"/>).</param>
|
||||
/// <param name="mainLoopDriver">Specifies the <see cref="MainLoop"/> to use.</param>
|
||||
public static void Init (ConsoleDriver driver = null, IMainLoopDriver mainLoopDriver = null) => Init (() => Toplevel.Create (), driver, mainLoopDriver, resetState: true);
|
||||
/// <param name="mainLoopDriver">
|
||||
/// Specifies the <see cref="MainLoop"/> to use.
|
||||
/// Must not be <see langword="null"/> if <paramref name="driver"/> is not <see langword="null"/>.
|
||||
/// </param>
|
||||
public static void Init (ConsoleDriver driver = null, IMainLoopDriver mainLoopDriver = null) => InternalInit (() => Toplevel.Create (), driver, mainLoopDriver);
|
||||
|
||||
internal static bool _initialized = false;
|
||||
internal static int _mainThreadId = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Internal function for initializing a Terminal.Gui application with a <see cref="Toplevel"/> factory object,
|
||||
/// a <see cref="ConsoleDriver"/>, and <see cref="MainLoop"/>.
|
||||
/// <para>
|
||||
/// This is a low-level function; most applications will use <see cref="Init(ConsoleDriver, IMainLoopDriver)"/> as it is simpler.</para>
|
||||
/// </summary>
|
||||
/// <param name="topLevelFactory">Specifies the <see cref="Toplevel"> factory funtion.</see>/></param>
|
||||
/// <param name="driver">The <see cref="ConsoleDriver"/> to use. If not specified the default driver for the
|
||||
/// platform will be used (see <see cref="WindowsDriver"/>, <see cref="CursesDriver"/>, and <see cref="NetDriver"/>).</param>
|
||||
/// <param name="mainLoopDriver">Specifies the <see cref="MainLoop"/> to use.</param>
|
||||
/// <param name="resetState">If <see langword="true"/> (default) all <see cref="Application"/> state will be reset.
|
||||
/// Set to <see langword="false"/> to not reset the state (for when this function is called via
|
||||
/// <see cref="Run{T}(Func{Exception, bool}, ConsoleDriver, IMainLoopDriver)"/> when <see cref="Init(ConsoleDriver, IMainLoopDriver)"/>
|
||||
/// has not already been called. f</param>
|
||||
internal static void Init (Func<Toplevel> topLevelFactory, ConsoleDriver driver = null, IMainLoopDriver mainLoopDriver = null, bool resetState = true)
|
||||
// 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<T>() - When the user wants to use a custom Toplevel. calledViaRunT will be true, enabling Run<T>() 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.
|
||||
internal static void InternalInit (Func<Toplevel> topLevelFactory, ConsoleDriver driver = null, IMainLoopDriver mainLoopDriver = null, bool calledViaRunT = false)
|
||||
{
|
||||
if (_initialized && driver == null) return;
|
||||
|
||||
@@ -359,6 +361,7 @@ namespace Terminal.Gui {
|
||||
throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
|
||||
}
|
||||
|
||||
// Note in this case, we don't verify the type of the Toplevel created by new T().
|
||||
// Used only for start debugging on Unix.
|
||||
//#if DEBUG
|
||||
// while (!System.Diagnostics.Debugger.IsAttached) {
|
||||
@@ -367,22 +370,29 @@ namespace Terminal.Gui {
|
||||
// System.Diagnostics.Debugger.Break ();
|
||||
//#endif
|
||||
|
||||
// Reset all class variables (Application is a singleton).
|
||||
if (resetState) {
|
||||
if (!calledViaRunT) {
|
||||
// Reset all class variables (Application is a singleton).
|
||||
ResetState ();
|
||||
}
|
||||
|
||||
// This supports Unit Tests and the passing of a mock driver/loopdriver
|
||||
// FakeDriver (for UnitTests)
|
||||
if (driver != null) {
|
||||
if (mainLoopDriver == null) {
|
||||
throw new ArgumentNullException ("mainLoopDriver cannot be null if driver is provided.");
|
||||
throw new ArgumentNullException ("InternalInit mainLoopDriver cannot be null if driver is provided.");
|
||||
}
|
||||
if (!(driver is FakeDriver)) {
|
||||
throw new InvalidOperationException ("InternalInit can only be called with FakeDriver.");
|
||||
}
|
||||
Driver = driver;
|
||||
}
|
||||
|
||||
if (Driver == null) {
|
||||
var p = Environment.OSVersion.Platform;
|
||||
if (UseSystemConsole) {
|
||||
if (ForceFakeConsole) {
|
||||
// For Unit Testing only
|
||||
Driver = new FakeDriver ();
|
||||
mainLoopDriver = new FakeMainLoop (() => FakeConsole.ReadKey (true));
|
||||
} else if (UseSystemConsole) {
|
||||
Driver = new NetDriver ();
|
||||
mainLoopDriver = new NetMainLoop (Driver);
|
||||
} else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) {
|
||||
@@ -395,7 +405,16 @@ namespace Terminal.Gui {
|
||||
}
|
||||
MainLoop = new MainLoop (mainLoopDriver);
|
||||
|
||||
Driver.Init (TerminalResized);
|
||||
try {
|
||||
Driver.Init (TerminalResized);
|
||||
} 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);
|
||||
}
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop));
|
||||
|
||||
Top = topLevelFactory ();
|
||||
@@ -1250,8 +1269,7 @@ namespace Terminal.Gui {
|
||||
/// Runs the application by calling <see cref="Run(Toplevel, Func{Exception, bool})"/>
|
||||
/// with a new instance of the specified <see cref="Toplevel"/>-derived class.
|
||||
/// <para>
|
||||
/// If <see cref="Init(ConsoleDriver, IMainLoopDriver)"/> has not arleady been called, this function will
|
||||
/// call <see cref="Init(Func{Toplevel}, ConsoleDriver, IMainLoopDriver, bool)"/>.
|
||||
/// Calling <see cref="Init(ConsoleDriver, IMainLoopDriver)"/> first is not needed as this function will initialze the application.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <see cref="Shutdown"/> must be called when the application is closing (typically after Run> has
|
||||
@@ -1263,27 +1281,31 @@ namespace Terminal.Gui {
|
||||
/// </remarks>
|
||||
/// <param name="errorHandler"></param>
|
||||
/// <param name="driver">The <see cref="ConsoleDriver"/> to use. If not specified the default driver for the
|
||||
/// platform will be used (see <see cref="WindowsDriver"/>, <see cref="CursesDriver"/>, and <see cref="NetDriver"/>).</param>
|
||||
/// platform will be used (<see cref="WindowsDriver"/>, <see cref="CursesDriver"/>, or <see cref="NetDriver"/>).
|
||||
/// This parameteter must be <see langword="null"/> if <see cref="Init(ConsoleDriver, IMainLoopDriver)"/> has already been called.
|
||||
/// </param>
|
||||
/// <param name="mainLoopDriver">Specifies the <see cref="MainLoop"/> to use.</param>
|
||||
public static void Run<T> (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null, IMainLoopDriver mainLoopDriver = null) where T : Toplevel, new()
|
||||
{
|
||||
if (_initialized && Driver != null) {
|
||||
var top = new T ();
|
||||
var type = top.GetType ().BaseType;
|
||||
while (type != typeof (Toplevel) && type != typeof (object)) {
|
||||
type = type.BaseType;
|
||||
if (_initialized) {
|
||||
if (Driver != null) {
|
||||
// Init() has been called and we have a driver, so just run the app.
|
||||
var top = new T ();
|
||||
var type = top.GetType ().BaseType;
|
||||
while (type != typeof (Toplevel) && type != typeof (object)) {
|
||||
type = type.BaseType;
|
||||
}
|
||||
if (type != typeof (Toplevel)) {
|
||||
throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel");
|
||||
}
|
||||
Run (top, errorHandler);
|
||||
} else {
|
||||
// This codepath 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<T>() cannot be called.");
|
||||
}
|
||||
if (type != typeof (Toplevel)) {
|
||||
throw new ArgumentException ($"{top.GetType ().Name} must be derived from TopLevel");
|
||||
}
|
||||
// Run() will eventually cause Application.Top to be set, via Begin() and SetCurrentAsTop()
|
||||
Run (top, errorHandler);
|
||||
} else {
|
||||
if (!_initialized && driver == null) {
|
||||
throw new ArgumentException ("Init has not been called; a valid driver and mainloop must be provided");
|
||||
}
|
||||
// Note in this case, we don't verify the type of the Toplevel created by new T().
|
||||
Init (() => new T (), Driver == null ? driver : Driver, Driver == null ? mainLoopDriver : null, resetState: false);
|
||||
// Init() has NOT been called.
|
||||
InternalInit (() => new T (), driver, mainLoopDriver, calledViaRunT: true);
|
||||
Run (Top, errorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ namespace UICatalog.Scenarios {
|
||||
[ScenarioCategory ("Dialogs")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
public class BackgroundWorkerCollection : Scenario {
|
||||
public override void Init (ColorScheme colorScheme)
|
||||
{
|
||||
// Do not call Init as Application.Run<T> will do it
|
||||
}
|
||||
|
||||
public override void Run ()
|
||||
{
|
||||
|
||||
76
UICatalog/Scenarios/Generic - Copy.cs
Normal file
76
UICatalog/Scenarios/Generic - Copy.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog.Scenarios {
|
||||
[ScenarioMetadata (Name: "Run<T> Example", Description: "Illustrates using Application.Run<T> to run a custom class")]
|
||||
[ScenarioCategory ("Top Level Windows")]
|
||||
public class RunTExample : Scenario {
|
||||
public override void Setup ()
|
||||
{
|
||||
// No need to call Init if Application.Run<T> is used
|
||||
}
|
||||
|
||||
public override void Run ()
|
||||
{
|
||||
Application.Run<ExampleWindow> ();
|
||||
}
|
||||
|
||||
public class ExampleWindow : Window {
|
||||
public TextField usernameText;
|
||||
|
||||
public ExampleWindow ()
|
||||
{
|
||||
Title = "Example App (Ctrl+Q to quit)";
|
||||
|
||||
// Create input components and labels
|
||||
var usernameLabel = new Label () {
|
||||
Text = "Username:"
|
||||
};
|
||||
|
||||
usernameText = new TextField ("") {
|
||||
// Position text field adjacent to the label
|
||||
X = Pos.Right (usernameLabel) + 1,
|
||||
|
||||
// Fill remaining horizontal space
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
var passwordLabel = new Label () {
|
||||
Text = "Password:",
|
||||
X = Pos.Left (usernameLabel),
|
||||
Y = Pos.Bottom (usernameLabel) + 1
|
||||
};
|
||||
|
||||
var passwordText = new TextField ("") {
|
||||
Secret = true,
|
||||
// align with the text box above
|
||||
X = Pos.Left (usernameText),
|
||||
Y = Pos.Top (passwordLabel),
|
||||
Width = Dim.Fill (),
|
||||
};
|
||||
|
||||
// Create login button
|
||||
var btnLogin = new Button () {
|
||||
Text = "Login",
|
||||
Y = Pos.Bottom (passwordLabel) + 1,
|
||||
// center the login button horizontally
|
||||
X = Pos.Center (),
|
||||
IsDefault = true,
|
||||
};
|
||||
|
||||
// When login button is clicked display a message popup
|
||||
btnLogin.Clicked += () => {
|
||||
if (usernameText.Text == "admin" && passwordText.Text == "password") {
|
||||
MessageBox.Query ("Login Successful", $"Username: {usernameText.Text}", "Ok");
|
||||
Application.RequestStop ();
|
||||
} else {
|
||||
MessageBox.ErrorQuery ("Error Logging In", "Incorrect username or password (hint: admin/password)", "Ok");
|
||||
}
|
||||
};
|
||||
|
||||
// Add the views to the Window
|
||||
Add (usernameLabel, usernameText, passwordLabel, passwordText, btnLogin);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -117,6 +117,7 @@ namespace UICatalog {
|
||||
|
||||
// Run UI Catalog UI. When it exits, if _selectedScenario is != null then
|
||||
// a Scenario was selected. Otherwise, the user wants to exit UI Catalog.
|
||||
Application.Init ();
|
||||
Application.Run<UICatalogTopLevel> ();
|
||||
Application.Shutdown ();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
@@ -100,7 +101,7 @@ namespace Terminal.Gui.Core {
|
||||
Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
|
||||
|
||||
Toplevel topLevel = null;
|
||||
Assert.Throws<InvalidOperationException> (() => Application.Init (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))));
|
||||
Assert.Throws<InvalidOperationException> (() => Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))));
|
||||
Shutdown ();
|
||||
|
||||
Assert.Null (Application.Top);
|
||||
@@ -109,7 +110,7 @@ namespace Terminal.Gui.Core {
|
||||
|
||||
// Now try the other way
|
||||
topLevel = null;
|
||||
Application.Init (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
|
||||
Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
|
||||
|
||||
Assert.Throws<InvalidOperationException> (() => Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))));
|
||||
Shutdown ();
|
||||
@@ -118,7 +119,7 @@ namespace Terminal.Gui.Core {
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class TestToplevel : Toplevel {
|
||||
public TestToplevel ()
|
||||
@@ -131,7 +132,7 @@ namespace Terminal.Gui.Core {
|
||||
public void Init_Begin_End_Cleans_Up ()
|
||||
{
|
||||
Init ();
|
||||
|
||||
|
||||
// Begin will cause Run() to be called, which will call Begin(). Thus will block the tests
|
||||
// if we don't stop
|
||||
Application.Iteration = () => {
|
||||
@@ -145,7 +146,7 @@ namespace Terminal.Gui.Core {
|
||||
};
|
||||
Application.NotifyNewRunState += NewRunStateFn;
|
||||
|
||||
Toplevel topLevel = new Toplevel();
|
||||
Toplevel topLevel = new Toplevel ();
|
||||
var rs = Application.Begin (topLevel);
|
||||
Assert.NotNull (rs);
|
||||
Assert.NotNull (runstate);
|
||||
@@ -181,7 +182,7 @@ namespace Terminal.Gui.Core {
|
||||
// NOTE: Run<T>, when called after Init has been called behaves differently than
|
||||
// when called if Init has not been called.
|
||||
Toplevel topLevel = null;
|
||||
Application.Init (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
|
||||
Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
|
||||
|
||||
Application.RunState runstate = null;
|
||||
Action<Application.RunState> NewRunStateFn = (rs) => {
|
||||
@@ -272,9 +273,9 @@ namespace Terminal.Gui.Core {
|
||||
Application.Iteration = () => {
|
||||
Application.RequestStop ();
|
||||
};
|
||||
|
||||
|
||||
// Init has been called and we're passing no driver to Run<TestTopLevel>. This is ok.
|
||||
Application.Run<TestToplevel> (errorHandler: null);
|
||||
Application.Run<TestToplevel> ();
|
||||
|
||||
Shutdown ();
|
||||
|
||||
@@ -284,14 +285,59 @@ namespace Terminal.Gui.Core {
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Run_T_NoInit_Throws ()
|
||||
public void Run_T_After_InitNullDriver_with_TestTopLevel_Throws ()
|
||||
{
|
||||
Application.ForceFakeConsole = true;
|
||||
|
||||
Application.Init (null, null);
|
||||
Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
|
||||
|
||||
Application.Iteration = () => {
|
||||
Application.RequestStop ();
|
||||
};
|
||||
|
||||
// Init has NOT been called and we're passing no driver to Run<TestToplevel>. This is an error.
|
||||
Assert.Throws<ArgumentException> (() => Application.Run<TestToplevel> (errorHandler: null, driver: null, mainLoopDriver: null));
|
||||
// Init has been called without selecting a driver and we're passing no driver to Run<TestTopLevel>. Bad
|
||||
Application.Run<TestToplevel> ();
|
||||
|
||||
Shutdown ();
|
||||
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws ()
|
||||
{
|
||||
Init ();
|
||||
|
||||
Application.Driver = null;
|
||||
|
||||
Application.Iteration = () => {
|
||||
Application.RequestStop ();
|
||||
};
|
||||
|
||||
// Init has been called, but Driver has been set to null. Bad.
|
||||
Assert.Throws<InvalidOperationException> (() => Application.Run<TestToplevel> ());
|
||||
|
||||
Shutdown ();
|
||||
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Run_T_NoInit_DoesNotThrow ()
|
||||
{
|
||||
Application.ForceFakeConsole = true;
|
||||
|
||||
Application.Iteration = () => {
|
||||
Application.RequestStop ();
|
||||
};
|
||||
|
||||
Application.Run<TestToplevel> ();
|
||||
Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
|
||||
|
||||
Shutdown ();
|
||||
|
||||
@@ -379,6 +425,9 @@ namespace Terminal.Gui.Core {
|
||||
Application.Shutdown ();
|
||||
Assert.Equal (3, count);
|
||||
}
|
||||
|
||||
// TODO: Add tests for Run that test errorHandler
|
||||
|
||||
#endregion
|
||||
|
||||
#region ShutdownTests
|
||||
@@ -407,7 +456,7 @@ namespace Terminal.Gui.Core {
|
||||
Assert.Null (SynchronizationContext.Current);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top ()
|
||||
|
||||
Reference in New Issue
Block a user