diff --git a/Terminal.Gui/Core/Responder.cs b/Terminal.Gui/Core/Responder.cs index c6fd75c74..52fce4b21 100644 --- a/Terminal.Gui/Core/Responder.cs +++ b/Terminal.Gui/Core/Responder.cs @@ -28,7 +28,7 @@ namespace Terminal.Gui { /// 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; } // Key handling /// @@ -133,7 +133,6 @@ namespace Terminal.Gui { return false; } - /// /// Method invoked when a mouse event is generated /// @@ -167,8 +166,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 +176,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..47481724e 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -895,26 +895,31 @@ namespace Terminal.Gui { } } + bool hasFocus; /// 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 +930,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 +1133,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 +1330,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 +1340,7 @@ namespace Terminal.Gui { } } if (focused != null) { - focused.HasFocus = false; + focused.SetHasFocus (false, focused); focused = null; } return false; @@ -1362,7 +1372,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 +1382,7 @@ namespace Terminal.Gui { } } if (focused != null) { - focused.HasFocus = false; + focused.SetHasFocus (false, this); focused = null; } return false; 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); diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 554424f5e..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; } 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 }