diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs index 1a5b4b362..0d9da0bdc 100644 --- a/Terminal.Gui/Views/Dialog.cs +++ b/Terminal.Gui/Views/Dialog.cs @@ -7,13 +7,21 @@ namespace Terminal.Gui.Views; /// scheme. /// /// -/// To run the modally, create the , and pass it to -/// . This will execute the dialog until -/// it terminates via the (`Esc` by default), -/// or when one of the views or buttons added to the dialog calls -/// . +/// +/// To run the modally, create the , and pass it to +/// . This will execute the dialog until +/// it terminates via the (`Esc` by default), +/// or when one of the views or buttons added to the dialog calls +/// . +/// +/// +/// Phase 2: now implements with +/// int? as the result type, returning the index of the clicked button. The +/// property replaces the need for manual result tracking. A result of indicates +/// the dialog was canceled (ESC pressed, window closed without clicking a button). +/// /// -public class Dialog : Window +public class Dialog : Window, IRunnable { /// /// Initializes a new instance of the class with no s. @@ -85,7 +93,13 @@ public class Dialog : Window } /// Gets a value indicating whether the was canceled. - /// The default value is . + /// + /// The default value is . + /// + /// Deprecated: Use instead. This property is maintained for backward + /// compatibility. A indicates the dialog was canceled. + /// + /// public bool Canceled { get { return _canceled; } @@ -101,6 +115,21 @@ public class Dialog : Window } } + /// + /// Gets or sets the result data extracted when the dialog was accepted, or if not accepted. + /// + /// + /// + /// Returns the zero-based index of the button that was clicked, or if the + /// dialog was canceled (ESC pressed, window closed without clicking a button). + /// + /// + /// This property is automatically set in when the dialog is + /// closing. The result is extracted by finding which button has focus when the dialog stops. + /// + /// + public int? Result { get; set; } + /// /// Defines the default border styling for . Can be configured via /// . @@ -168,4 +197,67 @@ public class Dialog : Window return false; } + + #region IRunnable Implementation + + /// + /// Called when the dialog is about to stop running. Extracts the button result before the dialog is removed + /// from the runnable stack. + /// + /// The current value of IsRunning. + /// The new value of IsRunning (true = starting, false = stopping). + /// to cancel; to proceed. + /// + /// This method is called by the IRunnable infrastructure when the dialog is stopping. It extracts + /// which button was clicked (if any) before views are disposed. + /// + protected virtual bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning) + { + if (!newIsRunning && oldIsRunning) // Stopping + { + // Extract result BEFORE disposal - find which button has focus or was last clicked + Result = null; // Default: canceled (null = no button clicked) + + for (var i = 0; i < _buttons.Count; i++) + { + if (_buttons [i].HasFocus) + { + Result = i; + _canceled = false; + break; + } + } + + // If no button has focus, check if any button was the last focused view + if (Result is null && MostFocused is Button btn && _buttons.Contains (btn)) + { + Result = _buttons.IndexOf (btn); + _canceled = false; + } + + // Update legacy Canceled property for backward compatibility + if (Result is null) + { + _canceled = true; + } + } + else if (newIsRunning) // Starting + { + // Clear result when starting + Result = null; + _canceled = true; // Default to canceled until a button is clicked + } + + // Call base implementation (Toplevel.IRunnable.RaiseIsRunningChanging) + return ((IRunnable)this).RaiseIsRunningChanging (oldIsRunning, newIsRunning); + } + + // Explicitly implement IRunnable to override the behavior from Toplevel's IRunnable + bool IRunnable.RaiseIsRunningChanging (bool oldIsRunning, bool newIsRunning) + { + // Call our virtual method so subclasses can override + return OnIsRunningChanging (oldIsRunning, newIsRunning); + } + + #endregion }