namespace Terminal.Gui.App;
///
/// Extension methods for that enable running any as a runnable session.
///
///
/// These extensions provide convenience methods for wrapping views in
/// and running them in a single call, similar to how works.
///
public static class ApplicationRunnableExtensions
{
///
/// Runs any View as a runnable session, extracting a typed result via a function.
///
/// The type of view to run.
/// The type of result data to extract.
/// The application instance. Cannot be null.
/// The view to run as a blocking session. Cannot be null.
///
/// Function that extracts the result from the view when stopping.
/// Called automatically when the runnable session ends.
///
/// Optional handler for unhandled exceptions during the session.
/// The extracted result, or null if the session was canceled.
///
/// Thrown if , , or is null.
///
///
///
/// This method wraps the view in a , runs it as a blocking
/// session, and returns the extracted result. The wrapper is NOT disposed automatically;
/// the caller is responsible for disposal.
///
///
/// The result is extracted before the view is disposed, ensuring all data is still accessible.
///
///
///
///
/// var app = Application.Create();
/// app.Init();
///
/// // Run a TextField and get the entered text
/// var text = app.RunView(
/// new TextField { Width = 40 },
/// tf => tf.Text);
/// Console.WriteLine($"You entered: {text}");
///
/// // Run a ColorPicker and get the selected color
/// var color = app.RunView(
/// new ColorPicker(),
/// cp => cp.SelectedColor);
/// Console.WriteLine($"Selected color: {color}");
///
/// // Run a FlagSelector and get the selected flags
/// var flags = app.RunView(
/// new FlagSelector<SelectorStyles>(),
/// fs => fs.Value);
/// Console.WriteLine($"Selected styles: {flags}");
///
/// app.Shutdown();
///
///
public static TResult? RunView (
this IApplication app,
TView view,
Func resultExtractor,
Func? errorHandler = null)
where TView : View
{
if (app is null)
{
throw new ArgumentNullException (nameof (app));
}
if (view is null)
{
throw new ArgumentNullException (nameof (view));
}
if (resultExtractor is null)
{
throw new ArgumentNullException (nameof (resultExtractor));
}
var wrapper = new RunnableWrapper { WrappedView = view };
// Subscribe to IsRunningChanging to extract result when stopping
wrapper.IsRunningChanging += (s, e) =>
{
if (!e.NewValue) // Stopping
{
wrapper.Result = resultExtractor (view);
}
};
app.Run (wrapper, errorHandler);
return wrapper.Result;
}
///
/// Runs any View as a runnable session without result extraction.
///
/// The type of view to run.
/// The application instance. Cannot be null.
/// The view to run as a blocking session. Cannot be null.
/// Optional handler for unhandled exceptions during the session.
/// The view that was run, allowing access to its state after the session ends.
/// Thrown if or is null.
///
///
/// This method wraps the view in a and runs it as a blocking
/// session. The wrapper is NOT disposed automatically; the caller is responsible for disposal.
///
///
/// Use this overload when you don't need automatic result extraction, but still want the view
/// to run as a blocking session. Access the view's properties directly after running.
///
///
///
///
/// var app = Application.Create();
/// app.Init();
///
/// // Run a ColorPicker without automatic result extraction
/// var colorPicker = new ColorPicker();
/// app.RunView(colorPicker);
///
/// // Access the view's state directly
/// Console.WriteLine($"Selected: {colorPicker.SelectedColor}");
///
/// app.Shutdown();
///
///
public static TView RunView (
this IApplication app,
TView view,
Func? errorHandler = null)
where TView : View
{
if (app is null)
{
throw new ArgumentNullException (nameof (app));
}
if (view is null)
{
throw new ArgumentNullException (nameof (view));
}
var wrapper = new RunnableWrapper { WrappedView = view };
app.Run (wrapper, errorHandler);
return view;
}
}