Merged v2_develop

This commit is contained in:
Tig
2024-03-29 09:25:21 -06:00
14 changed files with 2395 additions and 1337 deletions

View File

@@ -0,0 +1,545 @@
using System.Globalization;
using System.Text;
using Xunit.Abstractions;
// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
namespace Terminal.Gui.ViewTests;
public class DimAutoTests
{
private readonly ITestOutputHelper _output;
public DimAutoTests (ITestOutputHelper output)
{
_output = output;
Console.OutputEncoding = Encoding.Default;
// Change current culture
var culture = CultureInfo.CreateSpecificCulture ("en-US");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
// Test min - ensure that if min is specified in the DimAuto constructor it is honored
[Fact]
public void DimAuto_Min ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (min: 10),
Height = Dim.Auto (min: 10),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = 5,
Height = 5
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
Assert.Equal (10, superView.Frame.Width);
Assert.Equal (10, superView.Frame.Height);
}
// what happens if DimAuto (min: 10) and the subview moves to a negative coord?
[Fact]
public void DimAuto_Min_Resets_If_Subview_Moves_Negative ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (min: 10),
Height = Dim.Auto (min: 10),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = 5,
Height = 5
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
Assert.Equal (10, superView.Frame.Width);
Assert.Equal (10, superView.Frame.Height);
subView.X = -1;
subView.Y = -1;
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
Assert.Equal (5, subView.Frame.Width);
Assert.Equal (5, subView.Frame.Height);
Assert.Equal (10, superView.Frame.Width);
Assert.Equal (10, superView.Frame.Height);
}
[Fact]
public void DimAuto_Min_Resets_If_Subview_Shrinks ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (min: 10),
Height = Dim.Auto (min: 10),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = 5,
Height = 5
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
Assert.Equal (10, superView.Frame.Width);
Assert.Equal (10, superView.Frame.Height);
subView.Width = 3;
subView.Height = 3;
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
Assert.Equal (3, subView.Frame.Width);
Assert.Equal (3, subView.Frame.Height);
Assert.Equal (10, superView.Frame.Width);
Assert.Equal (10, superView.Frame.Height);
}
[Theory]
[InlineData (0, 0, 0, 0, 0)]
[InlineData (0, 0, 5, 0, 0)]
[InlineData (0, 0, 0, 5, 5)]
[InlineData (0, 0, 5, 5, 5)]
[InlineData (1, 0, 5, 0, 0)]
[InlineData (1, 0, 0, 5, 5)]
[InlineData (1, 0, 5, 5, 5)]
[InlineData (1, 1, 5, 5, 6)]
[InlineData (-1, 0, 5, 0, 0)]
[InlineData (-1, 0, 0, 5, 5)]
[InlineData (-1, 0, 5, 5, 5)]
[InlineData (-1, -1, 5, 5, 4)]
public void Height_Auto_Width_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedHeight)
{
var superView = new View
{
X = 0,
Y = 0,
Width = 10,
Height = Dim.Auto (),
ValidatePosDim = true
};
var subView = new View
{
X = subX,
Y = subY,
Width = subWidth,
Height = subHeight,
ValidatePosDim = true
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
Assert.Equal (new Rectangle (0, 0, 10, expectedHeight), superView.Frame);
}
[Fact]
public void NoSubViews_Does_Nothing ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = Dim.Auto (),
ValidatePosDim = true
};
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
superView.SetRelativeLayout (new Rectangle (10, 10, 10, 10));
Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame);
}
[Theory]
[InlineData (0, 0, 0, 0, 0, 0)]
[InlineData (0, 0, 5, 0, 5, 0)]
[InlineData (0, 0, 0, 5, 0, 5)]
[InlineData (0, 0, 5, 5, 5, 5)]
[InlineData (1, 0, 5, 0, 6, 0)]
[InlineData (1, 0, 0, 5, 1, 5)]
[InlineData (1, 0, 5, 5, 6, 5)]
[InlineData (1, 1, 5, 5, 6, 6)]
[InlineData (-1, 0, 5, 0, 4, 0)]
[InlineData (-1, 0, 0, 5, 0, 5)]
[InlineData (-1, 0, 5, 5, 4, 5)]
[InlineData (-1, -1, 5, 5, 4, 4)]
public void SubView_ChangesSuperViewSize (int subX, int subY, int subWidth, int subHeight, int expectedWidth, int expectedHeight)
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = Dim.Auto (),
ValidatePosDim = true
};
var subView = new View
{
X = subX,
Y = subY,
Width = subWidth,
Height = subHeight,
ValidatePosDim = true
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
Assert.Equal (new Rectangle (0, 0, expectedWidth, expectedHeight), superView.Frame);
}
// Test validation
[Fact]
public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = Dim.Auto (),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = 10,
ValidatePosDim = true
};
superView.BeginInit ();
superView.EndInit ();
Assert.Throws<InvalidOperationException> (() => superView.Add (subView));
subView.Width = 10;
superView.Add (subView);
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
superView.LayoutSubviews (); // no throw
subView.Width = Dim.Fill ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Width = 10;
subView.Height = Dim.Fill ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 10;
subView.Height = Dim.Percent (50);
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 10;
subView.X = Pos.Center ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
subView.Y = Pos.Center ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Y = 0;
subView.Width = 10;
subView.Height = 10;
subView.X = 0;
subView.Y = 0;
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0));
superView.LayoutSubviews ();
}
// Test validation
[Fact]
public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims_Combine ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = Dim.Auto (),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = 10,
Height = 10
};
var subView2 = new View
{
X = 0,
Y = 0,
Width = 10,
Height = 10
};
superView.Add (subView, subView2);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0));
superView.LayoutSubviews (); // no throw
subView.Height = Dim.Fill () + 3;
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 0;
subView.Height = 3 + Dim.Fill ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 0;
subView.Height = 3 + 5 + Dim.Fill ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 0;
subView.Height = 3 + 5 + Dim.Percent (10);
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.Height = 0;
// Tests nested Combine
subView.Height = 5 + new Dim.DimCombine (true, 3, new Dim.DimCombine (true, Dim.Percent (10), 9));
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
}
[Fact]
public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Pos_Combine ()
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = Dim.Auto (),
ValidatePosDim = true
};
var subView = new View
{
X = 0,
Y = 0,
Width = 10,
Height = 10
};
var subView2 = new View
{
X = 0,
Y = 0,
Width = 10,
Height = 10
};
superView.Add (subView, subView2);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0));
superView.LayoutSubviews (); // no throw
subView.X = Pos.Right (subView2);
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0));
superView.LayoutSubviews (); // no throw
subView.X = Pos.Right (subView2) + 3;
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)); // no throw
superView.LayoutSubviews (); // no throw
subView.X = new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, 7, 9));
superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)); // no throw
subView.X = Pos.Center () + 3;
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
subView.X = 3 + Pos.Center ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
subView.X = 3 + 5 + Pos.Center ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
subView.X = 3 + 5 + Pos.Percent (10);
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
subView.X = Pos.Percent (10) + Pos.Center ();
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
// Tests nested Combine
subView.X = 5 + new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, Pos.Center (), 9));
Assert.Throws<InvalidOperationException> (() => superView.SetRelativeLayout (new Rectangle (0, 0, 0, 0)));
subView.X = 0;
}
[Theory]
[InlineData (0, 0, 0, 0, 0)]
[InlineData (0, 0, 5, 0, 5)]
[InlineData (0, 0, 0, 5, 0)]
[InlineData (0, 0, 5, 5, 5)]
[InlineData (1, 0, 5, 0, 6)]
[InlineData (1, 0, 0, 5, 1)]
[InlineData (1, 0, 5, 5, 6)]
[InlineData (1, 1, 5, 5, 6)]
[InlineData (-1, 0, 5, 0, 4)]
[InlineData (-1, 0, 0, 5, 0)]
[InlineData (-1, 0, 5, 5, 4)]
[InlineData (-1, -1, 5, 5, 4)]
public void Width_Auto_Height_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedWidth)
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (),
Height = 10,
ValidatePosDim = true
};
var subView = new View
{
X = subX,
Y = subY,
Width = subWidth,
Height = subHeight,
ValidatePosDim = true
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 10));
Assert.Equal (new Rectangle (0, 0, expectedWidth, 10), superView.Frame);
}
// Test that when a view has Width set to DimAuto (min: x) the width is never < x even if SetRelativeLayout is called with smaller bounds
[Theory]
[InlineData (0, 0)]
[InlineData (1, 1)]
[InlineData (3, 3)]
[InlineData (4, 4)]
[InlineData (5, 4)] // This is clearly invalid, but we choose to not throw but log a debug message
public void Width_Auto_Min (int min, int expectedWidth)
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (min: min),
Height = 1,
ValidatePosDim = true
};
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 4, 1));
Assert.Equal (expectedWidth, superView.Frame.Width);
}
// Test Dim.Fill - Fill should not impact width of the DimAuto superview
[Theory]
[InlineData (0, 0, 0, 10, 10)]
[InlineData (0, 1, 0, 10, 10)]
[InlineData (0, 11, 0, 10, 10)]
[InlineData (0, 10, 0, 10, 10)]
[InlineData (0, 5, 0, 10, 10)]
[InlineData (1, 5, 0, 10, 9)]
[InlineData (1, 10, 0, 10, 9)]
[InlineData (0, 0, 1, 10, 9)]
[InlineData (0, 10, 1, 10, 9)]
[InlineData (0, 5, 1, 10, 9)]
[InlineData (1, 5, 1, 10, 8)]
[InlineData (1, 10, 1, 10, 8)]
public void Width_Fill_Fills (int subX, int superMinWidth, int fill, int expectedSuperWidth, int expectedSubWidth)
{
var superView = new View
{
X = 0,
Y = 0,
Width = Dim.Auto (min:superMinWidth),
Height = 1,
ValidatePosDim = true
};
var subView = new View
{
X = subX,
Y = 0,
Width = Dim.Fill (fill),
Height = 1,
ValidatePosDim = true
};
superView.Add (subView);
superView.BeginInit ();
superView.EndInit ();
superView.SetRelativeLayout (new Rectangle (0, 0, 10, 1));
Assert.Equal (expectedSuperWidth, superView.Frame.Width);
superView.LayoutSubviews ();
Assert.Equal (expectedSubWidth, subView.Frame.Width);
Assert.Equal (expectedSuperWidth, superView.Frame.Width);
}
// Test variations of Frame
}

