#nullable enable using System.ComponentModel; namespace Terminal.Gui.ViewBase; public partial class View { private string? _schemeName; /// /// Gets or sets the name of the scheme to use for this . If set, it overrides the scheme /// inherited from the . If a scheme was explicitly set ( is /// true), this property is ignored. /// /// /// /// Setting this property raises pre- and post-change events via , /// allowing customization or cancellation of the change. The event /// is raised before the change, and is raised after. /// /// /// The scheme name, or null if no scheme name is set. /// /// public string? SchemeName { get => _schemeName; set { bool changed = CWPPropertyHelper.ChangeProperty ( _schemeName, value, OnSchemeNameChanging, SchemeNameChanging, OnSchemeNameChanged, SchemeNameChanged, out string? finalValue); if (changed) { _schemeName = finalValue; } } } /// /// Called before the property changes, allowing subclasses to cancel or modify the change. /// /// The event arguments containing the current and proposed new scheme name. /// True to cancel the change, false to proceed. protected virtual bool OnSchemeNameChanging (ValueChangingEventArgs args) { return false; } /// /// Called after the property changes, allowing subclasses to react to the change. /// /// The event arguments containing the old and new scheme name. protected virtual void OnSchemeNameChanged (ValueChangedEventArgs args) { } /// /// Raised before the property changes, allowing handlers to modify or cancel the change. /// /// /// Set to true to cancel the change or modify /// to adjust the proposed value. /// /// /// /// view.SchemeNameChanging += (sender, args) => /// { /// if (args.NewValue == "InvalidScheme") /// { /// args.Handled = true; /// Console.WriteLine("Invalid scheme name cancelled."); /// } /// }; /// /// public event EventHandler>? SchemeNameChanging; /// /// Raised after the property changes, notifying handlers of the completed change. /// /// /// Provides the old and new scheme name via and /// , which may be null. /// /// /// /// view.SchemeNameChanged += (sender, args) => /// { /// Console.WriteLine($"SchemeName changed from {args.OldValue ?? "none"} to {args.NewValue ?? "none"}."); /// }; /// /// public event EventHandler>? SchemeNameChanged; // Both holds the set Scheme and is used to determine if a Scheme has been set or not private Scheme? _scheme; /// /// Gets whether a Scheme has been explicitly set for this View, or if it will inherit the Scheme from its /// . /// public bool HasScheme => _scheme is { }; /// /// Gets the scheme for the . If the scheme has not been explicitly set /// (see ), gets the 's scheme or falls back to the base scheme. /// /// The resolved scheme, never null. /// /// /// This method uses the Cancellable Work Pattern (CWP) via /// to allow customization or cancellation of scheme resolution through the method /// and event. /// /// /// /// /// view.GettingScheme += (sender, args) => /// { /// args.Result = SchemeManager.GetScheme("Custom"); /// args.Handled = true; /// }; /// Scheme scheme = view.GetScheme(); /// /// public Scheme GetScheme () { ResultEventArgs args = new (); return CWPWorkflowHelper.ExecuteWithResult ( onMethod: args => { bool cancelled = OnGettingScheme (out Scheme? newScheme); args.Result = newScheme; return cancelled; }, eventHandler: GettingScheme, args, DefaultAction); Scheme DefaultAction () { if (!HasScheme && !string.IsNullOrEmpty (SchemeName)) { return SchemeManager.GetScheme (SchemeName); } if (!HasScheme) { return SuperView?.GetScheme () ?? SchemeManager.GetScheme (Schemes.Base); } return _scheme!; } } /// /// Called when the for the is being retrieved. Subclasses can return /// true to stop further processing and optionally set to a different value. /// /// The scheme to use, or null to continue processing. /// True to stop default behavior, false to proceed. protected virtual bool OnGettingScheme (out Scheme? scheme) { scheme = null; return false; } /// /// Raised when the for the is being retrieved. Handlers can set /// to true to stop further processing and optionally set /// to a different value. /// public event EventHandler>? GettingScheme; /// /// Sets the scheme for the , marking it as explicitly set. /// /// The scheme to set, or null to clear the explicit scheme. /// True if the scheme was set, false if unchanged or cancelled. /// /// /// This method uses the Cancellable Work Pattern (CWP) via /// to allow customization or cancellation of the scheme change through the method /// and event. The event is raised after a successful change. /// /// /// If set to null, will be false, and the view will inherit the scheme from its /// or fall back to the base scheme. /// /// /// /// /// view.SchemeChanging += (sender, args) => /// { /// if (args.NewValue is null) /// { /// args.Handled = true; /// Console.WriteLine("Null scheme cancelled."); /// } /// }; /// view.SchemeChanged += (sender, args) => /// { /// Console.WriteLine($"Scheme changed to {args.NewValue?.Name ?? "none"}."); /// }; /// bool set = view.SetScheme(SchemeManager.GetScheme("Base")); /// /// public bool SetScheme (Scheme? scheme) { bool changed = CWPPropertyHelper.ChangeProperty ( _scheme, scheme, OnSettingScheme, SchemeChanging, OnSchemeChanged, SchemeChanged, out Scheme? finalValue); if (changed) { _scheme = finalValue; return true; } return false; } /// /// Called before the scheme is set, allowing subclasses to cancel or modify the change. /// /// The event arguments containing the current and proposed new scheme. /// True to cancel the change, false to proceed. protected virtual bool OnSettingScheme (ValueChangingEventArgs args) { return false; } /// /// Called after the scheme is set, allowing subclasses to react to the change. /// /// The event arguments containing the old and new scheme. protected virtual void OnSchemeChanged (ValueChangedEventArgs args) { SetNeedsDraw (); } /// /// Raised before the scheme is set, allowing handlers to modify or cancel the change. /// /// /// Set to true to cancel the change or modify /// to adjust the proposed scheme. /// public event EventHandler>? SchemeChanging; /// /// Raised after the scheme is set, notifying handlers of the completed change. /// /// /// Provides the old and new scheme via and /// , which may be null. /// public event EventHandler>? SchemeChanged; }