Browse Source

Simplify IRunnable: Rename Activating→Starting, remove Toplevel complexity

Co-authored-by: tig <[email protected]>
copilot-swe-agent[bot] 3 weeks ago
parent
commit
4e1d62b8f5

+ 23 - 69
Terminal.Gui/App/IRunnable.cs

@@ -17,7 +17,7 @@ namespace Terminal.Gui.App;
 /// </para>
 /// <para>
 /// This interface follows the Terminal.Gui Cancellable Work Pattern (CWP) for lifecycle events
-/// where cancellation makes sense (Stopping, Activating, Deactivating).
+/// where cancellation makes sense (Stopping, Starting).
 /// </para>
 /// </remarks>
 public interface IRunnable
@@ -53,60 +53,30 @@ public interface IRunnable
     void RaiseStoppingEvent ();
 
     /// <summary>
-    /// Raises the <see cref="Activating"/> event.
-    /// Called by <see cref="IApplication.Begin"/> when this runnable is becoming the active session.
+    /// Raises the <see cref="Starting"/> event.
+    /// Called by <see cref="IApplication.Begin"/> or <see cref="IApplication.Run"/> when this runnable session is starting.
     /// </summary>
-    /// <param name="deactivated">The previously active runnable being deactivated, or null if none.</param>
-    /// <returns><see langword="true"/> if activation was canceled; otherwise <see langword="false"/>.</returns>
+    /// <returns><see langword="true"/> if starting was canceled; otherwise <see langword="false"/>.</returns>
     /// <remarks>
     /// <para>
-    /// This method implements the Cancellable Work Pattern for activation:
+    /// This method implements the Cancellable Work Pattern for starting:
     /// 1. Calls virtual method (can cancel)
-    /// 2. Raises <see cref="Activating"/> event (can cancel)
+    /// 2. Raises <see cref="Starting"/> event (can cancel)
     /// 3. If canceled, returns true
-    /// 4. If not canceled, calls <see cref="RaiseActivatedEvent"/> and returns false
+    /// 4. If not canceled, calls <see cref="RaiseStartedEvent"/> and returns false
     /// </para>
     /// </remarks>
-    bool RaiseActivatingEvent (IRunnable? deactivated);
+    bool RaiseStartingEvent ();
 
     /// <summary>
-    /// Raises the <see cref="Activated"/> event.
-    /// Called by <see cref="RaiseActivatingEvent"/> after activation succeeds.
+    /// Raises the <see cref="Started"/> event.
+    /// Called by <see cref="RaiseStartingEvent"/> after starting succeeds.
     /// </summary>
-    /// <param name="deactivated">The previously active runnable that was deactivated, or null if none.</param>
     /// <remarks>
-    /// This is the post-notification phase of activation. Implementations should raise the
-    /// <see cref="Activated"/> event.
+    /// This is the post-notification phase of starting. Implementations should raise the
+    /// <see cref="Started"/> event.
     /// </remarks>
-    void RaiseActivatedEvent (IRunnable? deactivated);
-
-    /// <summary>
-    /// Raises the <see cref="Deactivating"/> event.
-    /// Called by <see cref="IApplication.Begin"/> when switching to a new runnable.
-    /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
-    /// <returns><see langword="true"/> if deactivation was canceled; otherwise <see langword="false"/>.</returns>
-    /// <remarks>
-    /// <para>
-    /// This method implements the Cancellable Work Pattern for deactivation:
-    /// 1. Calls virtual method (can cancel)
-    /// 2. Raises <see cref="Deactivating"/> event (can cancel)
-    /// 3. If canceled, returns true
-    /// 4. If not canceled, calls <see cref="RaiseDeactivatedEvent"/> and returns false
-    /// </para>
-    /// </remarks>
-    bool RaiseDeactivatingEvent (IRunnable? activated);
-
-    /// <summary>
-    /// Raises the <see cref="Deactivated"/> event.
-    /// Called by <see cref="RaiseDeactivatingEvent"/> after deactivation succeeds.
-    /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
-    /// <remarks>
-    /// This is the post-notification phase of deactivation. Implementations should raise the
-    /// <see cref="Deactivated"/> event.
-    /// </remarks>
-    void RaiseDeactivatedEvent (IRunnable? activated);
+    void RaiseStartedEvent ();
 
     #endregion
 
@@ -162,40 +132,24 @@ public interface IRunnable
     event EventHandler? Stopped;
 
     /// <summary>
