浏览代码

Refactored Leave event and added unit tests

Tig 10 月之前
父节点
当前提交
f512cd49c3

+ 2 - 2
Terminal.Gui/Application/Application.Mouse.cs

@@ -320,7 +320,7 @@ public static partial class Application // Mouse handling
                 Point frameLoc = adornmentView.ScreenToFrame (screenPosition);
                 if (adornmentView.Parent is { } && !adornmentView.Contains (frameLoc))
                 {
-                    view.NewMouseLeaveEvent (me);
+                    view.NewMouseLeaveEvent ();
                 }
             }
             else
@@ -328,7 +328,7 @@ public static partial class Application // Mouse handling
                 Point superViewLoc = view.SuperView?.ScreenToViewport (screenPosition) ?? screenPosition;
                 if (!view.Contains (superViewLoc))
                 {
-                    view.NewMouseLeaveEvent (me);
+                    view.NewMouseLeaveEvent ();
                 }
             }
         }

+ 53 - 57
Terminal.Gui/View/View.Mouse.cs

@@ -39,9 +39,6 @@ public partial class View // Mouse APIs
     /// </remarks>
     public event EventHandler<MouseEventEventArgs>? MouseEvent;
 
-    /// <summary>Event fired when the mouse leaves the View's <see cref="Viewport"/>.</summary>
-    public event EventHandler<MouseEventEventArgs>? MouseLeave;
-
     /// <summary>
     ///     Processes a <see cref="MouseEvent"/>. This method is called by <see cref="Application.OnMouseEvent"/> when a mouse
     ///     event occurs.
@@ -180,7 +177,7 @@ public partial class View // Mouse APIs
 
     /// <summary>
     ///     Called when the mouse moves over the View's <see cref="Frame"/> and no other non-Subview occludes it. <see cref="MouseLeave"/> will
-    ///     be raised when the mouse is no longer over the <see cref="Frame"/>. 
+    ///     be raised when the mouse is no longer over the <see cref="Frame"/>.
     /// </summary>
     /// <remarks>
     ///     <para>
@@ -230,40 +227,78 @@ public partial class View // Mouse APIs
     /// </remarks>
     public event EventHandler<CancelEventArgs>? MouseEnter;
 
-    #endregion MouseEnterLeave
-
-    /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
+    /// <summary>
+    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse leaves <see cref="Frame"/>, or is occluded by another non-SubView.
+    /// </summary>
     /// <remarks>
     ///     <para>
-    ///         The coordinates are relative to <see cref="View.Viewport"/>.
+    ///         This method calls <see cref="OnMouseLeave"/> and raises the <see cref="MouseLeave"/> event.
+    ///     </para>
+    ///     <para>
+    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
+    ///     </para>
+    ///     <para>
+    ///         See <see cref="SetHighlight"/> for more information.
     ///     </para>
     /// </remarks>
-    /// <param name="mouseEvent"></param>
-    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
+    internal void NewMouseLeaveEvent ()
     {
-        var args = new MouseEventEventArgs (mouseEvent);
+        OnMouseLeave ();
 
-        MouseEvent?.Invoke (this, args);
+        MouseLeave?.Invoke (this, EventArgs.Empty);
 
-        return args.Handled;
+#if HOVER
+        if (HighlightStyle.HasFlag (HighlightStyle.Hover))
+        {
+            SetHighlight (HighlightStyle.None);
+        }
+#endif
     }
 
     /// <summary>
-    ///     Called by <see cref="NewMouseEvent"/> when a mouse leaves <see cref="Viewport"/>. The view will
-    ///     no longer receive mouse events.
+    ///     Called when the mouse moves outside View's <see cref="Frame"/>, or is occluded by another non-SubView.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
+    ///     </para>
+    ///     <para>
+    ///         See <see cref="SetHighlight"/> for more information.
+    ///     </para>
+    /// </remarks>
+    protected virtual void OnMouseLeave () { }
+
+    /// <summary>
+    ///     Raised when the mouse moves outside View's <see cref="Frame"/>, or is occluded by another non-SubView. 
     /// </summary>
     /// <remarks>
     ///     <para>
-    ///         Override this method or subscribe to <see cref="MouseEnter"/> to change the default leave behavior.
+    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
     ///     </para>
     ///     <para>
+    ///         See <see cref="SetHighlight"/> for more information.
+    ///     </para>
+    /// </remarks>
+    public event EventHandler? MouseLeave;
+
+    #endregion MouseEnterLeave
+
+    /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
+    /// <remarks>
+    ///     <para>
     ///         The coordinates are relative to <see cref="View.Viewport"/>.
     ///     </para>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) { return false; }
+    protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
+    {
+        var args = new MouseEventEventArgs (mouseEvent);
+
+        MouseEvent?.Invoke (this, args);
+
+        return args.Handled;
+    }
 
     /// <summary>
     ///     Called when the view is to be highlighted.
@@ -385,45 +420,6 @@ public partial class View // Mouse APIs
         return false;
     }
 
