Merge pull request #3277 from tig/v2_3276_adornment_bounds

Fixes #3276. `Adornment.Bounds/FrameToScreen`
This commit is contained in:
Tig
2024-02-28 10:25:43 -07:00
committed by GitHub
10 changed files with 593 additions and 97 deletions

View File

@@ -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
};

View File

@@ -57,6 +57,9 @@ public class Responder : IDisposable
public event EventHandler Disposing;
/// <summary>Method invoked when a mouse event is generated</summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
/// <param name="mouseEvent">Contains the details about the mouse event.</param>
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, <see cref="OnMouseLeave(Gui.MouseEvent)"/> will be called.
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
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 <see cref="OnMouseEnter(Gui.MouseEvent)"/> is called).
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
public virtual bool OnMouseLeave (MouseEvent mouseEvent) { return false; }

View File

@@ -33,7 +33,7 @@ public class Adornment : View
/// <summary>Gets the rectangle that describes the inner area of the Adornment. The Location is always (0,0).</summary>
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
/// <inheritdoc/>
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);
}
/// <summary>Does nothing for Adornment</summary>

View File

@@ -545,28 +545,49 @@ public partial class View
}
}
#nullable enable
#nullable enable
/// <summary>Finds which view that belong to the <paramref name="start"/> superview at the provided location.</summary>
/// <param name="start">The superview where to look for.</param>
/// <param name="x">The column location in the superview.</param>
/// <param name="y">The row location in the superview.</param>
/// <param name="resultX">The found view screen relative column location.</param>
/// <param name="resultY">The found view screen relative row location.</param>
/// <param name="findAdornments">TODO: Remove this in PR #3273</param>
/// <returns>
/// The view that was found at the <paramref name="x"/> and <paramref name="y"/> coordinates.
/// <see langword="null"/> if no view was found.
/// </returns>
// 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
/// <summary>Gets the <see cref="Frame"/> with a screen-relative location.</summary>
/// <returns>The location and size of the view in screen-relative coordinates.</returns>

View File

@@ -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)
{

View File

@@ -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 ()
{

View File

@@ -0,0 +1,285 @@
using UICatalog.Scenarios;
using Xunit.Abstractions;
namespace Terminal.Gui.ViewTests;
/// <summary>
/// Tests View.FindDeepestView
/// </summary>
/// <param name="output"></param>
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<View> subviews = new List<View> ();
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));
}
}

View File

@@ -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 (

View File

@@ -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]

View File

@@ -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 }
)
);