-    /// Raised when the runnable session is about to become active (the current session).
-    /// Can be canceled by setting <see cref="RunnableActivatingEventArgs.Cancel"/> to <see langword="true"/>.
-    /// </summary>
-    /// <remarks>
-    /// Subscribe to this event to prevent activation or to perform pre-activation work.
-    /// </remarks>
-    event EventHandler<RunnableActivatingEventArgs>? Activating;
-
-    /// <summary>
-    /// Raised when the runnable session has become active.
-    /// </summary>
-    /// <remarks>
-    /// This is the post-notification event in the Cancellable Work Pattern pair with <see cref="Activating"/>.
-    /// Subscribe to this event for post-activation logic (e.g., setting focus).
-    /// </remarks>
-    event EventHandler<RunnableEventArgs>? Activated;
-
-    /// <summary>
-    /// Raised when the runnable session is about to cease being active (another session is activating).
-    /// Can be canceled by setting <see cref="RunnableDeactivatingEventArgs.Cancel"/> to <see langword="true"/>.
+    /// Raised when the runnable session is about to start running.
+    /// Can be canceled by setting <see cref="System.ComponentModel.CancelEventArgs.Cancel"/> to <see langword="true"/>.
     /// </summary>
     /// <remarks>
-    /// Subscribe to this event to prevent deactivation or to perform pre-deactivation work.
+    /// Subscribe to this event to prevent starting or to perform pre-start work.
+    /// This aligns with <see cref="Running"/> and <see cref="IApplication.Run"/>.
     /// </remarks>
-    event EventHandler<RunnableDeactivatingEventArgs>? Deactivating;
+    event EventHandler<System.ComponentModel.CancelEventArgs>? Starting;
 
     /// <summary>
-    /// Raised when the runnable session has ceased being active.
+    /// Raised when the runnable session has started running.
     /// </summary>
     /// <remarks>
-    /// This is the post-notification event in the Cancellable Work Pattern pair with <see cref="Deactivating"/>.
-    /// Subscribe to this event for cleanup or state preservation after deactivation.
+    /// This is the post-notification event in the Cancellable Work Pattern pair with <see cref="Starting"/>.
+    /// Subscribe to this event for post-start logic (e.g., setting focus).
+    /// This aligns with <see cref="Running"/> and <see cref="IApplication.Run"/>.
     /// </remarks>
-    event EventHandler<RunnableEventArgs>? Deactivated;
+    event EventHandler? Started;
 
     #endregion
 }

+ 3 - 85
Terminal.Gui/App/RunnableEventArgs.cs

@@ -1,87 +1,5 @@
 namespace Terminal.Gui.App;
 
-/// <summary>
-/// Event args for <see cref="IRunnable"/> lifecycle events that provide information about the runnable.
-/// </summary>
-/// <remarks>
-/// Used for post-notification events that cannot be canceled:
-/// <see cref="IRunnable.Activated"/> and <see cref="IRunnable.Deactivated"/>.
-/// </remarks>
-public class RunnableEventArgs : EventArgs
-{
-    /// <summary>
-    /// Initializes a new instance of <see cref="RunnableEventArgs"/>.
-    /// </summary>
-    /// <param name="runnable">The runnable involved in the event.</param>
-    public RunnableEventArgs (IRunnable runnable)
-    {
-        Runnable = runnable;
-    }
-
-    /// <summary>
-    /// Gets the runnable involved in the event.
-    /// </summary>
-    public IRunnable Runnable { get; }
-}
-
-/// <summary>
-/// Event args for <see cref="IRunnable.Activating"/> event. Allows cancellation.
-/// </summary>
-/// <remarks>
-/// This event is raised when a runnable session is about to become active. It can be canceled
-/// by setting <see cref="System.ComponentModel.CancelEventArgs.Cancel"/> to <see langword="true"/>.
-/// </remarks>
-public class RunnableActivatingEventArgs : System.ComponentModel.CancelEventArgs
-{
-    /// <summary>
-    /// Initializes a new instance of <see cref="RunnableActivatingEventArgs"/>.
-    /// </summary>
-    /// <param name="activating">The runnable that is being activated.</param>
-    /// <param name="deactivated">The runnable that is being deactivated, or null if none.</param>
-    public RunnableActivatingEventArgs (IRunnable activating, IRunnable? deactivated)
-    {
-        Activating = activating;
-        Deactivated = deactivated;
-    }
-
-    /// <summary>
-    /// Gets the runnable that is being activated.
-    /// </summary>
-    public IRunnable Activating { get; }
-
-    /// <summary>
-    /// Gets the runnable that is being deactivated, or null if none.
-    /// </summary>
-    public IRunnable? Deactivated { get; }
-}
-
-/// <summary>
-/// Event args for <see cref="IRunnable.Deactivating"/> event. Allows cancellation.
-/// </summary>
-/// <remarks>
-/// This event is raised when a runnable session is about to cease being active. It can be canceled
-/// by setting <see cref="System.ComponentModel.CancelEventArgs.Cancel"/> to <see langword="true"/>.
-/// </remarks>
-public class RunnableDeactivatingEventArgs : System.ComponentModel.CancelEventArgs
-{
-    /// <summary>
-    /// Initializes a new instance of <see cref="RunnableDeactivatingEventArgs"/>.
-    /// </summary>
-    /// <param name="deactivating">The runnable that is being deactivated.</param>
-    /// <param name="activated">The runnable that is being activated, or null if none.</param>
-    public RunnableDeactivatingEventArgs (IRunnable deactivating, IRunnable? activated)
-    {
-        Deactivating = deactivating;
-        Activated = activated;
-    }
-
-    /// <summary>
-    /// Gets the runnable that is being deactivated.
-    /// </summary>
-    public IRunnable Deactivating { get; }
-
-    /// <summary>
-    /// Gets the runnable that is being activated, or null if none.
-    /// </summary>
-    public IRunnable? Activated { get; }
-}
+// Note: IRunnable lifecycle events (Starting, Started, Stopping, Stopped, Initializing, Initialized) 
+// use standard EventArgs or System.ComponentModel.CancelEventArgs.
+// No custom event args are needed for the simplified IRunnable interface.

