Merge pull request #3267 from dodexahedron/v2_3256_cleanup_2

Stage 3 of #3256 - Miscellaneous cleanup before more removals
This commit is contained in:
Tig
2024-02-26 08:07:45 -07:00
committed by GitHub
20 changed files with 272 additions and 1064 deletions

View File

@@ -0,0 +1,51 @@
namespace Terminal.Gui;
public static partial class Application
{
/// <summary>
/// provides the sync context set while executing code in Terminal.Gui, to let
/// users use async/await on their code
/// </summary>
private sealed class MainLoopSyncContext : SynchronizationContext
{
public override SynchronizationContext CreateCopy () { return new MainLoopSyncContext (); }
public override void Post (SendOrPostCallback d, object state)
{
MainLoop.AddIdle (
() =>
{
d (state);
return false;
}
);
}
//_mainLoop.Driver.Wakeup ();
public override void Send (SendOrPostCallback d, object state)
{
if (Thread.CurrentThread.ManagedThreadId == _mainThreadId)
{
d (state);
}
else
{
var wasExecuted = false;
Invoke (
() =>
{
d (state);
wasExecuted = true;
}
);
while (!wasExecuted)
{
Thread.Sleep (15);
}
}
}
}
}

View File

@@ -716,53 +716,6 @@ public static partial class Application
/// </summary>
public static bool EndAfterFirstIteration { get; set; }
//
// provides the sync context set while executing code in Terminal.Gui, to let
// users use async/await on their code
//
private class MainLoopSyncContext : SynchronizationContext
{
public override SynchronizationContext CreateCopy () { return new MainLoopSyncContext (); }
public override void Post (SendOrPostCallback d, object state)
{
MainLoop.AddIdle (
() =>
{
d (state);
return false;
}
);
}
//_mainLoop.Driver.Wakeup ();
public override void Send (SendOrPostCallback d, object state)
{
if (Thread.CurrentThread.ManagedThreadId == _mainThreadId)
{
d (state);
}
else
{
var wasExecuted = false;
Invoke (
() =>
{
d (state);
wasExecuted = true;
}
);
while (!wasExecuted)
{
Thread.Sleep (15);
}
}
}
}
/// <summary>Building block API: Runs the main loop for the created <see cref="Toplevel"/>.</summary>
/// <param name="state">The state returned by the <see cref="Begin(Toplevel)"/> method.</param>
public static void RunLoop (RunState state)
@@ -1125,47 +1078,36 @@ public static partial class Application
}
}
private static View FindDeepestTop (Toplevel start, int x, int y, out int resx, out int resy)
#nullable enable
private static Toplevel? FindDeepestTop (Toplevel start, int x, int y)
{
Rectangle startFrame = start.Frame;
if (!startFrame.Contains (x, y))
if (!start.Frame.Contains (x, y))
{
resx = 0;
resy = 0;
return null;
}
if (_topLevels is { })
if (_topLevels is { Count: > 0 })
{
int count = _topLevels.Count;
int rx = x - start.Frame.X;
int ry = y - start.Frame.Y;
if (count > 0)
foreach (Toplevel t in _topLevels)
{
int rx = x - startFrame.X;
int ry = y - startFrame.Y;
foreach (Toplevel t in _topLevels)
if (t != Current)
{
if (t != Current)
if (t != start && t.Visible && t.Frame.Contains (rx, ry))
{
if (t != start && t.Visible && t.Frame.Contains (rx, ry))
{
start = t;
start = t;
break;
}
break;
}
}
}
}
resx = x - startFrame.X;
resy = y - startFrame.Y;
return start;
}
#nullable restore
private static View FindTopFromView (View view)
{
@@ -1181,12 +1123,13 @@ public static partial class Application
return top;
}
#nullable enable
// Only return true if the Current has changed.
private static bool MoveCurrent (Toplevel top)
private static bool MoveCurrent (Toplevel? top)
{
// The Current is modal and the top is not modal Toplevel then
// the Current must be moved above the first not modal Toplevel.
if (OverlappedTop != null
if (OverlappedTop is { }
&& top != OverlappedTop
&& top != Current
&& Current?.Modal == true
@@ -1218,7 +1161,7 @@ public static partial class Application
// The Current and the top are both not running Toplevel then
// the top must be moved above the first not running Toplevel.
if (OverlappedTop != null
if (OverlappedTop is { }
&& top != OverlappedTop
&& top != Current
&& Current?.Running == false
@@ -1261,6 +1204,7 @@ public static partial class Application
return true;
}
#nullable restore
/// <summary>Invoked when the terminal's size changed. The new size of the terminal is provided.</summary>
/// <remarks>
@@ -1406,8 +1350,9 @@ public static partial class Application
UnGrabbedMouse?.Invoke (view, new ViewEventArgs (view));
}
#nullable enable
// Used by OnMouseEvent to track the last view that was clicked on.
internal static View _mouseEnteredView;
internal static View? _mouseEnteredView;
/// <summary>Event fired when a mouse move or click occurs. Coordinates are screen relative.</summary>
/// <remarks>
@@ -1419,13 +1364,11 @@ public static partial class Application
/// </remarks>
public static event EventHandler<MouseEventEventArgs> MouseEvent;
/// <summary>Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.</summary>
/// <summary>Called when a mouse event occurs. Raises the <see cref="MouseEvent"/> event.</summary>
/// <remarks>This method can be used to simulate a mouse event, e.g. in unit tests.</remarks>
/// <param name="a">The mouse event with coordinates relative to the screen.</param>
public static void OnMouseEvent (MouseEventEventArgs a)
internal static void OnMouseEvent (MouseEventEventArgs a)
{
static bool OutsideRect (Point p, Rectangle r) { return p.X < 0 || p.X > r.Right || p.Y < 0 || p.Y > r.Bottom; }
if (IsMouseDisabled)
{
return;
@@ -1433,7 +1376,7 @@ public static partial class Application
var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y, out int screenX, out int screenY);
if (view is { } && view.WantContinuousButtonPressed)
if (view is { WantContinuousButtonPressed: true })
{
WantContinuousButtonPressedView = view;
}
@@ -1470,9 +1413,9 @@ public static partial class Application
View = view
};
if (OutsideRect (new Point (nme.X, nme.Y), MouseGrabView.Bounds))
if (MouseGrabView.Bounds.Contains (nme.X, nme.Y) is false)
{
// The mouse has moved outside the bounds of the the view that
// The mouse has moved outside the bounds of the view that
// grabbed the mouse, so we tell the view that last got
// OnMouseEnter the mouse is leaving
// BUGBUG: That sentence makes no sense. Either I'm missing something
@@ -1493,7 +1436,7 @@ public static partial class Application
&& a.MouseEvent.Flags != MouseFlags.ReportMousePosition
&& a.MouseEvent.Flags != 0)
{
View top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y, out _, out _);
View? top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y);
view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y, out screenX, out screenY);
if (view is { } && view != OverlappedTop && top != Current)
@@ -1502,136 +1445,143 @@ public static partial class Application
}
}
bool AdornmentHandledMouseEvent (Adornment frame)
if (view is null)
{
if (frame?.Thickness.Contains (frame.FrameToScreen (), a.MouseEvent.X, a.MouseEvent.Y) ?? false)
{
Point boundsPoint = frame.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = a.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
View = frame
};
frame.OnMouseEvent (me);
return true;
}
return false;
return;
}
if (view is { })
// Work inside-out (Padding, Border, Margin)
// TODO: Debate whether inside-out or outside-in is the right strategy
if (AdornmentHandledMouseEvent (view.Padding, a))
{
// Work inside-out (Padding, Border, Margin)
// TODO: Debate whether inside-out or outside-in is the right strategy
if (AdornmentHandledMouseEvent (view?.Padding))
return;
}
if (AdornmentHandledMouseEvent (view.Border, a))
{
if (view is not Toplevel)
{
return;
}
if (AdornmentHandledMouseEvent (view?.Border))
// TODO: This is a temporary hack to work around the fact that
// drag handling is handled in Toplevel (See Issue #2537)
var me = new MouseEvent
{
if (view is Toplevel)
{
// TODO: This is a temporary hack to work around the fact that
// drag handling is handled in Toplevel (See Issue #2537)
X = screenX,
Y = screenY,
Flags = a.MouseEvent.Flags,
OfX = screenX,
OfY = screenY,
View = view
};
var me = new MouseEvent
{
X = screenX,
Y = screenY,
Flags = a.MouseEvent.Flags,
OfX = screenX,
OfY = screenY,
View = view
};
if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}
if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}
WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;
if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}
BringOverlappedTopToFront ();
}
return;
if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}
if (AdornmentHandledMouseEvent (view?.Margin))
if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}
Rectangle bounds = view.BoundsToScreen (view.Bounds);
WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;
if (bounds.Contains (a.MouseEvent.X, a.MouseEvent.Y))
if (view.OnMouseEvent (me))
{
Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = a.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
View = view
};
if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}
if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}
WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;
if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}
BringOverlappedTopToFront ();
// Should we bubble up the event, if it is not handled?
//return;
}
BringOverlappedTopToFront ();
return;
}
if (AdornmentHandledMouseEvent (view?.Margin, a))
{
return;
}
Rectangle bounds = view.BoundsToScreen (view.Bounds);
if (bounds.Contains (a.MouseEvent.X, a.MouseEvent.Y))
{
Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = a.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
View = view
};
if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}
if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}
WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;
if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}
BringOverlappedTopToFront ();
}
return;
static bool AdornmentHandledMouseEvent (Adornment? frame, MouseEventEventArgs args)
{
if (frame?.Thickness.Contains (frame.FrameToScreen (), args.MouseEvent.X, args.MouseEvent.Y) is not true)
{
return false;
}
Point boundsPoint = frame.ScreenToBounds (args.MouseEvent.X, args.MouseEvent.Y);
var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = args.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
View = frame
};
frame.OnMouseEvent (me);
return true;
}
}
#nullable restore
#endregion Mouse handling
@@ -1846,8 +1796,4 @@ public static partial class Application
}
#endregion Keyboard handling
}
/// <summary>Event arguments for the <see cref="Application.Iteration"/> event.</summary>
public class IterationEventArgs
{ }
}

