diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 2eff63efb..670b5674e 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -1374,7 +1374,8 @@ public static partial class Application return; } - var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y, out int screenX, out int screenY); + // TODO: In PR #3273, FindDeepestView will return adornments. Update logic below to fix adornment mouse handling + var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y); if (view is { WantContinuousButtonPressed: true }) { @@ -1437,7 +1438,7 @@ public static partial class Application && a.MouseEvent.Flags != 0) { View? top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y); - view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y, out screenX, out screenY); + view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y); if (view is { } && view != OverlappedTop && top != Current) { @@ -1450,6 +1451,8 @@ public static partial class Application return; } + var screen = view.FrameToScreen (); + // Work inside-out (Padding, Border, Margin) // TODO: Debate whether inside-out or outside-in is the right strategy if (AdornmentHandledMouseEvent (view.Padding, a)) @@ -1469,11 +1472,11 @@ public static partial class Application var me = new MouseEvent { - X = screenX, - Y = screenY, + X = a.MouseEvent.X - screen.X, + Y = a.MouseEvent.Y - screen.Y, Flags = a.MouseEvent.Flags, - OfX = screenX, - OfY = screenY, + OfX = a.MouseEvent.X - screen.X, + OfY = a.MouseEvent.Y - screen.Y, View = view }; diff --git a/Terminal.Gui/Input/Responder.cs b/Terminal.Gui/Input/Responder.cs index 9f38757fa..d7f2ce6c3 100644 --- a/Terminal.Gui/Input/Responder.cs +++ b/Terminal.Gui/Input/Responder.cs @@ -57,6 +57,9 @@ public class Responder : IDisposable public event EventHandler Disposing; /// Method invoked when a mouse event is generated + /// + /// The coordinates are relative to . + /// /// true, if the event was handled, false otherwise. /// Contains the details about the mouse event. public virtual bool MouseEvent (MouseEvent mouseEvent) { return false; } @@ -81,6 +84,9 @@ public class Responder : IDisposable /// Called when the mouse first enters the view; the view will now receives mouse events until the mouse leaves /// the view. At which time, will be called. /// + /// + /// The coordinates are relative to . + /// /// /// true, if the event was handled, false otherwise. public virtual bool OnMouseEnter (MouseEvent mouseEvent) { return false; } @@ -89,6 +95,9 @@ public class Responder : IDisposable /// Called when the mouse has moved outside of the view; the view will no longer receive mouse events (until the /// mouse moves within the view again and is called). /// + /// + /// The coordinates are relative to . + /// /// /// true, if the event was handled, false otherwise. public virtual bool OnMouseLeave (MouseEvent mouseEvent) { return false; } diff --git a/Terminal.Gui/View/Adornment/Adornment.cs b/Terminal.Gui/View/Adornment/Adornment.cs index a88186d92..4f47e6e02 100644 --- a/Terminal.Gui/View/Adornment/Adornment.cs +++ b/Terminal.Gui/View/Adornment/Adornment.cs @@ -33,7 +33,7 @@ public class Adornment : View /// Gets the rectangle that describes the inner area of the Adornment. The Location is always (0,0). public override Rectangle Bounds { - get => Thickness?.GetInside (new (Point.Empty, Frame.Size)) ?? new Rectangle (Point.Empty, Frame.Size); + get => new Rectangle (Point.Empty, Thickness?.GetInside (new (Point.Empty, Frame.Size)).Size ?? Frame.Size); // QUESTION: So why even have a setter then? set => throw new InvalidOperationException ("It makes no sense to set Bounds of a Thickness."); } @@ -100,17 +100,19 @@ public class Adornment : View /// public override Rectangle FrameToScreen () { + if (Parent is null) + { + return Frame; + } + // Adornments are *Children* of a View, not SubViews. Thus View.FrameToScreen will not work. // To get the screen-relative coordinates of a Adornment, we need to know who // the Parent is - Rectangle ret = Parent?.Frame ?? Frame; - ret.Size = Frame.Size; - - ret.Location = Parent?.FrameToScreen ().Location ?? ret.Location; + Rectangle parent = Parent.FrameToScreen (); // We now have coordinates relative to our View. If our View's SuperView has // a SuperView, keep going... - return ret; + return new (new (parent.X + Frame.X, parent.Y + Frame.Y), Frame.Size); } /// Does nothing for Adornment diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 3fe411799..85441c1e5 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -545,28 +545,49 @@ public partial class View } } - #nullable enable +#nullable enable /// Finds which view that belong to the superview at the provided location. /// The superview where to look for. /// The column location in the superview. /// The row location in the superview. - /// The found view screen relative column location. - /// The found view screen relative row location. + /// TODO: Remove this in PR #3273 /// /// The view that was found at the and coordinates. /// if no view was found. /// + // CONCURRENCY: This method is not thread-safe. // Undefined behavior and likely program crashes are exposed by unsynchronized access to InternalSubviews. - public static View? FindDeepestView (View? start, int x, int y, out int resultX, out int resultY) + public static View? FindDeepestView (View? start, int x, int y, bool findAdornments = false) { - resultY = resultX = 0; - - if (start is null || !start.Frame.Contains (x, y)) + if (start is null || !start.Visible) { return null; } + if (!start.Frame.Contains (x, y)) + { + return null; + } + + if (findAdornments) + { + // TODO: This is a temporary hack for PR #3273; it is not actually used anywhere but unit tests at this point. + if (start.Margin.Thickness.Contains (start.Margin.Frame, x, y)) + { + return start.Margin; + } + if (start.Border.Thickness.Contains (start.Border.Frame, x, y)) + { + return start.Border; + } + if (start.Padding.Thickness.Contains (start.Padding.Frame, x, y)) + { + return start.Padding; + } + + } + if (start.InternalSubviews is { Count: > 0 }) { Point boundsOffset = start.GetBoundsOffset (); @@ -579,19 +600,14 @@ public partial class View if (v.Visible && v.Frame.Contains (rx, ry)) { - View? deep = FindDeepestView (v, rx, ry, out resultX, out resultY); - + View? deep = FindDeepestView (v, rx, ry, findAdornments); return deep ?? v; } } } - - resultX = x - start.Frame.X; - resultY = y - start.Frame.Y; - return start; } - #nullable restore +#nullable restore /// Gets the with a screen-relative location. /// The location and size of the view in screen-relative coordinates. diff --git a/Terminal.Gui/Views/Menu/Menu.cs b/Terminal.Gui/Views/Menu/Menu.cs index 28f9b1823..37de2476b 100644 --- a/Terminal.Gui/Views/Menu/Menu.cs +++ b/Terminal.Gui/Views/Menu/Menu.cs @@ -727,13 +727,7 @@ internal sealed class Menu : View locationOffset.Y += SuperView.Border.Thickness.Top; } - View view = FindDeepestView ( - this, - a.MouseEvent.X + locationOffset.X, - a.MouseEvent.Y + locationOffset.Y, - out int rx, - out int ry - ); + View view = FindDeepestView (this, a.MouseEvent.X + locationOffset.X, a.MouseEvent.Y + locationOffset.Y); if (view == this) { @@ -742,7 +736,13 @@ internal sealed class Menu : View throw new InvalidOperationException ("This shouldn't running on a invisible menu!"); } - var nme = new MouseEvent { X = rx, Y = ry, Flags = a.MouseEvent.Flags, View = view }; + var screen = view.FrameToScreen (); + var nme = new MouseEvent { + X = a.MouseEvent.X - screen.X, + Y = a.MouseEvent.Y - screen.Y, + Flags = a.MouseEvent.Flags, + View = view + }; if (MouseEvent (nme) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released) { diff --git a/UnitTests/View/Adornment/AdornmentTests.cs b/UnitTests/View/Adornment/AdornmentTests.cs index 8cc054e8b..6b2d5765b 100644 --- a/UnitTests/View/Adornment/AdornmentTests.cs +++ b/UnitTests/View/Adornment/AdornmentTests.cs @@ -7,6 +7,46 @@ public class AdornmentTests private readonly ITestOutputHelper _output; public AdornmentTests (ITestOutputHelper output) { _output = output; } + [Fact] + public void Bounds_Location_Always_Empty_Size_Correct () + { + var view = new View + { + X = 1, + Y = 2, + Width = 20, + Height = 31 + }; + + var marginThickness = 1; + view.Margin.Thickness = new Thickness (marginThickness); + + var borderThickness = 2; + view.Border.Thickness = new Thickness (borderThickness); + + var paddingThickness = 3; + view.Padding.Thickness = new Thickness (paddingThickness); + + view.BeginInit (); + view.EndInit (); + + Assert.Equal (new Rectangle (1, 2, 20, 31), view.Frame); + Assert.Equal (new Rectangle (0, 0, 8, 19), view.Bounds); + + Assert.Equal (new Rectangle (0, 0, view.Margin.Frame.Width - marginThickness * 2, view.Margin.Frame.Height - marginThickness * 2), view.Margin.Bounds); + + Assert.Equal (new Rectangle (0, 0, view.Border.Frame.Width - borderThickness * 2, view.Border.Frame.Height - borderThickness * 2), view.Border.Bounds); + + Assert.Equal ( + new Rectangle ( + 0, + 0, + view.Padding.Frame.Width - (marginThickness + borderThickness) * 2, + view.Padding.Frame.Height - (marginThickness + borderThickness) * 2), + view.Padding.Bounds); + } + + // Test that Adornment.Bounds_get override uses Parent not SuperView [Fact] public void BoundsToScreen_Uses_Parent_Not_SuperView () { @@ -25,6 +65,134 @@ public class AdornmentTests Assert.Equal (new Rectangle (2, 4, 5, 5), boundsAsScreen); } + [Fact] + public void Frames_are_Parent_SuperView_Relative () + { + var view = new View + { + X = 1, + Y = 2, + Width = 20, + Height = 31 + }; + + var marginThickness = 1; + view.Margin.Thickness = new Thickness (marginThickness); + + var borderThickness = 2; + view.Border.Thickness = new Thickness (borderThickness); + + var paddingThickness = 3; + view.Padding.Thickness = new Thickness (paddingThickness); + + view.BeginInit (); + view.EndInit (); + + Assert.Equal (new Rectangle (1, 2, 20, 31), view.Frame); + Assert.Equal (new Rectangle (0, 0, 8, 19), view.Bounds); + + // Margin.Frame is always the same as the view frame + Assert.Equal (new Rectangle (0, 0, 20, 31), view.Margin.Frame); + + // Border.Frame is View.Frame minus the Margin thickness + Assert.Equal ( + new Rectangle (marginThickness, marginThickness, view.Frame.Width - marginThickness * 2, view.Frame.Height - marginThickness * 2), + view.Border.Frame); + + // Padding.Frame is View.Frame minus the Border thickness plus Margin thickness + Assert.Equal ( + new Rectangle ( + marginThickness + borderThickness, + marginThickness + borderThickness, + view.Frame.Width - (marginThickness + borderThickness) * 2, + view.Frame.Height - (marginThickness + borderThickness) * 2), + view.Padding.Frame); + } + + // Test that Adornment.FrameToScreen override retains Frame.Size + [Theory] + [InlineData (0, 0, 0)] + [InlineData (0, 1, 1)] + [InlineData (0, 10, 10)] + [InlineData (1, 0, 0)] + [InlineData (1, 1, 1)] + [InlineData (1, 10, 10)] + public void FrameToScreen_Retains_Frame_Size (int marginThickness, int w, int h) + { + var parent = new View { X = 1, Y = 2, Width = w, Height = h }; + parent.Margin.Thickness = new Thickness (marginThickness); + + parent.BeginInit (); + parent.EndInit (); + + Assert.Equal (new Rectangle (1, 2, w, h), parent.Frame); + Assert.Equal (new Rectangle (0, 0, w, h), parent.Margin.Frame); + + Assert.Equal (parent.Frame, parent.Margin.FrameToScreen ()); + } + + // Test that Adornment.FrameToScreen override returns Frame if Parent is null + [Fact] + public void FrameToScreen_Returns_Frame_If_Parent_Is_Null () + { + var a = new Adornment + { + X = 1, + Y = 2, + Width = 3, + Height = 4 + }; + + Assert.Null (a.Parent); + Assert.Equal (a.Frame, a.FrameToScreen ()); + } + + // Test that Adornment.FrameToScreen override returns correct location + [Theory] + [InlineData (0, 0, 0, 0)] + [InlineData (0, 0, 1, 1)] + [InlineData (0, 0, 10, 10)] + [InlineData (1, 0, 0, 0)] + [InlineData (1, 0, 1, 1)] + [InlineData (1, 0, 10, 10)] + [InlineData (0, 1, 0, 0)] + [InlineData (0, 1, 1, 1)] + [InlineData (0, 1, 10, 10)] + [InlineData (1, 1, 0, 0)] + [InlineData (1, 1, 1, 1)] + [InlineData (1, 1, 10, 10)] + public void FrameToScreen_Returns_Screen_Location (int marginThickness, int borderThickness, int x, int y) + { + var superView = new View + { + X = 1, + Y = 1, + Width = 20, + Height = 20 + }; + superView.Margin.Thickness = new Thickness (marginThickness); + superView.Border.Thickness = new Thickness (borderThickness); + + var view = new View { X = x, Y = y, Width = 1, Height = 1 }; + superView.Add (view); + superView.BeginInit (); + superView.EndInit (); + + Assert.Equal (new Rectangle (x, y, 1, 1), view.Frame); + Assert.Equal (new Rectangle (0, 0, 20, 20), superView.Margin.Frame); + + Assert.Equal ( + new Rectangle (marginThickness, marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2), + superView.Border.Frame + ); + + Assert.Equal ( + new Rectangle (superView.Frame.X + marginThickness, superView.Frame.Y + marginThickness, 20 - marginThickness * 2, 20 - marginThickness * 2), + superView.Border.FrameToScreen () + ); + } + + // Test that Adornment.FrameToScreen override uses Parent not SuperView [Fact] public void FrameToScreen_Uses_Parent_Not_SuperView () { diff --git a/UnitTests/View/FindDeepestViewTests.cs b/UnitTests/View/FindDeepestViewTests.cs new file mode 100644 index 000000000..6434eaa8c --- /dev/null +++ b/UnitTests/View/FindDeepestViewTests.cs @@ -0,0 +1,285 @@ +using UICatalog.Scenarios; +using Xunit.Abstractions; + +namespace Terminal.Gui.ViewTests; + +/// +/// Tests View.FindDeepestView +/// +/// +public class FindDeepestViewTests (ITestOutputHelper output) +{ + // Test that FindDeepestView returns the correct view if the start view has no subviews + [Theory] + [InlineData (0, 0)] + [InlineData (1, 1)] + [InlineData (2, 2)] + public void Returns_Start_If_No_SubViews (int testX, int testY) + { + var start = new View () + { + Width = 10, Height = 10, + }; + + Assert.Same (start, View.FindDeepestView (start, testX, testY)); + } + + // Test that FindDeepestView returns null if the start view has no subviews and coords are outside the view + [Theory] + [InlineData (0, 0)] + [InlineData (2, 1)] + [InlineData (20, 20)] + public void Returns_Null_If_No_SubViews_Coords_Outside (int testX, int testY) + { + var start = new View () + { + X = 1, Y = 2, + Width = 10, Height = 10, + }; + + Assert.Null(View.FindDeepestView (start, testX, testY)); + } + + [Theory] + [InlineData (0, 0)] + [InlineData (2, 1)] + [InlineData (20, 20)] + public void Returns_Null_If_Start_Not_Visible (int testX, int testY) + { + var start = new View () + { + X = 1, Y = 2, + Width = 10, Height = 10, + Visible = false, + }; + + Assert.Null (View.FindDeepestView (start, testX, testY)); + } + + // Test that FindDeepestView returns the correct view if the start view has subviews + [Theory] + [InlineData (0, 0, false)] + [InlineData (1, 1, false)] + [InlineData (9, 9, false)] + [InlineData (10, 10, false)] + [InlineData (6, 7, false)] + + [InlineData (1, 2, true)] + [InlineData (5, 6, true)] + public void Returns_Correct_If_SubViews (int testX, int testY, bool expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10, + }; + + var subview = new View () + { + X = 1, Y = 2, + Width = 5, Height = 5, + }; + start.Add (subview); + + var found = View.FindDeepestView (start, testX, testY); + + Assert.Equal (expectedSubViewFound, found == subview); + } + + [Theory] + [InlineData (0, 0, false)] + [InlineData (1, 1, false)] + [InlineData (9, 9, false)] + [InlineData (10, 10, false)] + [InlineData (6, 7, false)] + [InlineData (1, 2, false)] + [InlineData (5, 6, false)] + public void Returns_Null_If_SubView_NotVisible (int testX, int testY, bool expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10, + }; + + var subview = new View () + { + X = 1, Y = 2, + Width = 5, Height = 5, + Visible = false + }; + start.Add (subview); + + var found = View.FindDeepestView (start, testX, testY); + + Assert.Equal (expectedSubViewFound, found == subview); + } + + + [Theory] + [InlineData (0, 0, false)] + [InlineData (1, 1, false)] + [InlineData (9, 9, false)] + [InlineData (10, 10, false)] + [InlineData (6, 7, false)] + [InlineData (1, 2, false)] + [InlineData (5, 6, false)] + public void Returns_Null_If_Not_Visible_And_SubView_Visible (int testX, int testY, bool expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10, + Visible = false + }; + + var subview = new View () + { + X = 1, Y = 2, + Width = 5, Height = 5, + }; + start.Add (subview); + subview.Visible = true; + Assert.True (subview.Visible); + Assert.False (start.Visible); + var found = View.FindDeepestView (start, testX, testY); + + Assert.Equal (expectedSubViewFound, found == subview); + } + + // Test that FindDeepestView works if the start view has positive Adornments + [Theory] + [InlineData (0, 0, false)] + [InlineData (1, 1, false)] + [InlineData (9, 9, false)] + [InlineData (10, 10, false)] + [InlineData (7, 8, false)] + [InlineData (1, 2, false)] + + [InlineData (2, 3, true)] + [InlineData (5, 6, true)] + [InlineData (2, 3, true)] + [InlineData (6, 7, true)] + public void Returns_Correct_If_Start_Has_Adornments (int testX, int testY, bool expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10, + }; + start.Margin.Thickness = new Thickness (1); + + var subview = new View () + { + X = 1, Y = 2, + Width = 5, Height = 5, + }; + start.Add (subview); + + var found = View.FindDeepestView (start, testX, testY, true); + + Assert.Equal (expectedSubViewFound, found == subview); + } + + [Theory] + [InlineData (0, 0, typeof(Margin))] + [InlineData (9, 9, typeof (Margin))] + + [InlineData (1, 1, typeof (Border))] + [InlineData (8, 8, typeof (Border))] + + [InlineData (2, 2, typeof (Padding))] + [InlineData (7, 7, typeof (Padding))] + + [InlineData (5, 5, typeof (View))] + public void Returns_Adornment_If_Start_Has_Adornments (int testX, int testY, Type expectedAdornmentType) + { + var start = new View () + { + Width = 10, Height = 10, + }; + start.Margin.Thickness = new Thickness (1); + start.Border.Thickness = new Thickness (1); + start.Padding.Thickness = new Thickness (1); + + var subview = new View () + { + X = 1, Y = 1, + Width = 1, Height = 1, + }; + start.Add (subview); + + var found = View.FindDeepestView (start, testX, testY, true); + Assert.Equal(expectedAdornmentType, found.GetType()); + } + + // Test that FindDeepestView works if the subview has positive Adornments + [Theory] + [InlineData (0, 0, false)] + [InlineData (1, 1, false)] + [InlineData (9, 9, false)] + [InlineData (10, 10, false)] + [InlineData (7, 8, false)] + [InlineData (6, 7, false)] + + [InlineData (1, 2, true)] + [InlineData (2, 3, true)] + [InlineData (5, 6, true)] + [InlineData (2, 3, true)] + public void Returns_Correct_If_SubView_Has_Adornments (int testX, int testY, bool expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10, + }; + + var subview = new View () + { + X = 1, Y = 2, + Width = 5, Height = 5, + }; + subview.Margin.Thickness = new Thickness (1); + start.Add (subview); + + var found = View.FindDeepestView (start, testX, testY); + + Assert.Equal (expectedSubViewFound, found == subview); + } + + // Test that FindDeepestView works with nested subviews + [Theory] + [InlineData (0, 0, -1)] + [InlineData (9, 9, -1)] + [InlineData (10, 10, -1)] + + [InlineData (1, 1, 0)] + [InlineData (1, 2, 0)] + [InlineData (2, 2, 1)] + [InlineData (3, 3, 2)] + [InlineData (5, 5, 2)] + public void Returns_Correct_With_NestedSubViews (int testX, int testY, int expectedSubViewFound) + { + var start = new View () + { + Width = 10, Height = 10 + }; + + int numSubViews = 3; + List subviews = new List (); + for (int i = 0; i < numSubViews; i++) + { + var subview = new View () + { + X = 1, Y = 1, + Width = 5, Height = 5, + }; + subviews.Add (subview); + + if (i > 0) + { + subviews [i - 1].Add (subview); + } + } + + start.Add (subviews [0]); + + var found = View.FindDeepestView (start, testX, testY); + Assert.Equal (expectedSubViewFound, subviews.IndexOf(found)); + } +} diff --git a/UnitTests/View/Layout/LayoutTests.cs b/UnitTests/View/Layout/LayoutTests.cs index b489464ac..ae30919fe 100644 --- a/UnitTests/View/Layout/LayoutTests.cs +++ b/UnitTests/View/Layout/LayoutTests.cs @@ -1,4 +1,5 @@ using Xunit.Abstractions; +using static Unix.Terminal.Curses; // Alias Console to MockConsole so we don't accidentally use Console @@ -549,7 +550,7 @@ public class LayoutTests Assert.Equal (new Rectangle (0, 2, 10, 3), win2.Frame); Assert.Equal (new Rectangle (0, 0, 8, 1), view2.Frame); Assert.Equal (new Rectangle (0, 0, 7, 1), view3.Frame); - var foundView = View.FindDeepestView (top, 9, 4, out int rx, out int ry); + var foundView = View.FindDeepestView (top, 9, 4); Assert.Equal (foundView, view2); Application.OnMouseEvent ( diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs index a7b087b22..ac93b2b15 100644 --- a/UnitTests/View/NavigationTests.cs +++ b/UnitTests/View/NavigationTests.cs @@ -856,39 +856,46 @@ public class NavigationTests top.BoundsToScreen (-1, -1, out col, out row); Assert.Equal (0, col); Assert.Equal (0, row); - Assert.Equal (top, View.FindDeepestView (top, 0, 0, out int rx, out int ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + var found = View.FindDeepestView (top, 0, 0); + Assert.Equal (top, found); + + Assert.Equal (0, found.Frame.X); + Assert.Equal (0, found.Frame.Y); Assert.Equal (new Point (3, 2), top.ScreenToFrame (3, 2)); top.BoundsToScreen (3, 2, out col, out row); Assert.Equal (4, col); Assert.Equal (3, row); - Assert.Equal (view, View.FindDeepestView (top, col, row, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); - Assert.Equal (top, View.FindDeepestView (top, 3, 2, out rx, out ry)); - Assert.Equal (3, rx); - Assert.Equal (2, ry); + found = View.FindDeepestView (top, col, row); + Assert.Equal (view, found); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); + found = View.FindDeepestView (top, 3, 2); + Assert.Equal (top, found); + //Assert.Equal (3, found.FrameToScreen ().X); + //Assert.Equal (2, found.FrameToScreen ().Y); Assert.Equal (new Point (13, 2), top.ScreenToFrame (13, 2)); top.BoundsToScreen (12, 2, out col, out row); Assert.Equal (13, col); Assert.Equal (3, row); - Assert.Equal (view, View.FindDeepestView (top, col, row, out rx, out ry)); - Assert.Equal (9, rx); - Assert.Equal (0, ry); + found = View.FindDeepestView (top, col, row); + Assert.Equal (view, found); + //Assert.Equal (9, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); top.BoundsToScreen (13, 2, out col, out row); Assert.Equal (14, col); Assert.Equal (3, row); - Assert.Equal (top, View.FindDeepestView (top, 13, 2, out rx, out ry)); - Assert.Equal (13, rx); - Assert.Equal (2, ry); + found = View.FindDeepestView (top, 13, 2); + Assert.Equal (top, found); + //Assert.Equal (13, found.FrameToScreen ().X); + //Assert.Equal (2, found.FrameToScreen ().Y); Assert.Equal (new Point (14, 3), top.ScreenToFrame (14, 3)); top.BoundsToScreen (14, 3, out col, out row); Assert.Equal (15, col); Assert.Equal (4, row); - Assert.Equal (top, View.FindDeepestView (top, 14, 3, out rx, out ry)); - Assert.Equal (14, rx); - Assert.Equal (3, ry); + found = View.FindDeepestView (top, 14, 3); + Assert.Equal (top, found); + //Assert.Equal (14, found.FrameToScreen ().X); + //Assert.Equal (3, found.FrameToScreen ().Y); // view Assert.Equal (new Point (-4, -3), view.ScreenToFrame (0, 0)); @@ -907,30 +914,34 @@ public class NavigationTests view.BoundsToScreen (-4, -3, out col, out row); Assert.Equal (0, col); Assert.Equal (0, row); - Assert.Equal (top, View.FindDeepestView (top, 0, 0, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + found = View.FindDeepestView (top, 0, 0); + Assert.Equal (top, found); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (-1, -1), view.ScreenToFrame (3, 2)); view.BoundsToScreen (0, 0, out col, out row); Assert.Equal (4, col); Assert.Equal (3, row); - Assert.Equal (view, View.FindDeepestView (top, 4, 3, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + found = View.FindDeepestView (top, 4, 3); + Assert.Equal (view, found); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (9, -1), view.ScreenToFrame (13, 2)); view.BoundsToScreen (10, 0, out col, out row); Assert.Equal (14, col); Assert.Equal (3, row); - Assert.Equal (top, View.FindDeepestView (top, 14, 3, out rx, out ry)); - Assert.Equal (14, rx); - Assert.Equal (3, ry); + found = View.FindDeepestView (top, 14, 3); + Assert.Equal (top, found); + //Assert.Equal (14, found.FrameToScreen ().X); + //Assert.Equal (3, found.FrameToScreen ().Y); Assert.Equal (new Point (10, 0), view.ScreenToFrame (14, 3)); view.BoundsToScreen (11, 1, out col, out row); Assert.Equal (15, col); Assert.Equal (4, row); - Assert.Equal (top, View.FindDeepestView (top, 15, 4, out rx, out ry)); - Assert.Equal (15, rx); - Assert.Equal (4, ry); + found = View.FindDeepestView (top, 15, 4); + Assert.Equal (top, found); + //Assert.Equal (15, found.FrameToScreen ().X); + //Assert.Equal (4, found.FrameToScreen ().Y); } [Fact] @@ -1004,30 +1015,31 @@ public class NavigationTests top.BoundsToScreen (-4, -3, out col, out row); Assert.Equal (0, col); Assert.Equal (0, row); - Assert.Null (View.FindDeepestView (top, -4, -3, out int rx, out int ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + var found = View.FindDeepestView (top, -4, -3); + Assert.Null (found); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (Point.Empty, top.ScreenToFrame (3, 2)); top.BoundsToScreen (0, 0, out col, out row); Assert.Equal (4, col); Assert.Equal (3, row); - Assert.Equal (top, View.FindDeepestView (top, 3, 2, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + Assert.Equal (top, View.FindDeepestView (top, 3, 2)); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (10, 0), top.ScreenToFrame (13, 2)); top.BoundsToScreen (10, 0, out col, out row); Assert.Equal (14, col); Assert.Equal (3, row); - Assert.Equal (top, View.FindDeepestView (top, 13, 2, out rx, out ry)); - Assert.Equal (10, rx); - Assert.Equal (0, ry); + Assert.Equal (top, View.FindDeepestView (top, 13, 2)); + //Assert.Equal (10, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (11, 1), top.ScreenToFrame (14, 3)); top.BoundsToScreen (11, 1, out col, out row); Assert.Equal (15, col); Assert.Equal (4, row); - Assert.Equal (top, View.FindDeepestView (top, 14, 3, out rx, out ry)); - Assert.Equal (11, rx); - Assert.Equal (1, ry); + Assert.Equal (top, View.FindDeepestView (top, 14, 3)); + //Assert.Equal (11, found.FrameToScreen ().X); + //Assert.Equal (1, found.FrameToScreen ().Y); // view Assert.Equal (new Point (-7, -5), view.ScreenToFrame (0, 0)); @@ -1043,44 +1055,44 @@ public class NavigationTests view.BoundsToScreen (-6, -4, out col, out row); Assert.Equal (1, col); Assert.Equal (1, row); - Assert.Null (View.FindDeepestView (top, 1, 1, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + Assert.Null (View.FindDeepestView (top, 1, 1)); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (-4, -3), view.ScreenToFrame (3, 2)); view.BoundsToScreen (-3, -2, out col, out row); Assert.Equal (4, col); Assert.Equal (3, row); - Assert.Equal (top, View.FindDeepestView (top, 4, 3, out rx, out ry)); - Assert.Equal (1, rx); - Assert.Equal (1, ry); + Assert.Equal (top, View.FindDeepestView (top, 4, 3)); + //Assert.Equal (1, found.FrameToScreen ().X); + //Assert.Equal (1, found.FrameToScreen ().Y); Assert.Equal (new Point (-1, -1), view.ScreenToFrame (6, 4)); view.BoundsToScreen (0, 0, out col, out row); Assert.Equal (7, col); Assert.Equal (5, row); - Assert.Equal (view, View.FindDeepestView (top, 7, 5, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + Assert.Equal (view, View.FindDeepestView (top, 7, 5)); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (6, -1), view.ScreenToFrame (13, 4)); view.BoundsToScreen (7, 0, out col, out row); Assert.Equal (14, col); Assert.Equal (5, row); - Assert.Equal (view, View.FindDeepestView (top, 14, 5, out rx, out ry)); - Assert.Equal (7, rx); - Assert.Equal (0, ry); + Assert.Equal (view, View.FindDeepestView (top, 14, 5)); + //Assert.Equal (7, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); Assert.Equal (new Point (7, -2), view.ScreenToFrame (14, 3)); view.BoundsToScreen (8, -1, out col, out row); Assert.Equal (15, col); Assert.Equal (4, row); - Assert.Equal (top, View.FindDeepestView (top, 15, 4, out rx, out ry)); - Assert.Equal (12, rx); - Assert.Equal (2, ry); + Assert.Equal (top, View.FindDeepestView (top, 15, 4)); + //Assert.Equal (12, found.FrameToScreen ().X); + //Assert.Equal (2, found.FrameToScreen ().Y); Assert.Equal (new Point (16, -2), view.ScreenToFrame (23, 3)); view.BoundsToScreen (17, -1, out col, out row); Assert.Equal (24, col); Assert.Equal (4, row); - Assert.Null (View.FindDeepestView (top, 24, 4, out rx, out ry)); - Assert.Equal (0, rx); - Assert.Equal (0, ry); + Assert.Null (View.FindDeepestView (top, 24, 4)); + //Assert.Equal (0, found.FrameToScreen ().X); + //Assert.Equal (0, found.FrameToScreen ().Y); } [Fact] diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs index 6910720fd..aa014591a 100644 --- a/UnitTests/Views/MenuBarTests.cs +++ b/UnitTests/Views/MenuBarTests.cs @@ -518,7 +518,7 @@ public class MenuBarTests Application.OnMouseEvent ( new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 4, Flags = MouseFlags.Button1Clicked } + new MouseEvent { X = 20, Y = 5, Flags = MouseFlags.Button1Clicked } ) ); @@ -555,7 +555,7 @@ public class MenuBarTests Application.OnMouseEvent ( new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 4 + i, Flags = MouseFlags.Button1Clicked } + new MouseEvent { X = 20, Y = 5 + i, Flags = MouseFlags.Button1Clicked } ) );