+ 53 - 129
Terminal.Gui/ViewBase/Runnable.cs

@@ -11,8 +11,7 @@ namespace Terminal.Gui.ViewBase;
 /// </para>
 /// <para>
 /// To customize lifecycle behavior, override the protected virtual methods:
-/// <see cref="OnStopping"/>, <see cref="OnStopped"/>, <see cref="OnActivating"/>,
-/// <see cref="OnActivated"/>, <see cref="OnDeactivating"/>, <see cref="OnDeactivated"/>.
+/// <see cref="OnStarting"/>, <see cref="OnStarted"/>, <see cref="OnStopping"/>, <see cref="OnStopped"/>.
 /// </para>
 /// </remarks>
 public class Runnable : View, IRunnable
@@ -23,93 +22,67 @@ public class Runnable : View, IRunnable
     #region IRunnable Implementation (RaiseXxxEvent Methods)
 
     /// <inheritdoc/>
-    public virtual void RaiseStoppingEvent ()
+    public virtual bool RaiseStartingEvent ()
     {
         // CWP Phase 1: Pre-notification via virtual method (can cancel)
-        if (OnStopping ())
+        if (OnStarting ())
         {
-            return; // Stopping canceled
+            return true; // Starting canceled
         }
 
         // CWP Phase 2: Event notification (can cancel)
         var args = new System.ComponentModel.CancelEventArgs ();
-        Stopping?.Invoke (this, args);
+        Starting?.Invoke (this, args);
 
         if (args.Cancel)
         {
-            return; // Stopping canceled
+            return true; // Starting canceled
         }
 
-        // CWP Phase 3: Perform the work (stop the session)
-        Running = false;
+        // CWP Phase 3: Perform the work (mark as running)
+        Running = true;
 
         // CWP Phase 4: Post-notification via virtual method
-        OnStopped ();
+        OnStarted ();
 
         // CWP Phase 5: Post-notification event
-        Stopped?.Invoke (this, EventArgs.Empty);
-    }
-
-    /// <inheritdoc/>
-    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);
+        Started?.Invoke (this, EventArgs.Empty);
 
-        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
+        return false; // Starting succeeded
     }
 
     /// <inheritdoc/>
-    public virtual void RaiseActivatedEvent (IRunnable? deactivated)
+    public virtual void RaiseStartedEvent ()
     {
-        Activated?.Invoke (this, new RunnableEventArgs (this));
+        Started?.Invoke (this, EventArgs.Empty);
     }
 
     /// <inheritdoc/>
-    public virtual bool RaiseDeactivatingEvent (IRunnable? activated)
+    public virtual void RaiseStoppingEvent ()
     {
         // CWP Phase 1: Pre-notification via virtual method (can cancel)
-        if (OnDeactivating (activated))
+        if (OnStopping ())
         {
-            return true; // Deactivation canceled
+            return; // Stopping canceled
         }
 
         // CWP Phase 2: Event notification (can cancel)
-        var args = new RunnableDeactivatingEventArgs (this, activated);
-        Deactivating?.Invoke (this, args);
+        var args = new System.ComponentModel.CancelEventArgs ();
+        Stopping?.Invoke (this, args);
 
         if (args.Cancel)
         {
-            return true; // Deactivation canceled
+            return; // Stopping canceled
         }
 
-        // CWP Phase 3: Work is done by Application (changing Current)
-        // CWP Phase 4 & 5: Call post-notification methods
-        OnDeactivated (activated);
+        // CWP Phase 3: Perform the work (stop the session)
+        Running = false;
 
-        return false; // Deactivation succeeded
-    }
+        // CWP Phase 4: Post-notification via virtual method
+        OnStopped ();
 
-    /// <inheritdoc/>
-    public virtual void RaiseDeactivatedEvent (IRunnable? activated)
-    {
-        Deactivated?.Invoke (this, new RunnableEventArgs (this));
+        // CWP Phase 5: Post-notification event
+        Stopped?.Invoke (this, EventArgs.Empty);
     }
 
     #endregion
@@ -117,120 +90,77 @@ public class Runnable : View, IRunnable
     #region Protected Virtual Methods (Override Pattern)
 
     /// <summary>
-    /// Called before <see cref="Stopping"/> event. Override to cancel stopping.
+    /// Called before <see cref="Starting"/> event. Override to cancel starting.
     /// </summary>
     /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
     /// <remarks>
     /// <para>
