Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More conservative version of IApplication #3878

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ public static partial class Application // Initialization (Init/Shutdown)
/// </param>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Init (IConsoleDriver? driver = null, string? driverName = null) { InternalInit (driver, driverName); }
public static void Init (IConsoleDriver? driver = null, string? driverName = null)
{
ApplicationImpl.Instance.Init (driver, driverName);
}

internal static int MainThreadId { get; set; } = -1;

Expand Down Expand Up @@ -210,20 +213,7 @@ internal static void InternalInit (
/// up (Disposed)
/// and terminal settings are restored.
/// </remarks>
public static void Shutdown ()
{
// TODO: Throw an exception if Init hasn't been called.

bool wasInitialized = Initialized;
ResetState ();
PrintJsonErrors ();

if (wasInitialized)
{
bool init = Initialized;
InitializedChanged?.Invoke (null, new (in init));
}
}
public static void Shutdown () => ApplicationImpl.Instance.Shutdown ();

/// <summary>
/// Gets whether the application has been initialized with <see cref="Init"/> and not yet shutdown with <see cref="Shutdown"/>.
Expand All @@ -242,4 +232,12 @@ public static void Shutdown ()
/// Intended to support unit tests that need to know when the application has been initialized.
/// </remarks>
public static event EventHandler<EventArgs<bool>>? InitializedChanged;

/// <summary>
/// Raises the <see cref="InitializedChanged"/> event.
/// </summary>
internal static void OnInitializedChanged (object sender, EventArgs<bool> e)
{
Application.InitializedChanged?.Invoke (sender,e);
}
}
86 changes: 4 additions & 82 deletions Terminal.Gui/Application/Application.Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ internal static bool PositionCursor ()
/// <returns>The created <see cref="Toplevel"/> object. The caller is responsible for disposing this object.</returns>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static Toplevel Run (Func<Exception, bool>? errorHandler = null, IConsoleDriver? driver = null) { return Run<Toplevel> (errorHandler, driver); }
public static Toplevel Run (Func<Exception, bool>? errorHandler = null, IConsoleDriver? driver = null) =>
ApplicationImpl.Instance.Run (errorHandler, driver);

/// <summary>
/// Runs the application by creating a <see cref="Toplevel"/>-derived object of type <c>T</c> and calling
Expand All @@ -331,20 +332,7 @@ internal static bool PositionCursor ()
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static T Run<T> (Func<Exception, bool>? errorHandler = null, IConsoleDriver? 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;
}
where T : Toplevel, new() => ApplicationImpl.Instance.Run<T> (errorHandler, driver);

/// <summary>Runs the Application using the provided <see cref="Toplevel"/> view.</summary>
/// <remarks>
Expand Down Expand Up @@ -385,73 +373,7 @@ public static T Run<T> (Func<Exception, bool>? errorHandler = null, IConsoleDriv
/// rethrows when null).
/// </param>
public static void Run (Toplevel view, Func<Exception, bool>? 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<T>() cannot be called."
);
}
}
else
{
// Init() has NOT been called.
throw new InvalidOperationException (
"Init() has not been called. Only Run() or Run<T>() 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
}
}
=> ApplicationImpl.Instance.Run (view, errorHandler);

/// <summary>Adds a timeout to the application.</summary>
/// <remarks>
Expand Down
91 changes: 91 additions & 0 deletions Terminal.Gui/Application/Application.cd
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="Terminal.Gui.Application">
<Position X="2.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>hEI4FAgAqARIspQfBQo0gTGiACNL0AICESJKoggBSg8=</HashCode>
<FileName>Application\Application.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.ApplicationNavigation" Collapsed="true">
<Position X="13.75" Y="1.75" Width="2" />
<TypeIdentifier>
<HashCode>AABAAAAAAABCAAAAAAAAAAAAAAAAIgIAAAAAAAAAAAA=</HashCode>
<FileName>Application\ApplicationNavigation.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.IterationEventArgs" Collapsed="true">
<Position X="16" Y="2" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Application\IterationEventArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.MainLoop" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="10.25" Y="2.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAAAIAAAASAAAQAQAAAAAIBADQAAEAAYIgIIwAAAAAI=</HashCode>
<FileName>Application\MainLoop.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="Terminal.Gui.MainLoopSyncContext" Collapsed="true">
<Position X="12" Y="2.75" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAgAAAAAAAAAAAEAAAAAACAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Application\MainLoopSyncContext.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.RunState" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="14.25" Y="3" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAACACAgAAAAAAAAAAAAAAAAACQAAAAAAAAAA=</HashCode>
<FileName>Application\RunState.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="Terminal.Gui.RunStateEventArgs" Collapsed="true">
<Position X="16" Y="3" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
<FileName>Application\RunStateEventArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.Timeout" Collapsed="true">
<Position X="10.25" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAQAA=</HashCode>
<FileName>Application\Timeout.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.TimeoutEventArgs" Collapsed="true">
<Position X="12" Y="3.75" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAACAIAAAAAAAAAAAA=</HashCode>
<FileName>Application\TimeoutEventArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Terminal.Gui.ApplicationImpl" BaseTypeListCollapsed="true">
<Position X="5.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAACAACAAAI=</HashCode>
<FileName>Application\ApplicationImpl.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Interface Name="Terminal.Gui.IMainLoopDriver" Collapsed="true">
<Position X="12" Y="5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAACAAAAAQAAAAABAAAAAAAEAAAAAAAAAAAAAA=</HashCode>
<FileName>Application\MainLoop.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="Terminal.Gui.IApplication">
<Position X="4" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAACAAAAAAI=</HashCode>
<FileName>Application\IApplication.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>
Loading
Loading