namespace Terminal.Gui.ViewBase; /// /// Base implementation of for views that can be run as sessions. /// /// /// /// Views can derive from this class or implement directly. /// This base class provides a complete reference implementation of the /// interface following Terminal.Gui's Cancellable Work Pattern. /// /// /// To customize lifecycle behavior, override the protected virtual methods: /// , , , /// , , . /// /// public class Runnable : View, IRunnable { /// public bool Running { get; set; } #region IRunnable Implementation (RaiseXxxEvent Methods) /// public virtual void RaiseStoppingEvent () { // CWP Phase 1: Pre-notification via virtual method (can cancel) if (OnStopping ()) { return; // Stopping canceled } // CWP Phase 2: Event notification (can cancel) var args = new System.ComponentModel.CancelEventArgs (); Stopping?.Invoke (this, args); if (args.Cancel) { return; // Stopping canceled } // CWP Phase 3: Perform the work (stop the session) Running = false; // CWP Phase 4: Post-notification via virtual method OnStopped (); // CWP Phase 5: Post-notification event Stopped?.Invoke (this, EventArgs.Empty); } /// public virtual bool RaiseActivatingEvent (IRunnable? deactivated) { // CWP Phase 1: Pre-notification via virtual method (can cancel) if (OnActivating (deactivated)) { return true; // Activation canceled } // CWP Phase 2: Event notification (can cancel) var args = new RunnableActivatingEventArgs (this, deactivated); Activating?.Invoke (this, args); if (args.Cancel) { return true; // Activation canceled } // CWP Phase 3: Work is done by Application (setting Current) // CWP Phase 4 & 5: Call post-notification methods OnActivated (deactivated); return false; // Activation succeeded } /// public virtual void RaiseActivatedEvent (IRunnable? deactivated) { Activated?.Invoke (this, new RunnableEventArgs (this)); } /// public virtual bool RaiseDeactivatingEvent (IRunnable? activated) { // CWP Phase 1: Pre-notification via virtual method (can cancel) if (OnDeactivating (activated)) { return true; // Deactivation canceled } // CWP Phase 2: Event notification (can cancel) var args = new RunnableDeactivatingEventArgs (this, activated); Deactivating?.Invoke (this, args); if (args.Cancel) { return true; // Deactivation canceled } // CWP Phase 3: Work is done by Application (changing Current) // CWP Phase 4 & 5: Call post-notification methods OnDeactivated (activated); return false; // Deactivation succeeded } /// public virtual void RaiseDeactivatedEvent (IRunnable? activated) { Deactivated?.Invoke (this, new RunnableEventArgs (this)); } #endregion #region Protected Virtual Methods (Override Pattern) /// /// Called before event. Override to cancel stopping. /// /// to cancel; to proceed. /// /// /// This is the first phase of the Cancellable Work Pattern for stopping. /// Default implementation returns (allow stopping). /// /// /// Override this method to provide custom logic for determining whether the runnable /// should stop (e.g., prompting the user to save changes). /// /// protected virtual bool OnStopping () { return false; // Default: allow stopping } /// /// Called after session has stopped. Override for post-stop cleanup. /// /// /// /// This is the fourth phase of the Cancellable Work Pattern for stopping. /// At this point, is . /// Default implementation does nothing. /// /// /// Override this method to perform cleanup work that should occur after the session stops. /// /// protected virtual void OnStopped () { // Default: do nothing } /// /// Called before event. Override to cancel activation. /// /// The previously active runnable being deactivated, or null if none. /// to cancel; to proceed. /// /// /// This is the first phase of the Cancellable Work Pattern for activation. /// Default implementation returns (allow activation). /// /// /// Override this method to provide custom logic for determining whether the runnable /// should become active. /// /// protected virtual bool OnActivating (IRunnable? deactivated) { return false; // Default: allow activation } /// /// Called after activation succeeds. Override for post-activation logic. /// /// The previously active runnable that was deactivated, or null if none. /// /// /// This is the fourth phase of the Cancellable Work Pattern for activation. /// Default implementation calls . /// /// /// Override this method to perform work that should occur after activation /// (e.g., setting focus, updating UI). Overrides must call base to ensure the /// event is raised. /// /// protected virtual void OnActivated (IRunnable? deactivated) { RaiseActivatedEvent (deactivated); } /// /// Called before event. Override to cancel deactivation. /// /// The newly activated runnable, or null if none. /// to cancel; to proceed. /// /// /// This is the first phase of the Cancellable Work Pattern for deactivation. /// Default implementation returns (allow deactivation). /// /// /// Override this method to provide custom logic for determining whether the runnable /// should be deactivated (e.g., preventing switching away if unsaved changes exist). /// /// protected virtual bool OnDeactivating (IRunnable? activated) { return false; // Default: allow deactivation } /// /// Called after deactivation succeeds. Override for post-deactivation logic. /// /// The newly activated runnable, or null if none. /// /// /// This is the fourth phase of the Cancellable Work Pattern for deactivation. /// Default implementation calls . /// /// /// Override this method to perform work that should occur after deactivation /// (e.g., saving state, releasing resources). Overrides must call base to ensure the /// event is raised. /// /// protected virtual void OnDeactivated (IRunnable? activated) { RaiseDeactivatedEvent (activated); } #endregion #region Events // Note: Initializing and Initialized events are inherited from View (ISupportInitialize pattern) /// public event EventHandler? Stopping; /// public event EventHandler? Stopped; /// public event EventHandler? Activating; /// public event EventHandler? Activated; /// public event EventHandler? Deactivating; /// public event EventHandler? Deactivated; #endregion /// /// Stops and closes this runnable session. /// /// /// /// This method calls to initiate the stopping process. /// The Application infrastructure will update this once IApplication supports IRunnable directly. /// /// public virtual void RequestStop () { // TODO: Phase 3 - Update Application.RequestStop to accept IRunnable // For now, directly call RaiseStoppingEvent which follows CWP RaiseStoppingEvent (); } }