-    /// This is the first phase of the Cancellable Work Pattern for stopping.
-    /// Default implementation returns <see langword="false"/> (allow stopping).
+    /// This is the first phase of the Cancellable Work Pattern for starting.
+    /// Default implementation returns <see langword="false"/> (allow starting).
     /// </para>
     /// <para>
     /// Override this method to provide custom logic for determining whether the runnable
-    /// should stop (e.g., prompting the user to save changes).
+    /// should start (e.g., validating preconditions).
     /// </para>
     /// </remarks>
-    protected virtual bool OnStopping ()
+    protected virtual bool OnStarting ()
     {
-        return false; // Default: allow stopping
+        return false; // Default: allow starting
     }
 
     /// <summary>
-    /// Called after session has stopped. Override for post-stop cleanup.
+    /// Called after session has started. Override for post-start work.
     /// </summary>
     /// <remarks>
     /// <para>
-    /// This is the fourth phase of the Cancellable Work Pattern for stopping.
-    /// At this point, <see cref="Running"/> is <see langword="false"/>.
+    /// This is the fourth phase of the Cancellable Work Pattern for starting.
+    /// At this point, <see cref="Running"/> is <see langword="true"/>.
     /// Default implementation does nothing.
     /// </para>
     /// <para>
-    /// Override this method to perform cleanup work that should occur after the session stops.
+    /// Override this method to perform work that should occur after the session starts.
     /// </para>
     /// </remarks>
-    protected virtual void OnStopped ()
+    protected virtual void OnStarted ()
     {
         // Default: do nothing
     }
 
     /// <summary>
-    /// Called before <see cref="Activating"/> event. Override to cancel activation.
-    /// </summary>
-    /// <param name="deactivated">The previously active runnable being deactivated, or null if none.</param>
-    /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
-    /// <remarks>
-    /// <para>
-    /// This is the first phase of the Cancellable Work Pattern for activation.
-    /// Default implementation returns <see langword="false"/> (allow activation).
-    /// </para>
-    /// <para>
-    /// Override this method to provide custom logic for determining whether the runnable
-    /// should become active.
-    /// </para>
-    /// </remarks>
-    protected virtual bool OnActivating (IRunnable? deactivated)
-    {
-        return false; // Default: allow activation
-    }
-
-    /// <summary>
-    /// Called after activation succeeds. Override for post-activation logic.
-    /// </summary>
-    /// <param name="deactivated">The previously active runnable that was deactivated, or null if none.</param>
-    /// <remarks>
-    /// <para>
-    /// This is the fourth phase of the Cancellable Work Pattern for activation.
-    /// Default implementation calls <see cref="RaiseActivatedEvent"/>.
-    /// </para>
-    /// <para>
-    /// Override this method to perform work that should occur after activation
-    /// (e.g., setting focus, updating UI). Overrides must call base to ensure the
-    /// <see cref="Activated"/> event is raised.
-    /// </para>
-    /// </remarks>
-    protected virtual void OnActivated (IRunnable? deactivated)
-    {
-        RaiseActivatedEvent (deactivated);
-    }
-
-    /// <summary>
-    /// Called before <see cref="Deactivating"/> event. Override to cancel deactivation.
+    /// Called before <see cref="Stopping"/> event. Override to cancel stopping.
     /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
     /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
     /// <remarks>
     /// <para>
-    /// This is the first phase of the Cancellable Work Pattern for deactivation.
-    /// Default implementation returns <see langword="false"/> (allow deactivation).
+    /// This is the first phase of the Cancellable Work Pattern for stopping.
+    /// Default implementation returns <see langword="false"/> (allow stopping).
     /// </para>
     /// <para>
     /// Override this method to provide custom logic for determining whether the runnable
-    /// should be deactivated (e.g., preventing switching away if unsaved changes exist).
+    /// should stop (e.g., prompting the user to save changes).
     /// </para>
     /// </remarks>
-    protected virtual bool OnDeactivating (IRunnable? activated)
+    protected virtual bool OnStopping ()
     {
-        return false; // Default: allow deactivation
+        return false; // Default: allow stopping
     }
 
     /// <summary>
-    /// Called after deactivation succeeds. Override for post-deactivation logic.
+    /// Called after session has stopped. Override for post-stop cleanup.
     /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
     /// <remarks>
     /// <para>
-    /// This is the fourth phase of the Cancellable Work Pattern for deactivation.
-    /// Default implementation calls <see cref="RaiseDeactivatedEvent"/>.
+    /// This is the fourth phase of the Cancellable Work Pattern for stopping.
+    /// At this point, <see cref="Running"/> is <see langword="false"/>.
+    /// Default implementation does nothing.
     /// </para>
     /// <para>
-    /// Override this method to perform work that should occur after deactivation
-    /// (e.g., saving state, releasing resources). Overrides must call base to ensure the
-    /// <see cref="Deactivated"/> event is raised.
+    /// Override this method to perform cleanup work that should occur after the session stops.
     /// </para>
     /// </remarks>