-    /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse leaves <see cref="Frame"/>.
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         A view must be visible to receive Enter events (Leave events are always received).
-    ///     </para>
-    ///     <para>
-    ///         This method calls <see cref="OnMouseLeave"/> to raise the <see cref="MouseLeave"/> event.
-    ///     </para>
-    ///     <para>
-    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
-    ///     </para>
-    ///     <para>
-    ///         See <see cref="SetHighlight"/> for more information.
-    ///     </para>
-    /// </remarks>
-    /// <param name="mouseEvent"></param>
-    /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise. </returns>
-    internal bool? NewMouseLeaveEvent (MouseEvent mouseEvent)
-    {
-        if (OnMouseLeave (mouseEvent))
-        {
-            return true;
-        }
-
-        var args = new MouseEventEventArgs (mouseEvent);
-        MouseLeave?.Invoke (this, args);
-
-#if HOVER
-        if (HighlightStyle.HasFlag (HighlightStyle.Hover))
-        {
-            SetHighlight (HighlightStyle.None);
-        }
-#endif
-
-        return args.Handled;
-    }
-
     /// <summary>
     ///     Enables the highlight for the view when the mouse is pressed. Called from OnMouseEvent.
     /// </summary>

+ 1 - 1
Terminal.Gui/Views/ScrollView.cs

@@ -747,7 +747,7 @@ public class ScrollView : View
 
     private void View_MouseEnter (object sender, CancelEventArgs e) { Application.GrabMouse (this); }
 
-    private void View_MouseLeave (object sender, MouseEventEventArgs e)
+    private void View_MouseLeave (object sender, EventArgs e)
     {
         if (Application.MouseGrabView is { } && Application.MouseGrabView != this && Application.MouseGrabView != _vertical && Application.MouseGrabView != _horizontal)
         {

+ 1 - 1
UICatalog/Scenarios/Mouse.cs

@@ -251,7 +251,7 @@ public class Mouse : Scenario
                     Padding.ColorScheme = Colors.ColorSchemes ["Error"];
                 }
 
-                void PaddingOnMouseLeave (object o, MouseEventEventArgs mouseEventEventArgs)
+                void PaddingOnMouseLeave (object o, EventArgs e)
                 {
                     Padding.ColorScheme = Colors.ColorSchemes ["Dialog"];
                 }

+ 2 - 4
UnitTests/Application/Mouse/ApplicationMouseEnterLeaveTests.cs

@@ -29,13 +29,11 @@ public class ApplicationMouseEnterLeaveTests
             return eventArgs.Cancel;
         }
 
-        protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
+        protected override void OnMouseLeave ()
         {
             OnMouseLeaveCalled++;
 
-            base.OnMouseLeave (mouseEvent);
-
-            return mouseEvent.Handled;
+            base.OnMouseLeave ();
         }
     }
 

+ 7 - 13
UnitTests/View/Mouse/MouseEnterLeaveTests.cs

@@ -30,13 +30,11 @@ public class MouseEnterLeaveTests
             return eventArgs.Cancel;
         }
 
-        protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
+        protected override void OnMouseLeave ()
         {
             OnMouseLeaveCalled = true;
 
-            base.OnMouseLeave (mouseEvent);
-
-            return mouseEvent.Handled;
+            base.OnMouseLeave ();
         }
 
         public bool MouseEnterRaised { get; private set; }
@@ -52,7 +50,7 @@ public class MouseEnterLeaveTests
             }
         }
 
-        private void OnMouseLeaveHandler (object s, MouseEventEventArgs e) { MouseLeaveRaised = true; }
+        private void OnMouseLeaveHandler (object s, EventArgs e) { MouseLeaveRaised = true; }
     }
 
     [Fact]
@@ -141,11 +139,10 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
+        view.NewMouseLeaveEvent ();
 
         // Assert
         Assert.True (view.OnMouseLeaveCalled);
-        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -165,11 +162,10 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
+        view.NewMouseLeaveEvent ();
 
         // Assert
         Assert.True (view.OnMouseLeaveCalled);
-        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -263,11 +259,10 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
+        view.NewMouseLeaveEvent ();
 
         // Assert
         Assert.True (view.MouseLeaveRaised);
-        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -287,11 +282,10 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
+        view.NewMouseLeaveEvent ();
 
         // Assert
         Assert.True (view.MouseLeaveRaised);
-        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup

+ 5 - 0
docfx/docs/mouse.md

@@ -25,3 +25,8 @@ When the user does something with the mouse, the `ConsoleDriver` maps the platfo
 ## **Global Mouse Handling**
 
 The @Terminal.Gui.Application.MouseEvent event can be used if an application wishes to receive all mouse events.
+
+## Mouse Enter/Leave Events
+
+The @Terminal.Gui.View.MouseEnter and @Terminal.Gui.View.MouseLeave events enable a View to take action when the mouse is over the view. Internally, this is used to enable @Terminal.Gui.View.Highlight.
+