From 9cfa78a0330f6ff05c9460d7064fd9167d90d60d Mon Sep 17 00:00:00 2001 From: BDisp Date: Tue, 21 Feb 2023 01:23:40 +0000 Subject: [PATCH] Fixes #2354. View.Redraw doesn't clear itself and PositionCursor doesn't ensure focus when a prior view was disabled. (#2355) * Fixes #2354. View should have a IgnoreHasFocusPropertyOnRedraw property to prevent unnecessary derived class. * Removed IgnoreHasFocusPropertyOnRedraw property. --------- Co-authored-by: Tig --- Terminal.Gui/Core/Toplevel.cs | 9 ++++++ Terminal.Gui/Core/View.cs | 47 +++++++++++++++++++++------- UnitTests/TopLevels/ToplevelTests.cs | 20 ++++++++++++ UnitTests/Views/ViewTests.cs | 3 ++ 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 881b97426..02691b84f 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -908,6 +908,12 @@ namespace Terminal.Gui { { if (!IsMdiContainer) { base.PositionCursor (); + if (Focused == null) { + EnsureFocus (); + if (Focused == null) { + Driver.SetCursorVisibility (CursorVisibility.Invisible); + } + } return; } @@ -920,6 +926,9 @@ namespace Terminal.Gui { } } base.PositionCursor (); + if (Focused == null) { + Driver.SetCursorVisibility (CursorVisibility.Invisible); + } } /// diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index adf368c81..018cf1384 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -951,6 +951,10 @@ namespace Terminal.Gui { view.tabIndex = tabIndexes.IndexOf (view); addingView = false; } + if (view.Enabled && !Enabled) { + view.oldEnabled = true; + view.Enabled = false; + } SetNeedsLayout (); SetNeedsDisplay (); OnAdded (view); @@ -1303,14 +1307,16 @@ namespace Terminal.Gui { return; } - if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.Height > 0) { + if (focused == null && SuperView != null) { + SuperView.EnsureFocus (); + } else if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.Height > 0) { focused.PositionCursor (); + } else if (focused?.Visible == true && focused?.Enabled == false) { + focused = null; + } else if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0) { + Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0); } else { - if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0) { - Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0); - } else { - Move (frame.X, frame.Y); - } + Move (frame.X, frame.Y); } } @@ -1504,13 +1510,13 @@ namespace Terminal.Gui { var clipRect = new Rect (Point.Empty, frame.Size); if (ColorScheme != null) { - Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal); + Driver.SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ()); } if (!IgnoreBorderPropertyOnRedraw && Border != null) { Border.DrawContent (this); } else if (ustring.IsNullOrEmpty (TextFormatter.Text) && - (GetType ().IsNestedPublic) && !IsOverridden (this, "Redraw") && + (GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") && (!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) { Clear (); @@ -1525,8 +1531,8 @@ namespace Terminal.Gui { if (TextFormatter != null) { TextFormatter.NeedsFormat = true; } - TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? ColorScheme.Focus : GetNormalColor (), - HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled, + TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (), + HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (), containerBounds); } @@ -2617,7 +2623,13 @@ namespace Terminal.Gui { get => base.Enabled; set { if (base.Enabled != value) { - base.Enabled = value; + if (value) { + if (SuperView == null || SuperView?.Enabled == true) { + base.Enabled = value; + } + } else { + base.Enabled = value; + } if (!value && HasFocus) { SetHasFocus (false, this); } @@ -2684,7 +2696,7 @@ namespace Terminal.Gui { /// to draw the view's border. If no border is drawn (and the view is expected to draw the border /// itself). /// - public virtual bool IgnoreBorderPropertyOnRedraw { get; set; } = false; + public virtual bool IgnoreBorderPropertyOnRedraw { get; set; } /// /// Pretty prints the View @@ -3109,6 +3121,17 @@ namespace Terminal.Gui { return Enabled ? ColorScheme.Normal : ColorScheme.Disabled; } + /// + /// Determines the current based on the value. + /// + /// if is + /// or if is . + /// If it's overridden can return other values. + public virtual Attribute GetFocusColor () + { + return Enabled ? ColorScheme.Focus : ColorScheme.Disabled; + } + /// /// Determines the current based on the value. /// diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs index 88f9181dd..e39a73a2c 100644 --- a/UnitTests/TopLevels/ToplevelTests.cs +++ b/UnitTests/TopLevels/ToplevelTests.cs @@ -1011,5 +1011,25 @@ namespace Terminal.Gui.TopLevelTests { Assert.True (isEnter); Assert.False (isLeave); } + + [Fact, AutoInitShutdown] + public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null () + { + var tf = new TextField ("test") { Width = 5 }; + var view = new View () { Width = 10, Height = 10 }; + view.Add (tf); + Application.Top.Add (view); + Application.Begin (Application.Top); + + Assert.True (tf.HasFocus); + Application.Driver.GetCursorVisibility (out CursorVisibility cursor); + Assert.Equal (CursorVisibility.Default, cursor); + + view.Enabled = false; + Assert.False (tf.HasFocus); + Application.Refresh (); + Application.Driver.GetCursorVisibility (out cursor); + Assert.Equal (CursorVisibility.Invisible, cursor); + } } } \ No newline at end of file diff --git a/UnitTests/Views/ViewTests.cs b/UnitTests/Views/ViewTests.cs index 1cfc1296b..396bf7bde 100644 --- a/UnitTests/Views/ViewTests.cs +++ b/UnitTests/Views/ViewTests.cs @@ -1,5 +1,6 @@ using NStack; using System; +using System.Collections.Generic; using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; @@ -4209,6 +4210,7 @@ cccccccccccccccccccc", output); v.CanFocus = true; Assert.False (v.HasFocus); v.SetFocus (); + Assert.True (v.HasFocus); Application.Refresh (); TestHelpers.AssertDriverColorsAre (@" 111111111111111111110", attributes); @@ -4491,6 +4493,7 @@ At 0,0 A text witith two lines. ", output); } + [Fact, AutoInitShutdown] public void Test_Nested_Views_With_Height_Equal_To_One () {