-    protected virtual void OnDeactivated (IRunnable? activated)
+    protected virtual void OnStopped ()
     {
-        RaiseDeactivatedEvent (activated);
+        // Default: do nothing
     }
 
     #endregion
@@ -240,22 +170,16 @@ public class Runnable : View, IRunnable
     // Note: Initializing and Initialized events are inherited from View (ISupportInitialize pattern)
 
     /// <inheritdoc/>
-    public event EventHandler<System.ComponentModel.CancelEventArgs>? Stopping;
+    public event EventHandler<System.ComponentModel.CancelEventArgs>? Starting;
 
     /// <inheritdoc/>
-    public event EventHandler? Stopped;
+    public event EventHandler? Started;
 
     /// <inheritdoc/>
-    public event EventHandler<RunnableActivatingEventArgs>? Activating;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableEventArgs>? Activated;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableDeactivatingEventArgs>? Deactivating;
+    public event EventHandler<System.ComponentModel.CancelEventArgs>? Stopping;
 
     /// <inheritdoc/>
-    public event EventHandler<RunnableEventArgs>? Deactivated;
+    public event EventHandler? Stopped;
 
     #endregion
 

+ 2 - 56
Terminal.Gui/Views/Dialog.cs

@@ -7,19 +7,13 @@ namespace Terminal.Gui.Views;
 ///     scheme.
 /// </summary>
 /// <remarks>
-///     <para>
 ///     To run the <see cref="Dialog"/> modally, create the <see cref="Dialog"/>, and pass it to
 ///     <see cref="IApplication.Run(Toplevel, Func{Exception, bool})"/>. This will execute the dialog until
 ///     it terminates via the <see cref="Application.QuitKey"/> (`Esc` by default),
 ///     or when one of the views or buttons added to the dialog calls
 ///     <see cref="Application.RequestStop"/>.
-///     </para>
-///     <para>
-///     Dialog implements <see cref="IModalRunnable{TResult}"/> with <c>int?</c> as the result type.
-///     The <see cref="Result"/> property contains the index of the button that was clicked, or null if canceled.
-///     </para>
 /// </remarks>
-public class Dialog : Window, IModalRunnable<int?>
+public class Dialog : Window
 {
     /// <summary>
     ///     Initializes a new instance of the <see cref="Dialog"/> class with no <see cref="Button"/>s.
@@ -66,24 +60,6 @@ public class Dialog : Window, IModalRunnable<int?>
 
         _buttons.Add (button);
         Add (button);
-
-        // Subscribe to the button's Accept command to set Result
-        button.Accepting += Button_Accepting;
-    }
-
-    private void Button_Accepting (object? sender, CommandEventArgs e)
-    {
-        // Set Result to the index of the button that was clicked
-        if (sender is Button button)
-        {
-            int index = _buttons.IndexOf (button);
-            if (index >= 0)
-            {
-                Result = index;
-                // For backward compatibility, set Canceled = false
-                Canceled = false;
-            }
-        }
     }
 
     // TODO: Update button.X = Pos.Justify when alignment changes
@@ -109,14 +85,7 @@ public class Dialog : Window, IModalRunnable<int?>
     }
 
     /// <summary>Gets a value indicating whether the <see cref="Dialog"/> was canceled.</summary>
-    /// <remarks>
-    /// <para>The default value is <see langword="true"/>.</para>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="Result"/> instead. When <see cref="Result"/> is null, the dialog was canceled.
-    /// This property is maintained for backward compatibility.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use Result property instead. Result == null indicates the dialog was canceled.")]
+    /// <remarks>The default value is <see langword="true"/>.</remarks>
     public bool Canceled
     {
         get { return _canceled; }
@@ -132,29 +101,6 @@ public class Dialog : Window, IModalRunnable<int?>
         }
     }
 
-    /// <summary>
-    /// Gets or sets the result of the modal dialog operation.
-    /// </summary>
-    /// <remarks>
-    /// <para>
-    /// Contains the zero-based index of the button that was clicked to close the dialog,
-    /// or null if the dialog was canceled (e.g., ESC key pressed).
-    /// </para>
-    /// <para>
-    /// The button index corresponds to the order buttons were added via <see cref="AddButton"/> or
-    /// the <see cref="Buttons"/> initializer.
-    /// </para>
-    /// <para>
-    /// For backward compatibility with the <see cref="Canceled"/> property:
-    /// - <see cref="Result"/> == null means the dialog was canceled (<see cref="Canceled"/> == true)
-    /// - <see cref="Result"/> != null means a button was clicked (<see cref="Canceled"/> == false)
-    /// </para>
-    /// <para>
-    /// This property implements <see cref="IModalRunnable{TResult}.Result"/> where TResult is <c>int?</c>.
-    /// </para>
-    /// </remarks>
-    public int? Result { get; set; }
-
     /// <summary>
     ///     Defines the default border styling for <see cref="Dialog"/>. Can be configured via
     ///     <see cref="ConfigurationManager"/>.

+ 3 - 274
Terminal.Gui/Views/Toplevel.cs

