From caa43eb37118414ac0d35a18c9e5076eec25f386 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Jul 2020 23:38:34 +0100 Subject: [PATCH 1/4] Fixes #743. Added View argument to the Enter and Leave events. --- Terminal.Gui/Core/Responder.cs | 10 +++-- Terminal.Gui/Core/View.cs | 65 +++++++++++++++++++-------------- Terminal.Gui/Views/Menu.cs | 2 +- Terminal.Gui/Views/TextField.cs | 4 +- UnitTests/ResponderTests.cs | 4 +- UnitTests/ViewTests.cs | 4 +- 6 files changed, 50 insertions(+), 39 deletions(-) diff --git a/Terminal.Gui/Core/Responder.cs b/Terminal.Gui/Core/Responder.cs index c6fd75c74..15bb22b05 100644 --- a/Terminal.Gui/Core/Responder.cs +++ b/Terminal.Gui/Core/Responder.cs @@ -24,11 +24,12 @@ namespace Terminal.Gui { /// true if can focus; otherwise, false. public virtual bool CanFocus { get; set; } + internal bool hasFocus; /// /// Gets or sets a value indicating whether this has focus. /// /// true if has focus; otherwise, false. - public virtual bool HasFocus { get; internal set; } + public virtual bool HasFocus { get { return hasFocus; } } // Key handling /// @@ -133,7 +134,6 @@ namespace Terminal.Gui { return false; } - /// /// Method invoked when a mouse event is generated /// @@ -167,8 +167,9 @@ namespace Terminal.Gui { /// /// Method invoked when a view gets focus. /// + /// The view that is losing focus. /// true, if the event was handled, false otherwise. - public virtual bool OnEnter () + public virtual bool OnEnter (View view) { return false; } @@ -176,8 +177,9 @@ namespace Terminal.Gui { /// /// Method invoked when a view loses focus. /// + /// The view that is getting focus. /// true, if the event was handled, false otherwise. - public virtual bool OnLeave () + public virtual bool OnLeave (View view) { return false; } diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 77f402f50..b798be760 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -898,23 +898,27 @@ namespace Terminal.Gui { /// public override bool HasFocus { get { - return base.HasFocus; + return hasFocus; } - internal set { - if (base.HasFocus != value) - if (value) - OnEnter (); - else - OnLeave (); - SetNeedsDisplay (); - base.HasFocus = value; + } - // Remove focus down the chain of subviews if focus is removed - if (!value && focused != null) { - focused.OnLeave (); - focused.HasFocus = false; - focused = null; - } + void SetHasFocus (bool value, View view) + { + if (hasFocus != value) { + hasFocus = value; + } + if (value) { + OnEnter (view); + } else { + OnLeave (view); + } + SetNeedsDisplay (); + + // Remove focus down the chain of subviews if focus is removed + if (!value && focused != null) { + focused.OnLeave (focused); + focused.hasFocus = false; + focused = null; } } @@ -925,35 +929,40 @@ namespace Terminal.Gui { /// /// Constructs. /// - public FocusEventArgs () { } + /// The view that gets or loses focus. + public FocusEventArgs (View view) { View = view; } /// /// Indicates if the current focus event has already been processed and the driver should stop notifying any other event subscriber. /// Its important to set this value to true specially when updating any View's layout from inside the subscriber method. /// public bool Handled { get; set; } + /// + /// Indicates the current view that gets or loses focus. + /// + public View View { get; set; } } /// - public override bool OnEnter () + public override bool OnEnter (View view) { - FocusEventArgs args = new FocusEventArgs (); + FocusEventArgs args = new FocusEventArgs (view); Enter?.Invoke (args); if (args.Handled) return true; - if (base.OnEnter ()) + if (base.OnEnter (view)) return true; return false; } /// - public override bool OnLeave () + public override bool OnLeave (View view) { - FocusEventArgs args = new FocusEventArgs (); + FocusEventArgs args = new FocusEventArgs (view); Leave?.Invoke (args); if (args.Handled) return true; - if (base.OnLeave ()) + if (base.OnLeave (view)) return true; return false; @@ -1123,10 +1132,10 @@ namespace Terminal.Gui { throw new ArgumentException ("the specified view is not part of the hierarchy of this view"); if (focused != null) - focused.HasFocus = false; + focused.SetHasFocus (false, view); focused = view; - focused.HasFocus = true; + focused.SetHasFocus (true, view); focused.EnsureFocus (); // Send focus upwards @@ -1320,7 +1329,7 @@ namespace Terminal.Gui { continue; } if (w.CanFocus && focused_idx != -1) { - focused.HasFocus = false; + focused.SetHasFocus (false, w); if (w != null && w.CanFocus) w.FocusLast (); @@ -1330,7 +1339,7 @@ namespace Terminal.Gui { } } if (focused != null) { - focused.HasFocus = false; + focused.SetHasFocus (false, focused); focused = null; } return false; @@ -1362,7 +1371,7 @@ namespace Terminal.Gui { continue; } if (w.CanFocus && focused_idx != -1) { - focused.HasFocus = false; + focused.SetHasFocus (false, w); if (w != null && w.CanFocus) w.FocusFirst (); @@ -1372,7 +1381,7 @@ namespace Terminal.Gui { } } if (focused != null) { - focused.HasFocus = false; + focused.SetHasFocus (false, focused); focused = null; } return false; diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 554424f5e..aa71c87bf 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -535,7 +535,7 @@ namespace Terminal.Gui { if (item == null || !item.IsEnabled ()) disabled = true; if (item != null && !disabled) current = me.Y - 1; - HasFocus = true; + hasFocus = true; SetNeedsDisplay (); CheckSubMenu (); return true; diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index 2fa43f832..1624b6e34 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -93,14 +93,14 @@ namespace Terminal.Gui { } /// - public override bool OnLeave () + public override bool OnLeave (View view) { if (Application.mouseGrabView != null && Application.mouseGrabView == this) Application.UngrabMouse (); if (SelectedLength != 0 && !(Application.mouseGrabView is MenuBar)) ClearAllSelection (); - return base.OnLeave (); + return base.OnLeave (view); } /// diff --git a/UnitTests/ResponderTests.cs b/UnitTests/ResponderTests.cs index 1e662a608..43e9cf186 100644 --- a/UnitTests/ResponderTests.cs +++ b/UnitTests/ResponderTests.cs @@ -32,8 +32,8 @@ namespace Terminal.Gui { Assert.False (r.MouseEvent (new MouseEvent () { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseEnter (new MouseEvent () { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseLeave (new MouseEvent () { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnEnter ()); - Assert.False (r.OnLeave ()); + Assert.False (r.OnEnter (new View ())); + Assert.False (r.OnLeave (new View ())); } } } diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index 43473921b..4904ff684 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -102,8 +102,8 @@ namespace Terminal.Gui { Assert.False (r.MouseEvent (new MouseEvent () { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseEnter (new MouseEvent () { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseLeave (new MouseEvent () { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnEnter ()); - Assert.False (r.OnLeave ()); + Assert.False (r.OnEnter (new View ())); + Assert.False (r.OnLeave (new View ())); // TODO: Add more } From 89afea2e7dfa59c5b103566db6087dd86c674e30 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Jul 2020 23:46:11 +0100 Subject: [PATCH 2/4] Fixing the ComboBox OnEnter. --- Terminal.Gui/Views/ComboBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index aff1f2c6f..2c3e4d5df 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -184,7 +184,7 @@ namespace Terminal.Gui { } /// - public override bool OnEnter () + public override bool OnEnter (View view) { if (!search.HasFocus) this.SetFocus (search); From f9d55c9d082ffed373d86f01ee02b49caac7876b Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Jul 2020 09:43:18 +0100 Subject: [PATCH 3/4] Ensures the HasFocus property only can be set by the SetHasFocus method. Removed unnecessary code in Menu. --- Terminal.Gui/Core/Responder.cs | 3 +-- Terminal.Gui/Core/View.cs | 1 + Terminal.Gui/Views/Menu.cs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/Core/Responder.cs b/Terminal.Gui/Core/Responder.cs index 15bb22b05..52fce4b21 100644 --- a/Terminal.Gui/Core/Responder.cs +++ b/Terminal.Gui/Core/Responder.cs @@ -24,12 +24,11 @@ namespace Terminal.Gui { /// true if can focus; otherwise, false. public virtual bool CanFocus { get; set; } - internal bool hasFocus; /// /// Gets or sets a value indicating whether this has focus. /// /// true if has focus; otherwise, false. - public virtual bool HasFocus { get { return hasFocus; } } + public virtual bool HasFocus { get; } // Key handling /// diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index b798be760..762c3702f 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -895,6 +895,7 @@ namespace Terminal.Gui { } } + bool hasFocus; /// public override bool HasFocus { get { diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index aa71c87bf..40d53fa22 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -535,8 +535,6 @@ namespace Terminal.Gui { if (item == null || !item.IsEnabled ()) disabled = true; if (item != null && !disabled) current = me.Y - 1; - hasFocus = true; - SetNeedsDisplay (); CheckSubMenu (); return true; } From a1202fe55e8031cb7887689464575fb96e032ddb Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 5 Jul 2020 02:04:40 +0100 Subject: [PATCH 4/4] Changed focused to this. --- Terminal.Gui/Core/View.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 762c3702f..47481724e 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1382,7 +1382,7 @@ namespace Terminal.Gui { } } if (focused != null) { - focused.SetHasFocus (false, focused); + focused.SetHasFocus (false, this); focused = null; } return false;