View File

@@ -0,0 +1,5 @@
namespace Terminal.Gui;
/// <summary>Event arguments for the <see cref="Application.Iteration"/> event.</summary>
public class IterationEventArgs : EventArgs
{ }

View File

@@ -90,9 +90,9 @@
<ItemGroup>
<Using Include="JetBrains.Annotations" />
<Using Include="System.Diagnostics.Contracts.PureAttribute" Alias="PureAttribute" />
<Using Include="System.Drawing.Rectangle" Alias="Rectangle" />
<Using Include="System.Text" />
<Using Include="JetBrains.Annotations" />
<Using Include="System.Diagnostics.Contracts.PureAttribute" Alias="PureAttribute" />
</ItemGroup>
<!-- =================================================================== -->
<!-- Nuget -->

View File

@@ -0,0 +1,11 @@
namespace Terminal.Gui;
public partial struct Point
{
public static implicit operator System.Drawing.Point (Terminal.Gui.Point tgp) => new (tgp.X, tgp.Y);
public static implicit operator Point (System.Drawing.Point sdp) => new (sdp.X, sdp.Y);
public static bool operator != (Point left, System.Drawing.Point right) => new System.Drawing.Point (left.X,left.Y) != right;
public static bool operator == (Point left, System.Drawing.Point right) => new System.Drawing.Point (left.X,left.Y) == right;
public static bool operator != (System.Drawing.Point left, Point right) => left != new System.Drawing.Point(right.X,right.Y);
public static bool operator == (System.Drawing.Point left, Point right) => left == new System.Drawing.Point(right.X,right.Y);
}

