Progress on low level unit tess

This commit is contained in:
Tig Kindel
2023-12-23 10:23:00 -07:00
parent bb04a629ff
commit f48ff99628
6 changed files with 242 additions and 57 deletions

View File

@@ -62,7 +62,7 @@ namespace Terminal.Gui;
/// </description>
/// </item>
/// <item>
/// <term><see cref="Pos.Left(int)"/></term>
/// <term><see cref="Pos.Left"/></term>
/// <description>
/// Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.
/// </description>
@@ -450,7 +450,7 @@ public class Pos {
/// </description>
/// </item>
/// <item>
/// <term><see cref="Auto()"/></term>
/// <term><see cref="Dim.Auto"/></term>
/// <description>
/// Creates a <see cref="Dim"/> object that automatically sizes the view to fit all of the view's SubViews.
/// </description>
@@ -596,7 +596,7 @@ public class Dim {
/// <returns>The AutoSize <see cref="Dim"/> object.</returns>
/// <param name="style">Specifies how <see cref="DimAuto"/> will compute the dimension. The default is <see cref="DimAutoStyle.Text"/>. NOT CURRENTLY SUPPORTED.</param>
/// <param name="min">Specifies the minimum dimension that view will be automatically sized to. NOT CURRENTLY SUPPORTED.</param>
/// <param name="min">Specifies the maximum dimension that view will be automatically sized to. NOT CURRENTLY SUPPORTED.</param>
/// <param name="max">Specifies the maximum dimension that view will be automatically sized to. NOT CURRENTLY SUPPORTED.</param>
public static Dim Auto (DimAutoStyle style = DimAutoStyle.Subviews, Dim min = null, Dim max = null)
{
if (style == DimAutoStyle.Text) {

View File

@@ -697,7 +697,7 @@ public partial class View {
// dimension: the current dimension (width or height)
// autosize: the size to use if autosize = true
// This mehod is recursive if d is Dim.DimCombine
int GetNewDimension (Dim d, int location, int dimension, int autosize)
int GetNewDimension (Dim d, int location, int dimension, int autosize)
{
int newDimension;
switch (d) {
@@ -724,9 +724,9 @@ public partial class View {
case Dim.DimAuto auto:
var thickness = GetFramesThickness ();
newDimension = GetNewDimension (auto._min, location, dimension, autosize);
//newDimension = GetNewDimension (auto._min, location, dimension, autosize);
if (width) {
int furthestRight = Subviews.Count == 0 ? 0 : Subviews.Max (v => v.Frame.X + v.Frame.Width);
int furthestRight = Subviews.Count == 0 ? 0 : Subviews.Where (v => v.X is not Pos.PosAnchorEnd).Max (v => v.Frame.X + v.Frame.Width);
//Debug.Assert(superviewBounds.Width == (SuperView?.Bounds.Width ?? 0));
newDimension = int.Max (furthestRight + thickness.Left + thickness.Right, auto._min?.Anchor (superviewBounds.Width) ?? 0);
} else {
@@ -752,20 +752,11 @@ public partial class View {
// Determine new location
switch (pos) {
case Pos.PosCenter posCenter:
if (dim == null) {
// BUGBUG: In what situation is dim == null here? None that I can find.
// dim == null is the same as dim == Dim.FIll (0)
throw new ArgumentException ();
newDimension = AutoSize ? autosizeDimension : superviewDimension;
newLocation = posCenter.Anchor (superviewDimension - newDimension);
} else {
//newLocation = posCenter?.Anchor (superviewDimension) ?? 0;
//newDimension = Math.Max (GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0);
newDimension = posCenter.Anchor (superviewDimension);
newDimension = AutoSize && autosizeDimension > newDimension ? autosizeDimension : newDimension;
newLocation = posCenter.Anchor (superviewDimension - newDimension);
}
// For Center, the dimension is dependent on location, but we need to force getting the dimension first
// using a location of 0
newDimension = Math.Max (GetNewDimension (dim, 0, superviewDimension, autosizeDimension), 0);
newLocation = posCenter.Anchor (superviewDimension - newDimension);
newDimension = Math.Max (GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0);
break;
case Pos.PosCombine combine:
@@ -786,7 +777,7 @@ public partial class View {
case Pos.PosFactor:
case Pos.PosFunc:
case Pos.PosView:
default:
default:
newLocation = pos?.Anchor (superviewDimension) ?? 0;
newDimension = Math.Max (GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0);
break;
@@ -1046,6 +1037,7 @@ public partial class View {
if (v.Width is Dim.DimAuto || v.Height is Dim.DimAuto) {
// If the view is auto-sized...
var f = v.Frame;
v._frame = new Rect (v.Frame.X, v.Frame.Y, 0, 0);
LayoutSubview (v, new Rect (GetBoundsOffset (), Bounds.Size));
if (v.Frame != f) {
// The subviews changed; do it again

View File

@@ -163,6 +163,19 @@ namespace UICatalog.Scenarios {
};
Application.Top.Add (oddballButton);
oddballButton = new Button ("Center - 1") {
X = Pos.Center () - 1,
Y = Pos.Bottom (oddballButton)
};
Application.Top.Add (oddballButton);
// Won't be visible:
//oddballButton = new Button ("1 - Center") {
// X = 1 - Pos.Center (),
// Y = Pos.Bottom (oddballButton)
//};
//Application.Top.Add (oddballButton);
// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
// The `- Pos.Percent(5)` is there so at least something is visible
oddballButton = new Button ("Center + Center - Percent(50)") {

View File

@@ -30,9 +30,9 @@ public class DimAutoDemo : Scenario {
var resetButton = new Button () {
Text = "P_ut Button Back",
X = Pos.Center (),
Y = Pos.Bottom (label)
};
resetButton.X = Pos.AnchorEnd () - 19;
var movingButton = new Button () {
Text = "Press to make button move down.",
@@ -44,9 +44,6 @@ public class DimAutoDemo : Scenario {
movingButton.Y = movingButton.Frame.Y + 1;
};
resetButton.Clicked += (s, e) => {
movingButton.Y = Pos.Bottom (resetButton);
};
var view = new FrameView () {
Title = "Type in the TextField to make View grow.",
@@ -58,6 +55,10 @@ public class DimAutoDemo : Scenario {
view.ValidatePosDim = true;
view.Add (textField, label, resetButton, movingButton);
resetButton.Clicked += (s, e) => {
movingButton.Y = Pos.Bottom (resetButton);
};
var dlgButton = new Button () {
Text = "Open Test _Dialog",
X = Pos.Right (view),
@@ -82,22 +83,31 @@ public class DimAutoDemo : Scenario {
//cancel.Clicked += (s, _) => Application.RequestStop (dlg);
//dlg.AddButton (cancel);
var label = new Label ("This is a label (AutoSize = false; Dim.Auto(3/20). Press Esc to close.") {
var label = new Label ("This is a label (AutoSize = false; Dim.Auto(3/20). Press Esc to close. Even more text.") {
AutoSize = false,
X = Pos.Center(),
X = Pos.Center (),
Y = 0,
Height = Dim.Auto (min: 3),
Width = Dim.Auto (min: 20),
ColorScheme = Colors.Menu
};
var text = new TextField () {
Text = "TextField... X = 1; Y = Pos.Bottom (label), Width = Dim.Fill (1); Height = Dim.Fill(1)",
TextFormatter = new TextFormatter () { WordWrap = true },
X = 20,
Y = Pos.Bottom (label),
Width = Dim.Fill (20),
Height = Dim.Fill (10)
};
var btn = new Button ("AnchorEnd") {
Y = Pos.AnchorEnd (1)
};
// TODO: We should really fix AnchorEnd to do this automatically.
btn.X = Pos.AnchorEnd () - (Pos.Right (btn) - Pos.Left (btn));
dlg.Add (btn);
dlg.Add (label);
dlg.Add (text);
dlg.Add (btn);
Application.Run (dlg);
}
}

View File

@@ -20,18 +20,18 @@ public class SetRelativeLayoutTests {
};
// Default layout style is Computed
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.X);
Assert.Null (view.Y);
view.BeginInit(); view.EndInit();
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.X);
Assert.Null (view.Y);
view.SetRelativeLayout(new Rect(5, 5, 10, 10));
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
view.SetRelativeLayout (new Rect (5, 5, 10, 10));
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.X);
Assert.Null (view.Y);
@@ -50,18 +50,18 @@ public class SetRelativeLayoutTests {
};
// Default layout style is Computed
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.X);
Assert.NotNull (view.Y);
view.BeginInit (); view.EndInit ();
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.X);
Assert.NotNull (view.Y);
view.SetRelativeLayout (new Rect (5, 5, 10, 10));
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.X);
Assert.NotNull (view.Y);
@@ -78,17 +78,17 @@ public class SetRelativeLayoutTests {
};
// Default layout style is Computed
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.Width);
Assert.Null (view.Height);
view.BeginInit (); view.EndInit ();
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.Width);
Assert.Null (view.Height);
view.SetRelativeLayout (new Rect (5, 5, 10, 10));
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.Null (view.Width);
Assert.Null (view.Height);
@@ -118,17 +118,17 @@ public class SetRelativeLayoutTests {
};
// Default layout style is Computed
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.Width);
Assert.NotNull (view.Height);
view.BeginInit (); view.EndInit ();
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.Width);
Assert.NotNull (view.Height);
view.SetRelativeLayout (new Rect (5, 5, 10, 10));
Assert.Equal (view.LayoutStyle, LayoutStyle.Computed);
Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
Assert.NotNull (view.Width);
Assert.NotNull (view.Height);
@@ -139,6 +139,93 @@ public class SetRelativeLayoutTests {
Assert.Equal (expectedDim, view.Frame.Height);
}
[Fact]
public void Fill_Pos_Within_Bounds ()
{
var screen = new Rect (0, 0, 80, 25);
var view = new View () {
X = 1,
Y = 1,
Width = 5,
Height = 4
};
view.SetRelativeLayout (screen);
Assert.Equal (1, view.Frame.X);
Assert.Equal (1, view.Frame.Y);
Assert.Equal (5, view.Frame.Width);
Assert.Equal (4, view.Frame.Height);
view.Width = 80;
view.Height = 25;
view.SetRelativeLayout (screen);
Assert.Equal (1, view.Frame.X);
Assert.Equal (1, view.Frame.Y);
Assert.Equal (80, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.Width = Dim.Fill ();
view.Height = Dim.Fill ();
view.SetRelativeLayout (screen);
Assert.Equal (1, view.Frame.X);
Assert.Equal (1, view.Frame.Y);
Assert.Equal (79, view.Frame.Width); // proof (80 - 1)
Assert.Equal (24, view.Frame.Height); // proof (25 - 1)
view.X = 79;
view.Width = Dim.Fill ();
view.Height = Dim.Fill ();
view.SetRelativeLayout (screen);
Assert.Equal (79, view.Frame.X);
Assert.Equal (1, view.Frame.Y);
Assert.Equal (1, view.Frame.Width); // proof (80 - 79)
Assert.Equal (24, view.Frame.Height);
view.X = 80;
view.Width = Dim.Fill ();
view.Height = Dim.Fill ();
view.SetRelativeLayout (screen);
Assert.Equal (80, view.Frame.X);
Assert.Equal (1, view.Frame.Y);
Assert.Equal (0, view.Frame.Width); // proof (80 - 80)
Assert.Equal (24, view.Frame.Height);
}
[Fact]
public void FIll_Pos_Outside_Bounds ()
{
var screen = new Rect (0, 0, 80, 25);
var view = new View () {
X = 90, // outside of screen +10
Y = -10, // outside of screen -10
Width = 15,
Height = 15
};
view.SetRelativeLayout (screen);
Assert.Equal (90, view.Frame.X);
Assert.Equal (-10, view.Frame.Y);
Assert.Equal (15, view.Frame.Width);
Assert.Equal (15, view.Frame.Height);
// prove Width=Height= same as screen size
view.Width = 80;
view.Height = 25;
view.SetRelativeLayout (screen);
Assert.Equal (90, view.Frame.X);
Assert.Equal (-10, view.Frame.Y);
Assert.Equal (80, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.Width = Dim.Fill ();
view.Height = Dim.Fill ();
view.SetRelativeLayout (screen);
Assert.Equal (90, view.Frame.X);
Assert.Equal (-10, view.Frame.Y);
Assert.Equal (0, view.Frame.Width); // proof: 15x15 view is placed beyond right side of screen, so fill width is 0
Assert.Equal (35, view.Frame.Height); // proof: 15x15 view is placed beyond top of screen 10 rows, screen is 25 rows. so fill height is 25 + 10 = 35
}
[Fact]
public void PosCombine_PosCenter_Minus_Absolute ()
{
@@ -148,31 +235,114 @@ public class SetRelativeLayoutTests {
var screen = new Rect (0, 0, 80, 25);
var view = new View () {
X = Pos.Center () - 41, // ((80 / 2) - (5 / 2)) - 41 = (40 - 2 - 41) = -3
Y = Pos.Center () - 13, // ((25 / 2) - (4 / 2)) - 13 = (12 - 2 - 13) = -3
Width = 5,
Height = 4
X = Pos.Center () - 41, // -2 off left edge of screen
Y = Pos.Center () - 13, // -1 off top edge of screen
Width = 1,
Height = 1
};
view.SetRelativeLayout (screen);
Assert.Equal (-21, view.Frame.X); // BUGBUG: Should be -3
Assert.Equal (-7, view.Frame.Y); // BUGBUG: Should be -3
Assert.Equal (-2, view.Frame.X); // proof: 1x1 view centered in 80x25 screen has x of 39, so -41 is -2
Assert.Equal (-1, view.Frame.Y); // proof: 1x1 view centered in 80x25 screen has y of 12, so -13 is -1
view.Width = 80;
view.Height = 25;
view.SetRelativeLayout (screen);
Assert.Equal (-41, view.Frame.X);
Assert.Equal (-13, view.Frame.Y);
Assert.Equal (80, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.Width = Dim.Fill ();
view.Height = Dim.Fill ();
view.SetRelativeLayout (screen);
Assert.Equal (-41, view.Frame.X);
Assert.Equal (-13, view.Frame.Y);
Assert.Equal (121, view.Frame.Width); // 121 = screen.Width - (-Center - 41)
Assert.Equal (38, view.Frame.Height);
}
[Fact]
public void FIll_And_PosCenter ()
{
var screen = new Rect (0, 0, 80, 25);
var view = new View () {
X = Pos.Center (),
Y = Pos.Center (),
Width = Dim.Fill(),
Height = Dim.Fill()
};
view.SetRelativeLayout (screen);
Assert.Equal (0, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (80, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () + 1;
view.SetRelativeLayout (screen);
Assert.Equal (1, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (79, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () + 79;
view.SetRelativeLayout (screen);
Assert.Equal (79, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (1, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () + 80;
view.SetRelativeLayout (screen);
Assert.Equal (80, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (0, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () - 1;
view.SetRelativeLayout (screen);
Assert.Equal (-1, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (81, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () - 2; // Fill means all the way to right. So width will be 82. (dim gets calc'd before pos).
view.SetRelativeLayout (screen);
Assert.Equal (-2, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (82, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () - 3; // Fill means all the way to right. So width will be 83. (dim gets calc'd before pos).
view.SetRelativeLayout (screen);
Assert.Equal (-3, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (83, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
view.X = Pos.Center () - 41; // Fill means all the way to right. So width will be . (dim gets calc'd before pos).
view.SetRelativeLayout (screen);
Assert.Equal (-41, view.Frame.X);
Assert.Equal (0, view.Frame.Y);
Assert.Equal (121, view.Frame.Width);
Assert.Equal (25, view.Frame.Height);
}
[Fact]
public void PosCombine_PosCenter_Plus_Absolute ()
{
var screen = new Rect (0, 0, 80, 25);
var view = new View () {
X = Pos.Center () + 41, // ((80 / 2) - (5 / 2)) + 41 = (40 - 2 + 41) = 79
X = Pos.Center () + 41, // ((80 / 2) - (5 / 2)) + 41 = (40 - 3 + 41) = 78
Y = Pos.Center () + 13, // ((25 / 2) - (4 / 2)) + 13 = (12 - 2 + 13) = 23
Width = 5,
Height = 4
};
view.SetRelativeLayout (screen);
Assert.Equal (79, view.Frame.X); // BUGBUG: Should be 79
Assert.Equal (23, view.Frame.Y); // BUGBUG: Should be 23
Assert.Equal (78, view.Frame.X);
Assert.Equal (23, view.Frame.Y);
}
[Fact] [TestRespondersDisposed]

View File

@@ -547,13 +547,13 @@ namespace Terminal.Gui.ViewTests {
// This test has been moved to SetRlativeLayoutTests because it is testing
// SetRelativeLayout. In addition, the old test was bogus because it was testing the wrong thing (and
// because in v1 Pos.Center was broken in this regard!
//view.X = Pos.Center () - 41;
//view.Y = Pos.Center () - 13;
//view.SetRelativeLayout (top.Bounds);
//top.LayoutSubviews (); // BUGBUG: v2 - ??
//view.BoundsToScreen (0, 0, out rcol, out rrow);
//Assert.Equal (-41, rcol);
//Assert.Equal (-13, rrow);
view.X = Pos.Center () - 41;
view.Y = Pos.Center () - 13;
view.SetRelativeLayout (top.Bounds);
top.LayoutSubviews (); // BUGBUG: v2 - ??
view.BoundsToScreen (0, 0, out rcol, out rrow);
Assert.Equal (-41, rcol);
Assert.Equal (-13, rrow);
Application.End (runState);
}