Skip to content

Commit 9cfa78a

Browse files
BDisptig
andauthored
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 <tig@users.noreply.github.com>
1 parent 47eb43f commit 9cfa78a

File tree

4 files changed

+67
-12
lines changed

4 files changed

+67
-12
lines changed

Terminal.Gui/Core/Toplevel.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,12 @@ public override void PositionCursor ()
908908
{
909909
if (!IsMdiContainer) {
910910
base.PositionCursor ();
911+
if (Focused == null) {
912+
EnsureFocus ();
913+
if (Focused == null) {
914+
Driver.SetCursorVisibility (CursorVisibility.Invisible);
915+
}
916+
}
911917
return;
912918
}
913919

@@ -920,6 +926,9 @@ public override void PositionCursor ()
920926
}
921927
}
922928
base.PositionCursor ();
929+
if (Focused == null) {
930+
Driver.SetCursorVisibility (CursorVisibility.Invisible);
931+
}
923932
}
924933

925934
/// <summary>

Terminal.Gui/Core/View.cs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,10 @@ public virtual void Add (View view)
951951
view.tabIndex = tabIndexes.IndexOf (view);
952952
addingView = false;
953953
}
954+
if (view.Enabled && !Enabled) {
955+
view.oldEnabled = true;
956+
view.Enabled = false;
957+
}
954958
SetNeedsLayout ();
955959
SetNeedsDisplay ();
956960
OnAdded (view);
@@ -1303,14 +1307,16 @@ public virtual void PositionCursor ()
13031307
return;
13041308
}
13051309

1306-
if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.Height > 0) {
1310+
if (focused == null && SuperView != null) {
1311+
SuperView.EnsureFocus ();
1312+
} else if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.Height > 0) {
13071313
focused.PositionCursor ();
1314+
} else if (focused?.Visible == true && focused?.Enabled == false) {
1315+
focused = null;
1316+
} else if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0) {
1317+
Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0);
13081318
} else {
1309-
if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0) {
1310-
Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0);
1311-
} else {
1312-
Move (frame.X, frame.Y);
1313-
}
1319+
Move (frame.X, frame.Y);
13141320
}
13151321
}
13161322

@@ -1504,13 +1510,13 @@ public virtual void Redraw (Rect bounds)
15041510
var clipRect = new Rect (Point.Empty, frame.Size);
15051511

15061512
if (ColorScheme != null) {
1507-
Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
1513+
Driver.SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ());
15081514
}
15091515

15101516
if (!IgnoreBorderPropertyOnRedraw && Border != null) {
15111517
Border.DrawContent (this);
15121518
} else if (ustring.IsNullOrEmpty (TextFormatter.Text) &&
1513-
(GetType ().IsNestedPublic) && !IsOverridden (this, "Redraw") &&
1519+
(GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") &&
15141520
(!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) {
15151521

15161522
Clear ();
@@ -1525,8 +1531,8 @@ public virtual void Redraw (Rect bounds)
15251531
if (TextFormatter != null) {
15261532
TextFormatter.NeedsFormat = true;
15271533
}
1528-
TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? ColorScheme.Focus : GetNormalColor (),
1529-
HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
1534+
TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (),
1535+
HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (),
15301536
containerBounds);
15311537
}
15321538

@@ -2617,7 +2623,13 @@ public override bool Enabled {
26172623
get => base.Enabled;
26182624
set {
26192625
if (base.Enabled != value) {
2620-
base.Enabled = value;
2626+
if (value) {
2627+
if (SuperView == null || SuperView?.Enabled == true) {
2628+
base.Enabled = value;
2629+
}
2630+
} else {
2631+
base.Enabled = value;
2632+
}
26212633
if (!value && HasFocus) {
26222634
SetHasFocus (false, this);
26232635
}
@@ -2684,7 +2696,7 @@ public virtual Border Border {
26842696
/// to draw the view's border. If <see langword="true"/> no border is drawn (and the view is expected to draw the border
26852697
/// itself).
26862698
/// </summary>
2687-
public virtual bool IgnoreBorderPropertyOnRedraw { get; set; } = false;
2699+
public virtual bool IgnoreBorderPropertyOnRedraw { get; set; }
26882700

26892701
/// <summary>
26902702
/// Pretty prints the View
@@ -3109,6 +3121,17 @@ public virtual Attribute GetNormalColor ()
31093121
return Enabled ? ColorScheme.Normal : ColorScheme.Disabled;
31103122
}
31113123

3124+
/// <summary>
3125+
/// Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.
3126+
/// </summary>
3127+
/// <returns><see cref="Terminal.Gui.ColorScheme.Focus"/> if <see cref="Enabled"/> is <see langword="true"/>
3128+
/// or <see cref="Terminal.Gui.ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>.
3129+
/// If it's overridden can return other values.</returns>
3130+
public virtual Attribute GetFocusColor ()
3131+
{
3132+
return Enabled ? ColorScheme.Focus : ColorScheme.Disabled;
3133+
}
3134+
31123135
/// <summary>
31133136
/// Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.
31143137
/// </summary>

UnitTests/TopLevels/ToplevelTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,5 +1011,25 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End ()
10111011
Assert.True (isEnter);
10121012
Assert.False (isLeave);
10131013
}
1014+
1015+
[Fact, AutoInitShutdown]
1016+
public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null ()
1017+
{
1018+
var tf = new TextField ("test") { Width = 5 };
1019+
var view = new View () { Width = 10, Height = 10 };
1020+
view.Add (tf);
1021+
Application.Top.Add (view);
1022+
Application.Begin (Application.Top);
1023+
1024+
Assert.True (tf.HasFocus);
1025+
Application.Driver.GetCursorVisibility (out CursorVisibility cursor);
1026+
Assert.Equal (CursorVisibility.Default, cursor);
1027+
1028+
view.Enabled = false;
1029+
Assert.False (tf.HasFocus);
1030+
Application.Refresh ();
1031+
Application.Driver.GetCursorVisibility (out cursor);
1032+
Assert.Equal (CursorVisibility.Invisible, cursor);
1033+
}
10141034
}
10151035
}

UnitTests/Views/ViewTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using NStack;
22
using System;
3+
using System.Collections.Generic;
34
using Terminal.Gui.Graphs;
45
using Xunit;
56
using Xunit.Abstractions;
@@ -4209,6 +4210,7 @@ public void Clear_Does_Not_Spillover_Its_Parent (bool label)
42094210
v.CanFocus = true;
42104211
Assert.False (v.HasFocus);
42114212
v.SetFocus ();
4213+
Assert.True (v.HasFocus);
42124214
Application.Refresh ();
42134215
TestHelpers.AssertDriverColorsAre (@"
42144216
111111111111111111110", attributes);
@@ -4491,6 +4493,7 @@ A text with some long width
44914493
A text witith two lines. ", output);
44924494
}
44934495

4496+
44944497
[Fact, AutoInitShutdown]
44954498
public void Test_Nested_Views_With_Height_Equal_To_One ()
44964499
{

0 commit comments

Comments
 (0)