View File

@@ -14,7 +14,7 @@ using System.Text.Json.Serialization;
namespace Terminal.Gui;
/// <summary>Represents an ordered pair of integer x- and y-coordinates that defines a point in a two-dimensional plane.</summary>
public struct Point
public partial struct Point
{
/// <summary>Gets or sets the x-coordinate of this Point.</summary>
[JsonInclude]

View File

@@ -1,294 +0,0 @@
//
// Derived from System.Drawing.Rectangle.cs
//
// Author:
// Mike Kestner (mkestner@speakeasy.net)
//
// Copyright (C) 2001 Mike Kestner
// Copyright (C) 2004 Novell, Inc. http://www.novell.com
//
namespace Terminal.Gui;
/// <summary>Stores a set of four integers that represent the location and size of a rectangle</summary>
public struct Rectangle
{
private int width;
private int height;
/// <summary>Gets or sets the x-coordinate of the upper-left corner of this Rectangle structure.</summary>
public int X;
/// <summary>Gets or sets the y-coordinate of the upper-left corner of this Rectangle structure.</summary>
public int Y;
/// <summary>Gets or sets the width of this Rect structure.</summary>
public int Width
{
get => width;
set
{
if (value < 0)
{
throw new ArgumentException ("Width must be greater or equal to 0.");
}
width = value;
}
}
/// <summary>Gets or sets the height of this Rectangle structure.</summary>
public int Height
{
get => height;
set
{
if (value < 0)
{
throw new ArgumentException ("Height must be greater or equal to 0.");
}
height = value;
}
}
/// <summary>Empty Shared Field</summary>
/// <remarks>An uninitialized Rectangle Structure.</remarks>
public static readonly Rectangle Empty;
/// <summary>FromLTRB Shared Method</summary>
/// <remarks>Produces a Rectangle structure from left, top, right and bottom coordinates.</remarks>
public static Rectangle FromLTRB (
int left,
int top,
int right,
int bottom
)
{
return new Rectangle (
left,
top,
right - left,
bottom - top
);
}
/// <summary>Produces a new Rect by inflating an existing Rect by the specified coordinate values.</summary>
/// <remarks>
/// Produces a new Rect by inflating an existing Rect by the specified coordinate values. The rectangle is
/// enlarged in both directions along an axis.
/// </remarks>
public static Rectangle Inflate (Rectangle rect, int x, int y)
{
var r = new Rectangle (rect.Location, rect.Size);
r.Inflate (x, y);
return r;
}
/// <summary>Inflates an existing Rect by the specified coordinate values.</summary>
/// <remarks>
/// This method enlarges this rectangle, not a copy of it. The rectangle is enlarged in both directions along an
/// axis.
/// </remarks>
public void Inflate (int width, int height)
{
// Set dims first so we don't lose the original values on exception
Width += width * 2;
Height += height * 2;
X -= width;
Y -= height;
}
/// <summary>Inflates an existing Rect by the specified Sizwe.</summary>
/// <remarks>
/// This method enlarges this rectangle, not a copy of it. The rectangle is enlarged in both directions along an
/// axis.
/// </remarks>
public void Inflate (Size size) { Inflate (size.Width, size.Height); }
/// <summary>Intersect Shared Method</summary>
/// <remarks>Produces a new Rectangle by intersecting 2 existing Rectangles. Returns Empty if there is no intersection.</remarks>
public static Rectangle Intersect (Rectangle a, Rectangle b)
{
// MS.NET returns a non-empty rectangle if the two rectangles
// touch each other
if (!a.IntersectsWithInclusive (b))
{
return Empty;
}
return FromLTRB (
Math.Max (a.Left, b.Left),
Math.Max (a.Top, b.Top),
Math.Min (a.Right, b.Right),
Math.Min (a.Bottom, b.Bottom)
);
}
/// <summary>Intersect Method</summary>
/// <remarks>Replaces the Rectangle with the intersection of itself and another Rectangle.</remarks>
public void Intersect (Rectangle rect) { this = Intersect (this, rect); }
/// <summary>Produces the uninion of two rectangles.</summary>
/// <remarks>Produces a new Rectangle from the union of 2 existing Rectangles.</remarks>
public static Rectangle Union (Rectangle a, Rectangle b)
{
//int x1 = Math.Min (a.X, b.X);
//int x2 = Math.Max (a.X + a.Width, b.X + b.Width);
//int y1 = Math.Min (a.Y, b.Y);oS
//int y2 = Math.Max (a.Y + a.Height, b.Y + b.Height);
//return new Rect (x1, y1, x2 - x1, y2 - y1);
int x1 = Math.Min (a.X, b.X);
int x2 = Math.Max (a.X + Math.Abs (a.Width), b.X + Math.Abs (b.Width));
int y1 = Math.Min (a.Y, b.Y);
int y2 = Math.Max (a.Y + Math.Abs (a.Height), b.Y + Math.Abs (b.Height));
return new Rectangle (x1, y1, x2 - x1, y2 - y1);
}
/// <summary>Equality Operator</summary>
/// <remarks>
/// Compares two Rectangle objects. The return value is based on the equivalence of the Location and Size
/// properties of the two Rectangles.
/// </remarks>
public static bool operator == (Rectangle left, Rectangle right) { return left.Location == right.Location && left.Size == right.Size; }
/// <summary>Inequality Operator</summary>
/// <remarks>
/// Compares two Rectangle objects. The return value is based on the equivalence of the Location and Size
/// properties of the two Rectangles.
/// </remarks>
public static bool operator != (Rectangle left, Rectangle right) { return left.Location != right.Location || left.Size != right.Size; }
// -----------------------
// Public Constructors
// -----------------------
/// <summary>Rectangle Constructor</summary>
/// <remarks>Creates a Rectangle from Point and Size values.</remarks>
public Rectangle (Point location, Size size)
{
X = location.X;
Y = location.Y;
width = size.Width;
height = size.Height;
Width = width;
Height = height;
}
/// <summary>Rectangle Constructor</summary>
/// <remarks>Creates a Rectangle from a specified x,y location and width and height values.</remarks>
public Rectangle (int x, int y, int width, int height)
{
X = x;
Y = y;
this.width = width;
this.height = height;
Width = this.width;
Height = this.height;
}
/// <summary>Bottom Property</summary>
/// <remarks>The Y coordinate of the bottom edge of the Rectangle. Read only.</remarks>
public int Bottom => Y + Height;
/// <summary>IsEmpty Property</summary>
/// <remarks>Indicates if the width or height are zero. Read only.</remarks>
public bool IsEmpty => X == 0 && Y == 0 && Width == 0 && Height == 0;
/// <summary>Left Property</summary>
/// <remarks>The X coordinate of the left edge of the Rectangle. Read only.</remarks>
public int Left => X;
/// <summary>Location Property</summary>
/// <remarks>The Location of the top-left corner of the Rectangle.</remarks>
public Point Location
{
get => new (X, Y);
set
{
X = value.X;
Y = value.Y;
}
}
/// <summary>Right Property</summary>
/// <remarks>The X coordinate of the right edge of the Rectangle. Read only.</remarks>
public int Right => X + Width;
/// <summary>Size Property</summary>
/// <remarks>The Size of the Rectangle.</remarks>
public Size Size
{
get => new (Width, Height);
set
{
Width = value.Width;
Height = value.Height;
}
}
/// <summary>Top Property</summary>
/// <remarks>The Y coordinate of the top edge of the Rectangle. Read only.</remarks>
public int Top => Y;
/// <summary>Contains Method</summary>
/// <remarks>Checks if an x,y coordinate lies within this Rectangle.</remarks>
public bool Contains (int x, int y) { return x >= Left && x < Right && y >= Top && y < Bottom; }
/// <summary>Contains Method</summary>
/// <remarks>Checks if a Point lies within this Rectangle.</remarks>
public bool Contains (Point pt) { return Contains (pt.X, pt.Y); }
/// <summary>Contains Method</summary>
/// <remarks>Checks if a Rectangle lies entirely within this Rectangle.</remarks>
public bool Contains (Rectangle rect) { return rect == Intersect (this, rect); }
/// <summary>Equals Method</summary>
/// <remarks>Checks equivalence of this Rectangle and another object.</remarks>
public override bool Equals (object obj)
{
if (!(obj is Rectangle))
{
return false;
}
return this == (Rectangle)obj;
}
/// <summary>GetHashCode Method</summary>
/// <remarks>Calculates a hashing value.</remarks>
public override int GetHashCode () { return X ^
((Y << 13) | (Y >>> 19)) ^
((Width << 26) | (Width >>> 6)) ^
((Height << 7) | (Height >>> 25)); }
/// <summary>IntersectsWith Method</summary>
/// <remarks>Checks if a Rectangle intersects with this one.</remarks>
public bool IntersectsWith (Rectangle rect) { return !(Left >= rect.Right || Right <= rect.Left || Top >= rect.Bottom || Bottom <= rect.Top); }
private bool IntersectsWithInclusive (Rectangle r) { return !(Left > r.Right || Right < r.Left || Top > r.Bottom || Bottom < r.Top); }
/// <summary>Offset Method</summary>
/// <remarks>Moves the Rectangle a specified distance.</remarks>
public void Offset (int x, int y)
{
X += x;
Y += y;
}
/// <summary>Offset Method</summary>
/// <remarks>Moves the Rectangle a specified distance.</remarks>
public void Offset (Point pos)
{
X += pos.X;
Y += pos.Y;
}
/// <summary>ToString Method</summary>
/// <remarks>Formats the Rectangle as a string in (x,y,w,h) notation.</remarks>
public override string ToString () { return $"{{X={X},Y={Y},Width={Width},Height={Height}}}"; }
}

View File

@@ -0,0 +1,11 @@
namespace Terminal.Gui;
public partial struct Size
{
public static implicit operator Size (System.Drawing.Size sds) => new (sds.Width, sds.Height);
public static implicit operator System.Drawing.Size (Size tgs) => new (tgs.Width, tgs.Height);
public static bool operator != (Size left, System.Drawing.Size right) => new System.Drawing.Size (left.Width,left.Height) != right;
public static bool operator == (Size left, System.Drawing.Size right) => new System.Drawing.Size (left.Width,left.Height) == right;
public static bool operator != (System.Drawing.Size left, Size right) => left != new System.Drawing.Size(right.Width,right.Height);
public static bool operator == (System.Drawing.Size left, Size right) => left == new System.Drawing.Size(right.Width,right.Height);
}

View File

@@ -11,7 +11,7 @@
namespace Terminal.Gui;
/// <summary>Stores an ordered pair of integers, which specify a Height and Width.</summary>
public struct Size
public partial struct Size
{
private int width, height;

View File

@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using System.Diagnostics;
namespace Terminal.Gui;
@@ -542,61 +542,53 @@ public partial class View
}
}
#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="resx">The found view screen relative column location.</param>
/// <param name="resy">The found view screen relative row location.</param>
/// <param name="resultX">The found view screen relative column location.</param>
/// <param name="resultY">The found view screen relative row location.</param>
/// <returns>
/// The view that was found at the <praramref name="x"/> and <praramref name="y"/> coordinates.
/// The view that was found at the <paramref name="x"/> and <paramref name="y"/> coordinates.
/// <see langword="null"/> if no view was found.
/// </returns>
public static View FindDeepestView (View start, int x, int y, out int resx, out int resy)
// 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)
{
resy = resx = 0;
resultY = resultX = 0;
if (start is null || !start.Frame.Contains (x, y))
{
return null;
}
Rectangle startFrame = start.Frame;
if (start.InternalSubviews is { })
if (start.InternalSubviews is { Count: > 0 })
{
int count = start.InternalSubviews.Count;
Point boundsOffset = start.GetBoundsOffset ();
int rx = x - (start.Frame.X + boundsOffset.X);
int ry = y - (start.Frame.Y + boundsOffset.Y);
if (count > 0)
for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
{
Point boundsOffset = start.GetBoundsOffset ();
int rx = x - (startFrame.X + boundsOffset.X);
int ry = y - (startFrame.Y + boundsOffset.Y);
View v = start.InternalSubviews [i];
for (int i = count - 1; i >= 0; i--)
if (v.Visible && v.Frame.Contains (rx, ry))
{
View v = start.InternalSubviews [i];
View? deep = FindDeepestView (v, rx, ry, out resultX, out resultY);
if (v.Visible && v.Frame.Contains (rx, ry))
{
View deep = FindDeepestView (v, rx, ry, out resx, out resy);
if (deep is null)
{
return v;
}
return deep;
}
return deep ?? v;
}
}
}
resx = x - startFrame.X;
resy = y - startFrame.Y;
resultX = x - start.Frame.X;
resultY = y - start.Frame.Y;
return start;
}
#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

