mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Initial plan * Refactor Application.Mouse - Create IMouse interface and Mouse implementation Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add enhanced documentation for Application.Mouse property Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add parallelizable unit tests for IMouse interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor Application.Mouse for decoupling and parallelism Co-authored-by: tig <585482+tig@users.noreply.github.com> * Move HandleMouseGrab method to IMouseGrabHandler interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add parallelizable tests for IMouse and IMouseGrabHandler interfaces Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add MouseEventRoutingTests - 27 parallelizable tests for View mouse event handling Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix terminology: Replace parent/child with superView/subView in MouseEventRoutingTests Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix coding standards: Use explicit types and target-typed new() in test files Co-authored-by: tig <585482+tig@users.noreply.github.com> * Update coding standards documentation with explicit var and target-typed new() guidance Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor Application classes and improve maintainability Refactored `Sixel` property to be immutable, enhancing thread safety. Cleaned up `ApplicationImpl` by removing redundant fields, restructuring methods (`CreateDriver`, `CreateSubcomponents`), and improving exception handling. Updated `Run<T>` and `Shutdown` methods for consistency. Standardized logging/debugging messages and fixed formatting issues. Reorganized `IApplication` interface, added detailed XML documentation, and grouped related methods logically. Performed general code cleanup, including fixing typos, improving readability, and removing legacy/unnecessary code to reduce technical debt. * Code cleanup * Remove unreferenced LayoutAndDraw method from ApplicationImpl * Code cleanup and TODOs - Updated namespaces to reflect the new structure. - Added `Driver`, `Force16Colors`, and `ForceDriver` properties. - Introduced `Sixel` collection for sixel image management. - Added lifecycle methods: `GetDriverTypes`, `Shutdown`, and events. - Refactored `Init` to support legacy and modern drivers. - Improved driver event handling and screen abstraction. - Updated `Run` method to align with the application lifecycle. - Simplified `IConsoleDriver` documentation. - Removed redundant methods and improved code readability. * Refactor LayoutAndDraw logic for better encapsulation Refactored `Application.Run` to delegate `LayoutAndDraw` to `ApplicationImpl.Instance.LayoutAndDraw`, improving separation of concerns. Renamed `forceDraw` to `forceRedraw` for clarity and moved `LayoutAndDraw` implementation to `ApplicationImpl`. Added a new `LayoutAndDraw` method in `ApplicationImpl` to handle layout and drawing, including managing `TopLevels`, handling active popovers, and refreshing the screen. Updated the `IApplication` interface to reflect the new method and improved its documentation. Implemented `RequestStop` in `ApplicationImpl` and fixed formatting inconsistencies in `Run<T>`. Added TODOs for future refactoring to encapsulate `Top` and `TopLevels` into an `IViewHierarchy` and move certain properties to `IApplication`. * Refactor ApplicationImpl to enhance mouse and keyboard support Added a new `Mouse` property to the `ApplicationImpl` class, replacing its previous declaration, to improve mouse functionality. Updated `MouseGrabHandler` to initialize with a default instance of `MouseGrabHandler`. Added comments to ensure the preservation of existing keyboard settings (`QuitKey`, `ArrangeKey`, `NextTabKey`) for backward compatibility. These changes enhance clarity, functionality, and maintainability of the class. * Merge IMouseGrabHandler into IMouse - consolidate mouse handling into single interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Rename Mouse to MouseImpl and Keyboard to KeyboardImpl for consistency Co-authored-by: tig <585482+tig@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tig <585482+tig@users.noreply.github.com> Co-authored-by: Tig <tig@users.noreply.github.com>
This commit is contained in:
@@ -309,7 +309,7 @@ public class ApplicationTests
|
||||
|
||||
// Public Properties
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Don't check Application.ForceDriver
|
||||
// Assert.Empty (Application.ForceDriver);
|
||||
@@ -574,7 +574,7 @@ public class ApplicationTests
|
||||
Assert.Null (Application.Top);
|
||||
RunState rs = Application.Begin (new ());
|
||||
Assert.Equal (Application.Top, rs.Toplevel);
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView); // public
|
||||
Assert.Null (Application.Mouse.MouseGrabView); // public
|
||||
Application.Top!.Dispose ();
|
||||
}
|
||||
|
||||
@@ -932,7 +932,7 @@ public class ApplicationTests
|
||||
Assert.Equal (new (0, 0), w.Frame.Location);
|
||||
|
||||
Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
|
||||
Assert.Equal (w.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (w.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (0, 0), w.Frame.Location);
|
||||
|
||||
// Move down and to the right.
|
||||
|
||||
@@ -260,39 +260,39 @@ public class ApplicationMouseTests
|
||||
// if (iterations == 0)
|
||||
// {
|
||||
// Assert.True (tf.HasFocus);
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RaiseMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
|
||||
|
||||
// Assert.Equal (sv, Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Equal (sv, Application.Mouse.MouseGrabView);
|
||||
|
||||
// MessageBox.Query ("Title", "Test", "Ok");
|
||||
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
// }
|
||||
// else if (iterations == 1)
|
||||
// {
|
||||
// // Application.MouseGrabHandler.MouseGrabView is null because
|
||||
// // Application.Mouse.MouseGrabView is null because
|
||||
// // another toplevel (Dialog) was opened
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RaiseMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
|
||||
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RaiseMouseEvent (new () { ScreenPosition = new (40, 12), Flags = MouseFlags.ReportMousePosition });
|
||||
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
|
||||
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RequestStop ();
|
||||
// }
|
||||
// else if (iterations == 2)
|
||||
// {
|
||||
// Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
// Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Application.RequestStop ();
|
||||
// }
|
||||
@@ -313,33 +313,33 @@ public class ApplicationMouseTests
|
||||
var view2 = new View { Id = "view2" };
|
||||
var view3 = new View { Id = "view3" };
|
||||
|
||||
Application.MouseGrabHandler.GrabbedMouse += Application_GrabbedMouse;
|
||||
Application.MouseGrabHandler.UnGrabbedMouse += Application_UnGrabbedMouse;
|
||||
Application.Mouse.GrabbedMouse += Application_GrabbedMouse;
|
||||
Application.Mouse.UnGrabbedMouse += Application_UnGrabbedMouse;
|
||||
|
||||
Application.MouseGrabHandler.GrabMouse (view1);
|
||||
Application.Mouse.GrabMouse (view1);
|
||||
Assert.Equal (0, count);
|
||||
Assert.Equal (grabView, view1);
|
||||
Assert.Equal (view1, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (view1, Application.Mouse.MouseGrabView);
|
||||
|
||||
Application.MouseGrabHandler.UngrabMouse ();
|
||||
Application.Mouse.UngrabMouse ();
|
||||
Assert.Equal (1, count);
|
||||
Assert.Equal (grabView, view1);
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
Application.MouseGrabHandler.GrabbedMouse += Application_GrabbedMouse;
|
||||
Application.MouseGrabHandler.UnGrabbedMouse += Application_UnGrabbedMouse;
|
||||
Application.Mouse.GrabbedMouse += Application_GrabbedMouse;
|
||||
Application.Mouse.UnGrabbedMouse += Application_UnGrabbedMouse;
|
||||
|
||||
Application.MouseGrabHandler.GrabMouse (view2);
|
||||
Application.Mouse.GrabMouse (view2);
|
||||
Assert.Equal (1, count);
|
||||
Assert.Equal (grabView, view2);
|
||||
Assert.Equal (view2, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (view2, Application.Mouse.MouseGrabView);
|
||||
|
||||
Application.MouseGrabHandler.UngrabMouse ();
|
||||
Application.Mouse.UngrabMouse ();
|
||||
Assert.Equal (2, count);
|
||||
Assert.Equal (grabView, view2);
|
||||
Assert.Equal (view3, Application.MouseGrabHandler.MouseGrabView);
|
||||
Application.MouseGrabHandler.UngrabMouse ();
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (view3, Application.Mouse.MouseGrabView);
|
||||
Application.Mouse.UngrabMouse ();
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
void Application_GrabbedMouse (object sender, ViewEventArgs e)
|
||||
{
|
||||
@@ -354,7 +354,7 @@ public class ApplicationMouseTests
|
||||
grabView = view2;
|
||||
}
|
||||
|
||||
Application.MouseGrabHandler.GrabbedMouse -= Application_GrabbedMouse;
|
||||
Application.Mouse.GrabbedMouse -= Application_GrabbedMouse;
|
||||
}
|
||||
|
||||
void Application_UnGrabbedMouse (object sender, ViewEventArgs e)
|
||||
@@ -375,10 +375,10 @@ public class ApplicationMouseTests
|
||||
if (count > 1)
|
||||
{
|
||||
// It's possible to grab another view after the previous was ungrabbed
|
||||
Application.MouseGrabHandler.GrabMouse (view3);
|
||||
Application.Mouse.GrabMouse (view3);
|
||||
}
|
||||
|
||||
Application.MouseGrabHandler.UnGrabbedMouse -= Application_UnGrabbedMouse;
|
||||
Application.Mouse.UnGrabbedMouse -= Application_UnGrabbedMouse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,18 +393,18 @@ public class ApplicationMouseTests
|
||||
top.Add (view);
|
||||
Application.Begin (top);
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Application.MouseGrabHandler.GrabMouse (view);
|
||||
Assert.Equal (view, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
Application.Mouse.GrabMouse (view);
|
||||
Assert.Equal (view, Application.Mouse.MouseGrabView);
|
||||
top.Remove (view);
|
||||
Application.MouseGrabHandler.UngrabMouse ();
|
||||
Application.Mouse.UngrabMouse ();
|
||||
view.Dispose ();
|
||||
#if DEBUG_IDISPOSABLE
|
||||
Assert.True (view.WasDisposed);
|
||||
#endif
|
||||
|
||||
Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (0, count);
|
||||
top.Dispose ();
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ public class ShadowStyleTests (ITestOutputHelper output)
|
||||
view.NewMouseEvent (new () { Flags = MouseFlags.Button1Released, Position = new (0, 0) });
|
||||
Assert.Equal (origThickness, view.Margin.Thickness);
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
view.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
view.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
view.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
// testView.Dispose ();
|
||||
|
||||
// // Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// // Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
// Application.ResetState (true);
|
||||
|
||||
//}
|
||||
@@ -442,7 +442,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
testView.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -504,7 +504,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
testView.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
testView.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ public class MouseTests : TestsAllViews
|
||||
|
||||
testView.Dispose ();
|
||||
|
||||
// Button1Pressed, Button1Released cause Application.MouseGrabHandler.MouseGrabView to be set
|
||||
// Button1Pressed, Button1Released cause Application.Mouse.MouseGrabView to be set
|
||||
Application.ResetState (true);
|
||||
}
|
||||
private class MouseEventTestView : View
|
||||
|
||||
@@ -2578,11 +2578,11 @@ Edit
|
||||
|
||||
if (i is < 0 or > 0)
|
||||
{
|
||||
Assert.Equal (menu, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (menu, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal (menuBar, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (menuBar, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
|
||||
Assert.Equal ("_Edit", miCurrent.Parent.Title);
|
||||
|
||||
@@ -305,17 +305,17 @@ public class ToplevelTests
|
||||
}
|
||||
else if (iterations == 2)
|
||||
{
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Grab the mouse
|
||||
Application.RaiseMouseEvent (new () { ScreenPosition = new (3, 2), Flags = MouseFlags.Button1Pressed });
|
||||
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (2, 2, 10, 3), Application.Top.Frame);
|
||||
}
|
||||
else if (iterations == 3)
|
||||
{
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Drag to left
|
||||
Application.RaiseMouseEvent (
|
||||
@@ -326,19 +326,19 @@ public class ToplevelTests
|
||||
});
|
||||
AutoInitShutdownAttribute.RunIteration ();
|
||||
|
||||
Assert.Equal (Application.Top.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 2, 10, 3), Application.Top.Frame);
|
||||
}
|
||||
else if (iterations == 4)
|
||||
{
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 2), Application.Top.Frame.Location);
|
||||
|
||||
Assert.Equal (Application.Top.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top.Border, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 5)
|
||||
{
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Drag up
|
||||
Application.RaiseMouseEvent (
|
||||
@@ -349,26 +349,26 @@ public class ToplevelTests
|
||||
});
|
||||
AutoInitShutdownAttribute.RunIteration ();
|
||||
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame);
|
||||
}
|
||||
else if (iterations == 6)
|
||||
{
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 1), Application.Top.Frame.Location);
|
||||
|
||||
Assert.Equal (Application.Top.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame);
|
||||
}
|
||||
else if (iterations == 7)
|
||||
{
|
||||
Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (Application.Top!.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Ungrab the mouse
|
||||
Application.RaiseMouseEvent (new () { ScreenPosition = new (2, 1), Flags = MouseFlags.Button1Released });
|
||||
AutoInitShutdownAttribute.RunIteration ();
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 8)
|
||||
{
|
||||
@@ -411,7 +411,7 @@ public class ToplevelTests
|
||||
{
|
||||
location = win.Frame;
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Grab the mouse
|
||||
Application.RaiseMouseEvent (
|
||||
@@ -420,11 +420,11 @@ public class ToplevelTests
|
||||
ScreenPosition = new (win.Frame.X, win.Frame.Y), Flags = MouseFlags.Button1Pressed
|
||||
});
|
||||
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 2)
|
||||
{
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Drag to left
|
||||
movex = 1;
|
||||
@@ -438,18 +438,18 @@ public class ToplevelTests
|
||||
| MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 3)
|
||||
{
|
||||
// we should have moved +1, +0
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
location.Offset (movex, movey);
|
||||
}
|
||||
else if (iterations == 4)
|
||||
{
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Drag up
|
||||
movex = 0;
|
||||
@@ -463,18 +463,18 @@ public class ToplevelTests
|
||||
| MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 5)
|
||||
{
|
||||
// we should have moved +0, -1
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
location.Offset (movex, movey);
|
||||
Assert.Equal (location, win.Frame);
|
||||
}
|
||||
else if (iterations == 6)
|
||||
{
|
||||
Assert.Equal (win.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (win.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
// Ungrab the mouse
|
||||
movex = 0;
|
||||
@@ -487,7 +487,7 @@ public class ToplevelTests
|
||||
Flags = MouseFlags.Button1Released
|
||||
});
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
}
|
||||
else if (iterations == 7)
|
||||
{
|
||||
@@ -602,11 +602,11 @@ public class ToplevelTests
|
||||
Assert.Equal (new (0, 0, 40, 10), top.Frame);
|
||||
Assert.Equal (new (0, 0, 20, 3), window.Frame);
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
|
||||
|
||||
Assert.Equal (window.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (window.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
Application.RaiseMouseEvent (
|
||||
new ()
|
||||
@@ -694,14 +694,14 @@ public class ToplevelTests
|
||||
|
||||
RunState rs = Application.Begin (window);
|
||||
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (0, 0, 10, 3), window.Frame);
|
||||
|
||||
Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
|
||||
|
||||
var firstIteration = false;
|
||||
AutoInitShutdownAttribute.RunIteration ();
|
||||
Assert.Equal (window.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (window.Border, Application.Mouse.MouseGrabView);
|
||||
|
||||
Assert.Equal (new (0, 0, 10, 3), window.Frame);
|
||||
|
||||
@@ -713,7 +713,7 @@ public class ToplevelTests
|
||||
|
||||
firstIteration = false;
|
||||
AutoInitShutdownAttribute.RunIteration ();
|
||||
Assert.Equal (window.Border, Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Equal (window.Border, Application.Mouse.MouseGrabView);
|
||||
Assert.Equal (new (1, 1, 10, 3), window.Frame);
|
||||
|
||||
Application.End (rs);
|
||||
|
||||
@@ -13,7 +13,7 @@ public class KeyboardTests
|
||||
public void Constructor_InitializesKeyBindings ()
|
||||
{
|
||||
// Arrange & Act
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull (keyboard.KeyBindings);
|
||||
@@ -25,7 +25,7 @@ public class KeyboardTests
|
||||
public void QuitKey_DefaultValue_IsEsc ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.Esc, keyboard.QuitKey);
|
||||
@@ -35,7 +35,7 @@ public class KeyboardTests
|
||||
public void QuitKey_SetValue_UpdatesKeyBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key newQuitKey = Key.Q.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -51,7 +51,7 @@ public class KeyboardTests
|
||||
public void ArrangeKey_DefaultValue_IsCtrlF5 ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.F5.WithCtrl, keyboard.ArrangeKey);
|
||||
@@ -61,7 +61,7 @@ public class KeyboardTests
|
||||
public void NextTabKey_DefaultValue_IsTab ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.Tab, keyboard.NextTabKey);
|
||||
@@ -71,7 +71,7 @@ public class KeyboardTests
|
||||
public void PrevTabKey_DefaultValue_IsShiftTab ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.Tab.WithShift, keyboard.PrevTabKey);
|
||||
@@ -81,7 +81,7 @@ public class KeyboardTests
|
||||
public void NextTabGroupKey_DefaultValue_IsF6 ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.F6, keyboard.NextTabGroupKey);
|
||||
@@ -91,7 +91,7 @@ public class KeyboardTests
|
||||
public void PrevTabGroupKey_DefaultValue_IsShiftF6 ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.F6.WithShift, keyboard.PrevTabGroupKey);
|
||||
@@ -101,7 +101,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Add_CanAddCustomBinding ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key customKey = Key.K.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -116,7 +116,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Remove_CanRemoveBinding ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key customKey = Key.K.WithCtrl;
|
||||
keyboard.KeyBindings.Add (customKey, Command.Accept);
|
||||
|
||||
@@ -131,7 +131,7 @@ public class KeyboardTests
|
||||
public void KeyDown_Event_CanBeSubscribed ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
bool eventRaised = false;
|
||||
|
||||
// Act
|
||||
@@ -148,7 +148,7 @@ public class KeyboardTests
|
||||
public void KeyUp_Event_CanBeSubscribed ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
bool eventRaised = false;
|
||||
|
||||
// Act
|
||||
@@ -165,7 +165,7 @@ public class KeyboardTests
|
||||
public void InvokeCommand_WithInvalidCommand_ThrowsNotSupportedException ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
// Pick a command that isn't registered
|
||||
Command invalidCommand = (Command)9999;
|
||||
Key testKey = Key.A;
|
||||
@@ -179,8 +179,8 @@ public class KeyboardTests
|
||||
public void Multiple_Keyboards_CanExistIndependently ()
|
||||
{
|
||||
// Arrange & Act
|
||||
var keyboard1 = new Keyboard ();
|
||||
var keyboard2 = new Keyboard ();
|
||||
var keyboard1 = new KeyboardImpl ();
|
||||
var keyboard2 = new KeyboardImpl ();
|
||||
|
||||
keyboard1.QuitKey = Key.Q.WithCtrl;
|
||||
keyboard2.QuitKey = Key.X.WithCtrl;
|
||||
@@ -195,7 +195,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Replace_UpdatesExistingBinding ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key oldKey = Key.Esc;
|
||||
Key newKey = Key.Q.WithCtrl;
|
||||
|
||||
@@ -217,7 +217,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Clear_RemovesAllBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
// Verify initial state has bindings
|
||||
Assert.True (keyboard.KeyBindings.TryGet (keyboard.QuitKey, out _));
|
||||
|
||||
@@ -232,7 +232,7 @@ public class KeyboardTests
|
||||
public void AddKeyBindings_PopulatesDefaultBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
keyboard.KeyBindings.Clear ();
|
||||
Assert.False (keyboard.KeyBindings.TryGet (keyboard.QuitKey, out _));
|
||||
|
||||
@@ -250,7 +250,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Add_Adds ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Act
|
||||
keyboard.KeyBindings.Add (Key.A, Command.Accept);
|
||||
@@ -267,7 +267,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Remove_Removes ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
keyboard.KeyBindings.Add (Key.A, Command.Accept);
|
||||
Assert.True (keyboard.KeyBindings.TryGet (Key.A, out _));
|
||||
|
||||
@@ -282,7 +282,7 @@ public class KeyboardTests
|
||||
public void QuitKey_Default_Is_Esc ()
|
||||
{
|
||||
// Arrange & Act
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (Key.Esc, keyboard.QuitKey);
|
||||
@@ -292,7 +292,7 @@ public class KeyboardTests
|
||||
public void QuitKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key prevKey = keyboard.QuitKey;
|
||||
|
||||
// Act - Change QuitKey
|
||||
@@ -309,7 +309,7 @@ public class KeyboardTests
|
||||
public void NextTabKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key prevKey = keyboard.NextTabKey;
|
||||
Key newKey = Key.N.WithCtrl;
|
||||
|
||||
@@ -326,7 +326,7 @@ public class KeyboardTests
|
||||
public void PrevTabKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key newKey = Key.P.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -342,7 +342,7 @@ public class KeyboardTests
|
||||
public void NextTabGroupKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key newKey = Key.PageDown.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -359,7 +359,7 @@ public class KeyboardTests
|
||||
public void PrevTabGroupKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key newKey = Key.PageUp.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -376,7 +376,7 @@ public class KeyboardTests
|
||||
public void ArrangeKey_Setter_UpdatesBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key newKey = Key.A.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -392,7 +392,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_AddWithTarget_StoresTarget ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
var view = new View ();
|
||||
|
||||
// Act
|
||||
@@ -410,7 +410,7 @@ public class KeyboardTests
|
||||
public void InvokeCommandsBoundToKey_ReturnsNull_WhenNoBindingExists ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key unboundKey = Key.Z.WithAlt.WithCtrl;
|
||||
|
||||
// Act
|
||||
@@ -424,7 +424,7 @@ public class KeyboardTests
|
||||
public void InvokeCommandsBoundToKey_InvokesCommand_WhenBindingExists ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
// QuitKey has a bound command by default
|
||||
|
||||
// Act
|
||||
@@ -440,8 +440,8 @@ public class KeyboardTests
|
||||
public void Multiple_Keyboards_Independent_KeyBindings ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard1 = new Keyboard ();
|
||||
var keyboard2 = new Keyboard ();
|
||||
var keyboard1 = new KeyboardImpl ();
|
||||
var keyboard2 = new KeyboardImpl ();
|
||||
|
||||
// Act
|
||||
keyboard1.KeyBindings.Add (Key.X, Command.Accept);
|
||||
@@ -459,7 +459,7 @@ public class KeyboardTests
|
||||
public void KeyBindings_Replace_PreservesCommandsForNewKey ()
|
||||
{
|
||||
// Arrange
|
||||
var keyboard = new Keyboard ();
|
||||
var keyboard = new KeyboardImpl ();
|
||||
Key oldKey = Key.Esc;
|
||||
Key newKey = Key.Q.WithCtrl;
|
||||
|
||||
|
||||
444
Tests/UnitTestsParallelizable/Application/MouseInterfaceTests.cs
Normal file
444
Tests/UnitTestsParallelizable/Application/MouseInterfaceTests.cs
Normal file
@@ -0,0 +1,444 @@
|
||||
using Terminal.Gui.App;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace UnitTests_Parallelizable.ApplicationTests;
|
||||
|
||||
/// <summary>
|
||||
/// Parallelizable tests for IMouse interface.
|
||||
/// Tests the decoupled mouse handling without Application.Init or global state.
|
||||
/// </summary>
|
||||
[Trait ("Category", "Input")]
|
||||
public class MouseInterfaceTests (ITestOutputHelper output)
|
||||
{
|
||||
private readonly ITestOutputHelper _output = output;
|
||||
|
||||
#region IMouse Basic Properties
|
||||
|
||||
[Fact]
|
||||
public void Mouse_LastMousePosition_InitiallyNull ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Null (mouse.LastMousePosition);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 0)]
|
||||
[InlineData (10, 20)]
|
||||
[InlineData (-5, -10)]
|
||||
[InlineData (100, 200)]
|
||||
public void Mouse_LastMousePosition_CanBeSetAndRetrieved (int x, int y)
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
Point testPosition = new (x, y);
|
||||
|
||||
// Act
|
||||
mouse.LastMousePosition = testPosition;
|
||||
|
||||
// Assert
|
||||
Assert.Equal (testPosition, mouse.LastMousePosition);
|
||||
Assert.Equal (testPosition, mouse.GetLastMousePosition ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_IsMouseDisabled_DefaultsFalse ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Act & Assert
|
||||
Assert.False (mouse.IsMouseDisabled);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (true)]
|
||||
[InlineData (false)]
|
||||
public void Mouse_IsMouseDisabled_CanBeSetAndRetrieved (bool disabled)
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Act
|
||||
mouse.IsMouseDisabled = disabled;
|
||||
|
||||
// Assert
|
||||
Assert.Equal (disabled, mouse.IsMouseDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_CachedViewsUnderMouse_InitiallyEmpty ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Act & Assert
|
||||
Assert.NotNull (mouse.CachedViewsUnderMouse);
|
||||
Assert.Empty (mouse.CachedViewsUnderMouse);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouse Event Handling
|
||||
|
||||
[Fact]
|
||||
public void Mouse_MouseEvent_CanSubscribeAndFire ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventFired = false;
|
||||
MouseEventArgs capturedArgs = null;
|
||||
|
||||
mouse.MouseEvent += (sender, args) =>
|
||||
{
|
||||
eventFired = true;
|
||||
capturedArgs = args;
|
||||
};
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (5, 10),
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert
|
||||
Assert.True (eventFired);
|
||||
Assert.NotNull (capturedArgs);
|
||||
Assert.Equal (testEvent.ScreenPosition, capturedArgs.ScreenPosition);
|
||||
Assert.Equal (testEvent.Flags, capturedArgs.Flags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_MouseEvent_CanUnsubscribe ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventCount = 0;
|
||||
|
||||
void Handler (object sender, MouseEventArgs args) => eventCount++;
|
||||
|
||||
mouse.MouseEvent += Handler;
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (0, 0),
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
};
|
||||
|
||||
// Act - Fire once
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
Assert.Equal (1, eventCount);
|
||||
|
||||
// Unsubscribe
|
||||
mouse.MouseEvent -= Handler;
|
||||
|
||||
// Fire again
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert - Count should not increase
|
||||
Assert.Equal (1, eventCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_RaiseMouseEvent_WithDisabledMouse_DoesNotFireEvent ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventFired = false;
|
||||
|
||||
mouse.MouseEvent += (sender, args) => { eventFired = true; };
|
||||
mouse.IsMouseDisabled = true;
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (0, 0),
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert
|
||||
Assert.False (eventFired);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (MouseFlags.Button1Pressed)]
|
||||
[InlineData (MouseFlags.Button1Released)]
|
||||
[InlineData (MouseFlags.Button1Clicked)]
|
||||
[InlineData (MouseFlags.Button2Pressed)]
|
||||
[InlineData (MouseFlags.WheeledUp)]
|
||||
[InlineData (MouseFlags.ReportMousePosition)]
|
||||
public void Mouse_RaiseMouseEvent_CorrectlyPassesFlags (MouseFlags flags)
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
MouseFlags? capturedFlags = null;
|
||||
|
||||
mouse.MouseEvent += (sender, args) => { capturedFlags = args.Flags; };
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (5, 5),
|
||||
Flags = flags
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull (capturedFlags);
|
||||
Assert.Equal (flags, capturedFlags.Value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouse ResetState
|
||||
|
||||
[Fact]
|
||||
public void Mouse_ResetState_ClearsCachedViews ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new () { Width = 10, Height = 10 };
|
||||
|
||||
mouse.CachedViewsUnderMouse.Add (testView);
|
||||
Assert.Single (mouse.CachedViewsUnderMouse);
|
||||
|
||||
// Act
|
||||
mouse.ResetState ();
|
||||
|
||||
// Assert
|
||||
Assert.Empty (mouse.CachedViewsUnderMouse);
|
||||
|
||||
testView.Dispose ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_ResetState_ClearsEventHandlers ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventCount = 0;
|
||||
|
||||
mouse.MouseEvent += (sender, args) => eventCount++;
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (0, 0),
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
};
|
||||
|
||||
// Verify event fires before reset
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
Assert.Equal (1, eventCount);
|
||||
|
||||
// Act
|
||||
mouse.ResetState ();
|
||||
|
||||
// Raise event again
|
||||
mouse.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert - Event count should not increase after reset
|
||||
Assert.Equal (1, eventCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_ResetState_DoesNotClearLastMousePosition ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
Point testPosition = new (42, 84);
|
||||
|
||||
mouse.LastMousePosition = testPosition;
|
||||
|
||||
// Act
|
||||
mouse.ResetState ();
|
||||
|
||||
// Assert - LastMousePosition should NOT be cleared (per design)
|
||||
Assert.Equal (testPosition, mouse.LastMousePosition);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMouse Isolation
|
||||
|
||||
[Fact]
|
||||
public void Mouse_Instances_AreIndependent ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse1 = new ();
|
||||
MouseImpl mouse2 = new ();
|
||||
|
||||
// Act
|
||||
mouse1.IsMouseDisabled = true;
|
||||
mouse1.LastMousePosition = new Point (10, 10);
|
||||
|
||||
// Assert - mouse2 should be unaffected
|
||||
Assert.False (mouse2.IsMouseDisabled);
|
||||
Assert.Null (mouse2.LastMousePosition);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_Events_AreIndependent ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse1 = new ();
|
||||
var mouse1EventCount = 0;
|
||||
|
||||
MouseImpl mouse2 = new ();
|
||||
var mouse2EventCount = 0;
|
||||
|
||||
mouse1.MouseEvent += (sender, args) => mouse1EventCount++;
|
||||
mouse2.MouseEvent += (sender, args) => mouse2EventCount++;
|
||||
|
||||
MouseEventArgs testEvent = new ()
|
||||
{
|
||||
ScreenPosition = new Point (0, 0),
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse1.RaiseMouseEvent (testEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (1, mouse1EventCount);
|
||||
Assert.Equal (0, mouse2EventCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_CachedViews_AreIndependent ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse1 = new ();
|
||||
MouseImpl mouse2 = new ();
|
||||
|
||||
View view1 = new ();
|
||||
View view2 = new ();
|
||||
|
||||
// Act
|
||||
mouse1.CachedViewsUnderMouse.Add (view1);
|
||||
mouse2.CachedViewsUnderMouse.Add (view2);
|
||||
|
||||
// Assert
|
||||
Assert.Single (mouse1.CachedViewsUnderMouse);
|
||||
Assert.Single (mouse2.CachedViewsUnderMouse);
|
||||
Assert.Contains (view1, mouse1.CachedViewsUnderMouse);
|
||||
Assert.Contains (view2, mouse2.CachedViewsUnderMouse);
|
||||
Assert.DoesNotContain (view2, mouse1.CachedViewsUnderMouse);
|
||||
Assert.DoesNotContain (view1, mouse2.CachedViewsUnderMouse);
|
||||
|
||||
view1.Dispose ();
|
||||
view2.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mouse Grab Tests
|
||||
|
||||
[Fact]
|
||||
public void Mouse_GrabMouse_SetsMouseGrabView ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new ();
|
||||
|
||||
// Act
|
||||
mouse.GrabMouse (testView);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (testView, mouse.MouseGrabView);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_UngrabMouse_ClearsMouseGrabView ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new ();
|
||||
mouse.GrabMouse (testView);
|
||||
|
||||
// Act
|
||||
mouse.UngrabMouse ();
|
||||
|
||||
// Assert
|
||||
Assert.Null (mouse.MouseGrabView);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_GrabbingMouse_CanBeCanceled ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new ();
|
||||
var eventFired = false;
|
||||
|
||||
mouse.GrabbingMouse += (sender, args) =>
|
||||
{
|
||||
eventFired = true;
|
||||
args.Cancel = true;
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.GrabMouse (testView);
|
||||
|
||||
// Assert
|
||||
Assert.True (eventFired);
|
||||
Assert.Null (mouse.MouseGrabView); // Should not be set because it was cancelled
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_GrabbedMouse_EventFired ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new ();
|
||||
var eventFired = false;
|
||||
View? eventView = null;
|
||||
|
||||
mouse.GrabbedMouse += (sender, args) =>
|
||||
{
|
||||
eventFired = true;
|
||||
eventView = args.View;
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.GrabMouse (testView);
|
||||
|
||||
// Assert
|
||||
Assert.True (eventFired);
|
||||
Assert.Equal (testView, eventView);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_UnGrabbedMouse_EventFired ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
View testView = new ();
|
||||
mouse.GrabMouse (testView);
|
||||
|
||||
var eventFired = false;
|
||||
View? eventView = null;
|
||||
|
||||
mouse.UnGrabbedMouse += (sender, args) =>
|
||||
{
|
||||
eventFired = true;
|
||||
eventView = args.View;
|
||||
};
|
||||
|
||||
// Act
|
||||
mouse.UngrabMouse ();
|
||||
|
||||
// Assert
|
||||
Assert.True (eventFired);
|
||||
Assert.Equal (testView, eventView);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
125
Tests/UnitTestsParallelizable/Application/MouseTests.cs
Normal file
125
Tests/UnitTestsParallelizable/Application/MouseTests.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using Terminal.Gui.App;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace UnitTests_Parallelizable.ApplicationTests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="IMouse"/> interface and <see cref="MouseImpl"/> implementation.
|
||||
/// These tests demonstrate the decoupled mouse handling that enables parallel test execution.
|
||||
/// </summary>
|
||||
public class MouseTests (ITestOutputHelper output)
|
||||
{
|
||||
private readonly ITestOutputHelper _output = output;
|
||||
|
||||
[Fact]
|
||||
public void Mouse_Instance_CreatedSuccessfully ()
|
||||
{
|
||||
// Arrange & Act
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull (mouse);
|
||||
Assert.False (mouse.IsMouseDisabled);
|
||||
Assert.Null (mouse.LastMousePosition);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_LastMousePosition_CanBeSetAndRetrieved ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
Point expectedPosition = new (10, 20);
|
||||
|
||||
// Act
|
||||
mouse.LastMousePosition = expectedPosition;
|
||||
Point? actualPosition = mouse.GetLastMousePosition ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedPosition, actualPosition);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_IsMouseDisabled_CanBeSetAndRetrieved ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Act
|
||||
mouse.IsMouseDisabled = true;
|
||||
|
||||
// Assert
|
||||
Assert.True (mouse.IsMouseDisabled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_CachedViewsUnderMouse_InitializedEmpty ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull (mouse.CachedViewsUnderMouse);
|
||||
Assert.Empty (mouse.CachedViewsUnderMouse);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_ResetState_ClearsEventAndCachedViews ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventFired = false;
|
||||
mouse.MouseEvent += (sender, args) => eventFired = true;
|
||||
mouse.CachedViewsUnderMouse.Add (new View ());
|
||||
|
||||
// Act
|
||||
mouse.ResetState ();
|
||||
|
||||
// Assert - CachedViewsUnderMouse should be cleared
|
||||
Assert.Empty (mouse.CachedViewsUnderMouse);
|
||||
|
||||
// Event handlers should be cleared
|
||||
MouseEventArgs mouseEvent = new () { ScreenPosition = new Point (0, 0), Flags = MouseFlags.Button1Pressed };
|
||||
mouse.RaiseMouseEvent (mouseEvent);
|
||||
Assert.False (eventFired, "Event should not fire after ResetState");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_RaiseMouseEvent_DoesNotUpdateLastPositionWhenNotInitialized ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
MouseEventArgs mouseEvent = new () { ScreenPosition = new Point (5, 10), Flags = MouseFlags.Button1Pressed };
|
||||
|
||||
// Act - Application is not initialized, so LastMousePosition should not be set
|
||||
mouse.RaiseMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
// Since Application.Initialized is false, LastMousePosition should remain null
|
||||
// This behavior matches the original implementation
|
||||
Assert.Null (mouse.LastMousePosition);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mouse_MouseEvent_CanBeSubscribedAndUnsubscribed ()
|
||||
{
|
||||
// Arrange
|
||||
MouseImpl mouse = new ();
|
||||
var eventCount = 0;
|
||||
EventHandler<MouseEventArgs> handler = (sender, args) => eventCount++;
|
||||
|
||||
// Act - Subscribe
|
||||
mouse.MouseEvent += handler;
|
||||
MouseEventArgs mouseEvent = new () { ScreenPosition = new Point (0, 0), Flags = MouseFlags.Button1Pressed };
|
||||
mouse.RaiseMouseEvent (mouseEvent);
|
||||
|
||||
// Assert - Event fired once
|
||||
Assert.Equal (1, eventCount);
|
||||
|
||||
// Act - Unsubscribe
|
||||
mouse.MouseEvent -= handler;
|
||||
mouse.RaiseMouseEvent (mouseEvent);
|
||||
|
||||
// Assert - Event count unchanged
|
||||
Assert.Equal (1, eventCount);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class GlobalTestSetup : IDisposable
|
||||
|
||||
// Public Properties
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MouseGrabHandler.MouseGrabView);
|
||||
Assert.Null (Application.Mouse.MouseGrabView);
|
||||
|
||||
// Don't check Application.ForceDriver
|
||||
// Assert.Empty (Application.ForceDriver);
|
||||
|
||||
@@ -0,0 +1,498 @@
|
||||
using Terminal.Gui.App;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace UnitTests_Parallelizable.ApplicationTests;
|
||||
|
||||
/// <summary>
|
||||
/// Parallelizable tests for mouse event routing and coordinate transformation.
|
||||
/// These tests validate mouse event handling without Application.Begin or global state.
|
||||
/// </summary>
|
||||
[Trait ("Category", "Input")]
|
||||
public class MouseEventRoutingTests (ITestOutputHelper output)
|
||||
{
|
||||
private readonly ITestOutputHelper _output = output;
|
||||
|
||||
#region Mouse Event Routing to Views
|
||||
|
||||
[Theory]
|
||||
[InlineData (5, 5, 5, 5, true)] // Click inside view
|
||||
[InlineData (0, 0, 0, 0, true)] // Click at origin
|
||||
[InlineData (9, 9, 9, 9, true)] // Click at far corner (view is 10x10)
|
||||
[InlineData (10, 10, -1, -1, false)] // Click outside view
|
||||
[InlineData (-1, -1, -1, -1, false)] // Click outside view
|
||||
public void View_NewMouseEvent_ReceivesCorrectCoordinates (int screenX, int screenY, int expectedViewX, int expectedViewY, bool shouldReceive)
|
||||
{
|
||||
// Arrange
|
||||
View view = new ()
|
||||
{
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = 10,
|
||||
Height = 10
|
||||
};
|
||||
|
||||
Point? receivedPosition = null;
|
||||
var eventReceived = false;
|
||||
|
||||
view.MouseEvent += (sender, args) =>
|
||||
{
|
||||
eventReceived = true;
|
||||
receivedPosition = args.Position;
|
||||
};
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (screenX, screenY),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
if (shouldReceive)
|
||||
{
|
||||
Assert.True (eventReceived);
|
||||
Assert.NotNull (receivedPosition);
|
||||
Assert.Equal (expectedViewX, receivedPosition.Value.X);
|
||||
Assert.Equal (expectedViewY, receivedPosition.Value.Y);
|
||||
}
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 0, 5, 5, 5, 5, true)] // View at origin, click at (5,5) in view
|
||||
[InlineData (10, 10, 5, 5, 5, 5, true)] // View offset, but we still pass view-relative coords
|
||||
[InlineData (0, 0, 0, 0, 0, 0, true)] // View at origin, click at origin
|
||||
[InlineData (5, 5, 9, 9, 9, 9, true)] // View offset, click at far corner (view-relative)
|
||||
[InlineData (0, 0, 10, 10, -1, -1, false)] // Click outside view bounds
|
||||
[InlineData (0, 0, -1, -1, -1, -1, false)] // Click outside view bounds
|
||||
public void View_WithOffset_ReceivesCorrectCoordinates (
|
||||
int viewX,
|
||||
int viewY,
|
||||
int viewRelativeX,
|
||||
int viewRelativeY,
|
||||
int expectedViewX,
|
||||
int expectedViewY,
|
||||
bool shouldReceive)
|
||||
{
|
||||
// Arrange
|
||||
// Note: When testing View.NewMouseEvent directly (without Application routing),
|
||||
// coordinates are already view-relative. The view's X/Y position doesn't affect
|
||||
// the coordinate transformation at this level.
|
||||
View view = new ()
|
||||
{
|
||||
X = viewX,
|
||||
Y = viewY,
|
||||
Width = 10,
|
||||
Height = 10
|
||||
};
|
||||
|
||||
Point? receivedPosition = null;
|
||||
var eventReceived = false;
|
||||
|
||||
view.MouseEvent += (sender, args) =>
|
||||
{
|
||||
eventReceived = true;
|
||||
receivedPosition = args.Position;
|
||||
};
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (viewRelativeX, viewRelativeY),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
if (shouldReceive)
|
||||
{
|
||||
Assert.True (eventReceived, $"Event should be received at view-relative ({viewRelativeX},{viewRelativeY})");
|
||||
Assert.NotNull (receivedPosition);
|
||||
Assert.Equal (expectedViewX, receivedPosition.Value.X);
|
||||
Assert.Equal (expectedViewY, receivedPosition.Value.Y);
|
||||
}
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region View Hierarchy Mouse Event Routing
|
||||
|
||||
[Fact]
|
||||
public void SubView_ReceivesMouseEvent_WithCorrectRelativeCoordinates ()
|
||||
{
|
||||
// Arrange
|
||||
View superView = new ()
|
||||
{
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = 20,
|
||||
Height = 20
|
||||
};
|
||||
|
||||
View subView = new ()
|
||||
{
|
||||
X = 5,
|
||||
Y = 5,
|
||||
Width = 10,
|
||||
Height = 10
|
||||
};
|
||||
|
||||
superView.Add (subView);
|
||||
|
||||
Point? subViewReceivedPosition = null;
|
||||
var subViewEventReceived = false;
|
||||
|
||||
subView.MouseEvent += (sender, args) =>
|
||||
{
|
||||
subViewEventReceived = true;
|
||||
subViewReceivedPosition = args.Position;
|
||||
};
|
||||
|
||||
// Click at position (2, 2) relative to subView (which is at 5,5 relative to superView)
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (2, 2), // Relative to subView
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
subView.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.True (subViewEventReceived);
|
||||
Assert.NotNull (subViewReceivedPosition);
|
||||
Assert.Equal (2, subViewReceivedPosition.Value.X);
|
||||
Assert.Equal (2, subViewReceivedPosition.Value.Y);
|
||||
|
||||
subView.Dispose ();
|
||||
superView.Dispose ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MouseClick_OnSubView_RaisesMouseClickEvent ()
|
||||
{
|
||||
// Arrange
|
||||
View superView = new ()
|
||||
{
|
||||
Width = 20,
|
||||
Height = 20
|
||||
};
|
||||
|
||||
View subView = new ()
|
||||
{
|
||||
X = 5,
|
||||
Y = 5,
|
||||
Width = 10,
|
||||
Height = 10
|
||||
};
|
||||
|
||||
superView.Add (subView);
|
||||
|
||||
var clickCount = 0;
|
||||
subView.MouseClick += (sender, args) => clickCount++;
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
subView.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (1, clickCount);
|
||||
|
||||
subView.Dispose ();
|
||||
superView.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mouse Event Propagation
|
||||
|
||||
[Fact]
|
||||
public void View_HandledEvent_StopsPropagation ()
|
||||
{
|
||||
// Arrange
|
||||
View view = new () { Width = 10, Height = 10 };
|
||||
var handlerCalled = false;
|
||||
var clickHandlerCalled = false;
|
||||
|
||||
view.MouseEvent += (sender, args) =>
|
||||
{
|
||||
handlerCalled = true;
|
||||
args.Handled = true; // Mark as handled
|
||||
};
|
||||
|
||||
view.MouseClick += (sender, args) => { clickHandlerCalled = true; };
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
bool? result = view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.True (result.HasValue && result.Value); // Event was handled
|
||||
Assert.True (handlerCalled);
|
||||
Assert.False (clickHandlerCalled); // Click handler should not be called when event is handled
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void View_UnhandledEvent_ContinuesProcessing ()
|
||||
{
|
||||
// Arrange
|
||||
View view = new () { Width = 10, Height = 10 };
|
||||
var eventHandlerCalled = false;
|
||||
var clickHandlerCalled = false;
|
||||
|
||||
view.MouseEvent += (sender, args) =>
|
||||
{
|
||||
eventHandlerCalled = true;
|
||||
// Don't set Handled = true
|
||||
};
|
||||
|
||||
view.MouseClick += (sender, args) => { clickHandlerCalled = true; };
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.True (eventHandlerCalled);
|
||||
Assert.True (clickHandlerCalled); // Click handler should be called when event is not handled
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mouse Button Events
|
||||
|
||||
[Theory]
|
||||
[InlineData (MouseFlags.Button1Pressed, 1, 0, 0)]
|
||||
[InlineData (MouseFlags.Button1Released, 0, 1, 0)]
|
||||
[InlineData (MouseFlags.Button1Clicked, 0, 0, 1)]
|
||||
public void View_MouseButtonEvents_RaiseCorrectHandlers (MouseFlags flags, int expectedPressed, int expectedReleased, int expectedClicked)
|
||||
{
|
||||
// Arrange
|
||||
View view = new () { Width = 10, Height = 10 };
|
||||
var pressedCount = 0;
|
||||
var releasedCount = 0;
|
||||
var clickedCount = 0;
|
||||
|
||||
view.MouseEvent += (sender, args) =>
|
||||
{
|
||||
if (args.Flags.HasFlag (MouseFlags.Button1Pressed))
|
||||
{
|
||||
pressedCount++;
|
||||
}
|
||||
|
||||
if (args.Flags.HasFlag (MouseFlags.Button1Released))
|
||||
{
|
||||
releasedCount++;
|
||||
}
|
||||
};
|
||||
|
||||
view.MouseClick += (sender, args) => { clickedCount++; };
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = flags
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedPressed, pressedCount);
|
||||
Assert.Equal (expectedReleased, releasedCount);
|
||||
Assert.Equal (expectedClicked, clickedCount);
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (MouseFlags.Button1Clicked)]
|
||||
[InlineData (MouseFlags.Button2Clicked)]
|
||||
[InlineData (MouseFlags.Button3Clicked)]
|
||||
[InlineData (MouseFlags.Button4Clicked)]
|
||||
public void View_AllMouseButtons_TriggerClickEvent (MouseFlags clickFlag)
|
||||
{
|
||||
// Arrange
|
||||
View view = new () { Width = 10, Height = 10 };
|
||||
var clickCount = 0;
|
||||
|
||||
view.MouseClick += (sender, args) => clickCount++;
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = clickFlag
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (1, clickCount);
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disabled View Tests
|
||||
|
||||
[Fact]
|
||||
public void View_Disabled_DoesNotRaiseMouseEvent ()
|
||||
{
|
||||
// Arrange
|
||||
View view = new ()
|
||||
{
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
var eventCalled = false;
|
||||
view.MouseEvent += (sender, args) => { eventCalled = true; };
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.False (eventCalled);
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void View_Disabled_DoesNotRaiseMouseClickEvent ()
|
||||
{
|
||||
// Arrange
|
||||
View view = new ()
|
||||
{
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
var clickCalled = false;
|
||||
view.MouseClick += (sender, args) => { clickCalled = true; };
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.False (clickCalled);
|
||||
|
||||
view.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Focus and Selection Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData (true, true)]
|
||||
[InlineData (false, false)]
|
||||
public void MouseClick_SetsFocus_BasedOnCanFocus (bool canFocus, bool expectFocus)
|
||||
{
|
||||
// Arrange
|
||||
View superView = new () { CanFocus = true, Width = 20, Height = 20 };
|
||||
View subView = new ()
|
||||
{
|
||||
X = 5,
|
||||
Y = 5,
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
CanFocus = canFocus
|
||||
};
|
||||
|
||||
superView.Add (subView);
|
||||
superView.SetFocus (); // Give superView focus first
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (2, 2),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
subView.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectFocus, subView.HasFocus);
|
||||
|
||||
subView.Dispose ();
|
||||
superView.Dispose ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MouseClick_RaisesSelecting_WhenCanFocus ()
|
||||
{
|
||||
// Arrange
|
||||
View superView = new () { CanFocus = true, Width = 20, Height = 20 };
|
||||
View view = new ()
|
||||
{
|
||||
X = 5,
|
||||
Y = 5,
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
CanFocus = true
|
||||
};
|
||||
|
||||
superView.Add (view);
|
||||
|
||||
var selectingCount = 0;
|
||||
view.Selecting += (sender, args) => selectingCount++;
|
||||
|
||||
MouseEventArgs mouseEvent = new ()
|
||||
{
|
||||
Position = new Point (5, 5),
|
||||
Flags = MouseFlags.Button1Clicked
|
||||
};
|
||||
|
||||
// Act
|
||||
view.NewMouseEvent (mouseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (1, selectingCount);
|
||||
|
||||
view.Dispose ();
|
||||
superView.Dispose ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user