namespace Terminal.Gui.App; using System; /// /// Provides helper methods for executing single-phase and result-producing workflows in the Cancellable Work Pattern (CWP). /// /// /// /// Used for workflows that allow customization or cancellation, such as command execution /// (e.g., ) or scheme resolution (e.g., ). /// The method handles workflows without results, while /// handles workflows producing results. /// /// /// public static class CWPWorkflowHelper { /// /// Executes a single-phase CWP workflow with a virtual method, event, and optional default action. /// /// The type of the result in the event arguments. /// The virtual method invoked first, returning true to mark the workflow as handled. /// The event handler to invoke, or null if no handlers are subscribed. /// The event arguments containing a result and handled status. /// The default action to execute if the workflow is not handled, or null if none. /// True if the workflow was handled, false if not, or null if no event handlers are subscribed. /// /// Thrown if or is null. /// /// /// /// ResultEventArgs<bool> args = new(); /// Func<ResultEventArgs<bool>, bool> onAccepting = _ => false; /// EventHandler<ResultEventArgs<bool>>? acceptingHandler = null; /// Action? defaultAction = () => args.Result = true; /// bool? handled = CWPWorkflowHelper.Execute(onAccepting, acceptingHandler, args, defaultAction); /// /// public static bool? Execute ( Func, bool> onMethod, EventHandler>? eventHandler, ResultEventArgs args, Action? defaultAction = null) { ArgumentNullException.ThrowIfNull (onMethod); ArgumentNullException.ThrowIfNull (args); bool handled = onMethod (args) || args.Handled; if (handled) { return true; } eventHandler?.Invoke (null, args); if (args.Handled) { return true; } if (defaultAction is {}) { defaultAction (); return true; } return eventHandler is null ? null : false; } /// /// Executes a CWP workflow that produces a result, suitable for methods like . /// /// The type of the result, which may be a nullable reference type (e.g., ?). /// The virtual method invoked first, returning true to mark the workflow as handled. /// The event handler to invoke, or null if no handlers are subscribed. /// The event arguments containing a result and handled status. /// The default action that produces the result if the workflow is not handled. /// The result from the event arguments or the default action. /// /// Thrown if , , or is null. /// /// /// Thrown if is null for non-nullable reference types when is true. /// /// /// /// ResultEventArgs<Scheme?> args = new(); /// Func<ResultEventArgs<Scheme?>, bool> onGettingScheme = _ => false; /// EventHandler<ResultEventArgs<Scheme?>>? gettingSchemeHandler = null; /// Func<Scheme> defaultAction = () => SchemeManager.GetScheme("Base"); /// Scheme scheme = CWPWorkflowHelper.ExecuteWithResult(onGettingScheme, gettingSchemeHandler, args, defaultAction); /// /// public static TResult ExecuteWithResult ( Func, bool> onMethod, EventHandler>? eventHandler, ResultEventArgs args, Func defaultAction) { ArgumentNullException.ThrowIfNull (onMethod); ArgumentNullException.ThrowIfNull (args); ArgumentNullException.ThrowIfNull (defaultAction); bool handled = onMethod (args) || args.Handled; if (handled) { if (args.Result is null && !typeof (TResult).IsValueType && !Nullable.GetUnderlyingType (typeof (TResult))?.IsValueType == true) { throw new InvalidOperationException ("Result cannot be null for non-nullable reference types when Handled is true."); } return args.Result!; } eventHandler?.Invoke (null, args); if (!args.Handled) { return defaultAction (); } if (args.Result is null && !typeof (TResult).IsValueType && !Nullable.GetUnderlyingType (typeof (TResult))?.IsValueType == true) { throw new InvalidOperationException ("Result cannot be null for non-nullable reference types when Handled is true."); } return args.Result!; } }