@@ -38,11 +38,12 @@ public static partial class Application
}
}
#nullable enable
/// <summary>
/// The <see cref="Toplevel"/> object used for the application on startup which
/// <see cref="Toplevel.IsOverlappedContainer"/> is true.
/// </summary>
public static Toplevel OverlappedTop
public static Toplevel? OverlappedTop
{
get
{
@@ -54,6 +55,7 @@ public static partial class Application
return null;
}
}
#nullable restore
/// <summary>Brings the superview of the most focused overlapped view is on front.</summary>
public static void BringOverlappedTopToFront ()

View File

@@ -425,4 +425,5 @@
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/Name/@EntryValue">Concurrency Issue</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/Pattern/@EntryValue">(?&lt;=\W|^)(?&lt;TAG&gt;CONCURRENCY)(\W|$)(.*)</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/TodoIconStyle/@EntryValue">Warning</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unsynchronized/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

View File

@@ -7,7 +7,6 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Terminal.Gui;
using Rectangle = Terminal.Gui.Rectangle;
namespace UICatalog.Scenarios;

View File

@@ -7,7 +7,6 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Terminal.Gui;
using Color = Terminal.Gui.Color;
using Rectangle = Terminal.Gui.Rectangle;
namespace UICatalog.Scenarios;

View File