View File

@@ -1,9 +1,7 @@
using System.Globalization;
using System.Text;
using Xunit.Abstractions;
// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
using static Terminal.Gui.Dim;
namespace Terminal.Gui.ViewTests;
@@ -26,7 +24,7 @@ public class DimTests
// A new test that does not depend on Application is needed.
[Fact]
[AutoInitShutdown]
public void Dim_Add_Operator ()
public void Add_Operator ()
{
Toplevel top = new ();
@@ -76,176 +74,7 @@ public class DimTests
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Dim_Referencing_SuperView_Does_Not_Throw ()
{
var super = new View { Width = 10, Height = 10, Text = "super" };
var view = new View
{
Width = Dim.Width (super), // this is allowed
Height = Dim.Height (super), // this is allowed
Text = "view"
};
super.Add (view);
super.BeginInit ();
super.EndInit ();
Exception exception = Record.Exception (super.LayoutSubviews);
Assert.Null (exception);
super.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[AutoInitShutdown]
public void Dim_Subtract_Operator ()
{
Toplevel top = new ();
var view = new View { X = 0, Y = 0, Width = 20, Height = 0 };
var field = new TextField { X = 0, Y = Pos.Bottom (view), Width = 20 };
var count = 20;
List<Label> listLabels = new ();
for (var i = 0; i < count; i++)
{
field.Text = $"Label {i}";
var label = new Label { X = 0, Y = view.Bounds.Height, /*Width = 20,*/ Text = field.Text };
view.Add (label);
Assert.Equal ($"Label {i}", label.Text);
Assert.Equal ($"Absolute({i})", label.Y.ToString ());
listLabels.Add (label);
Assert.Equal ($"Absolute({i})", view.Height.ToString ());
view.Height += 1;
Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
}
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
view.Remove (listLabels [count - 1]);
listLabels [count - 1].Dispose ();
Assert.Equal ($"Absolute({count})", view.Height.ToString ());
view.Height -= 1;
count--;
Assert.Equal ($"Absolute({count})", view.Height.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count > 0)
{
field.NewKeyDownEvent (Key.Enter);
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
Assert.Equal (0, count);
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Dim_SyperView_Referencing_SubView_Throws ()
{
var super = new View { Width = 10, Height = 10, Text = "super" };
var view2 = new View { Width = 10, Height = 10, Text = "view2" };
var view = new View
{
Width = Dim.Width (view2), // this is not allowed
Height = Dim.Height (view2), // this is not allowed
Text = "view"
};
view.Add (view2);
super.Add (view);
super.BeginInit ();
super.EndInit ();
Assert.Throws<InvalidOperationException> (super.LayoutSubviews);
super.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void
Dim_Validation_Do_Not_Throws_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
{
var t = new View { Width = 80, Height = 25, Text = "top" };
var w = new Window { Width = Dim.Fill (), Height = Dim.Sized (10) };
var v = new View { Width = Dim.Width (w) - 2, Height = Dim.Percent (10), Text = "v" };
w.Add (v);
t.Add (w);
Assert.Equal (LayoutStyle.Absolute, t.LayoutStyle);
Assert.Equal (LayoutStyle.Computed, w.LayoutStyle);
Assert.Equal (LayoutStyle.Computed, v.LayoutStyle);
t.LayoutSubviews ();
Assert.Equal (2, v.Width = 2);
Assert.Equal (2, v.Height = 2);
// Force v to be LayoutStyle.Absolute;
v.Frame = new Rectangle (0, 1, 3, 4);
Assert.Equal (LayoutStyle.Absolute, v.LayoutStyle);
t.LayoutSubviews ();
Assert.Equal (2, v.Width = 2);
Assert.Equal (2, v.Height = 2);
t.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Dim_Validation_Do_Not_Throws_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Null ()
{
var t = new View { Width = 80, Height = 25, Text = "top" };
var w = new Window
{
X = 1,
Y = 2,
Width = 4,
Height = 5,
Title = "w"
};
t.Add (w);
t.LayoutSubviews ();
Assert.Equal (3, w.Width = 3);
Assert.Equal (4, w.Height = 4);
t.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void DimCombine_ObtuseScenario_Does_Not_Throw_If_Two_SubViews_Refs_The_Same_SuperView ()
public void Combine_ObtuseScenario_Does_Not_Throw_If_Two_SubViews_Refs_The_Same_SuperView ()
{
var t = new View { Width = 80, Height = 25, Text = "top" };
@@ -318,7 +147,7 @@ public class DimTests
/// <summary>This is an intentionally obtuse test. See https://github.com/gui-cs/Terminal.Gui/issues/2461</summary>
[Fact]
[TestRespondersDisposed]
public void DimCombine_ObtuseScenario_Throw_If_SuperView_Refs_SubView ()
public void Combine_ObtuseScenario_Throw_If_SuperView_Refs_SubView ()
{
var t = new View { Width = 80, Height = 25 };
@@ -366,45 +195,65 @@ public class DimTests
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Theory]
[AutoInitShutdown]
[InlineData (0, true)]
[InlineData (0, false)]
[InlineData (50, true)]
[InlineData (50, false)]
public void DimPercentPlusOne (int startingDistance, bool testHorizontal)
[Fact]
[TestRespondersDisposed]
public void Combine_View_Not_Added_Throws ()
{
var container = new View { Width = 100, Height = 100 };
var t = new View { Width = 80, Height = 50 };
var label = new Label
{
AutoSize = false,
X = testHorizontal ? startingDistance : 0,
Y = testHorizontal ? 0 : startingDistance,
Width = testHorizontal ? Dim.Percent (50) + 1 : 1,
Height = testHorizontal ? 1 : Dim.Percent (50) + 1
};
var super = new View { Width = Dim.Width (t) - 2, Height = Dim.Height (t) - 2 };
t.Add (super);
container.Add (label);
var top = new Toplevel ();
top.Add (container);
top.BeginInit ();
top.EndInit ();
top.LayoutSubviews ();
var sub = new View ();
super.Add (sub);
Assert.Equal (100, container.Frame.Width);
Assert.Equal (100, container.Frame.Height);
var v1 = new View { Width = Dim.Width (super) - 2, Height = Dim.Height (super) - 2 };
var v2 = new View { Width = Dim.Width (v1) - 2, Height = Dim.Height (v1) - 2 };
sub.Add (v1);
if (testHorizontal)
{
Assert.Equal (51, label.Frame.Width);
Assert.Equal (1, label.Frame.Height);
}
else
{
Assert.Equal (1, label.Frame.Width);
Assert.Equal (51, label.Frame.Height);
}
// v2 not added to sub; should cause exception on Layout since it's referenced by sub.
sub.Width = Dim.Fill () - Dim.Width (v2);
sub.Height = Dim.Fill () - Dim.Height (v2);
t.BeginInit ();
t.EndInit ();
Assert.Throws<InvalidOperationException> (() => t.LayoutSubviews ());
t.Dispose ();
v2.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void
Dim_Validation_Does_Not_Throw_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
{
var t = new View { Width = 80, Height = 25, Text = "top" };
var w = new Window { Width = Dim.Fill (), Height = Dim.Sized (10) };
var v = new View { Width = Dim.Width (w) - 2, Height = Dim.Percent (10), Text = "v" };
w.Add (v);
t.Add (w);
Assert.Equal (LayoutStyle.Absolute, t.LayoutStyle);
Assert.Equal (LayoutStyle.Computed, w.LayoutStyle);
Assert.Equal (LayoutStyle.Computed, v.LayoutStyle);
t.LayoutSubviews ();
Assert.Equal (2, v.Width = 2);
Assert.Equal (2, v.Height = 2);
// Force v to be LayoutStyle.Absolute;
v.Frame = new Rectangle (0, 1, 3, 4);
Assert.Equal (LayoutStyle.Absolute, v.LayoutStyle);
t.LayoutSubviews ();
Assert.Equal (2, v.Width = 2);
Assert.Equal (2, v.Height = 2);
t.Dispose ();
}
[Fact]
@@ -417,6 +266,90 @@ public class DimTests
Assert.Equal (dim1, dim2);
}
// Tests that Dim.Fill honors the margin parameter correctly
[Theory]
[InlineData (0, true, 25)]
[InlineData (0, false, 25)]
[InlineData (1, true, 24)]
[InlineData (1, false, 24)]
[InlineData (2, true, 23)]
[InlineData (2, false, 23)]
[InlineData (-2, true, 27)]
[InlineData (-2, false, 27)]
public void Fill_Margin (int margin, bool width, int expected)
{
var super = new View { Width = 25, Height = 25 };
var view = new View
{
X = 0,
Y = 0,
Width = width ? Dim.Fill (margin) : 1,
Height = width ? 1 : Dim.Fill (margin)
};
super.Add (view);
super.BeginInit ();
super.EndInit ();
super.LayoutSubviews ();
Assert.Equal (25, super.Frame.Width);
Assert.Equal (25, super.Frame.Height);
if (width)
{
Assert.Equal (expected, view.Frame.Width);
Assert.Equal (1, view.Frame.Height);
}
else
{
Assert.Equal (1, view.Frame.Width);
Assert.Equal (expected, view.Frame.Height);
}
}
// Tests that Dim.Fill fills the dimension REMAINING from the View's X position to the end of the super view's width
[Theory]
[InlineData (0, true, 25)]
[InlineData (0, false, 25)]
[InlineData (1, true, 24)]
[InlineData (1, false, 24)]
[InlineData (2, true, 23)]
[InlineData (2, false, 23)]
[InlineData (-2, true, 27)]
[InlineData (-2, false, 27)]
public void Fill_Offset (int offset, bool width, int expected)
{
var super = new View { Width = 25, Height = 25 };
var view = new View
{
X = width ? offset : 0,
Y = width ? 0 : offset,
Width = width ? Dim.Fill () : 1,
Height = width ? 1 : Dim.Fill ()
};
super.Add (view);
super.BeginInit ();
super.EndInit ();
super.LayoutSubviews ();
Assert.Equal (25, super.Frame.Width);
Assert.Equal (25, super.Frame.Height);
if (width)
{
Assert.Equal (expected, view.Frame.Width);
Assert.Equal (1, view.Frame.Height);
}
else
{
Assert.Equal (1, view.Frame.Width);
Assert.Equal (expected, view.Frame.Height);
}
}
// TODO: Other Dim.Height tests (e.g. Equal?)
[Fact]
@@ -507,9 +440,9 @@ public class DimTests
Assert.Equal (20, dimCombine.Anchor (100));
var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
var dimViewHeight = new Dim.DimView (view, 0);
var dimViewHeight = new Dim.DimView (view, Side.Height);
Assert.Equal (1, dimViewHeight.Anchor (0));
var dimViewWidth = new Dim.DimView (view, 1);
var dimViewWidth = new Dim.DimView (view, Side.Width);
Assert.Equal (20, dimViewWidth.Anchor (0));
view.Dispose ();
@@ -616,45 +549,45 @@ public class DimTests
t.Ready += (s, e) =>
{
Assert.Equal ("Absolute(100)", w.Width.ToString ());
Assert.Equal ("Absolute(100)", w.Height.ToString ());
Assert.Equal (100, w.Frame.Width);
Assert.Equal (100, w.Frame.Height);
Assert.Equal ("Absolute(100)", w.Width.ToString ());
Assert.Equal ("Absolute(100)", w.Height.ToString ());
Assert.Equal (100, w.Frame.Width);
Assert.Equal (100, w.Frame.Height);
Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
Assert.Equal ("Absolute(5)", f1.Height.ToString ());
Assert.Equal (49, f1.Frame.Width); // 50-1=49
Assert.Equal (5, f1.Frame.Height);
Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
Assert.Equal ("Absolute(5)", f1.Height.ToString ());
Assert.Equal (49, f1.Frame.Width); // 50-1=49
Assert.Equal (5, f1.Frame.Height);
Assert.Equal ("Fill(0)", f2.Width.ToString ());
Assert.Equal ("Absolute(5)", f2.Height.ToString ());
Assert.Equal (49, f2.Frame.Width); // 50-1=49
Assert.Equal (5, f2.Frame.Height);
Assert.Equal ("Fill(0)", f2.Width.ToString ());
Assert.Equal ("Absolute(5)", f2.Height.ToString ());
Assert.Equal (49, f2.Frame.Width); // 50-1=49
Assert.Equal (5, f2.Frame.Height);
#if DEBUG
#if DEBUG
Assert.Equal ($"Combine(View(Width,FrameView(f1){f1.Border.Frame})-Absolute(2))", v1.Width.ToString ());
#else
#else
Assert.Equal ($"Combine(View(Width,FrameView(){f1.Border.Frame})-Absolute(2))", v1.Width.ToString ());
#endif
#endif
Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
Assert.Equal (47, v1.Frame.Width); // 49-2=47
Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89
#if DEBUG
#if DEBUG
Assert.Equal (
$"Combine(View(Width,FrameView(f2){f2.Frame})-Absolute(2))",
v2.Width.ToString ()
#else
#else
Assert.Equal (
$"Combine(View(Width,FrameView(){f2.Frame})-Absolute(2))",
v2.Width.ToString ()
#endif
#endif
);
#if DEBUG
#if DEBUG
Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
#else
#else
Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
#endif
#endif
Assert.Equal (47, v2.Frame.Width); // 49-2=47
Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89
@@ -667,11 +600,11 @@ public class DimTests
Assert.Equal ("Absolute(50)", v4.Height.ToString ());
Assert.Equal (50, v4.Frame.Width);
Assert.Equal (50, v4.Frame.Height);
#if DEBUG
#if DEBUG
Assert.Equal ($"Combine(View(Width,Button(v1){v1.Frame})-View(Width,Button(v3){v3.Bounds}))", v5.Width.ToString ());
#else
#else
Assert.Equal ($"Combine(View(Height,Button(){v1.Frame})-View(Height,Button(){v3.Bounds}))", v5.Height.ToString ( ));
#endif
#endif
Assert.Equal (38, v5.Frame.Width); // 47-9=38
Assert.Equal (80, v5.Frame.Height); // 89-9=80
@@ -703,22 +636,22 @@ public class DimTests
Assert.Equal (5, f2.Frame.Height);
v1.Text = "Button1";
#if DEBUG
#if DEBUG
Assert.Equal ($"Combine(View(Width,FrameView(f1){f1.Frame})-Absolute(2))", v1.Width.ToString ());
#else
#else
Assert.Equal ($"Combine(View(Width,FrameView(){f1.Frame})-Absolute(2))", v1.Width.ToString ());
#endif
#endif
Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
Assert.Equal (97, v1.Frame.Width); // 99-2=97
Assert.Equal (189, v1.Frame.Height); // 198-2-7=189
v2.Text = "Button2";
#if DEBUG
Assert.Equal ( $"Combine(View(Width,FrameView(f2){f2.Frame})-Absolute(2))", v2.Width.ToString ());
#else
#if DEBUG
Assert.Equal ($"Combine(View(Width,FrameView(f2){f2.Frame})-Absolute(2))", v2.Width.ToString ());
#else
Assert.Equal ($"Combine(View(Width,FrameView(){f2.Frame})-Absolute(2))", v2.Width.ToString ());
#endif
#endif
Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
Assert.Equal (97, v2.Frame.Width); // 99-2=97
Assert.Equal (189, v2.Frame.Height); // 198-2-7=189
@@ -728,7 +661,7 @@ public class DimTests
Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
// 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width
Assert.Equal (19, v3.Frame.Width );
Assert.Equal (19, v3.Frame.Width);
// 199*10%=19
Assert.Equal (19, v3.Frame.Height);
@@ -746,13 +679,13 @@ public class DimTests
v5.Text = "Button5";
#if DEBUG
#if DEBUG
Assert.Equal ($"Combine(View(Width,Button(v1){v1.Frame})-View(Width,Button(v3){v3.Frame}))", v5.Width.ToString ());
Assert.Equal ($"Combine(View(Height,Button(v1){v1.Frame})-View(Height,Button(v3){v3.Frame}))", v5.Height.ToString ());
#else
#else
Assert.Equal ($"Combine(View(Width,Button(){v1.Frame})-View(Width,Button(){v3.Frame}))", v5.Width.ToString ());
Assert.Equal ($"Combine(View(Height,Button(){v1.Frame})-View(Height,Button(){v3.Frame}))", v5.Height.ToString ());
#endif
#endif
Assert.Equal (78, v5.Frame.Width); // 97-9=78
Assert.Equal (170, v5.Frame.Height); // 189-19=170
@@ -826,6 +759,89 @@ public class DimTests
Assert.Throws<ArgumentException> (() => dim = Dim.Percent (1000001));
}
[Theory]
[InlineData (0, false, true, 12)]
[InlineData (0, false, false, 12)]
[InlineData (1, false, true, 12)]
[InlineData (1, false, false, 12)]
[InlineData (2, false, true, 12)]
[InlineData (2, false, false, 12)]
[InlineData (0, true, true, 12)]
[InlineData (0, true, false, 12)]
[InlineData (1, true, true, 12)]
[InlineData (1, true, false, 12)]
[InlineData (2, true, true, 11)]
[InlineData (2, true, false, 11)]
public void Percent_Position (int position, bool usePosition, bool width, int expected)
{
var super = new View { Width = 25, Height = 25 };
var view = new View
{
X = width ? position : 0,
Y = width ? 0 : position,
Width = width ? Dim.Percent (50, usePosition) : 1,
Height = width ? 1 : Dim.Percent (50, usePosition)
};
super.Add (view);
super.BeginInit ();
super.EndInit ();
super.LayoutSubviews ();
Assert.Equal (25, super.Frame.Width);
Assert.Equal (25, super.Frame.Height);
if (width)
{
Assert.Equal (expected, view.Frame.Width);
Assert.Equal (1, view.Frame.Height);
}
else
{
Assert.Equal (1, view.Frame.Width);
Assert.Equal (expected, view.Frame.Height);
}
}
[Theory]
[InlineData (0, true)]
[InlineData (0, false)]
[InlineData (50, true)]
[InlineData (50, false)]
public void Percent_PlusOne (int startingDistance, bool testHorizontal)
{
var super = new View { Width = 100, Height = 100 };
var view = new View
{
X = testHorizontal ? startingDistance : 0,
Y = testHorizontal ? 0 : startingDistance,
Width = testHorizontal ? Dim.Percent (50) + 1 : 1,
Height = testHorizontal ? 1 : Dim.Percent (50) + 1
};
super.Add (view);
super.BeginInit ();
super.EndInit ();
super.LayoutSubviews ();
Assert.Equal (100, super.Frame.Width);
Assert.Equal (100, super.Frame.Height);
if (testHorizontal)
{
Assert.Equal (51, view.Frame.Width);
Assert.Equal (1, view.Frame.Height);
}
else
{
Assert.Equal (1, view.Frame.Width);
Assert.Equal (51, view.Frame.Height);
}
}
[Fact]
public void Percent_SetsValue ()
{
@@ -844,47 +860,24 @@ public class DimTests
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void PosCombine_View_Not_Added_Throws ()
public void Referencing_SuperView_Does_Not_Throw ()
{
var t = new View { Width = 80, Height = 50 };
var super = new View { Width = 10, Height = 10, Text = "super" };
var super = new View { Width = Dim.Width (t) - 2, Height = Dim.Height (t) - 2 };
t.Add (super);
var view = new View
{
Width = Dim.Width (super), // this is allowed
Height = Dim.Height (super), // this is allowed
Text = "view"
};
var sub = new View ();
super.Add (sub);
super.Add (view);
super.BeginInit ();
super.EndInit ();
var v1 = new View { Width = Dim.Width (super) - 2, Height = Dim.Height (super) - 2 };
var v2 = new View { Width = Dim.Width (v1) - 2, Height = Dim.Height (v1) - 2 };
sub.Add (v1);
// v2 not added to sub; should cause exception on Layout since it's referenced by sub.
sub.Width = Dim.Fill () - Dim.Width (v2);
sub.Height = Dim.Fill () - Dim.Height (v2);
t.BeginInit ();
t.EndInit ();
Assert.Throws<InvalidOperationException> (() => t.LayoutSubviews ());
t.Dispose ();
v2.Dispose ();
}
[Fact]
[TestRespondersDisposed]
public void SetsValue ()
{
var testVal = Rectangle.Empty;
var testValView = new View { Frame = testVal };
Dim dim = Dim.Width (testValView);
Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
testValView.Dispose ();
testVal = new Rectangle (1, 2, 3, 4);
testValView = new View { Frame = testVal };
dim = Dim.Width (testValView);
Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
testValView.Dispose ();
Exception exception = Record.Exception (super.LayoutSubviews);
Assert.Null (exception);
super.Dispose ();
}
[Fact]
@@ -928,6 +921,119 @@ public class DimTests
Assert.Equal ($"Absolute({testVal})", dim.ToString ());
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[AutoInitShutdown]
public void Subtract_Operator ()
{
Toplevel top = new Toplevel ();
var view = new View { X = 0, Y = 0, Width = 20, Height = 0 };
var field = new TextField { X = 0, Y = Pos.Bottom (view), Width = 20 };
var count = 20;
List<Label> listLabels = new ();
for (var i = 0; i < count; i++)
{
field.Text = $"Label {i}";
var label = new Label { X = 0, Y = view.Bounds.Height, /*Width = 20,*/ Text = field.Text };
view.Add (label);
Assert.Equal ($"Label {i}", label.Text);
Assert.Equal ($"Absolute({i})", label.Y.ToString ());
listLabels.Add (label);
Assert.Equal ($"Absolute({i})", view.Height.ToString ());
view.Height += 1;
Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
}
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
view.Remove (listLabels [count - 1]);
listLabels [count - 1].Dispose ();
Assert.Equal ($"Absolute({count})", view.Height.ToString ());
view.Height -= 1;
count--;
Assert.Equal ($"Absolute({count})", view.Height.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count > 0)
{
field.NewKeyDownEvent (new Key (KeyCode.Enter));
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
top.Dispose ();
Assert.Equal (0, count);
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void SyperView_Referencing_SubView_Throws ()
{
var super = new View { Width = 10, Height = 10, Text = "super" };
var view2 = new View { Width = 10, Height = 10, Text = "view2" };
var view = new View
{
Width = Dim.Width (view2), // this is not allowed
Height = Dim.Height (view2), // this is not allowed
Text = "view"
};
view.Add (view2);
super.Add (view);
super.BeginInit ();
super.EndInit ();
Assert.Throws<InvalidOperationException> (super.LayoutSubviews);
super.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Validation_Does_Not_Throw_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Null ()
{
var t = new View { Width = 80, Height = 25, Text = "top" };
var w = new Window
{
X = 1,
Y = 2,
Width = 4,
Height = 5,
Title = "w"
};
t.Add (w);
t.LayoutSubviews ();
Assert.Equal (3, w.Width = 3);
Assert.Equal (4, w.Height = 4);
t.Dispose ();
}
[Fact]
[TestRespondersDisposed]
public void Width_Equals ()
@@ -985,4 +1091,21 @@ public class DimTests
Dim dim = Dim.Width (null);
Assert.Throws<NullReferenceException> (() => dim.ToString ());
}
[Fact]
[TestRespondersDisposed]
public void Width_SetsValue ()
{
var testVal = Rectangle.Empty;
var testValView = new View { Frame = testVal };
Dim dim = Dim.Width (testValView);
Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
testValView.Dispose ();
testVal = new Rectangle (1, 2, 3, 4);
testValView = new View { Frame = testVal };
dim = Dim.Width (testValView);
Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
testValView.Dispose ();
}
}

View File

@@ -1,13 +1,65 @@
using Xunit.Abstractions;
// Alias Console to MockConsole so we don't accidentally use Console
using static Terminal.Gui.Pos;
namespace Terminal.Gui.ViewTests;
public class PosTests
public class PosTests (ITestOutputHelper output)
{
private readonly ITestOutputHelper _output;
public PosTests (ITestOutputHelper output) { _output = output; }
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Add_Operator ()
{
Application.Init (new FakeDriver ());
Toplevel top = new Toplevel();
var view = new View { X = 0, Y = 0, Width = 20, Height = 20 };
var field = new TextField { X = 0, Y = 0, Width = 20 };
var count = 0;
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
field.Text = $"View {count}";
var view2 = new View { X = 0, Y = field.Y, Width = 20, Text = field.Text };
view.Add (view2);
Assert.Equal ($"View {count}", view2.Text);
Assert.Equal ($"Absolute({count})", view2.Y.ToString ());
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
field.Y += 1;
count++;
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count < 20)
{
field.NewKeyDownEvent (new Key (KeyCode.Enter));
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
top.Dispose ();
Assert.Equal (20, count);
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
[Fact]
public void AnchorEnd_Equal ()
@@ -154,12 +206,10 @@ public class PosTests
var expected = $@"
┌────────────────┐
│012345678 {
b
}│
│012345678 {b}│
└────────────────┘
";
_ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
_ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
}
[Fact]
@@ -193,8 +243,60 @@ public class PosTests
Assert.Equal ("Center", pos.ToString ());
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
public void DoNotReturnPosCombine ()
public void Combine_Referencing_Same_View ()
{
var super = new View { Width = 10, Height = 10, Text = "super" };
var view1 = new View { Width = 2, Height = 2, Text = "view1" };
var view2 = new View { Width = 2, Height = 2, Text = "view2" };
view2.X = Pos.AnchorEnd () - (Pos.Right (view2) - Pos.Left (view2));
super.Add (view1, view2);
super.BeginInit ();
super.EndInit ();
Exception exception = Record.Exception (super.LayoutSubviews);
Assert.Null (exception);
Assert.Equal (new Rectangle (0, 0, 10, 10), super.Frame);
Assert.Equal (new Rectangle (0, 0, 2, 2), view1.Frame);
Assert.Equal (new Rectangle (8, 0, 2, 2), view2.Frame);
super.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Combine_WHY_Throws ()
{
Application.Init (new FakeDriver ());
Toplevel t = new Toplevel();
var w = new Window { X = Pos.Left (t) + 2, Y = Pos.Top (t) + 2 };
var f = new FrameView ();
var v1 = new View { X = Pos.Left (w) + 2, Y = Pos.Top (w) + 2 };
var v2 = new View { X = Pos.Left (v1) + 2, Y = Pos.Top (v1) + 2 };
f.Add (v1); // v2 not added
w.Add (f);
t.Add (w);
f.X = Pos.X (v2) - Pos.X (v1);
f.Y = Pos.Y (v2) - Pos.Y (v1);
Assert.Throws<InvalidOperationException> (() => Application.Run (t));
t.Dispose ();
Application.Shutdown ();
v2.Dispose ();
}
[Fact]
public void DoesNotReturnPosCombine ()
{
var v = new View { Id = "V" };
@@ -297,13 +399,13 @@ public class PosTests
Assert.Equal (20, posCombine.Anchor (100));
var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
var posViewX = new Pos.PosView (view, 0);
var posViewX = new Pos.PosView (view, Pos.Side.X);
Assert.Equal (20, posViewX.Anchor (0));
var posViewY = new Pos.PosView (view, 1);
var posViewY = new Pos.PosView (view, Pos.Side.Y);
Assert.Equal (10, posViewY.Anchor (0));
var posRight = new Pos.PosView (view, 2);
var posRight = new Pos.PosView (view, Pos.Side.Right);
Assert.Equal (40, posRight.Anchor (0));
var posViewBottom = new Pos.PosView (view, 3);
var posViewBottom = new Pos.PosView (view, Side.Bottom);
Assert.Equal (11, posViewBottom.Anchor (0));
view.Dispose ();
@@ -437,239 +539,13 @@ public class PosTests
Assert.NotEqual (pos1, pos2);
}
[Fact]
public void Percent_SetsValue ()
{
float f = 0;
Pos pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
f = 0.5F;
pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
f = 100;
pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
}
[Fact]
public void Percent_ThrowsOnIvalid ()
{
Pos pos = Pos.Percent (0);
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (-1));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (101));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (100.0001F));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (1000001));
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Pos_Add_Operator ()
{
Application.Init (new FakeDriver ());
Toplevel top = new ();
var view = new View { X = 0, Y = 0, Width = 20, Height = 20 };
var field = new TextField { X = 0, Y = 0, Width = 20 };
var count = 0;
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
field.Text = $"View {count}";
var view2 = new View { X = 0, Y = field.Y, Width = 20, Text = field.Text };
view.Add (view2);
Assert.Equal ($"View {count}", view2.Text);
Assert.Equal ($"Absolute({count})", view2.Y.ToString ());
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
field.Y += 1;
count++;
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count < 20)
{
field.NewKeyDownEvent (Key.Enter);
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
Assert.Equal (20, count);
top.Dispose ();
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Pos_Subtract_Operator ()
{
Application.Init (new FakeDriver ());
Toplevel top = new ();
var view = new View { X = 0, Y = 0, Width = 20, Height = 20 };
var field = new TextField { X = 0, Y = 0, Width = 20 };
var count = 20;
List<View> listViews = new ();
for (var i = 0; i < count; i++)
{
field.Text = $"View {i}";
var view2 = new View { X = 0, Y = field.Y, Width = 20, Text = field.Text };
view.Add (view2);
Assert.Equal ($"View {i}", view2.Text);
Assert.Equal ($"Absolute({i})", field.Y.ToString ());
listViews.Add (view2);
Assert.Equal ($"Absolute({i})", field.Y.ToString ());
field.Y += 1;
Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ());
}
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
Assert.Equal ($"View {count - 1}", listViews [count - 1].Text);
view.Remove (listViews [count - 1]);
listViews [count - 1].Dispose ();
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
field.Y -= 1;
count--;
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count > 0)
{
field.NewKeyDownEvent (Key.Enter);
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
Assert.Equal (0, count);
top.Dispose ();
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Null ()
{
Application.Init (new FakeDriver ());
Toplevel t = new ();
var w = new Window { X = 1, Y = 2, Width = 3, Height = 5 };
t.Add (w);
t.Ready += (s, e) =>
{
Assert.Equal (2, w.X = 2);
Assert.Equal (2, w.Y = 2);
};
Application.Iteration += (s, a) => Application.RequestStop ();
Application.Run (t);
t.Dispose ();
Application.Shutdown ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
public void PosCombine_Referencing_Same_View ()
{
var super = new View { Width = 10, Height = 10, Text = "super" };
var view1 = new View { Width = 2, Height = 2, Text = "view1" };
var view2 = new View { Width = 2, Height = 2, Text = "view2" };
view2.X = Pos.AnchorEnd () - (Pos.Right (view2) - Pos.Left (view2));
super.Add (view1, view2);
super.BeginInit ();
super.EndInit ();
Exception exception = Record.Exception (super.LayoutSubviews);
Assert.Null (exception);
Assert.Equal (new Rectangle (0, 0, 10, 10), super.Frame);
Assert.Equal (new Rectangle (0, 0, 2, 2), view1.Frame);
Assert.Equal (new Rectangle (8, 0, 2, 2), view2.Frame);
super.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void PosCombine_Will_Throws ()
{
Application.Init (new FakeDriver ());
Toplevel t = new ();
var w = new Window { X = Pos.Left (t) + 2, Y = Pos.Top (t) + 2 };
var f = new FrameView ();
var v1 = new View { X = Pos.Left (w) + 2, Y = Pos.Top (w) + 2 };
var v2 = new View { X = Pos.Left (v1) + 2, Y = Pos.Top (v1) + 2 };
f.Add (v1); // v2 not added
w.Add (f);
t.Add (w);
f.X = Pos.X (v2) - Pos.X (v1);
f.Y = Pos.Y (v2) - Pos.Y (v1);
Assert.Throws<InvalidOperationException> (() => Application.Run (t));
t.Dispose ();
Application.Shutdown ();
v2.Dispose ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Theory]
[AutoInitShutdown]
[InlineData (true)]
[InlineData (false)]
public void PosPercentPlusOne (bool testHorizontal)
public void Percent_PlusOne (bool testHorizontal)
{
var container = new View { Width = 100, Height = 100 };
@@ -701,12 +577,36 @@ public class PosTests
}
}
[Fact]
public void Percent_SetsValue ()
{
float f = 0;
Pos pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
f = 0.5F;
pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
f = 100;
pos = Pos.Percent (f);
Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
}
[Fact]
public void Percent_ThrowsOnIvalid ()
{
Pos pos = Pos.Percent (0);
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (-1));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (101));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (100.0001F));
Assert.Throws<ArgumentException> (() => pos = Pos.Percent (1000001));
}
// TODO: Test Left, Top, Right bottom Equal
/// <summary>Tests Pos.Left, Pos.X, Pos.Top, Pos.Y, Pos.Right, and Pos.Bottom set operations</summary>
[Fact]
[TestRespondersDisposed]
public void PosSide_SetsValue ()
public void Side_SetsValue ()
{
string side; // used in format string
var testRect = Rectangle.Empty;
@@ -931,7 +831,7 @@ public class PosTests
}
[Fact]
public void SetSide_Null_Throws ()
public void Side_SetToNull_Throws ()
{
Pos pos = Pos.Left (null);
Assert.Throws<NullReferenceException> (() => pos.ToString ());
@@ -951,4 +851,97 @@ public class PosTests
pos = Pos.Right (null);
Assert.Throws<NullReferenceException> (() => pos.ToString ());
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
[TestRespondersDisposed]
public void Subtract_Operator ()
{
Application.Init (new FakeDriver ());
Toplevel top = new Toplevel ();
var view = new View { X = 0, Y = 0, Width = 20, Height = 20 };
var field = new TextField { X = 0, Y = 0, Width = 20 };
var count = 20;
List<View> listViews = new ();
for (var i = 0; i < count; i++)
{
field.Text = $"View {i}";
var view2 = new View { X = 0, Y = field.Y, Width = 20, Text = field.Text };
view.Add (view2);
Assert.Equal ($"View {i}", view2.Text);
Assert.Equal ($"Absolute({i})", field.Y.ToString ());
listViews.Add (view2);
Assert.Equal ($"Absolute({i})", field.Y.ToString ());
field.Y += 1;
Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ());
}
field.KeyDown += (s, k) =>
{
if (k.KeyCode == KeyCode.Enter)
{
Assert.Equal ($"View {count - 1}", listViews [count - 1].Text);
view.Remove (listViews [count - 1]);
listViews [count - 1].Dispose ();
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
field.Y -= 1;
count--;
Assert.Equal ($"Absolute({count})", field.Y.ToString ());
}
};
Application.Iteration += (s, a) =>
{
while (count > 0)
{
field.NewKeyDownEvent (new Key (KeyCode.Enter));
}
Application.RequestStop ();
};
var win = new Window ();
win.Add (view);
win.Add (field);
top.Add (win);
Application.Run (top);
top.Dispose ();
Assert.Equal (0, count);
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
// TODO: A new test that calls SetRelativeLayout directly is needed.
[Fact]
public void Validation_Does_Not_Throw_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Null ()
{
Application.Init (new FakeDriver ());
Toplevel t = new Toplevel ();
var w = new Window { X = 1, Y = 2, Width = 3, Height = 5 };
t.Add (w);
t.Ready += (s, e) =>
{
Assert.Equal (2, w.X = 2);
Assert.Equal (2, w.Y = 2);
};
Application.Iteration += (s, a) => Application.RequestStop ();
Application.Run (t);
t.Dispose ();
Application.Shutdown ();
}
}

View File

@@ -930,31 +930,31 @@ public class AutoSizeTrueTests
Application.Begin (top);
((FakeDriver)Application.Driver).SetBufferSize (10, 4);
Size size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 1), size);
Size size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 1), size);
view.Text = $"{text}\n{text}";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 2), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 2), size);
view.Text = $"{text}\n{text}\n{text}+";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length + 1, 3), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length + 1, 3), size);
text = string.Empty;
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (Size.Empty, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (0, 0), size);
text = "1";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (_size1x1, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (1, 1), size);
text = "界";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (new (2, 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, 1), size);
}
[Fact]
@@ -970,31 +970,31 @@ public class AutoSizeTrueTests
Application.Begin (top);
((FakeDriver)Application.Driver).SetBufferSize (10, 4);
Size size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 1), size);
Size size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 1), size);
view.Text = $"{text}\n{text}";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 2), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 2), size);
view.Text = $"{text}\n{text}\n{text}+";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length + 1, 3), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length + 1, 3), size);
text = string.Empty;
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (Size.Empty, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (0, 0), size);
text = "1";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (_size1x1, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (1, 1), size);
text = "界";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (new (2, 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, 1), size);
}
[Fact]
@@ -1010,31 +1010,31 @@ public class AutoSizeTrueTests
Application.Begin (top);
((FakeDriver)Application.Driver).SetBufferSize (10, 4);
Size size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 1), size);
Size size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 1), size);
view.Text = $"{text}\n{text}";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 2), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 2), size);
view.Text = $"{text}\n{text}\n{text}+";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length + 1, 3), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length + 1, 3), size);
text = string.Empty;
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (Size.Empty, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (0, 0), size);
text = "1";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (_size1x1, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (1, 1), size);
text = "界";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (new (2, 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, 1), size);
}
[Fact]
@@ -1050,31 +1050,31 @@ public class AutoSizeTrueTests
Application.Begin (top);
((FakeDriver)Application.Driver).SetBufferSize (10, 4);
Size size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 1), size);
Size size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 1), size);
view.Text = $"{text}\n{text}";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length, 2), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length, 2), size);
view.Text = $"{text}\n{text}\n{text}+";
size = view.GetAutoSize ();
Assert.Equal (new (text.Length + 1, 3), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (text.Length + 1, 3), size);
text = string.Empty;
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (Size.Empty, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (0, 0), size);
text = "1";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (_size1x1, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (1, 1), size);
text = "界";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (new (2, 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, 1), size);
}
[Fact]
@@ -1090,31 +1090,31 @@ public class AutoSizeTrueTests
Application.Begin (top);
((FakeDriver)Application.Driver).SetBufferSize (10, 4);
Size size = view.GetAutoSize ();
Assert.Equal (new (1, text.Length), size);
Size size = view.GetTextAutoSize();
Assert.Equal (new Size (1, text.Length), size);
view.Text = $"{text}\n{text}";
size = view.GetAutoSize ();
Assert.Equal (new (2, text.Length), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, text.Length), size);
view.Text = $"{text}\n{text}\n{text}+";
size = view.GetAutoSize ();
Assert.Equal (new (3, text.Length + 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (3, text.Length + 1), size);
text = string.Empty;
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (Size.Empty, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (0, 0), size);
text = "1";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (_size1x1, size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (1, 1), size);
text = "界";
view.Text = text;
size = view.GetAutoSize ();
Assert.Equal (new (2, 1), size);
size = view.GetTextAutoSize();
Assert.Equal (new Size (2, 1), size);
}
[Fact]
@@ -2134,7 +2134,7 @@ Y
[AutoInitShutdown]
public void AutoSize_True_Width_Height_Stay_True_If_TextFormatter_Size_Fit ()
{
var text = "Fi_nish 終";
var text = "Finish 終";
var horizontalView = new View
{
@@ -2159,18 +2159,17 @@ Y
Assert.True (horizontalView.AutoSize);
Assert.True (verticalView.AutoSize);
Assert.Equal (new (text.GetColumns (), 1), horizontalView.TextFormatter.Size);
Assert.Equal (new (2, 9), verticalView.TextFormatter.Size);
Assert.Equal (new (0, 0, 10, 1), horizontalView.Frame);
Assert.Equal (new (0, 3, 10, 9), verticalView.Frame);
Assert.Equal (new (2, 8), verticalView.TextFormatter.Size);
//Assert.Equal (new (0, 0, 10, 1), horizontalView.Frame);
//Assert.Equal (new (0, 3, 10, 9), verticalView.Frame);
var expected = @"
┌────────────────────┐
│Fi_nish 終 │
│Finish 終
│ │
│ │
│F │
│i │
│_ │
│n │
│i │
│s │
@@ -2185,27 +2184,27 @@ Y
│ │
│ │
│ │
│ │
└────────────────────┘
";
Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
verticalView.Text = "最初_の行二行目";
verticalView.Text = "最初の行二行目";
Application.Top.Draw ();
Assert.True (horizontalView.AutoSize);
Assert.True (verticalView.AutoSize);
// height was initialized with 8 and can only grow or keep initial value
Assert.Equal (new Rectangle (0, 3, 10, 9), verticalView.Frame);
Assert.Equal (new Rectangle (0, 3, 9, 8), verticalView.Frame);
expected = @"
┌────────────────────┐
│Fi_nish 終 │
│Finish 終
│ │
│ │
│最 │
│初 │
│_ │
│の │
│行 │
│二 │
@@ -2220,6 +2219,7 @@ Y
│ │
│ │
│ │
│ │
└────────────────────┘
";