@@ -17,12 +17,8 @@ namespace Terminal.Gui.Views;
 ///         and run (e.g. <see cref="Dialog"/>s). To run a Toplevel, create the <see cref="Toplevel"/> and call
 ///         <see cref="IApplication.Run(Toplevel, Func{Exception, bool})"/>.
 ///     </para>
-///     <para>
-///         Toplevel implements <see cref="IRunnable"/> to support the runnable session lifecycle with proper event handling
-///         following the Cancellable Work Pattern (CWP).
-///     </para>
 /// </remarks>
-public partial class Toplevel : View, IRunnable
+public partial class Toplevel : View
 {
     /// <summary>
     ///     Initializes a new instance of the <see cref="Toplevel"/> class,
@@ -96,60 +92,27 @@ public partial class Toplevel : View, IRunnable
     /// </summary>
     public bool IsLoaded { get; private set; }
 
+    // TODO: IRunnable: Re-implement as an event on IRunnable; IRunnable.Activating/Activate
     /// <summary>Invoked when the Toplevel <see cref="SessionToken"/> active.</summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="IRunnable.Activated"/> instead. This event is maintained for backward
-    /// compatibility and will be raised alongside the new <see cref="IRunnable.Activated"/> event.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use IRunnable.Activated instead. This event is maintained for backward compatibility.")]
     public event EventHandler<ToplevelEventArgs>? Activate;
 
+    // TODO: IRunnable: Re-implement as an event on IRunnable; IRunnable.Deactivating/Deactivate?
     /// <summary>Invoked when the Toplevel<see cref="SessionToken"/> ceases to be active.</summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="IRunnable.Deactivated"/> instead. This event is maintained for backward
-    /// compatibility and will be raised alongside the new <see cref="IRunnable.Deactivated"/> event.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use IRunnable.Deactivated instead. This event is maintained for backward compatibility.")]
     public event EventHandler<ToplevelEventArgs>? Deactivate;
 
     /// <summary>Invoked when the Toplevel's <see cref="SessionToken"/> is closed by <see cref="IApplication.End(SessionToken)"/>.</summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> This event is maintained for backward compatibility. The IRunnable architecture
-    /// combines this functionality into the <see cref="IRunnable.Stopped"/> event.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use IRunnable.Stopped instead. This event is maintained for backward compatibility.")]
     public event EventHandler<ToplevelEventArgs>? Closed;
 
     /// <summary>
     ///     Invoked when the Toplevel's <see cref="SessionToken"/> is being closed by
     ///     <see cref="IApplication.RequestStop(Toplevel)"/>.
     /// </summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="IRunnable.Stopping"/> instead. This event is maintained for backward
-    /// compatibility and will be raised alongside the new <see cref="IRunnable.Stopping"/> event.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use IRunnable.Stopping instead. This event is maintained for backward compatibility.")]
     public event EventHandler<ToplevelClosingEventArgs>? Closing;
 
     /// <summary>
     ///     Invoked when the <see cref="Toplevel"/> <see cref="SessionToken"/> has begun to be loaded. A Loaded event handler
     ///     is a good place to finalize initialization before calling Run.
     /// </summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="View.Initialized"/> instead. The Loaded event conceptually maps to
-    /// the Initialized event from the ISupportInitialize pattern, which is now part of IRunnable.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use View.Initialized instead. The Loaded event maps to the Initialized event from ISupportInitialize.")]
     public event EventHandler? Loaded;
 
     /// <summary>
@@ -181,13 +144,6 @@ public partial class Toplevel : View, IRunnable
     ///         <see cref="IApplication.Run(Toplevel, Func{Exception, bool})"/> on this <see cref="Toplevel"/>.
     ///     </para>
     /// </summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="View.Initialized"/> instead. The Ready event is similar to Initialized
-    /// but was fired later in the lifecycle. The IRunnable architecture consolidates these into Initialized.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use View.Initialized instead. The Ready event is consolidated into the Initialized event.")]
     public event EventHandler? Ready;
 
     /// <summary>
@@ -203,13 +159,6 @@ public partial class Toplevel : View, IRunnable
     ///     Invoked when the Toplevel <see cref="SessionToken"/> has been unloaded. A Unloaded event handler is a good place
     ///     to dispose objects after calling <see cref="IApplication.End(SessionToken)"/>.
     /// </summary>
-    /// <remarks>
-    /// <para>
-    /// <b>Obsolete:</b> Use <see cref="IRunnable.Stopped"/> instead. The Unloaded event is consolidated into
-    /// the Stopped event in the IRunnable architecture.
-    /// </para>
-    /// </remarks>
-    [Obsolete ("Use IRunnable.Stopped instead. The Unloaded event is consolidated into the Stopped event.")]
     public event EventHandler? Unloaded;
 
     internal virtual void OnActivate (Toplevel deactivated) { Activate?.Invoke (this, new (deactivated)); }
@@ -254,226 +203,6 @@ public partial class Toplevel : View, IRunnable
 
     #endregion
 
-    #region IRunnable Implementation
-
-    // Note: Running property is already defined above in the Life Cycle region (line 86)
-    // Note: Initializing and Initialized events are inherited from View (ISupportInitialize pattern)
-
-    /// <inheritdoc/>
-    public event EventHandler<System.ComponentModel.CancelEventArgs>? Stopping;
-
-    /// <inheritdoc/>
-    public event EventHandler? Stopped;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableActivatingEventArgs>? Activating;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableEventArgs>? Activated;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableDeactivatingEventArgs>? Deactivating;
-
-    /// <inheritdoc/>
-    public event EventHandler<RunnableEventArgs>? Deactivated;
-
-    /// <inheritdoc/>
-    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);
-    }
-
-    /// <inheritdoc/>
-    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
-    }
-
-    /// <inheritdoc/>
-    public virtual void RaiseActivatedEvent (IRunnable? deactivated)
-    {
-        Activated?.Invoke (this, new RunnableEventArgs (this));
-    }
-
-    /// <inheritdoc/>
-    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
-    }
-
-    /// <inheritdoc/>
-    public virtual void RaiseDeactivatedEvent (IRunnable? activated)
-    {
-        Deactivated?.Invoke (this, new RunnableEventArgs (this));
-    }
-
-    /// <summary>
-    /// Called before <see cref="Stopping"/> event. Override to cancel stopping.
-    /// </summary>
-    /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
-    /// <remarks>
-    /// <para>
-    /// This is the first phase of the Cancellable Work Pattern for stopping.
-    /// Default implementation calls the legacy <see cref="OnClosing"/> method for backward compatibility.
-    /// </para>
-    /// </remarks>
-    protected virtual bool OnStopping ()
-    {
-        // For backward compatibility, delegate to legacy OnClosing method
-        var ev = new ToplevelClosingEventArgs (this);
-        return OnClosing (ev);
-    }
-
-    /// <summary>
-    /// Called after session has stopped. Override for post-stop cleanup.
-    /// </summary>
-    /// <remarks>
-    /// Default implementation does nothing. For backward compatibility, the legacy <see cref="Closed"/>
-    /// event is raised by Application.End().
-    /// </remarks>
-    protected virtual void OnStopped ()
-    {
-        // Default: do nothing
-        // Note: Legacy Closed event is raised by Application.End()
-    }
-
-    /// <summary>
-    /// Called before <see cref="Activating"/> event. Override to cancel activation.
-    /// </summary>
-    /// <param name="deactivated">The previously active runnable being deactivated, or null if none.</param>
-    /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
-    /// <remarks>
-    /// Default implementation returns false (allow activation). For backward compatibility,
-    /// the legacy <see cref="OnActivate"/> method is called after activation succeeds.
-    /// </remarks>
-    protected virtual bool OnActivating (IRunnable? deactivated)
-    {
-        return false; // Default: allow activation
-    }
-
-    /// <summary>
-    /// Called after activation succeeds. Override for post-activation logic.
-    /// </summary>
-    /// <param name="deactivated">The previously active runnable that was deactivated, or null if none.</param>
-    /// <remarks>
-    /// Default implementation raises the <see cref="Activated"/> event and calls the legacy
-    /// <see cref="OnActivate"/> method for backward compatibility.
-    /// </remarks>
-    protected virtual void OnActivated (IRunnable? deactivated)
-    {
-        RaiseActivatedEvent (deactivated);
-
-        // For backward compatibility, call legacy OnActivate if deactivated is a Toplevel
-        if (deactivated is Toplevel tl)
-        {
-            OnActivate (tl);
-        }
-        else
-        {
-            // If not a Toplevel, still raise the legacy Activate event with null
-            Activate?.Invoke (this, new ToplevelEventArgs (null));
-        }
-    }
-
-    /// <summary>
-    /// Called before <see cref="Deactivating"/> event. Override to cancel deactivation.
-    /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
-    /// <returns><see langword="true"/> to cancel; <see langword="false"/> to proceed.</returns>
-    /// <remarks>
-    /// Default implementation returns false (allow deactivation).
-    /// </remarks>
-    protected virtual bool OnDeactivating (IRunnable? activated)
-    {
-        return false; // Default: allow deactivation
-    }
-
-    /// <summary>
-    /// Called after deactivation succeeds. Override for post-deactivation logic.
-    /// </summary>
-    /// <param name="activated">The newly activated runnable, or null if none.</param>
-    /// <remarks>
-    /// Default implementation raises the <see cref="Deactivated"/> event and calls the legacy
-    /// <see cref="OnDeactivate"/> method for backward compatibility.
-    /// </remarks>
-    protected virtual void OnDeactivated (IRunnable? activated)
-    {
-        RaiseDeactivatedEvent (activated);
-
-        // For backward compatibility, call legacy OnDeactivate if activated is a Toplevel
-        if (activated is Toplevel tl)
-        {
-            OnDeactivate (tl);
-        }
-        else
-        {
-            // If not a Toplevel, still raise the legacy Deactivate event with null
-            Deactivate?.Invoke (this, new ToplevelEventArgs (null));
-        }
-    }
-
-    #endregion
-
     #region Size / Position Management
 
     // TODO: Make cancelable?