@@ -37,4 +37,7 @@
<ItemGroup>
<ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Drawing.Rectangle" Alias="Rectangle" />
</ItemGroup>
</Project>

View File

@@ -246,7 +246,7 @@ public class DialogTests
new Button { Text = btn3Text },
new Button { Text = btn4Text }
);
Assert.Equal (new Size (width, 1), dlg.Frame.Size);
Assert.Equal (new Size (width, 1), (Size)dlg.Frame.Size);
TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
End (runstate);
@@ -1114,7 +1114,7 @@ public class DialogTests
// Default location is centered, so 100 / 2 - 85 / 2 = 7
var expected = 7;
Assert.Equal (new Point (expected, expected), d.Frame.Location);
Assert.Equal (new Point (expected, expected), (Point)d.Frame.Location);
}
[Fact]
@@ -1127,7 +1127,7 @@ public class DialogTests
// Default location is centered, so 100 / 2 - 85 / 2 = 7
var expected = 1;
Assert.Equal (new Point (expected, expected), d.Frame.Location);
Assert.Equal (new Point (expected, expected), (Point)d.Frame.Location);
}
[Fact]
@@ -1140,7 +1140,7 @@ public class DialogTests
((FakeDriver)Driver).SetBufferSize (20, 10);
// Default location is centered, so 100 / 2 - 85 / 2 = 7
Assert.Equal (new Point (expected, expected), d.Frame.Location);
Assert.Equal (new Point (expected, expected), (Point)d.Frame.Location);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1170,7 +1170,7 @@ public class DialogTests
var d = new Dialog { X = 5, Y = 5, Height = 3, Width = 5 };
Begin (d);
Assert.Equal (new Point (5, 5), d.Frame.Location);
Assert.Equal (new Point (5, 5), (Point)d.Frame.Location);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1191,7 +1191,7 @@ public class DialogTests
Begin (d);
// This is because of PostionTopLevels and EnsureVisibleBounds
Assert.Equal (new Point (3, 2), d.Frame.Location);
Assert.Equal (new Point (3, 2), (Point)d.Frame.Location);
// #3127: Before
// Assert.Equal (new Size (17, 8), d.Frame.Size);
@@ -1208,7 +1208,7 @@ public class DialogTests
//╚══└───────────────┘", _output);
// #3127: After: Because Toplevel is now Width/Height = Dim.Filll
Assert.Equal (new Size (15, 6), d.Frame.Size);
Assert.Equal (new Size (15, 6), (Size)d.Frame.Size);
TestHelpers.AssertDriverContentsWithFrameAre (
@"
@@ -1272,7 +1272,7 @@ public class DialogTests
((FakeDriver)Driver).SetBufferSize (100, 100);
// Default size is Percent(85)
Assert.Equal (new Size ((int)(100 * .85), (int)(100 * .85)), d.Frame.Size);
Assert.Equal (new Size ((int)(100 * .85), (int)(100 * .85)), (Size)d.Frame.Size);
}
[Fact]
@@ -1285,7 +1285,7 @@ public class DialogTests
((FakeDriver)Driver).SetBufferSize (100, 100);
// Default size is Percent(85)
Assert.Equal (new Size (50, 50), d.Frame.Size);
Assert.Equal (new Size (50, 50), (Size)d.Frame.Size);
}
[Fact]

