Browse Source

Fixes #4320 - `Dialog` focus (#4321)

* Fixes #4320 - Dialog and MessageBox rendering of Text should ignore HasFocus

Refactor and enhance text drawing logic

Refactored `DoDrawText` in `View.Drawing.cs` to improve efficiency by adding early exits for unnecessary operations and introducing extensibility points (`OnDrawingText`, `OnDrewText`, and `DrewText` event). Simplified `DrawText` by delegating logic to `DoDrawText`.

Added `OnDrewText` and `DrewText` event to allow custom post-draw handling. Updated `Dialog` class to ensure consistent text rendering using the `Normal` attribute and cleaned up event handling logic.

* Update Terminal.Gui/ViewBase/View.Drawing.cs

Co-authored-by: Copilot <[email protected]>

* Refactor Dialog text rendering logic

Refactored the `Dialog` class to improve text rendering behavior:
- Introduced `_drawingText` flag to track text drawing state.
- Updated `OnDrawingText` to set `_drawingText` to `true`.
- Updated `OnDrewText` to reset `_drawingText` to `false`.
- Replaced `GettingAttributeForRoleHandler` with `OnGettingAttributeForRole`.
  - Ensures `VisualRole.Focus` uses the normal scheme attribute when drawing text.
- Removed unused event handler `GettingAttributeForRoleHandler`.

---------

Co-authored-by: Copilot <[email protected]>
Tig 1 month ago
parent
commit
db5fdebfa9
2 changed files with 51 additions and 10 deletions
  1. 21 10
      Terminal.Gui/ViewBase/View.Drawing.cs
  2. 30 0
      Terminal.Gui/Views/Dialog.cs

+ 21 - 10
Terminal.Gui/ViewBase/View.Drawing.cs

@@ -377,6 +377,16 @@ public partial class View // Drawing APIs
 
     private void DoDrawText (DrawContext? context = null)
     {
+        if (!NeedsDraw)
+        {
+            return;
+        }
+
+        if (!string.IsNullOrEmpty (TextFormatter.Text))
+        {
+            TextFormatter.NeedsFormat = true;
+        }
+
         if (OnDrawingText (context))
         {
             return;
@@ -397,6 +407,9 @@ public partial class View // Drawing APIs
         }
 
         DrawText (context);
+
+        OnDrewText();
+        DrewText?.Invoke(this, EventArgs.Empty);
     }
 
     /// <summary>
@@ -425,11 +438,6 @@ public partial class View // Drawing APIs
     /// <param name="context">The draw context to report drawn areas to.</param>
     public void DrawText (DrawContext? context = null)
     {
-        if (!string.IsNullOrEmpty (TextFormatter.Text))
-        {
-            TextFormatter.NeedsFormat = true;
-        }
-
         var drawRect = new Rectangle (ContentToScreen (Point.Empty), GetContentSize ());
 
         // Use GetDrawRegion to get precise drawn areas
@@ -438,11 +446,6 @@ public partial class View // Drawing APIs
         // Report the drawn area to the context
         context?.AddDrawnRegion (textRegion);
 
-        if (!NeedsDraw)
-        {
-            return;
-        }
-
         TextFormatter?.Draw (
                              drawRect,
                              HasFocus ? GetAttributeForRole (VisualRole.Focus) : GetAttributeForRole (VisualRole.Normal),
@@ -454,6 +457,14 @@ public partial class View // Drawing APIs
         SetSubViewNeedsDraw ();
     }
 
+    /// <summary>
+    ///     Called when the <see cref="Text"/> of the View has been drawn.
+    /// </summary>
+    protected virtual void OnDrewText () { }
+
+    /// <summary>Raised when the <see cref="Text"/> of the View has been drawn.</summary>
+    public event EventHandler? DrewText;
+
     #endregion DrawText
     #region DrawContent
 

+ 30 - 0
Terminal.Gui/Views/Dialog.cs

@@ -138,4 +138,34 @@ public class Dialog : Window
     /// </summary>
     [ConfigurationProperty (Scope = typeof (ThemeScope))]
     public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.Transparent;
+
+
+    // Dialogs are Modal and Focus is indicated by their Border. The following code ensures the
+    // Text of the dialog (e.g. for a MessageBox) is always drawn using the Normal Attribute.
+    private bool _drawingText;
+
+    /// <inheritdoc/>
+    protected override bool OnDrawingText ()
+    {
+        _drawingText = true;
+        return false;
+    }
+
+    /// <inheritdoc/>
+    protected override void OnDrewText ()
+    {
+        _drawingText = false;
+    }
+
+    /// <inheritdoc />
+    protected override bool OnGettingAttributeForRole (in VisualRole role, ref Attribute currentAttribute)
+    {
+        if (_drawingText && role is VisualRole.Focus && Border?.Thickness != Thickness.Empty)
+        {
+            currentAttribute = GetScheme ().Normal;
+            return true;
+        }
+
+        return false;
+    }
 }