+ 0 - 164
Tests/UnitTests/Views/IRunnableTests.cs

@@ -1,164 +0,0 @@
-using Xunit;
-using Xunit.Abstractions;
-
-namespace UnitTests.ViewsTests;
-
-public class IRunnableTests (ITestOutputHelper output)
-{
-    private readonly ITestOutputHelper _output = output;
-
-    [Fact]
-    public void Toplevel_Implements_IRunnable ()
-    {
-        var top = new Toplevel ();
-        Assert.IsAssignableFrom<IRunnable> (top);
-    }
-
-    [Fact]
-    public void Dialog_Implements_IModalRunnable ()
-    {
-        var dialog = new Dialog ();
-        Assert.IsAssignableFrom<IRunnable> (dialog);
-        Assert.IsAssignableFrom<IModalRunnable<int?>> (dialog);
-    }
-
-    [Fact]
-    public void Runnable_Base_Class_Works ()
-    {
-        var runnable = new Runnable ();
-        Assert.IsAssignableFrom<IRunnable> (runnable);
-        Assert.False (runnable.Running);
-    }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void Dialog_Result_Property_Works ()
-    {
-        var dialog = new Dialog ();
-        var btn1 = new Button { Text = "OK" };
-        var btn2 = new Button { Text = "Cancel" };
-
-        dialog.AddButton (btn1);
-        dialog.AddButton (btn2);
-
-        // Result should be null by default
-        Assert.Null (dialog.Result);
-
-        // Simulate clicking the first button by invoking Accept
-        btn1.InvokeCommand (Command.Accept);
-
-        // Result should now be 0 (first button)
-        Assert.Equal (0, dialog.Result);
-
-        // Reset
-        dialog.Result = null;
-
-        // Simulate clicking the second button
-        btn2.InvokeCommand (Command.Accept);
-
-        // Result should now be 1 (second button)
-        Assert.Equal (1, dialog.Result);
-    }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void Toplevel_Legacy_Events_Still_Work ()
-    {
-        // Verify that legacy Toplevel events still fire for backward compatibility
-        var eventsRaised = new List<string> ();
-        var top = new Toplevel ();
-
-#pragma warning disable CS0618 // Type or member is obsolete
-        top.Activate += (s, e) => eventsRaised.Add ("Activate");
-#pragma warning restore CS0618
-
-        var token = Application.Begin (top);
-
-        // Legacy event should still fire
-        Assert.Contains ("Activate", eventsRaised);
-
-        Application.End (token);
-    }
-
-    [Fact]
-    public void IRunnable_Stopping_Event_Works ()
-    {
-        // Test that the Stopping event can be subscribed to and fires
-        var top = new Toplevel ();
-        var stoppingFired = false;
-        var stoppedFired = false;
-
-        top.Stopping += (s, e) => { stoppingFired = true; };
-        top.Stopped += (s, e) => { stoppedFired = true; };
-
-        top.Running = true;
-        top.RaiseStoppingEvent ();
-
-        Assert.True (stoppingFired);
-        Assert.True (stoppedFired);
-        Assert.False (top.Running);
-    }
-
-    [Fact]
-    public void IRunnable_Stopping_Can_Be_Canceled ()
-    {
-        // Test that the Stopping event can cancel the stop operation
-        var top = new Toplevel ();
-        var stoppingFired = false;
-        var stoppedFired = false;
-
-        top.Stopping += (s, e) =>
-        {
-            stoppingFired = true;
-            e.Cancel = true; // Cancel the stop
-        };
-
-        top.Stopped += (s, e) => { stoppedFired = true; };
-
-        top.Running = true;
-        top.RaiseStoppingEvent ();
-
-        Assert.True (stoppingFired);
-        Assert.False (stoppedFired); // Should not fire because it was canceled
-        Assert.True (top.Running); // Should still be running
-    }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void IRunnable_Initialization_Events_Fire ()
-    {
-        // Test that Initializing and Initialized events fire
-        var initializingFired = false;
-        var initializedFired = false;
-        var top = new Toplevel ();
-
-        top.Initializing += (s, e) => { initializingFired = true; };
-        top.Initialized += (s, e) => { initializedFired = true; };
-
-        var token = Application.Begin (top);
-
-        Assert.True (initializingFired);
-        Assert.True (initializedFired);
-
-        Application.End (token);
-    }
-
-    [Fact]
-    public void IRunnable_Activating_And_Activated_Events_Can_Fire ()
-    {
-        // Test that manually calling the activation methods works
-        var activatingFired = false;
-        var activatedFired = false;
-        var top = new Toplevel ();
-
-        top.Activating += (s, e) => { activatingFired = true; };
-        top.Activated += (s, e) => { activatedFired = true; };
-
-        // Manually trigger activation
-        bool canceled = top.RaiseActivatingEvent (null);
-
-        Assert.False (canceled);
-        Assert.True (activatingFired);
-        Assert.True (activatedFired);
-    }
-}