View File

@@ -153,7 +153,7 @@ public class MessageBoxTests
// Default location is centered, so
// X = (100 / 2) - (60 / 2) = 20
// Y = (100 / 2) - (5 / 2) = 47
Assert.Equal (new Point (20, 47), Application.Current.Frame.Location);
Assert.Equal (new Point (20, 47), (Point)Application.Current.Frame.Location);
Application.RequestStop ();
}
@@ -295,7 +295,7 @@ public class MessageBoxTests
╚══════════════════╝",
_output
);
Assert.Equal (new Size (20 - 2, 10 - 2), Application.Current.Frame.Size);
Assert.Equal (new Size (20 - 2, 10 - 2), (Size)Application.Current.Frame.Size);
Application.RequestStop ();
// Really long text
@@ -607,7 +607,7 @@ ffffffffffffffffffff
Assert.IsType<Dialog> (Application.Current);
// Default size is Percent(60)
Assert.Equal (new Size ((int)(100 * .60), 5), Application.Current.Frame.Size);
Assert.Equal (new Size ((int)(100 * .60), 5), (Size)Application.Current.Frame.Size);
Application.RequestStop ();
}
@@ -801,7 +801,7 @@ ffffffffffffffffffff
Application.Refresh ();
Assert.IsType<Dialog> (Application.Current);
Assert.Equal (new Size (height, width), Application.Current.Frame.Size);
Assert.Equal (new Size (height, width), (Size)Application.Current.Frame.Size);
Application.RequestStop ();
}
@@ -839,7 +839,7 @@ ffffffffffffffffffff
Application.Refresh ();
Assert.IsType<Dialog> (Application.Current);
Assert.Equal (new Size (height, width), Application.Current.Frame.Size);
Assert.Equal (new Size (height, width), (Size)Application.Current.Frame.Size);
Application.RequestStop ();
}
@@ -873,7 +873,7 @@ ffffffffffffffffffff
Application.Refresh ();
Assert.IsType<Dialog> (Application.Current);
Assert.Equal (new Size (height, width), Application.Current.Frame.Size);
Assert.Equal (new Size (height, width), (Size)Application.Current.Frame.Size);
Application.RequestStop ();
}
@@ -901,7 +901,7 @@ ffffffffffffffffffff
{
Application.Refresh ();
Assert.Equal (new Size (7, 5), Application.Current.Frame.Size);
Assert.Equal (new Size (7, 5), (Size)Application.Current.Frame.Size);
TestHelpers.AssertDriverContentsWithFrameAre (
@$"

View File

@@ -1,519 +0,0 @@
namespace Terminal.Gui.TypeTests;
public class RectangleTests
{
[Theory]
// Empty
[InlineData (
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
)]
[InlineData (
0,
0,
0,
0,
1,
0,
-1,
0,
2,
0
)]
[InlineData (
0,
0,
0,
0,
0,
1,
0,
-1,
0,
2
)]
[InlineData (
0,
0,
0,
0,
1,
1,
-1,
-1,
2,
2
)]
[InlineData (
0,
0,
0,
0,
-1,
-1, // Throws
0,
0,
0,
0
)]
// Zero location, Size of 1
[InlineData (
0,
0,
1,
1,
0,
0,
0,
0,
1,
1
)]
[InlineData (
0,
0,
1,
1,
1,
0,
-1,
0,
3,
1
)]
[InlineData (
0,
0,
1,
1,
0,
1,
0,
-1,
1,
3
)]
[InlineData (
0,
0,
1,
1,
1,
1,
-1,
-1,
3,
3
)]
// Positive location, Size of 1
[InlineData (
1,
1,
1,
1,
0,
0,
1,
1,
1,
1
)]
[InlineData (
1,
1,
1,
1,
1,
0,
0,
1,
3,
1
)]
[InlineData (
1,
1,
1,
1,
0,
1,
1,
0,
1,
3
)]
[InlineData (
1,
1,
1,
1,
1,
1,
0,
0,
3,
3
)]
public void Inflate (
int x,
int y,
int width,
int height,
int inflateWidth,
int inflateHeight,
int expectedX,
int exptectedY,
int expectedWidth,
int expectedHeight
)
{
var rect = new Rectangle (x, y, width, height);
if (rect.Width + inflateWidth < 0 || rect.Height + inflateHeight < 0)
{
Assert.Throws<ArgumentException> (() => rect.Inflate (inflateWidth, inflateHeight));
}
else
{
rect.Inflate (inflateWidth, inflateHeight);
}
Assert.Equal (expectedWidth, rect.Width);
Assert.Equal (expectedHeight, rect.Height);
Assert.Equal (expectedX, rect.X);
Assert.Equal (exptectedY, rect.Y);
// Use the other overload (Size)
rect = new Rectangle (x, y, width, height);
if (rect.Width + inflateWidth < 0 || rect.Height + inflateHeight < 0)
{
Assert.Throws<ArgumentException> (() => rect.Inflate (new Size (inflateWidth, inflateHeight)));
}
else
{
rect.Inflate (new Size (inflateWidth, inflateHeight));
}
Assert.Equal (expectedWidth, rect.Width);
Assert.Equal (expectedHeight, rect.Height);
Assert.Equal (expectedX, rect.X);
Assert.Equal (exptectedY, rect.Y);
}
[Fact]
public void Negative_X_Y_Positions ()
{
var rect = new Rectangle (-10, -5, 100, 50);
int yCount = 0, xCount = 0, yxCount = 0;
for (int line = rect.Y; line < rect.Y + rect.Height; line++)
{
yCount++;
xCount = 0;
for (int col = rect.X; col < rect.X + rect.Width; col++)
{
xCount++;
yxCount++;
}
}
Assert.Equal (yCount, rect.Height);
Assert.Equal (xCount, rect.Width);
Assert.Equal (yxCount, rect.Height * rect.Width);
}
[Fact]
public void Positive_X_Y_Positions ()
{
var rect = new Rectangle (10, 5, 100, 50);
int yCount = 0, xCount = 0, yxCount = 0;
for (int line = rect.Y; line < rect.Y + rect.Height; line++)
{
yCount++;
xCount = 0;
for (int col = rect.X; col < rect.X + rect.Width; col++)
{
xCount++;
yxCount++;
}
}
Assert.Equal (yCount, rect.Height);
Assert.Equal (xCount, rect.Width);
Assert.Equal (yxCount, rect.Height * rect.Width);
}
[Fact]
public void Rect_Contains ()
{
var rect = new Rectangle (0, 0, 3, 3);
Assert.True (rect.Contains (new Point (1, 1)));
Assert.True (rect.Contains (new Point (1, 2)));
Assert.True (rect.Contains (new Point (2, 1)));
Assert.True (rect.Contains (new Point (2, 2)));
Assert.False (rect.Contains (new Point (-1, 1)));
Assert.False (rect.Contains (new Point (1, -1)));
Assert.False (rect.Contains (new Point (3, 2)));
Assert.False (rect.Contains (new Point (2, 3)));
Assert.False (rect.Contains (new Point (3, 3)));
Assert.True (rect.Contains (new Rectangle (1, 1, 2, 2)));
Assert.True (rect.Contains (new Rectangle (1, 2, 2, 1)));
Assert.True (rect.Contains (new Rectangle (2, 1, 1, 2)));
Assert.True (rect.Contains (new Rectangle (2, 2, 1, 1)));
Assert.True (rect.Contains (new Rectangle (0, 0, 3, 3)));
Assert.False (rect.Contains (new Rectangle (-1, 1, 3, 3)));
Assert.False (rect.Contains (new Rectangle (1, -1, 3, 3)));
Assert.False (rect.Contains (new Rectangle (3, 2, 3, 3)));
Assert.False (rect.Contains (new Rectangle (2, 3, 3, 3)));
Assert.False (rect.Contains (new Rectangle (3, 3, 3, 3)));
Assert.True (rect.Contains (1, 1));
Assert.True (rect.Contains (1, 2));
Assert.True (rect.Contains (2, 1));
Assert.True (rect.Contains (2, 2));
Assert.False (rect.Contains (-1, 1));
Assert.False (rect.Contains (1, -1));
Assert.False (rect.Contains (3, 2));
Assert.False (rect.Contains (2, 3));
Assert.False (rect.Contains (3, 3));
}
[Fact]
public void Rect_Equals ()
{
var rect1 = new Rectangle ();
var rect2 = new Rectangle ();
Assert.Equal (rect1, rect2);
rect1 = new Rectangle (1, 2, 3, 4);
rect2 = new Rectangle (1, 2, 3, 4);
Assert.Equal (rect1, rect2);
rect1 = new Rectangle (1, 2, 3, 4);
rect2 = new Rectangle (-1, 2, 3, 4);
Assert.NotEqual (rect1, rect2);
}
[Fact]
public void Rect_New ()
{
var rect = new Rectangle ();
Assert.True (rect.IsEmpty);
rect = new Rectangle (new Point (), new Size ());
Assert.True (rect.IsEmpty);
rect = new Rectangle (1, 2, 3, 4);
Assert.False (rect.IsEmpty);
rect = new Rectangle (-1, -2, 3, 4);
Assert.False (rect.IsEmpty);
Action action = () => new Rectangle (1, 2, -3, 4);
var ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Width must be greater or equal to 0.", ex.Message);
action = () => new Rectangle (1, 2, 3, -4);
ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Height must be greater or equal to 0.", ex.Message);
action = () => new Rectangle (1, 2, -3, -4);
ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Width must be greater or equal to 0.", ex.Message);
}
[Fact]
public void Rect_SetsValue ()
{
var rect = new Rectangle { X = 0, Y = 0 };
Assert.True (rect.IsEmpty);
rect = new Rectangle { X = -1, Y = -2 };
Assert.False (rect.IsEmpty);
rect = new Rectangle { Width = 3, Height = 4 };
Assert.False (rect.IsEmpty);
rect = new Rectangle { X = -1, Y = -2, Width = 3, Height = 4 };
Assert.False (rect.IsEmpty);
Action action = () => { rect = new Rectangle { X = -1, Y = -2, Width = -3, Height = 4 }; };
var ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Width must be greater or equal to 0.", ex.Message);
action = () => { rect = new Rectangle { X = -1, Y = -2, Width = 3, Height = -4 }; };
ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Height must be greater or equal to 0.", ex.Message);
action = () => { rect = new Rectangle { X = -1, Y = -2, Width = -3, Height = -4 }; };
ex = Assert.Throws<ArgumentException> (action);
Assert.Equal ("Width must be greater or equal to 0.", ex.Message);
}
[Fact]
public void Union_EmptyRectangles ()
{
var r1 = new Rectangle (0, 0, 0, 0);
var r2 = new Rectangle (1, 1, 0, 0);
Rectangle result = Rectangle.Union (r1, r2);
Assert.Equal (new Rectangle (0, 0, 1, 1), result);
}
[Fact]
public void Union_NegativeCoords ()
{
// arrange
var rect1 = new Rectangle (-2, -2, 4, 4);
var rect2 = new Rectangle (-1, -1, 5, 5);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (-2, -2, 6, 6), result);
}
[Fact]
public void Union_PositiveCoords ()
{
var r1 = new Rectangle (0, 0, 2, 2);
var r2 = new Rectangle (1, 1, 2, 2);
Rectangle result = Rectangle.Union (r1, r2);
Assert.Equal (new Rectangle (0, 0, 3, 3), result);
}
[Fact]
public void Union_RectangleAHasNegativeCoordinates_ReturnsCombinedRectangle ()
{
// arrange
var rect1 = new Rectangle (-2, -2, 5, 5);
var rect2 = new Rectangle (3, 3, 4, 4);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (-2, -2, 9, 9), result);
}
[Fact]
public void Union_RectangleAIsLarger_ReturnsA ()
{
// arrange
var rect1 = new Rectangle (1, 1, 6, 6);
var rect2 = new Rectangle (2, 2, 3, 3);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 6, 6), result);
}
[Fact]
public void Union_RectangleBIsLarger_ReturnsB ()
{
// arrange
var rect1 = new Rectangle (1, 1, 3, 3);
var rect2 = new Rectangle (2, 2, 6, 6);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 7, 7), result);
}
[Fact]
public void Union_RectanglesDoNotOverlap_ReturnsCombinedRectangle ()
{
// arrange
var rect1 = new Rectangle (1, 1, 3, 3);
var rect2 = new Rectangle (5, 5, 3, 3);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 7, 7), result);
}
[Fact]
public void Union_RectanglesOverlap_ReturnsCombinedRectangle ()
{
// arrange
var rect1 = new Rectangle (1, 1, 3, 3);
var rect2 = new Rectangle (2, 2, 3, 3);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 4, 4), result);
}
[Fact]
public void Union_RectanglesTouchHorizontally_ReturnsCombinedRectangle ()
{
// arrange
var rect1 = new Rectangle (1, 1, 3, 3);
var rect2 = new Rectangle (4, 2, 3, 3);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 6, 4), result);
}
[Fact]
public void Union_RectanglesTouchVertically_ReturnsCombinedRectangle ()
{
// arrange
var rect1 = new Rectangle (1, 1, 3, 3);
var rect2 = new Rectangle (2, 4, 3, 3);
// act
Rectangle result = Rectangle.Union (rect1, rect2);
// assert
Assert.Equal (new Rectangle (1, 1, 4, 6), result);
}
[Fact]
public void Union_SameRectangle ()
{
var r1 = new Rectangle (0, 0, 2, 2);
var r2 = new Rectangle (0, 0, 2, 2);
Rectangle result = Rectangle.Union (r1, r2);
Assert.Equal (new Rectangle (0, 0, 2, 2), result);
}
[Theory]
[CombinatorialData]
public void ToString_ReturnsExpectedString ([CombinatorialValues(-1,0,1)]int x, [CombinatorialValues(-1,0,1)]int y, [CombinatorialValues(1,10)]int width, [CombinatorialValues(1,10)]int height)
{
Rectangle r = new (x, y, width, height);
string expectedString = $"{{X={r.X},Y={r.Y},Width={r.Width},Height={r.Height}}}";
Assert.Equal (expectedString, r.ToString ());
}
}

View File

@@ -46,6 +46,7 @@
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Drawing.Rectangle" Alias="Rectangle" />
<Using Include="Terminal.Gui" />
<Using Include="Xunit" />
</ItemGroup>

View File

@@ -2692,12 +2692,12 @@ Y
Assert.True (horizontalView.AutoSize);
Assert.Equal (new Rectangle (0, 0, 12, 1), horizontalView.Frame);
Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal ((Size)horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.True (verticalView.AutoSize);
Assert.Equal (new Rectangle (0, 0, 2, 11), verticalView.Frame);
Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal ((Size)verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
text = "Say He_llo 你";
horizontalView.Text = text;
@@ -2706,12 +2706,12 @@ Y
Assert.True (horizontalView.AutoSize);
Assert.Equal (new Rectangle (0, 0, 12, 1), horizontalView.Frame);
Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal ((Size)horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
Assert.True (verticalView.AutoSize);
Assert.Equal (new Rectangle (0, 0, 2, 11), verticalView.Frame);
Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
Assert.Equal ((Size)verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
}
[Fact]