From d3dfb16597b517ca0a780caaa1d1494b8efc2cf9 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 09:51:22 -0600 Subject: [PATCH 01/16] Initial commit. Made all calls to AnchorEnd() be AnchorEnd(0) in prep --- Terminal.Gui/View/Layout/PosDim.cs | 31 ++++++++++++++----- UICatalog/Scenarios/ColorPicker.cs | 6 ++-- UICatalog/Scenarios/ComputedLayout.cs | 6 ++-- UICatalog/Scenarios/DynamicMenuBar.cs | 4 +-- UICatalog/Scenarios/DynamicStatusBar.cs | 4 +-- UICatalog/Scenarios/Scrolling.cs | 4 +-- UICatalog/Scenarios/ViewExperiments.cs | 2 +- UICatalog/Scenarios/WindowsAndFrameViews.cs | 2 +- UnitTests/View/Layout/PosTests.cs | 6 ++-- .../View/Layout/SetRelativeLayoutTests.cs | 2 +- UnitTests/Views/ButtonTests.cs | 4 +-- UnitTests/Views/CheckBoxTests.cs | 4 +-- UnitTests/Views/LabelTests.cs | 2 +- 13 files changed, 46 insertions(+), 31 deletions(-) diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 6da3a0a03..3b63f9a5b 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -125,20 +125,35 @@ public class Pos { /// - /// Creates a object that is anchored to the end (right side or bottom) of the dimension, useful - /// to flush the layout from the right or bottom. + /// Creates a object that has its end (right side or bottom) anchored to the end (right side or + /// bottom) + /// of the SuperView, useful to flush the layout from the right or bottom. + /// + /// The object anchored to the end (the bottom or the right side). + /// + /// This sample shows how align a to the bottom-right the SuperView. + /// + /// anchorButton.X = Pos.AnchorEnd (0); + /// anchorButton.Y = Pos.AnchorEnd (0); + /// + /// + public static Pos AnchorEnd () { return new PosAnchorEnd (0); } + + /// + /// Creates a object that is anchored to the end (right side or bottom) of the SuperView, + /// useful to flush the layout from the right or bottom. /// /// The object anchored to the end (the bottom or the right side). /// The view will be shifted left or up by the amount specified. /// - /// This sample shows how align a to the bottom-right of a . - /// - /// // See Issue #502 - /// anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); - /// anchorButton.Y = Pos.AnchorEnd (1); + /// This sample shows how align a such that its left side is offset 10 columns from + /// the right edge of the SuperView. + /// + /// anchorButton.X = Pos.AnchorEnd (10); + /// anchorButton.Y = 1 /// /// - public static Pos AnchorEnd (int offset = 0) + public static Pos AnchorEnd (int offset) { if (offset < 0) { diff --git a/UICatalog/Scenarios/ColorPicker.cs b/UICatalog/Scenarios/ColorPicker.cs index 8ae76c5dc..bc426e4e2 100644 --- a/UICatalog/Scenarios/ColorPicker.cs +++ b/UICatalog/Scenarios/ColorPicker.cs @@ -44,20 +44,20 @@ public class ColorPickers : Scenario backgroundColorPicker = new ColorPicker { Title = "Background Color", - // TODO: Replace with Pos.AnchorEnd () when #2900 is done + // TODO: Replace with Pos.AnchorEnd (0) when #2900 is done X = Pos.AnchorEnd ((8 * 4) + 2), // 8 box * 4 width + 2 for border BoxHeight = 1, BoxWidth = 4, BorderStyle = LineStyle.Single }; - //backgroundColorPicker.X = Pos.AnchorEnd () - (Pos.Right (backgroundColorPicker) - Pos.Left (backgroundColorPicker)); + //backgroundColorPicker.X = Pos.AnchorEnd (0) - (Pos.Right (backgroundColorPicker) - Pos.Left (backgroundColorPicker)); backgroundColorPicker.ColorChanged += BackgroundColor_ColorChanged; Win.Add (backgroundColorPicker); _backgroundColorLabel = new Label (); _backgroundColorLabel.X = - Pos.AnchorEnd () - (Pos.Right (_backgroundColorLabel) - Pos.Left (_backgroundColorLabel)); + Pos.AnchorEnd (0) - (Pos.Right (_backgroundColorLabel) - Pos.Left (_backgroundColorLabel)); _backgroundColorLabel.Y = Pos.Bottom (backgroundColorPicker) + 1; Win.Add (_backgroundColorLabel); diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs index d51311c90..65904cdf9 100644 --- a/UICatalog/Scenarios/ComputedLayout.cs +++ b/UICatalog/Scenarios/ComputedLayout.cs @@ -316,8 +316,8 @@ public class ComputedLayout : Scenario Top.Add (oddballButton); // Demonstrate AnchorEnd - Button is anchored to bottom/right - var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd () - 1 }; - anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); + var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd (0) - 1 }; + anchorButton.X = Pos.AnchorEnd (0) - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); anchorButton.Accept += (s, e) => { @@ -362,7 +362,7 @@ public class ComputedLayout : Scenario // Show positioning vertically using Pos.AnchorEnd via Pos.Combine var leftButton = new Button { - Text = "Left", Y = Pos.AnchorEnd () - 1 // Pos.Combine + Text = "Left", Y = Pos.AnchorEnd (0) - 1 // Pos.Combine }; leftButton.Accept += (s, e) => diff --git a/UICatalog/Scenarios/DynamicMenuBar.cs b/UICatalog/Scenarios/DynamicMenuBar.cs index bb5451655..f6ec1616e 100644 --- a/UICatalog/Scenarios/DynamicMenuBar.cs +++ b/UICatalog/Scenarios/DynamicMenuBar.cs @@ -604,7 +604,7 @@ public class DynamicMenuBar : Scenario var _btnRemoveMenuBar = new Button { Y = 1, Text = "Remove a MenuBar" }; - _btnRemoveMenuBar.X = Pos.AnchorEnd () - (Pos.Right (_btnRemoveMenuBar) - Pos.Left (_btnRemoveMenuBar)); + _btnRemoveMenuBar.X = Pos.AnchorEnd (0) - (Pos.Right (_btnRemoveMenuBar) - Pos.Left (_btnRemoveMenuBar)); _frmMenu.Add (_btnRemoveMenuBar); var _btnPrevious = new Button @@ -614,7 +614,7 @@ public class DynamicMenuBar : Scenario _frmMenu.Add (_btnPrevious); var _btnAdd = new Button { Y = Pos.Top (_btnPrevious) + 2, Text = " Add " }; - _btnAdd.X = Pos.AnchorEnd () - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); + _btnAdd.X = Pos.AnchorEnd (0) - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); _frmMenu.Add (_btnAdd); var _btnNext = new Button { X = Pos.X (_btnAdd), Y = Pos.Top (_btnPrevious), Text = ">" }; diff --git a/UICatalog/Scenarios/DynamicStatusBar.cs b/UICatalog/Scenarios/DynamicStatusBar.cs index 55a114d38..f7934024a 100644 --- a/UICatalog/Scenarios/DynamicStatusBar.cs +++ b/UICatalog/Scenarios/DynamicStatusBar.cs @@ -371,11 +371,11 @@ public class DynamicStatusBar : Scenario var _btnRemoveStatusBar = new Button { Y = 1, Text = "Remove a StatusBar" }; - _btnRemoveStatusBar.X = Pos.AnchorEnd () - (Pos.Right (_btnRemoveStatusBar) - Pos.Left (_btnRemoveStatusBar)); + _btnRemoveStatusBar.X = Pos.AnchorEnd (0) - (Pos.Right (_btnRemoveStatusBar) - Pos.Left (_btnRemoveStatusBar)); _frmStatusBar.Add (_btnRemoveStatusBar); var _btnAdd = new Button { Y = Pos.Top (_btnRemoveStatusBar) + 2, Text = " Add " }; - _btnAdd.X = Pos.AnchorEnd () - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); + _btnAdd.X = Pos.AnchorEnd (0) - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); _frmStatusBar.Add (_btnAdd); _lstItems = new ListView diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index aaf4ae626..ec17a1d16 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -122,10 +122,10 @@ public class Scrolling : Scenario ); // Demonstrate AnchorEnd - Button is anchored to bottom/right - var anchorButton = new Button { Y = Pos.AnchorEnd () - 1, Text = "Bottom Right" }; + var anchorButton = new Button { Y = Pos.AnchorEnd (0) - 1, Text = "Bottom Right" }; // TODO: Use Pos.Width instead of (Right-Left) when implemented (#502) - anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); + anchorButton.X = Pos.AnchorEnd (0) - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); anchorButton.Accept += (s, e) => { diff --git a/UICatalog/Scenarios/ViewExperiments.cs b/UICatalog/Scenarios/ViewExperiments.cs index dda940810..98319d10c 100644 --- a/UICatalog/Scenarios/ViewExperiments.cs +++ b/UICatalog/Scenarios/ViewExperiments.cs @@ -200,7 +200,7 @@ public class ViewExperiments : Scenario view.Add (edit); edit = new TextField { Text = "AnchorEnd[Right];AnchorEnd (1)", Y = Pos.AnchorEnd (1), Width = 30, Height = 1 }; - edit.X = Pos.AnchorEnd () - (Pos.Right (edit) - Pos.Left (edit)); + edit.X = Pos.AnchorEnd (0) - (Pos.Right (edit) - Pos.Left (edit)); view.Add (edit); edit = new TextField diff --git a/UICatalog/Scenarios/WindowsAndFrameViews.cs b/UICatalog/Scenarios/WindowsAndFrameViews.cs index ba6fec117..51f4e0631 100644 --- a/UICatalog/Scenarios/WindowsAndFrameViews.cs +++ b/UICatalog/Scenarios/WindowsAndFrameViews.cs @@ -207,7 +207,7 @@ public class WindowsAndFrameViews : Scenario new CheckBox { X = 0, Y = Pos.AnchorEnd (1), Text = "Btn1 (Y = Pos.AnchorEnd (1))" } ); var c = new CheckBox { Y = Pos.AnchorEnd (1), Text = "Btn2 (Y = Pos.AnchorEnd (1))" }; - c.X = Pos.AnchorEnd () - (Pos.Right (c) - Pos.Left (c)); + c.X = Pos.AnchorEnd (0) - (Pos.Right (c) - Pos.Left (c)); frame.Add (c); frame.Add (subFrameViewofFV); diff --git a/UnitTests/View/Layout/PosTests.cs b/UnitTests/View/Layout/PosTests.cs index dc9b7eb43..f4379c17b 100644 --- a/UnitTests/View/Layout/PosTests.cs +++ b/UnitTests/View/Layout/PosTests.cs @@ -98,7 +98,7 @@ public class PosTests public void AnchorEnd_SetsValue () { var n = 0; - Pos pos = Pos.AnchorEnd (); + Pos pos = Pos.AnchorEnd (0); Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); n = 5; @@ -122,7 +122,7 @@ public class PosTests int Btn_Width () { return btn?.Viewport.Width ?? 0; } - btn = new Button { Text = "Ok", X = Pos.AnchorEnd () - Pos.Function (Btn_Width) }; + btn = new Button { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) }; var view = new View { @@ -619,7 +619,7 @@ public class PosTests 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)); + view2.X = Pos.AnchorEnd (0) - (Pos.Right (view2) - Pos.Left (view2)); super.Add (view1, view2); super.BeginInit (); diff --git a/UnitTests/View/Layout/SetRelativeLayoutTests.cs b/UnitTests/View/Layout/SetRelativeLayoutTests.cs index 63a9f313d..f217a132a 100644 --- a/UnitTests/View/Layout/SetRelativeLayoutTests.cs +++ b/UnitTests/View/Layout/SetRelativeLayoutTests.cs @@ -405,7 +405,7 @@ public class SetRelativeLayoutTests { var screen = new Size (30, 1); var view = new View { Text = "abc", AutoSize = true }; // BUGBUG: AutoSize or Width must be set - view.X = Pos.AnchorEnd () - Pos.Function (GetViewWidth); + view.X = Pos.AnchorEnd (0) - Pos.Function (GetViewWidth); int GetViewWidth () { return view.Frame.Width; } diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index 313df7ce6..3d37a8f7e 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -164,8 +164,8 @@ public class ButtonTests (ITestOutputHelper output) var btn = new Button { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true }; var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; - btn.X = Pos.AnchorEnd () - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); - btn.X = Pos.AnchorEnd () - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); + btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); + btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs index 88e2afe9a..ff554c827 100644 --- a/UnitTests/Views/CheckBoxTests.cs +++ b/UnitTests/Views/CheckBoxTests.cs @@ -77,7 +77,7 @@ public class CheckBoxTests { var checkBox = new CheckBox { Y = Pos.Center (), Text = "C_heck this out 你" }; - checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); + checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); @@ -121,7 +121,7 @@ public class CheckBoxTests { var checkBox = new CheckBox { Y = Pos.Center (), Text = "Check this out 你" }; - checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); + checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; win.Add (checkBox); diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs index 660baf395..48ba65a32 100644 --- a/UnitTests/Views/LabelTests.cs +++ b/UnitTests/Views/LabelTests.cs @@ -92,7 +92,7 @@ public class LabelTests public void AutoSize_Stays_True_AnchorEnd () { var label = new Label { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true }; - label.X = Pos.AnchorEnd () - Pos.Function (() => label.TextFormatter.Text.GetColumns ()); + label.X = Pos.AnchorEnd (0) - Pos.Function (() => label.TextFormatter.Text.GetColumns ()); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); From 537f909e9f07205de21caf1f9fa069668cf30aaf Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 09:59:00 -0600 Subject: [PATCH 02/16] Factored AnchorEnd unit tests out to separate file. --- Terminal.Gui/View/Layout/PosDim.cs | 6 +- UnitTests/View/Layout/AnchorEndTests.cs | 952 ++++++++++++++++++++++++ UnitTests/View/Layout/PosTests.cs | 243 ++---- 3 files changed, 1001 insertions(+), 200 deletions(-) create mode 100644 UnitTests/View/Layout/AnchorEndTests.cs diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 3b63f9a5b..9159ea9b9 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -137,7 +137,11 @@ public class Pos /// anchorButton.Y = Pos.AnchorEnd (0); /// /// - public static Pos AnchorEnd () { return new PosAnchorEnd (0); } + public static Pos AnchorEnd () + { + throw new NotImplementedException (); + //return new PosAnchorEnd (0); + } /// /// Creates a object that is anchored to the end (right side or bottom) of the SuperView, diff --git a/UnitTests/View/Layout/AnchorEndTests.cs b/UnitTests/View/Layout/AnchorEndTests.cs new file mode 100644 index 000000000..dddcd98f1 --- /dev/null +++ b/UnitTests/View/Layout/AnchorEndTests.cs @@ -0,0 +1,952 @@ +using Xunit.Abstractions; + +namespace Terminal.Gui.ViewTests; + +public class AnchorEndTests (ITestOutputHelper output) +{ + [Fact] + public void AnchorEnd_Equal () + { + var n1 = 0; + var n2 = 0; + + Pos pos1 = Pos.AnchorEnd (n1); + Pos pos2 = Pos.AnchorEnd (n2); + Assert.Equal (pos1, pos2); + + // Test inequality + n2 = 5; + pos2 = Pos.AnchorEnd (n2); + Assert.NotEqual (pos1, pos2); + } + + // 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 AnchorEnd_Equal_Inside_Window () + { + var viewWidth = 10; + var viewHeight = 1; + + var tv = new TextView + { + X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight + }; + + var win = new Window (); + + win.Add (tv); + + Toplevel top = new (); + top.Add (win); + RunState rs = Application.Begin (top); + + Assert.Equal (new (0, 0, 80, 25), top.Frame); + Assert.Equal (new (0, 0, 80, 25), win.Frame); + Assert.Equal (new (68, 22, 10, 1), tv.Frame); + Application.End (rs); + } + + // 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 AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel () + { + var viewWidth = 10; + var viewHeight = 1; + + var tv = new TextView + { + X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight + }; + + var win = new Window (); + + win.Add (tv); + + var menu = new MenuBar (); + var status = new StatusBar (); + Toplevel top = new (); + top.Add (win, menu, status); + RunState rs = Application.Begin (top); + + Assert.Equal (new (0, 0, 80, 25), top.Frame); + Assert.Equal (new (0, 0, 80, 1), menu.Frame); + Assert.Equal (new (0, 24, 80, 1), status.Frame); + Assert.Equal (new (0, 1, 80, 23), win.Frame); + Assert.Equal (new (68, 20, 10, 1), tv.Frame); + + Application.End (rs); + } + + [Fact] + public void AnchorEnd_Negative_Throws () + { + Pos pos; + int n = -1; + Assert.Throws (() => pos = Pos.AnchorEnd (n)); + } + + [Fact] + public void AnchorEnd_SetsValue () + { + var n = 0; + Pos pos = Pos.AnchorEnd (0); + Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); + + n = 5; + pos = Pos.AnchorEnd (n); + Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); + } + + // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests. + [Fact] + [SetupFakeDriver] + public void AnchorEnd_View_And_Button () + { + ((FakeDriver)Application.Driver).SetBufferSize (20, 5); + + var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}"; + + var frame = new FrameView { Width = 18, Height = 3 }; + Assert.Equal (16, frame.Viewport.Width); + + Button btn = null; + + int Btn_Width () { return btn?.Viewport.Width ?? 0; } + + btn = new() { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) }; + + var view = new View + { + Text = "0123456789abcdefghij", + + // Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15) + // Dim.Function (Btn_Width) is 6 + // Width should be 15 - 6 = 9 + Width = Dim.Fill (1) - Dim.Function (Btn_Width), + Height = 1 + }; + + frame.Add (btn, view); + frame.BeginInit (); + frame.EndInit (); + frame.Draw (); + + Assert.Equal (6, btn.Viewport.Width); + Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10 + Assert.Equal (0, btn.Frame.Y); + Assert.Equal (6, btn.Frame.Width); + Assert.Equal (1, btn.Frame.Height); + + Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9 + Assert.Equal (0, view.Frame.X); + Assert.Equal (0, view.Frame.Y); + Assert.Equal (9, view.Frame.Width); + Assert.Equal (1, view.Frame.Height); + + var expected = $@" +┌────────────────┐ +│012345678 { + b +}│ +└────────────────┘ +"; + _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + } + + [Fact] + public void At_Equal () + { + var n1 = 0; + var n2 = 0; + + Pos pos1 = Pos.At (n1); + Pos pos2 = Pos.At (n2); + Assert.Equal (pos1, pos2); + } + + [Fact] + public void At_SetsValue () + { + Pos pos = Pos.At (0); + Assert.Equal ("Absolute(0)", pos.ToString ()); + + pos = Pos.At (5); + Assert.Equal ("Absolute(5)", pos.ToString ()); + + pos = Pos.At (-1); + Assert.Equal ("Absolute(-1)", pos.ToString ()); + } + + [Fact] + public void Center_SetsValue () + { + Pos pos = Pos.Center (); + Assert.Equal ("Center", pos.ToString ()); + } + + [Fact] + public void DoNotReturnPosCombine () + { + var v = new View { Id = "V" }; + + Pos pos = Pos.Left (v); + + Assert.Equal ( + $"View(side=x,target=View(V){v.Frame})", + pos.ToString () + ); + + pos = Pos.X (v); + + Assert.Equal ( + $"View(side=x,target=View(V){v.Frame})", + pos.ToString () + ); + + pos = Pos.Top (v); + + Assert.Equal ( + $"View(side=y,target=View(V){v.Frame})", + pos.ToString () + ); + + pos = Pos.Y (v); + + Assert.Equal ( + $"View(side=y,target=View(V){v.Frame})", + pos.ToString () + ); + + pos = Pos.Right (v); + + Assert.Equal ( + $"View(side=right,target=View(V){v.Frame})", + pos.ToString () + ); + + pos = Pos.Bottom (v); + + Assert.Equal ( + $"View(side=bottom,target=View(V){v.Frame})", + pos.ToString () + ); + } + + [Fact] + public void Function_Equal () + { + Func f1 = () => 0; + Func f2 = () => 0; + + Pos pos1 = Pos.Function (f1); + Pos pos2 = Pos.Function (f2); + Assert.Equal (pos1, pos2); + + f2 = () => 1; + pos2 = Pos.Function (f2); + Assert.NotEqual (pos1, pos2); + } + + [Fact] + public void Function_SetsValue () + { + var text = "Test"; + Pos pos = Pos.Function (() => text.Length); + Assert.Equal ("PosFunc(4)", pos.ToString ()); + + text = "New Test"; + Assert.Equal ("PosFunc(8)", pos.ToString ()); + + text = ""; + Assert.Equal ("PosFunc(0)", pos.ToString ()); + } + + [Fact] + [TestRespondersDisposed] + public void Internal_Tests () + { + var posFactor = new Pos.PosFactor (0.10F); + Assert.Equal (10, posFactor.Anchor (100)); + + var posAnchorEnd = new Pos.PosAnchorEnd (1); + Assert.Equal (99, posAnchorEnd.Anchor (100)); + + var posCenter = new Pos.PosCenter (); + Assert.Equal (50, posCenter.Anchor (100)); + + var posAbsolute = new Pos.PosAbsolute (10); + Assert.Equal (10, posAbsolute.Anchor (0)); + + var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute); + Assert.Equal (posCombine._left, posFactor); + Assert.Equal (posCombine._right, posAbsolute); + Assert.Equal (20, posCombine.Anchor (100)); + + posCombine = new (true, posAbsolute, posFactor); + Assert.Equal (posCombine._left, posAbsolute); + Assert.Equal (posCombine._right, posFactor); + Assert.Equal (20, posCombine.Anchor (100)); + + var view = new View { Frame = new (20, 10, 20, 1) }; + var posViewX = new Pos.PosView (view, 0); + Assert.Equal (20, posViewX.Anchor (0)); + var posViewY = new Pos.PosView (view, 1); + Assert.Equal (10, posViewY.Anchor (0)); + var posRight = new Pos.PosView (view, 2); + Assert.Equal (40, posRight.Anchor (0)); + var posViewBottom = new Pos.PosView (view, 3); + Assert.Equal (11, posViewBottom.Anchor (0)); + + view.Dispose (); + } + + // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved + // TODO: A new test that calls SetRelativeLayout directly is needed. + // See: https://github.com/gui-cs/Terminal.Gui/issues/504 + [Fact] + [TestRespondersDisposed] + public void LeftTopBottomRight_Win_ShouldNotThrow () + { + // Setup Fake driver + (Toplevel top, Window win, Button button) setup () + { + Application.Init (new FakeDriver ()); + Application.Iteration += (s, a) => { Application.RequestStop (); }; + var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; + var top = new Toplevel (); + top.Add (win); + + var button = new Button { X = Pos.Center (), Text = "button" }; + win.Add (button); + + return (top, win, button); + } + + RunState rs; + + void cleanup (RunState rs) + { + // Cleanup + Application.End (rs); + + Application.Top.Dispose (); + + // Shutdown must be called to safely clean up Application if Init has been called + Application.Shutdown (); + } + + // Test cases: + (Toplevel top, Window win, Button button) app = setup (); + app.button.Y = Pos.Left (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + + app = setup (); + app.button.Y = Pos.X (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + + app = setup (); + app.button.Y = Pos.Top (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + + app = setup (); + app.button.Y = Pos.Y (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + + app = setup (); + app.button.Y = Pos.Bottom (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + + app = setup (); + app.button.Y = Pos.Right (app.win); + rs = Application.Begin (app.top); + + // If Application.RunState is used then we must use Application.RunLoop with the rs parameter + Application.RunLoop (rs); + cleanup (rs); + } + + [Fact] + public void New_Works () + { + var pos = new Pos (); + Assert.Equal ("Terminal.Gui.Pos", pos.ToString ()); + } + + [Fact] + public void Percent_Equal () + { + float n1 = 0; + float n2 = 0; + Pos pos1 = Pos.Percent (n1); + Pos pos2 = Pos.Percent (n2); + Assert.Equal (pos1, pos2); + + n1 = n2 = 1; + pos1 = Pos.Percent (n1); + pos2 = Pos.Percent (n2); + Assert.Equal (pos1, pos2); + + n1 = n2 = 0.5f; + pos1 = Pos.Percent (n1); + pos2 = Pos.Percent (n2); + Assert.Equal (pos1, pos2); + + n1 = n2 = 100f; + pos1 = Pos.Percent (n1); + pos2 = Pos.Percent (n2); + Assert.Equal (pos1, pos2); + + n1 = 0; + n2 = 1; + pos1 = Pos.Percent (n1); + pos2 = Pos.Percent (n2); + Assert.NotEqual (pos1, pos2); + + n1 = 0.5f; + n2 = 1.5f; + pos1 = Pos.Percent (n1); + pos2 = Pos.Percent (n2); + 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 (() => pos = Pos.Percent (-1)); + Assert.Throws (() => pos = Pos.Percent (101)); + Assert.Throws (() => pos = Pos.Percent (100.0001F)); + Assert.Throws (() => 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 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 (0) - (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 (0, 0, 10, 10), super.Frame); + Assert.Equal (new (0, 0, 2, 2), view1.Frame); + Assert.Equal (new (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 (() => 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) + { + var container = new View { Width = 100, Height = 100 }; + + var view = new View + { + X = testHorizontal ? Pos.Percent (50) + Pos.Percent (10) + 1 : 1, + Y = testHorizontal ? 1 : Pos.Percent (50) + Pos.Percent (10) + 1, + Width = 10, + Height = 10 + }; + + container.Add (view); + var top = new Toplevel (); + top.Add (container); + top.LayoutSubviews (); + + Assert.Equal (100, container.Frame.Width); + Assert.Equal (100, container.Frame.Height); + + if (testHorizontal) + { + Assert.Equal (61, view.Frame.X); + Assert.Equal (1, view.Frame.Y); + } + else + { + Assert.Equal (1, view.Frame.X); + Assert.Equal (61, view.Frame.Y); + } + } + + // TODO: Test Left, Top, Right bottom Equal + + /// Tests Pos.Left, Pos.X, Pos.Top, Pos.Y, Pos.Right, and Pos.Bottom set operations + [Fact] + [TestRespondersDisposed] + public void PosSide_SetsValue () + { + string side; // used in format string + var testRect = Rectangle.Empty; + var testInt = 0; + Pos pos; + + // Pos.Left + side = "x"; + testInt = 0; + testRect = Rectangle.Empty; + pos = Pos.Left (new ()); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + pos = Pos.Left (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + testRect = new (1, 2, 3, 4); + pos = Pos.Left (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + // Pos.Left(win) + 0 + pos = Pos.Left (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = 1; + + // Pos.Left(win) +1 + pos = Pos.Left (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = -1; + + // Pos.Left(win) -1 + pos = Pos.Left (new() { Frame = testRect }) - testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + // Pos.X + side = "x"; + testInt = 0; + testRect = Rectangle.Empty; + pos = Pos.X (new ()); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + pos = Pos.X (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + testRect = new (1, 2, 3, 4); + pos = Pos.X (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + // Pos.X(win) + 0 + pos = Pos.X (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = 1; + + // Pos.X(win) +1 + pos = Pos.X (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = -1; + + // Pos.X(win) -1 + pos = Pos.X (new() { Frame = testRect }) - testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + // Pos.Top + side = "y"; + testInt = 0; + testRect = Rectangle.Empty; + pos = Pos.Top (new ()); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + pos = Pos.Top (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + testRect = new (1, 2, 3, 4); + pos = Pos.Top (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + // Pos.Top(win) + 0 + pos = Pos.Top (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = 1; + + // Pos.Top(win) +1 + pos = Pos.Top (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = -1; + + // Pos.Top(win) -1 + pos = Pos.Top (new() { Frame = testRect }) - testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + // Pos.Y + side = "y"; + testInt = 0; + testRect = Rectangle.Empty; + pos = Pos.Y (new ()); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + pos = Pos.Y (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + testRect = new (1, 2, 3, 4); + pos = Pos.Y (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + // Pos.Y(win) + 0 + pos = Pos.Y (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = 1; + + // Pos.Y(win) +1 + pos = Pos.Y (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = -1; + + // Pos.Y(win) -1 + pos = Pos.Y (new() { Frame = testRect }) - testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + // Pos.Bottom + side = "bottom"; + testRect = Rectangle.Empty; + testInt = 0; + pos = Pos.Bottom (new ()); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + pos = Pos.Bottom (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + testRect = new (1, 2, 3, 4); + pos = Pos.Bottom (new() { Frame = testRect }); + Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); + + // Pos.Bottom(win) + 0 + pos = Pos.Bottom (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = 1; + + // Pos.Bottom(win) +1 + pos = Pos.Bottom (new() { Frame = testRect }) + testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + + testInt = -1; + + // Pos.Bottom(win) -1 + pos = Pos.Bottom (new() { Frame = testRect }) - testInt; + + Assert.Equal ( + $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", + pos.ToString () + ); + +#if DEBUG_IDISPOSABLE + + // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above. + Responder.Instances.Clear (); +#endif + } + + [Fact] + public void SetSide_Null_Throws () + { + Pos pos = Pos.Left (null); + Assert.Throws (() => pos.ToString ()); + + pos = Pos.X (null); + Assert.Throws (() => pos.ToString ()); + + pos = Pos.Top (null); + Assert.Throws (() => pos.ToString ()); + + pos = Pos.Y (null); + Assert.Throws (() => pos.ToString ()); + + pos = Pos.Bottom (null); + Assert.Throws (() => pos.ToString ()); + + pos = Pos.Right (null); + Assert.Throws (() => pos.ToString ()); + } +} diff --git a/UnitTests/View/Layout/PosTests.cs b/UnitTests/View/Layout/PosTests.cs index f4379c17b..56cfc3801 100644 --- a/UnitTests/View/Layout/PosTests.cs +++ b/UnitTests/View/Layout/PosTests.cs @@ -1,167 +1,9 @@ using Xunit.Abstractions; -// Alias Console to MockConsole so we don't accidentally use Console - namespace Terminal.Gui.ViewTests; -public class PosTests +public class PosTests (ITestOutputHelper output) { - private readonly ITestOutputHelper _output; - public PosTests (ITestOutputHelper output) { _output = output; } - - [Fact] - public void AnchorEnd_Equal () - { - var n1 = 0; - var n2 = 0; - - Pos pos1 = Pos.AnchorEnd (n1); - Pos pos2 = Pos.AnchorEnd (n2); - Assert.Equal (pos1, pos2); - - // Test inequality - n2 = 5; - pos2 = Pos.AnchorEnd (n2); - Assert.NotEqual (pos1, pos2); - } - - // 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 AnchorEnd_Equal_Inside_Window () - { - var viewWidth = 10; - var viewHeight = 1; - - var tv = new TextView - { - X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight - }; - - var win = new Window (); - - win.Add (tv); - - Toplevel top = new (); - top.Add (win); - RunState rs = Application.Begin (top); - - Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame); - Assert.Equal (new Rectangle (0, 0, 80, 25), win.Frame); - Assert.Equal (new Rectangle (68, 22, 10, 1), tv.Frame); - Application.End (rs); - } - - // 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 AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel () - { - var viewWidth = 10; - var viewHeight = 1; - - var tv = new TextView - { - X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight - }; - - var win = new Window (); - - win.Add (tv); - - var menu = new MenuBar (); - var status = new StatusBar (); - Toplevel top = new (); - top.Add (win, menu, status); - RunState rs = Application.Begin (top); - - Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame); - Assert.Equal (new Rectangle (0, 0, 80, 1), menu.Frame); - Assert.Equal (new Rectangle (0, 24, 80, 1), status.Frame); - Assert.Equal (new Rectangle (0, 1, 80, 23), win.Frame); - Assert.Equal (new Rectangle (68, 20, 10, 1), tv.Frame); - - Application.End (rs); - } - - [Fact] - public void AnchorEnd_Negative_Throws () - { - Pos pos; - int n = -1; - Assert.Throws (() => pos = Pos.AnchorEnd (n)); - } - - [Fact] - public void AnchorEnd_SetsValue () - { - var n = 0; - Pos pos = Pos.AnchorEnd (0); - Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); - - n = 5; - pos = Pos.AnchorEnd (n); - Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); - } - - // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests. - [Fact] - [SetupFakeDriver] - public void AnchorEnd_View_And_Button () - { - ((FakeDriver)Application.Driver).SetBufferSize (20, 5); - - var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}"; - - var frame = new FrameView { Width = 18, Height = 3 }; - Assert.Equal (16, frame.Viewport.Width); - - Button btn = null; - - int Btn_Width () { return btn?.Viewport.Width ?? 0; } - - btn = new Button { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) }; - - var view = new View - { - Text = "0123456789abcdefghij", - - // Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15) - // Dim.Function (Btn_Width) is 6 - // Width should be 15 - 6 = 9 - Width = Dim.Fill (1) - Dim.Function (Btn_Width), - Height = 1 - }; - - frame.Add (btn, view); - frame.BeginInit (); - frame.EndInit (); - frame.Draw (); - - Assert.Equal (6, btn.Viewport.Width); - Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10 - Assert.Equal (0, btn.Frame.Y); - Assert.Equal (6, btn.Frame.Width); - Assert.Equal (1, btn.Frame.Height); - - Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9 - Assert.Equal (0, view.Frame.X); - Assert.Equal (0, view.Frame.Y); - Assert.Equal (9, view.Frame.Width); - Assert.Equal (1, view.Frame.Height); - - var expected = $@" -┌────────────────┐ -│012345678 { - b -}│ -└────────────────┘ -"; - _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - } - [Fact] public void At_Equal () { @@ -291,12 +133,12 @@ public class PosTests Assert.Equal (posCombine._right, posAbsolute); Assert.Equal (20, posCombine.Anchor (100)); - posCombine = new Pos.PosCombine (true, posAbsolute, posFactor); + posCombine = new (true, posAbsolute, posFactor); Assert.Equal (posCombine._left, posAbsolute); Assert.Equal (posCombine._right, posFactor); Assert.Equal (20, posCombine.Anchor (100)); - var view = new View { Frame = new Rectangle (20, 10, 20, 1) }; + var view = new View { Frame = new (20, 10, 20, 1) }; var posViewX = new Pos.PosView (view, 0); Assert.Equal (20, posViewX.Anchor (0)); var posViewY = new Pos.PosView (view, 1); @@ -339,6 +181,7 @@ public class PosTests Application.End (rs); Application.Top.Dispose (); + // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -513,6 +356,7 @@ public class PosTests Assert.Equal (20, count); top.Dispose (); + // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -582,6 +426,7 @@ public class PosTests Assert.Equal (0, count); top.Dispose (); + // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } @@ -627,9 +472,9 @@ public class PosTests 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); + Assert.Equal (new (0, 0, 10, 10), super.Frame); + Assert.Equal (new (0, 0, 2, 2), view1.Frame); + Assert.Equal (new (8, 0, 2, 2), view2.Frame); super.Dispose (); } @@ -717,18 +562,18 @@ public class PosTests side = "x"; testInt = 0; testRect = Rectangle.Empty; - pos = Pos.Left (new View ()); + pos = Pos.Left (new ()); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - pos = Pos.Left (new View { Frame = testRect }); + pos = Pos.Left (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - testRect = new Rectangle (1, 2, 3, 4); - pos = Pos.Left (new View { Frame = testRect }); + testRect = new (1, 2, 3, 4); + pos = Pos.Left (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); // Pos.Left(win) + 0 - pos = Pos.Left (new View { Frame = testRect }) + testInt; + pos = Pos.Left (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -738,7 +583,7 @@ public class PosTests testInt = 1; // Pos.Left(win) +1 - pos = Pos.Left (new View { Frame = testRect }) + testInt; + pos = Pos.Left (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -748,7 +593,7 @@ public class PosTests testInt = -1; // Pos.Left(win) -1 - pos = Pos.Left (new View { Frame = testRect }) - testInt; + pos = Pos.Left (new() { Frame = testRect }) - testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -759,18 +604,18 @@ public class PosTests side = "x"; testInt = 0; testRect = Rectangle.Empty; - pos = Pos.X (new View ()); + pos = Pos.X (new ()); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - pos = Pos.X (new View { Frame = testRect }); + pos = Pos.X (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - testRect = new Rectangle (1, 2, 3, 4); - pos = Pos.X (new View { Frame = testRect }); + testRect = new (1, 2, 3, 4); + pos = Pos.X (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); // Pos.X(win) + 0 - pos = Pos.X (new View { Frame = testRect }) + testInt; + pos = Pos.X (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -780,7 +625,7 @@ public class PosTests testInt = 1; // Pos.X(win) +1 - pos = Pos.X (new View { Frame = testRect }) + testInt; + pos = Pos.X (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -790,7 +635,7 @@ public class PosTests testInt = -1; // Pos.X(win) -1 - pos = Pos.X (new View { Frame = testRect }) - testInt; + pos = Pos.X (new() { Frame = testRect }) - testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -801,18 +646,18 @@ public class PosTests side = "y"; testInt = 0; testRect = Rectangle.Empty; - pos = Pos.Top (new View ()); + pos = Pos.Top (new ()); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - pos = Pos.Top (new View { Frame = testRect }); + pos = Pos.Top (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - testRect = new Rectangle (1, 2, 3, 4); - pos = Pos.Top (new View { Frame = testRect }); + testRect = new (1, 2, 3, 4); + pos = Pos.Top (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); // Pos.Top(win) + 0 - pos = Pos.Top (new View { Frame = testRect }) + testInt; + pos = Pos.Top (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -822,7 +667,7 @@ public class PosTests testInt = 1; // Pos.Top(win) +1 - pos = Pos.Top (new View { Frame = testRect }) + testInt; + pos = Pos.Top (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -832,7 +677,7 @@ public class PosTests testInt = -1; // Pos.Top(win) -1 - pos = Pos.Top (new View { Frame = testRect }) - testInt; + pos = Pos.Top (new() { Frame = testRect }) - testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -843,18 +688,18 @@ public class PosTests side = "y"; testInt = 0; testRect = Rectangle.Empty; - pos = Pos.Y (new View ()); + pos = Pos.Y (new ()); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - pos = Pos.Y (new View { Frame = testRect }); + pos = Pos.Y (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - testRect = new Rectangle (1, 2, 3, 4); - pos = Pos.Y (new View { Frame = testRect }); + testRect = new (1, 2, 3, 4); + pos = Pos.Y (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); // Pos.Y(win) + 0 - pos = Pos.Y (new View { Frame = testRect }) + testInt; + pos = Pos.Y (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -864,7 +709,7 @@ public class PosTests testInt = 1; // Pos.Y(win) +1 - pos = Pos.Y (new View { Frame = testRect }) + testInt; + pos = Pos.Y (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -874,7 +719,7 @@ public class PosTests testInt = -1; // Pos.Y(win) -1 - pos = Pos.Y (new View { Frame = testRect }) - testInt; + pos = Pos.Y (new() { Frame = testRect }) - testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -885,18 +730,18 @@ public class PosTests side = "bottom"; testRect = Rectangle.Empty; testInt = 0; - pos = Pos.Bottom (new View ()); + pos = Pos.Bottom (new ()); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - pos = Pos.Bottom (new View { Frame = testRect }); + pos = Pos.Bottom (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - testRect = new Rectangle (1, 2, 3, 4); - pos = Pos.Bottom (new View { Frame = testRect }); + testRect = new (1, 2, 3, 4); + pos = Pos.Bottom (new() { Frame = testRect }); Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); // Pos.Bottom(win) + 0 - pos = Pos.Bottom (new View { Frame = testRect }) + testInt; + pos = Pos.Bottom (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -906,7 +751,7 @@ public class PosTests testInt = 1; // Pos.Bottom(win) +1 - pos = Pos.Bottom (new View { Frame = testRect }) + testInt; + pos = Pos.Bottom (new() { Frame = testRect }) + testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", @@ -916,7 +761,7 @@ public class PosTests testInt = -1; // Pos.Bottom(win) -1 - pos = Pos.Bottom (new View { Frame = testRect }) - testInt; + pos = Pos.Bottom (new() { Frame = testRect }) - testInt; Assert.Equal ( $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", From 719f39c8b3cd76b4b470f7881243ae1b1358f3fd Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 10:33:18 -0600 Subject: [PATCH 03/16] Removed dupe tests --- UnitTests/View/Layout/AnchorEndTests.cs | 793 ------------------------ 1 file changed, 793 deletions(-) diff --git a/UnitTests/View/Layout/AnchorEndTests.cs b/UnitTests/View/Layout/AnchorEndTests.cs index dddcd98f1..d934f3c36 100644 --- a/UnitTests/View/Layout/AnchorEndTests.cs +++ b/UnitTests/View/Layout/AnchorEndTests.cs @@ -156,797 +156,4 @@ public class AnchorEndTests (ITestOutputHelper output) "; _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); } - - [Fact] - public void At_Equal () - { - var n1 = 0; - var n2 = 0; - - Pos pos1 = Pos.At (n1); - Pos pos2 = Pos.At (n2); - Assert.Equal (pos1, pos2); - } - - [Fact] - public void At_SetsValue () - { - Pos pos = Pos.At (0); - Assert.Equal ("Absolute(0)", pos.ToString ()); - - pos = Pos.At (5); - Assert.Equal ("Absolute(5)", pos.ToString ()); - - pos = Pos.At (-1); - Assert.Equal ("Absolute(-1)", pos.ToString ()); - } - - [Fact] - public void Center_SetsValue () - { - Pos pos = Pos.Center (); - Assert.Equal ("Center", pos.ToString ()); - } - - [Fact] - public void DoNotReturnPosCombine () - { - var v = new View { Id = "V" }; - - Pos pos = Pos.Left (v); - - Assert.Equal ( - $"View(side=x,target=View(V){v.Frame})", - pos.ToString () - ); - - pos = Pos.X (v); - - Assert.Equal ( - $"View(side=x,target=View(V){v.Frame})", - pos.ToString () - ); - - pos = Pos.Top (v); - - Assert.Equal ( - $"View(side=y,target=View(V){v.Frame})", - pos.ToString () - ); - - pos = Pos.Y (v); - - Assert.Equal ( - $"View(side=y,target=View(V){v.Frame})", - pos.ToString () - ); - - pos = Pos.Right (v); - - Assert.Equal ( - $"View(side=right,target=View(V){v.Frame})", - pos.ToString () - ); - - pos = Pos.Bottom (v); - - Assert.Equal ( - $"View(side=bottom,target=View(V){v.Frame})", - pos.ToString () - ); - } - - [Fact] - public void Function_Equal () - { - Func f1 = () => 0; - Func f2 = () => 0; - - Pos pos1 = Pos.Function (f1); - Pos pos2 = Pos.Function (f2); - Assert.Equal (pos1, pos2); - - f2 = () => 1; - pos2 = Pos.Function (f2); - Assert.NotEqual (pos1, pos2); - } - - [Fact] - public void Function_SetsValue () - { - var text = "Test"; - Pos pos = Pos.Function (() => text.Length); - Assert.Equal ("PosFunc(4)", pos.ToString ()); - - text = "New Test"; - Assert.Equal ("PosFunc(8)", pos.ToString ()); - - text = ""; - Assert.Equal ("PosFunc(0)", pos.ToString ()); - } - - [Fact] - [TestRespondersDisposed] - public void Internal_Tests () - { - var posFactor = new Pos.PosFactor (0.10F); - Assert.Equal (10, posFactor.Anchor (100)); - - var posAnchorEnd = new Pos.PosAnchorEnd (1); - Assert.Equal (99, posAnchorEnd.Anchor (100)); - - var posCenter = new Pos.PosCenter (); - Assert.Equal (50, posCenter.Anchor (100)); - - var posAbsolute = new Pos.PosAbsolute (10); - Assert.Equal (10, posAbsolute.Anchor (0)); - - var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute); - Assert.Equal (posCombine._left, posFactor); - Assert.Equal (posCombine._right, posAbsolute); - Assert.Equal (20, posCombine.Anchor (100)); - - posCombine = new (true, posAbsolute, posFactor); - Assert.Equal (posCombine._left, posAbsolute); - Assert.Equal (posCombine._right, posFactor); - Assert.Equal (20, posCombine.Anchor (100)); - - var view = new View { Frame = new (20, 10, 20, 1) }; - var posViewX = new Pos.PosView (view, 0); - Assert.Equal (20, posViewX.Anchor (0)); - var posViewY = new Pos.PosView (view, 1); - Assert.Equal (10, posViewY.Anchor (0)); - var posRight = new Pos.PosView (view, 2); - Assert.Equal (40, posRight.Anchor (0)); - var posViewBottom = new Pos.PosView (view, 3); - Assert.Equal (11, posViewBottom.Anchor (0)); - - view.Dispose (); - } - - // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved - // TODO: A new test that calls SetRelativeLayout directly is needed. - // See: https://github.com/gui-cs/Terminal.Gui/issues/504 - [Fact] - [TestRespondersDisposed] - public void LeftTopBottomRight_Win_ShouldNotThrow () - { - // Setup Fake driver - (Toplevel top, Window win, Button button) setup () - { - Application.Init (new FakeDriver ()); - Application.Iteration += (s, a) => { Application.RequestStop (); }; - var win = new Window { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; - var top = new Toplevel (); - top.Add (win); - - var button = new Button { X = Pos.Center (), Text = "button" }; - win.Add (button); - - return (top, win, button); - } - - RunState rs; - - void cleanup (RunState rs) - { - // Cleanup - Application.End (rs); - - Application.Top.Dispose (); - - // Shutdown must be called to safely clean up Application if Init has been called - Application.Shutdown (); - } - - // Test cases: - (Toplevel top, Window win, Button button) app = setup (); - app.button.Y = Pos.Left (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - - app = setup (); - app.button.Y = Pos.X (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - - app = setup (); - app.button.Y = Pos.Top (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - - app = setup (); - app.button.Y = Pos.Y (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - - app = setup (); - app.button.Y = Pos.Bottom (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - - app = setup (); - app.button.Y = Pos.Right (app.win); - rs = Application.Begin (app.top); - - // If Application.RunState is used then we must use Application.RunLoop with the rs parameter - Application.RunLoop (rs); - cleanup (rs); - } - - [Fact] - public void New_Works () - { - var pos = new Pos (); - Assert.Equal ("Terminal.Gui.Pos", pos.ToString ()); - } - - [Fact] - public void Percent_Equal () - { - float n1 = 0; - float n2 = 0; - Pos pos1 = Pos.Percent (n1); - Pos pos2 = Pos.Percent (n2); - Assert.Equal (pos1, pos2); - - n1 = n2 = 1; - pos1 = Pos.Percent (n1); - pos2 = Pos.Percent (n2); - Assert.Equal (pos1, pos2); - - n1 = n2 = 0.5f; - pos1 = Pos.Percent (n1); - pos2 = Pos.Percent (n2); - Assert.Equal (pos1, pos2); - - n1 = n2 = 100f; - pos1 = Pos.Percent (n1); - pos2 = Pos.Percent (n2); - Assert.Equal (pos1, pos2); - - n1 = 0; - n2 = 1; - pos1 = Pos.Percent (n1); - pos2 = Pos.Percent (n2); - Assert.NotEqual (pos1, pos2); - - n1 = 0.5f; - n2 = 1.5f; - pos1 = Pos.Percent (n1); - pos2 = Pos.Percent (n2); - 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 (() => pos = Pos.Percent (-1)); - Assert.Throws (() => pos = Pos.Percent (101)); - Assert.Throws (() => pos = Pos.Percent (100.0001F)); - Assert.Throws (() => 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 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 (0) - (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 (0, 0, 10, 10), super.Frame); - Assert.Equal (new (0, 0, 2, 2), view1.Frame); - Assert.Equal (new (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 (() => 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) - { - var container = new View { Width = 100, Height = 100 }; - - var view = new View - { - X = testHorizontal ? Pos.Percent (50) + Pos.Percent (10) + 1 : 1, - Y = testHorizontal ? 1 : Pos.Percent (50) + Pos.Percent (10) + 1, - Width = 10, - Height = 10 - }; - - container.Add (view); - var top = new Toplevel (); - top.Add (container); - top.LayoutSubviews (); - - Assert.Equal (100, container.Frame.Width); - Assert.Equal (100, container.Frame.Height); - - if (testHorizontal) - { - Assert.Equal (61, view.Frame.X); - Assert.Equal (1, view.Frame.Y); - } - else - { - Assert.Equal (1, view.Frame.X); - Assert.Equal (61, view.Frame.Y); - } - } - - // TODO: Test Left, Top, Right bottom Equal - - /// Tests Pos.Left, Pos.X, Pos.Top, Pos.Y, Pos.Right, and Pos.Bottom set operations - [Fact] - [TestRespondersDisposed] - public void PosSide_SetsValue () - { - string side; // used in format string - var testRect = Rectangle.Empty; - var testInt = 0; - Pos pos; - - // Pos.Left - side = "x"; - testInt = 0; - testRect = Rectangle.Empty; - pos = Pos.Left (new ()); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - pos = Pos.Left (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - testRect = new (1, 2, 3, 4); - pos = Pos.Left (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - // Pos.Left(win) + 0 - pos = Pos.Left (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = 1; - - // Pos.Left(win) +1 - pos = Pos.Left (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = -1; - - // Pos.Left(win) -1 - pos = Pos.Left (new() { Frame = testRect }) - testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - // Pos.X - side = "x"; - testInt = 0; - testRect = Rectangle.Empty; - pos = Pos.X (new ()); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - pos = Pos.X (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - testRect = new (1, 2, 3, 4); - pos = Pos.X (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - // Pos.X(win) + 0 - pos = Pos.X (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = 1; - - // Pos.X(win) +1 - pos = Pos.X (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = -1; - - // Pos.X(win) -1 - pos = Pos.X (new() { Frame = testRect }) - testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - // Pos.Top - side = "y"; - testInt = 0; - testRect = Rectangle.Empty; - pos = Pos.Top (new ()); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - pos = Pos.Top (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - testRect = new (1, 2, 3, 4); - pos = Pos.Top (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - // Pos.Top(win) + 0 - pos = Pos.Top (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = 1; - - // Pos.Top(win) +1 - pos = Pos.Top (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = -1; - - // Pos.Top(win) -1 - pos = Pos.Top (new() { Frame = testRect }) - testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - // Pos.Y - side = "y"; - testInt = 0; - testRect = Rectangle.Empty; - pos = Pos.Y (new ()); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - pos = Pos.Y (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - testRect = new (1, 2, 3, 4); - pos = Pos.Y (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - // Pos.Y(win) + 0 - pos = Pos.Y (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = 1; - - // Pos.Y(win) +1 - pos = Pos.Y (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = -1; - - // Pos.Y(win) -1 - pos = Pos.Y (new() { Frame = testRect }) - testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - // Pos.Bottom - side = "bottom"; - testRect = Rectangle.Empty; - testInt = 0; - pos = Pos.Bottom (new ()); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - pos = Pos.Bottom (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - testRect = new (1, 2, 3, 4); - pos = Pos.Bottom (new() { Frame = testRect }); - Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ()); - - // Pos.Bottom(win) + 0 - pos = Pos.Bottom (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = 1; - - // Pos.Bottom(win) +1 - pos = Pos.Bottom (new() { Frame = testRect }) + testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - - testInt = -1; - - // Pos.Bottom(win) -1 - pos = Pos.Bottom (new() { Frame = testRect }) - testInt; - - Assert.Equal ( - $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", - pos.ToString () - ); - -#if DEBUG_IDISPOSABLE - - // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above. - Responder.Instances.Clear (); -#endif - } - - [Fact] - public void SetSide_Null_Throws () - { - Pos pos = Pos.Left (null); - Assert.Throws (() => pos.ToString ()); - - pos = Pos.X (null); - Assert.Throws (() => pos.ToString ()); - - pos = Pos.Top (null); - Assert.Throws (() => pos.ToString ()); - - pos = Pos.Y (null); - Assert.Throws (() => pos.ToString ()); - - pos = Pos.Bottom (null); - Assert.Throws (() => pos.ToString ()); - - pos = Pos.Right (null); - Assert.Throws (() => pos.ToString ()); - } } From 05d3399f35cb099f73a842e50d17a329d19df644 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 11:19:10 -0600 Subject: [PATCH 04/16] Added primitive AnchorEnd tests --- UnitTests/View/Layout/AnchorEndTests.cs | 239 +++++++++++++++--------- 1 file changed, 152 insertions(+), 87 deletions(-) diff --git a/UnitTests/View/Layout/AnchorEndTests.cs b/UnitTests/View/Layout/AnchorEndTests.cs index d934f3c36..1d88bd160 100644 --- a/UnitTests/View/Layout/AnchorEndTests.cs +++ b/UnitTests/View/Layout/AnchorEndTests.cs @@ -1,25 +1,165 @@ using Xunit.Abstractions; +using static Terminal.Gui.Pos; namespace Terminal.Gui.ViewTests; public class AnchorEndTests (ITestOutputHelper output) { [Fact] - public void AnchorEnd_Equal () + public void PosAnchorEnd_Constructor () { - var n1 = 0; - var n2 = 0; - - Pos pos1 = Pos.AnchorEnd (n1); - Pos pos2 = Pos.AnchorEnd (n2); - Assert.Equal (pos1, pos2); - - // Test inequality - n2 = 5; - pos2 = Pos.AnchorEnd (n2); - Assert.NotEqual (pos1, pos2); + var posAnchorEnd = new PosAnchorEnd (10); + Assert.NotNull (posAnchorEnd); } + [Theory] + [InlineData (0, 0, true)] + [InlineData (10, 10, true)] + [InlineData (0, 10, false)] + [InlineData (10, 1, false)] + public void PosAnchorEnd_Equals (int offset1, int offset2, bool expectedEquals) + { + var posAnchorEnd1 = new PosAnchorEnd (offset1); + var posAnchorEnd2 = new PosAnchorEnd (offset2); + + Assert.Equal (expectedEquals, posAnchorEnd1.Equals (posAnchorEnd2)); + Assert.Equal (expectedEquals, posAnchorEnd2.Equals (posAnchorEnd1)); + } + + [Fact] + public void PosAnchorEnd_GetHashCode () + { + var posAnchorEnd = new PosAnchorEnd (10); + var expectedHashCode = 10.GetHashCode (); + + Assert.Equal (expectedHashCode, posAnchorEnd.GetHashCode ()); + } + + [Fact] + public void PosAnchorEnd_ToString () + { + var posAnchorEnd = new PosAnchorEnd (10); + var expectedString = "AnchorEnd(10)"; + + Assert.Equal (expectedString, posAnchorEnd.ToString ()); + } + + [Fact] + public void PosAnchorEnd_Anchor () + { + var posAnchorEnd = new PosAnchorEnd (10); + var width = 50; + var expectedAnchor = width - 10; + + Assert.Equal (expectedAnchor, posAnchorEnd.Anchor (width)); + } + + [Fact] + public void AnchorEnd_CreatesCorrectInstance () + { + var pos = Pos.AnchorEnd (10); + Assert.IsType (pos); + } + + [Fact] + public void AnchorEnd_Negative_Throws () + { + Pos pos; + int n = -1; + Assert.Throws (() => pos = Pos.AnchorEnd (n)); + } + + [Theory] + [InlineData (0)] + [InlineData (1)] + public void AnchorEnd_SetsValue_Anchor_Is_Negative (int offset) + { + Pos pos = Pos.AnchorEnd (offset); + Assert.Equal (offset, -pos.Anchor (0)); + } + + [Theory] + [InlineData (0, 0, 25)] + [InlineData (0, 10, 25)] + [InlineData (1, 10, 24)] + [InlineData (10, 10, 15)] + [InlineData (20, 10, 5)] + public void AnchorEnd_With_Offset_PositionsViewOffsetFromRight (int offset, int width, int expectedXPosition) + { + // Arrange + var superView = new View { Width = 25, Height = 25 }; + var view = new View + { + X = Pos.AnchorEnd (offset), + Width = width, + Height = 1 + }; + superView.Add (view); + superView.BeginInit (); + superView.EndInit (); + + // Act + superView.LayoutSubviews (); + + // Assert + Assert.Equal (expectedXPosition, view.Frame.X); + } + + // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests. + [Fact] + [SetupFakeDriver] + public void AnchorEnd_View_And_Button () + { + ((FakeDriver)Application.Driver).SetBufferSize (20, 5); + + var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}"; + + var frame = new FrameView { Width = 18, Height = 3 }; + Assert.Equal (16, frame.Viewport.Width); + + Button btn = null; + + int Btn_Width () { return btn?.Viewport.Width ?? 0; } + + btn = new () { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) }; + + var view = new View + { + Text = "0123456789abcdefghij", + + // Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15) + // Dim.Function (Btn_Width) is 6 + // Width should be 15 - 6 = 9 + Width = Dim.Fill (1) - Dim.Function (Btn_Width), + Height = 1 + }; + + frame.Add (btn, view); + frame.BeginInit (); + frame.EndInit (); + frame.Draw (); + + Assert.Equal (6, btn.Viewport.Width); + Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10 + Assert.Equal (0, btn.Frame.Y); + Assert.Equal (6, btn.Frame.Width); + Assert.Equal (1, btn.Frame.Height); + + Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9 + Assert.Equal (0, view.Frame.X); + Assert.Equal (0, view.Frame.Y); + Assert.Equal (9, view.Frame.Width); + Assert.Equal (1, view.Frame.Height); + + var expected = $@" +┌────────────────┐ +│012345678 {b}│ +└────────────────┘ +"; + _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + } + + // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved // TODO: A new test that calls SetRelativeLayout directly is needed. [Fact] @@ -81,79 +221,4 @@ public class AnchorEndTests (ITestOutputHelper output) Application.End (rs); } - [Fact] - public void AnchorEnd_Negative_Throws () - { - Pos pos; - int n = -1; - Assert.Throws (() => pos = Pos.AnchorEnd (n)); - } - - [Fact] - public void AnchorEnd_SetsValue () - { - var n = 0; - Pos pos = Pos.AnchorEnd (0); - Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); - - n = 5; - pos = Pos.AnchorEnd (n); - Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); - } - - // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests. - [Fact] - [SetupFakeDriver] - public void AnchorEnd_View_And_Button () - { - ((FakeDriver)Application.Driver).SetBufferSize (20, 5); - - var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}"; - - var frame = new FrameView { Width = 18, Height = 3 }; - Assert.Equal (16, frame.Viewport.Width); - - Button btn = null; - - int Btn_Width () { return btn?.Viewport.Width ?? 0; } - - btn = new() { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) }; - - var view = new View - { - Text = "0123456789abcdefghij", - - // Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15) - // Dim.Function (Btn_Width) is 6 - // Width should be 15 - 6 = 9 - Width = Dim.Fill (1) - Dim.Function (Btn_Width), - Height = 1 - }; - - frame.Add (btn, view); - frame.BeginInit (); - frame.EndInit (); - frame.Draw (); - - Assert.Equal (6, btn.Viewport.Width); - Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10 - Assert.Equal (0, btn.Frame.Y); - Assert.Equal (6, btn.Frame.Width); - Assert.Equal (1, btn.Frame.Height); - - Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9 - Assert.Equal (0, view.Frame.X); - Assert.Equal (0, view.Frame.Y); - Assert.Equal (9, view.Frame.Width); - Assert.Equal (1, view.Frame.Height); - - var expected = $@" -┌────────────────┐ -│012345678 { - b -}│ -└────────────────┘ -"; - _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - } } From 671a18f1b576f7923545e4fa4822cd2186bc4d4c Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 11:22:53 -0600 Subject: [PATCH 05/16] Added tests to test new fn; which isn't implemented yet, so they fail. --- UnitTests/View/Layout/AnchorEndTests.cs | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/UnitTests/View/Layout/AnchorEndTests.cs b/UnitTests/View/Layout/AnchorEndTests.cs index 1d88bd160..37449bd67 100644 --- a/UnitTests/View/Layout/AnchorEndTests.cs +++ b/UnitTests/View/Layout/AnchorEndTests.cs @@ -84,6 +84,8 @@ public class AnchorEndTests (ITestOutputHelper output) [InlineData (1, 10, 24)] [InlineData (10, 10, 15)] [InlineData (20, 10, 5)] + [InlineData (25, 10, 0)] + [InlineData (26, 10, -1)] public void AnchorEnd_With_Offset_PositionsViewOffsetFromRight (int offset, int width, int expectedXPosition) { // Arrange @@ -105,6 +107,34 @@ public class AnchorEndTests (ITestOutputHelper output) Assert.Equal (expectedXPosition, view.Frame.X); } + [Theory] + [InlineData (0, 25)] + [InlineData (10, 15)] + [InlineData (9, 16)] + [InlineData (11, 14)] + [InlineData (25, 0)] + [InlineData (26, -1)] + public void AnchorEnd_No_Offset_PositionsViewOffsetByWidth (int width, int expectedXPosition) + { + // Arrange + var superView = new View { Width = 25, Height = 25 }; + var view = new View + { + X = Pos.AnchorEnd (), + Width = width, + Height = 1 + }; + superView.Add (view); + superView.BeginInit (); + superView.EndInit (); + + // Act + superView.LayoutSubviews (); + + // Assert + Assert.Equal (expectedXPosition, view.Frame.X); + } + // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests. [Fact] [SetupFakeDriver] From 162aa081ada43f27c5990b5941a8a5634ea307cc Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 11:47:51 -0600 Subject: [PATCH 06/16] Implemented AnchorEnd(); added .UseDimForOffset property --- Terminal.Gui/View/Layout/PosDim.cs | 26 +++++++++++++++++++++---- Terminal.Gui/View/Layout/ViewLayout.cs | 15 ++++++++++++-- UnitTests/View/Layout/AnchorEndTests.cs | 21 ++++++++++++++++++-- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 9159ea9b9..2230ee970 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -139,8 +139,7 @@ public class Pos /// public static Pos AnchorEnd () { - throw new NotImplementedException (); - //return new PosAnchorEnd (0); + return new PosAnchorEnd (); } /// @@ -336,11 +335,30 @@ public class Pos internal class PosAnchorEnd : Pos { private readonly int _offset; + public PosAnchorEnd () { UseDimForOffset = true; } public PosAnchorEnd (int offset) { _offset = offset; } public override bool Equals (object other) { return other is PosAnchorEnd anchorEnd && anchorEnd._offset == _offset; } public override int GetHashCode () { return _offset.GetHashCode (); } - public override string ToString () { return $"AnchorEnd({_offset})"; } - internal override int Anchor (int width) { return width - _offset; } + + public bool UseDimForOffset { get; set; } + + public override string ToString () + { + if (UseDimForOffset) + { + return "AnchorEnd()"; + } + return $"AnchorEnd({_offset})"; + } + + internal override int Anchor (int width) + { + if (UseDimForOffset) + { + return width; + } + return width - _offset; + } } internal class PosCenter : Pos diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index f593d93d2..69a07f066 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -1109,7 +1109,6 @@ public partial class View GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0 ); - break; case Pos.PosCombine combine: @@ -1148,7 +1147,19 @@ public partial class View break; - case Pos.PosAnchorEnd: + case Pos.PosAnchorEnd anchorEnd: + newLocation = anchorEnd.Anchor (superviewDimension); + if (anchorEnd.UseDimForOffset) + { + newLocation -= dim.Anchor (0); + } + + newDimension = Math.Max ( + GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension), + 0 + ); + break; + case Pos.PosAbsolute: case Pos.PosFactor: case Pos.PosFunc: diff --git a/UnitTests/View/Layout/AnchorEndTests.cs b/UnitTests/View/Layout/AnchorEndTests.cs index 37449bd67..ec5dc5c16 100644 --- a/UnitTests/View/Layout/AnchorEndTests.cs +++ b/UnitTests/View/Layout/AnchorEndTests.cs @@ -107,6 +107,23 @@ public class AnchorEndTests (ITestOutputHelper output) Assert.Equal (expectedXPosition, view.Frame.X); } + // UseDimForOffset tests + + [Fact] + public void AnchorEnd_UseDimForOffset_CreatesCorrectInstance () + { + var pos = Pos.AnchorEnd (); + Assert.IsType (pos); + Assert.True (((PosAnchorEnd)pos).UseDimForOffset); + } + + [Fact] + public void AnchorEnd_UseDimForOffset_SetsValue_Anchor_Is_Negative () + { + Pos pos = Pos.AnchorEnd (); + Assert.Equal (-10, -pos.Anchor (10)); + } + [Theory] [InlineData (0, 25)] [InlineData (10, 15)] @@ -114,14 +131,14 @@ public class AnchorEndTests (ITestOutputHelper output) [InlineData (11, 14)] [InlineData (25, 0)] [InlineData (26, -1)] - public void AnchorEnd_No_Offset_PositionsViewOffsetByWidth (int width, int expectedXPosition) + public void AnchorEnd_UseDimForOffset_PositionsViewOffsetByDim (int dim, int expectedXPosition) { // Arrange var superView = new View { Width = 25, Height = 25 }; var view = new View { X = Pos.AnchorEnd (), - Width = width, + Width = dim, Height = 1 }; superView.Add (view); From d8bbbb8152beb7d9ec2def8927621e3ccf67ed35 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 11:50:49 -0600 Subject: [PATCH 07/16] Code cleanup --- Terminal.Gui/View/Layout/PosDim.cs | 111 +++++++++-------------------- 1 file changed, 33 insertions(+), 78 deletions(-) diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 2230ee970..97ebb7fc0 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -314,18 +314,15 @@ public class Pos private static void SetPosCombine (Pos left, PosCombine newPos) { - var view = left as PosView; - - if (view is { }) + if (left is PosView { } view) { view.Target.SetNeedsLayout (); } } - internal class PosAbsolute : Pos + internal class PosAbsolute (int n) : Pos { - private readonly int _n; - public PosAbsolute (int n) { _n = n; } + private readonly int _n = n; public override bool Equals (object other) { return other is PosAbsolute abs && abs._n == _n; } public override int GetHashCode () { return _n.GetHashCode (); } public override string ToString () { return $"Absolute({_n})"; } @@ -340,15 +337,14 @@ public class Pos public override bool Equals (object other) { return other is PosAnchorEnd anchorEnd && anchorEnd._offset == _offset; } public override int GetHashCode () { return _offset.GetHashCode (); } - public bool UseDimForOffset { get; set; } + /// + /// If true, the offset is the width of the view, if false, the offset is the offset value. + /// + internal bool UseDimForOffset { get; set; } public override string ToString () { - if (UseDimForOffset) - { - return "AnchorEnd()"; - } - return $"AnchorEnd({_offset})"; + return UseDimForOffset ? "AnchorEnd()" : $"AnchorEnd({_offset})"; } internal override int Anchor (int width) @@ -367,17 +363,10 @@ public class Pos internal override int Anchor (int width) { return width / 2; } } - internal class PosCombine : Pos + internal class PosCombine (bool add, Pos left, Pos right) : Pos { - internal bool _add; - internal Pos _left, _right; - - public PosCombine (bool add, Pos left, Pos right) - { - _left = left; - _right = right; - _add = add; - } + internal bool _add = add; + internal Pos _left = left, _right = right; public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; } @@ -395,10 +384,9 @@ public class Pos } } - internal class PosFactor : Pos + internal class PosFactor (float n) : Pos { - private readonly float _factor; - public PosFactor (float n) { _factor = n; } + private readonly float _factor = n; public override bool Equals (object other) { return other is PosFactor f && f._factor == _factor; } public override int GetHashCode () { return _factor.GetHashCode (); } public override string ToString () { return $"Factor({_factor})"; } @@ -406,27 +394,18 @@ public class Pos } // Helper class to provide dynamic value by the execution of a function that returns an integer. - internal class PosFunc : Pos + internal class PosFunc (Func n) : Pos { - private readonly Func _function; - public PosFunc (Func n) { _function = n; } + private readonly Func _function = n; public override bool Equals (object other) { return other is PosFunc f && f._function () == _function (); } public override int GetHashCode () { return _function.GetHashCode (); } public override string ToString () { return $"PosFunc({_function ()})"; } internal override int Anchor (int width) { return _function (); } } - internal class PosView : Pos + internal class PosView (View view, int side) : Pos { - public readonly View Target; - - private readonly int side; - - public PosView (View view, int side) - { - Target = view; - this.side = side; - } + public readonly View Target = view; public override bool Equals (object other) { return other is PosView abs && abs.Target == Target; } public override int GetHashCode () { return Target.GetHashCode (); } @@ -670,27 +649,19 @@ public class Dim // BUGBUG: newPos is never used. private static void SetDimCombine (Dim left, DimCombine newPos) { (left as DimView)?.Target.SetNeedsLayout (); } - internal class DimAbsolute : Dim + internal class DimAbsolute (int n) : Dim { - private readonly int _n; - public DimAbsolute (int n) { _n = n; } + private readonly int _n = n; public override bool Equals (object other) { return other is DimAbsolute abs && abs._n == _n; } public override int GetHashCode () { return _n.GetHashCode (); } public override string ToString () { return $"Absolute({_n})"; } internal override int Anchor (int width) { return _n; } } - internal class DimCombine : Dim + internal class DimCombine (bool add, Dim left, Dim right) : Dim { - internal bool _add; - internal Dim _left, _right; - - public DimCombine (bool add, Dim left, Dim right) - { - _left = left; - _right = right; - _add = add; - } + internal bool _add = add; + internal Dim _left = left, _right = right; public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; } @@ -708,16 +679,10 @@ public class Dim } } - internal class DimFactor : Dim + internal class DimFactor (float n, bool r = false) : Dim { - private readonly float _factor; - private readonly bool _remaining; - - public DimFactor (float n, bool r = false) - { - _factor = n; - _remaining = r; - } + private readonly float _factor = n; + private readonly bool _remaining = r; public override bool Equals (object other) { return other is DimFactor f && f._factor == _factor && f._remaining == _remaining; } public override int GetHashCode () { return _factor.GetHashCode (); } @@ -726,10 +691,9 @@ public class Dim internal override int Anchor (int width) { return (int)(width * _factor); } } - internal class DimFill : Dim + internal class DimFill (int margin) : Dim { - private readonly int _margin; - public DimFill (int margin) { _margin = margin; } + private readonly int _margin = margin; public override bool Equals (object other) { return other is DimFill fill && fill._margin == _margin; } public override int GetHashCode () { return _margin.GetHashCode (); } public override string ToString () { return $"Fill({_margin})"; } @@ -737,27 +701,18 @@ public class Dim } // Helper class to provide dynamic value by the execution of a function that returns an integer. - internal class DimFunc : Dim + internal class DimFunc (Func n) : Dim { - private readonly Func _function; - public DimFunc (Func n) { _function = n; } + private readonly Func _function = n; public override bool Equals (object other) { return other is DimFunc f && f._function () == _function (); } public override int GetHashCode () { return _function.GetHashCode (); } public override string ToString () { return $"DimFunc({_function ()})"; } internal override int Anchor (int width) { return _function (); } } - internal class DimView : Dim + internal class DimView (View view, int side) : Dim { - private readonly int _side; - - public DimView (View view, int side) - { - Target = view; - _side = side; - } - - public View Target { get; init; } + public View Target { get; init; } = view; public override bool Equals (object other) { return other is DimView abs && abs.Target == Target; } public override int GetHashCode () { return Target.GetHashCode (); } @@ -768,7 +723,7 @@ public class Dim throw new NullReferenceException (); } - string tside = _side switch + string tside = side switch { 0 => "Height", 1 => "Width", @@ -780,7 +735,7 @@ public class Dim internal override int Anchor (int width) { - return _side switch + return side switch { 0 => Target.Frame.Height, 1 => Target.Frame.Width, From 264ba87e73a46f007d2cacc08ce5fb574290119d Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 16 Apr 2024 14:00:38 -0600 Subject: [PATCH 08/16] AnchorEnd() works! Cleaned up usages and modernized Sceanrios --- Terminal.Gui/View/Layout/PosDim.cs | 15 ++- Terminal.Gui/View/Layout/ViewLayout.cs | 2 +- UICatalog/Scenarios/Adornments.cs | 17 +-- UICatalog/Scenarios/AllViewsTester.cs | 8 +- UICatalog/Scenarios/Animation.cs | 4 +- UICatalog/Scenarios/BasicColors.cs | 32 +++-- UICatalog/Scenarios/Buttons.cs | 4 +- UICatalog/Scenarios/ColorPicker.cs | 40 ++++--- UICatalog/Scenarios/ComputedLayout.cs | 89 +++++++------- UICatalog/Scenarios/ContentScrolling.cs | 17 +-- UICatalog/Scenarios/DynamicMenuBar.cs | 2 +- UICatalog/Scenarios/DynamicStatusBar.cs | 4 +- UICatalog/Scenarios/HotKeys.cs | 110 ++++++++--------- UICatalog/Scenarios/LineCanvasExperiment.cs | 28 ++--- .../Scenarios/TextAlignmentsAndDirection.cs | 58 +++++---- UICatalog/Scenarios/TrueColors.cs | 112 ++++++++++-------- UICatalog/Scenarios/ViewExperiments.cs | 32 ++--- UICatalog/Scenarios/WindowsAndFrameViews.cs | 79 ++++++------ UnitTests/View/Layout/AnchorEndTests.cs | 26 ++++ 19 files changed, 358 insertions(+), 321 deletions(-) diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 97ebb7fc0..bf98db91b 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -125,16 +125,16 @@ public class Pos { /// - /// Creates a object that has its end (right side or bottom) anchored to the end (right side or - /// bottom) - /// of the SuperView, useful to flush the layout from the right or bottom. + /// Creates a object that is anchored to the end (right side or + /// bottom) of the SuperView, minus the respective dimension of the View. This is equivalent to using , + /// with an offset equivalent to the View's respective dimension. /// - /// The object anchored to the end (the bottom or the right side). + /// The object anchored to the end (the bottom or the right side) minus the View's dimension. /// /// This sample shows how align a to the bottom-right the SuperView. /// - /// anchorButton.X = Pos.AnchorEnd (0); - /// anchorButton.Y = Pos.AnchorEnd (0); + /// anchorButton.X = Pos.AnchorEnd (); + /// anchorButton.Y = Pos.AnchorEnd (); /// /// public static Pos AnchorEnd () @@ -149,8 +149,7 @@ public class Pos /// The object anchored to the end (the bottom or the right side). /// The view will be shifted left or up by the amount specified. /// - /// This sample shows how align a such that its left side is offset 10 columns from - /// the right edge of the SuperView. + /// This sample shows how align a 10 column wide to the bottom-right the SuperView. /// /// anchorButton.X = Pos.AnchorEnd (10); /// anchorButton.Y = 1 diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 69a07f066..fe7ccebb0 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -1151,7 +1151,7 @@ public partial class View newLocation = anchorEnd.Anchor (superviewDimension); if (anchorEnd.UseDimForOffset) { - newLocation -= dim.Anchor (0); + newLocation -= dim.Anchor (superviewDimension); } newDimension = Math.Max ( diff --git a/UICatalog/Scenarios/Adornments.cs b/UICatalog/Scenarios/Adornments.cs index 27aefbddc..ab68fb961 100644 --- a/UICatalog/Scenarios/Adornments.cs +++ b/UICatalog/Scenarios/Adornments.cs @@ -38,7 +38,7 @@ public class Adornments : Scenario app.Add (window); var tf1 = new TextField { Width = 10, Text = "TextField" }; - var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11) }; + var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd () }; color.BorderStyle = LineStyle.RoundedDotted; color.ColorChanged += (s, e) => @@ -68,15 +68,16 @@ public class Adornments : Scenario }; label.Border.Thickness = new (1, 3, 1, 1); - var btnButtonInWindow = new Button { X = Pos.AnchorEnd (10), Y = Pos.AnchorEnd (1), Text = "Button" }; + var btnButtonInWindow = new Button { X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Button" }; - var tv = new Label + var labelAnchorEnd = new Label { AutoSize = false, - Y = Pos.AnchorEnd (3), - Width = 25, - Height = Dim.Fill (), - Text = "Label\nY=AnchorEnd(3),Height=Dim.Fill()" + Y = Pos.AnchorEnd (), + Width = 40, + Height = Dim.Percent(20), + Text = "Label\nY=AnchorEnd(),Height=Dim.Percent(10)", + ColorScheme = Colors.ColorSchemes ["Error"] }; window.Margin.Data = "Margin"; @@ -94,7 +95,7 @@ public class Adornments : Scenario }; longLabel.TextFormatter.WordWrap = true; - window.Add (tf1, color, button, label, btnButtonInWindow, tv, longLabel); + window.Add (tf1, color, button, label, btnButtonInWindow, labelAnchorEnd, longLabel); editor.Initialized += (s, e) => { editor.ViewToEdit = window; }; diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs index 22d6d11dc..b9b20377e 100644 --- a/UICatalog/Scenarios/AllViewsTester.cs +++ b/UICatalog/Scenarios/AllViewsTester.cs @@ -147,7 +147,7 @@ public class AllViewsTester : Scenario }; _settingsPane.Add (_computedCheckBox); - string [] radioItems = { "_Percent(x)", "_AnchorEnd(x)", "_Center", "A_t(x)" }; + string [] radioItems = { "_Percent(x)", "_AnchorEnd", "_Center", "A_t(x)" }; _locationFrame = new FrameView { @@ -179,7 +179,7 @@ public class AllViewsTester : Scenario _locationFrame.Add (_xRadioGroup); - radioItems = new [] { "P_ercent(y)", "A_nchorEnd(y)", "C_enter", "At(_y)" }; + radioItems = new [] { "P_ercent(y)", "A_nchorEnd", "C_enter", "At(_y)" }; label = new Label { X = Pos.Right (_xRadioGroup) + 1, Y = 0, Text = "Y:" }; _locationFrame.Add (label); _yText = new TextField { X = Pos.Right (label) + 1, Y = 0, Width = 4, Text = $"{_yVal}" }; @@ -388,7 +388,7 @@ public class AllViewsTester : Scenario view.X = _xRadioGroup.SelectedItem switch { 0 => Pos.Percent (_xVal), - 1 => Pos.AnchorEnd (_xVal), + 1 => Pos.AnchorEnd (), 2 => Pos.Center (), 3 => Pos.At (_xVal), _ => view.X @@ -397,7 +397,7 @@ public class AllViewsTester : Scenario view.Y = _yRadioGroup.SelectedItem switch { 0 => Pos.Percent (_yVal), - 1 => Pos.AnchorEnd (_yVal), + 1 => Pos.AnchorEnd (), 2 => Pos.Center (), 3 => Pos.At (_yVal), _ => view.Y diff --git a/UICatalog/Scenarios/Animation.cs b/UICatalog/Scenarios/Animation.cs index 80bebdec2..42ad540c1 100644 --- a/UICatalog/Scenarios/Animation.cs +++ b/UICatalog/Scenarios/Animation.cs @@ -34,12 +34,12 @@ public class Animation : Scenario win.Add (imageView); - var lbl = new Label { Y = Pos.AnchorEnd (2), Text = "Image by Wikiscient" }; + var lbl = new Label { Y = Pos.AnchorEnd (), Text = "Image by Wikiscient" }; win.Add (lbl); var lbl2 = new Label { - Y = Pos.AnchorEnd (1), Text = "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif" + X = Pos.AnchorEnd(), Y = Pos.AnchorEnd (), Text = "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif" }; win.Add (lbl2); diff --git a/UICatalog/Scenarios/BasicColors.cs b/UICatalog/Scenarios/BasicColors.cs index 9fc6fead5..e12e51284 100644 --- a/UICatalog/Scenarios/BasicColors.cs +++ b/UICatalog/Scenarios/BasicColors.cs @@ -8,8 +8,15 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Text and Formatting")] public class BasicColors : Scenario { - public override void Setup () + public override void Main () { + Application.Init (); + + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + }; + var vx = 30; var x = 30; var y = 14; @@ -31,7 +38,7 @@ public class BasicColors : Scenario Text = bg.ToString (), TextDirection = TextDirection.TopBottom_LeftRight }; - Win.Add (vl); + app.Add (vl); var hl = new Label { @@ -44,7 +51,7 @@ public class BasicColors : Scenario ColorScheme = new ColorScheme { Normal = attr }, Text = bg.ToString () }; - Win.Add (hl); + app.Add (hl); vx++; foreach (ColorName fg in colors) @@ -56,7 +63,7 @@ public class BasicColors : Scenario { ColorScheme = new ColorScheme { Normal = c }, X = x, Y = y, Text = t [^1].ToString () }; - Win.Add (l); + app.Add (l); x++; } @@ -64,24 +71,24 @@ public class BasicColors : Scenario y++; } - Win.Add ( + app.Add ( new Label { X = Pos.AnchorEnd (36), Text = "Mouse over to get the Attribute:" } ); - Win.Add (new Label { X = Pos.AnchorEnd (35), Y = 2, Text = "Foreground:" }); + app.Add (new Label { X = Pos.AnchorEnd (35), Y = 2, Text = "Foreground:" }); var lblForeground = new Label { X = Pos.AnchorEnd (23), Y = 2 }; - Win.Add (lblForeground); + app.Add (lblForeground); var viewForeground = new View { X = Pos.AnchorEnd (2), Y = 2, ColorScheme = new ColorScheme (), Text = " " }; - Win.Add (viewForeground); + app.Add (viewForeground); - Win.Add (new Label { X = Pos.AnchorEnd (35), Y = 4, Text = "Background:" }); + app.Add (new Label { X = Pos.AnchorEnd (35), Y = 4, Text = "Background:" }); var lblBackground = new Label { X = Pos.AnchorEnd (23), Y = 4 }; - Win.Add (lblBackground); + app.Add (lblBackground); var viewBackground = new View { X = Pos.AnchorEnd (2), Y = 4, ColorScheme = new ColorScheme (), Text = " " }; - Win.Add (viewBackground); + app.Add (viewBackground); Application.MouseEvent += (s, e) => { @@ -103,5 +110,8 @@ public class BasicColors : Scenario new ColorScheme (viewBackground.ColorScheme) { Normal = new Attribute (back, back) }; } }; + + Application.Run (app); + app.Dispose (); } } diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index f405e063c..33590a7e0 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -29,7 +29,7 @@ public class Buttons : Scenario // This is the default button (IsDefault = true); if user presses ENTER in the TextField // the scenario will quit - var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), IsDefault = true, Text = "_Quit" }; + var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), IsDefault = true, Text = "_Quit" }; defaultButton.Accept += (s, e) => Application.RequestStop (); main.Add (defaultButton); @@ -459,7 +459,7 @@ public class Buttons : Scenario _up = new () { AutoSize = false, - X = Pos.AnchorEnd (1), + X = Pos.AnchorEnd (), Y = Pos.Top (_number), Height = 1, Width = 1, diff --git a/UICatalog/Scenarios/ColorPicker.cs b/UICatalog/Scenarios/ColorPicker.cs index bc426e4e2..fe2b08fad 100644 --- a/UICatalog/Scenarios/ColorPicker.cs +++ b/UICatalog/Scenarios/ColorPicker.cs @@ -24,42 +24,45 @@ public class ColorPickers : Scenario private ColorPicker foregroundColorPicker; /// Setup the scenario. - public override void Setup () + public override void Main () { - // Scenario Window's. - Win.Title = GetName (); + Application.Init (); + + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + }; // Foreground ColorPicker. foregroundColorPicker = new ColorPicker { Title = "Foreground Color", BorderStyle = LineStyle.Single }; foregroundColorPicker.ColorChanged += ForegroundColor_ColorChanged; - Win.Add (foregroundColorPicker); + app.Add (foregroundColorPicker); _foregroundColorLabel = new Label { X = Pos.Left (foregroundColorPicker), Y = Pos.Bottom (foregroundColorPicker) + 1 }; - Win.Add (_foregroundColorLabel); + app.Add (_foregroundColorLabel); // Background ColorPicker. backgroundColorPicker = new ColorPicker { Title = "Background Color", - // TODO: Replace with Pos.AnchorEnd (0) when #2900 is done - X = Pos.AnchorEnd ((8 * 4) + 2), // 8 box * 4 width + 2 for border + X = Pos.AnchorEnd (), BoxHeight = 1, BoxWidth = 4, - BorderStyle = LineStyle.Single + BorderStyle = LineStyle.Single, }; - //backgroundColorPicker.X = Pos.AnchorEnd (0) - (Pos.Right (backgroundColorPicker) - Pos.Left (backgroundColorPicker)); backgroundColorPicker.ColorChanged += BackgroundColor_ColorChanged; - Win.Add (backgroundColorPicker); - _backgroundColorLabel = new Label (); + app.Add (backgroundColorPicker); + _backgroundColorLabel = new Label () + { + X = Pos.AnchorEnd (), + Y = Pos.Bottom (backgroundColorPicker) + 1 + }; - _backgroundColorLabel.X = - Pos.AnchorEnd (0) - (Pos.Right (_backgroundColorLabel) - Pos.Left (_backgroundColorLabel)); - _backgroundColorLabel.Y = Pos.Bottom (backgroundColorPicker) + 1; - Win.Add (_backgroundColorLabel); + app.Add (_backgroundColorLabel); // Demo Label. _demoView = new View @@ -74,12 +77,15 @@ public class ColorPickers : Scenario Height = 5, Width = 20 }; - Win.Add (_demoView); + app.Add (_demoView); // Set default colors. foregroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Foreground.GetClosestNamedColor (); backgroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Background.GetClosestNamedColor (); - Win.Initialized += (s, e) => Win.LayoutSubviews (); + app.Initialized += (s, e) => app.LayoutSubviews (); + + Application.Run (app); + app.Dispose (); } /// Fired when background color is changed. diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs index 65904cdf9..c8013c46a 100644 --- a/UICatalog/Scenarios/ComputedLayout.cs +++ b/UICatalog/Scenarios/ComputedLayout.cs @@ -13,17 +13,15 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Layout")] public class ComputedLayout : Scenario { - public override void Init () + public override void Main () { Application.Init (); - ConfigurationManager.Themes.Theme = Theme; - ConfigurationManager.Apply (); - Top = new (); - Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - } - public override void Setup () - { + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + }; + // Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width const string rule = "|123456789"; @@ -38,7 +36,7 @@ public class ComputedLayout : Scenario Text = rule }; - Top.Add (horizontalRuler); + app.Add (horizontalRuler); // Demonstrate using Dim to create a vertical ruler that always measures the parent window's height const string vrule = "|\n1\n2\n3\n4\n5\n6\n7\n8\n9\n"; @@ -54,7 +52,7 @@ public class ComputedLayout : Scenario Text = vrule }; - Top.LayoutComplete += (s, a) => + app.LayoutComplete += (s, a) => { horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling (horizontalRuler.Viewport.Width / (double)rule.Length)) [ @@ -65,15 +63,15 @@ public class ComputedLayout : Scenario [..(verticalRuler.Viewport.Height * 2)]; }; - Top.Add (verticalRuler); + app.Add (verticalRuler); // Demonstrate At - Using Pos.At to locate a view in an absolute location var atButton = new Button { Text = "At(2,1)", X = Pos.At (2), Y = Pos.At (1) }; - Top.Add (atButton); + app.Add (atButton); // Throw in a literal absolute - Should function identically to above var absoluteButton = new Button { Text = "X = 30, Y = 1", X = 30, Y = 1 }; - Top.Add (absoluteButton); + app.Add (absoluteButton); // Demonstrate using Dim to create a window that fills the parent with a margin var margin = 10; @@ -84,7 +82,7 @@ public class ComputedLayout : Scenario subWin.Title = $"{subWin.GetType ().Name} {{X={subWin.X},Y={subWin.Y},Width={subWin.Width},Height={subWin.Height}}}"; }; - Top.Add (subWin); + app.Add (subWin); var i = 1; var txt = "Resize the terminal to see computed layout in action."; @@ -209,7 +207,7 @@ public class ComputedLayout : Scenario } ); frameView.Add (labelList.ToArray ()); - Top.Add (frameView); + app.Add (frameView); frameView = new FrameView { @@ -223,7 +221,7 @@ public class ComputedLayout : Scenario fv.Title = $"{frameView.GetType ().Name} {{X={fv.X},Y={fv.Y},Width={fv.Width},Height={fv.Height}}}"; }; - Top.Add (frameView); + app.Add (frameView); // Demonstrate Dim & Pos using percentages - a TextField that is 30% height and 80% wide var textView = new TextView @@ -237,7 +235,7 @@ public class ComputedLayout : Scenario textView.Text = "This TextView should horizontally & vertically centered and \n10% of the screeen height, and 80% of its width."; - Top.Add (textView); + app.Add (textView); var oddballButton = new Button { @@ -245,7 +243,7 @@ public class ComputedLayout : Scenario X = Pos.Center (), Y = Pos.Bottom (textView) + 1 }; - Top.Add (oddballButton); + app.Add (oddballButton); #region Issue2358 @@ -253,19 +251,19 @@ public class ComputedLayout : Scenario // Until https://github.com/gui-cs/Terminal.Gui/issues/2358 is fixed these won't work right oddballButton = new Button { Text = "Center + 0", X = Pos.Center () + 0, Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); oddballButton = new Button { Text = "Center + 1", X = Pos.Center () + 1, Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); oddballButton = new Button { Text = "0 + Center", X = 0 + Pos.Center (), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); oddballButton = new Button { Text = "1 + Center", X = 1 + Pos.Center (), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); oddballButton = new Button { Text = "Center - 1", X = Pos.Center () - 1, Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.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 @@ -275,7 +273,7 @@ public class ComputedLayout : Scenario X = Pos.Center () + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.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 @@ -285,7 +283,7 @@ public class ComputedLayout : Scenario X = Pos.Percent (50) + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.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 @@ -295,7 +293,7 @@ public class ComputedLayout : Scenario X = Pos.Center () + Pos.Percent (50) - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); #endregion @@ -306,29 +304,29 @@ public class ComputedLayout : Scenario X = Pos.Center () + Pos.Center () - Pos.Percent (50), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); // This demonstrates combining Percents) oddballButton = new Button { Text = "Percent(40) + Percent(10)", X = Pos.Percent (40) + Pos.Percent (10), Y = Pos.Bottom (oddballButton) }; - Top.Add (oddballButton); + app.Add (oddballButton); // Demonstrate AnchorEnd - Button is anchored to bottom/right - var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd (0) - 1 }; - anchorButton.X = Pos.AnchorEnd (0) - (Pos.Right (anchorButton) - Pos.Left (anchorButton)); + var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd ()}; + anchorButton.X = Pos.AnchorEnd (); anchorButton.Accept += (s, e) => { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Top.LayoutSubviews causes the Computed layout to + // The call to app.LayoutSubviews causes the Computed layout to // get updated. anchorButton.Text += "!"; - Top.LayoutSubviews (); + app.LayoutSubviews (); }; - Top.Add (anchorButton); + app.Add (anchorButton); // Demonstrate AnchorEnd(n) // This is intentionally convoluted to illustrate potential bugs. @@ -342,7 +340,7 @@ public class ComputedLayout : Scenario X = 5, Y = Pos.AnchorEnd (2) }; - Top.Add (anchorEndLabel1); + app.Add (anchorEndLabel1); // Demonstrate DimCombine (via AnchorEnd(n) - 1) // This is intentionally convoluted to illustrate potential bugs. @@ -357,7 +355,7 @@ public class ComputedLayout : Scenario X = 5, Y = Pos.AnchorEnd (2) - 1 // Pos.Combine }; - Top.Add (anchorEndLabel2); + app.Add (anchorEndLabel2); // Show positioning vertically using Pos.AnchorEnd via Pos.Combine var leftButton = new Button @@ -369,10 +367,10 @@ public class ComputedLayout : Scenario { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Top.LayoutSubviews causes the Computed layout to + // The call to app.LayoutSubviews causes the Computed layout to // get updated. leftButton.Text += "!"; - Top.LayoutSubviews (); + app.LayoutSubviews (); }; // show positioning vertically using Pos.AnchorEnd @@ -385,10 +383,10 @@ public class ComputedLayout : Scenario { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Top.LayoutSubviews causes the Computed layout to + // The call to app.LayoutSubviews causes the Computed layout to // get updated. centerButton.Text += "!"; - Top.LayoutSubviews (); + app.LayoutSubviews (); }; // show positioning vertically using another window and Pos.Bottom @@ -398,18 +396,21 @@ public class ComputedLayout : Scenario { // This demonstrates how to have a dynamically sized button // Each time the button is clicked the button's text gets longer - // The call to Top.LayoutSubviews causes the Computed layout to + // The call to app.LayoutSubviews causes the Computed layout to // get updated. rightButton.Text += "!"; - Top.LayoutSubviews (); + app.LayoutSubviews (); }; // Center three buttons with 5 spaces between them leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5; rightButton.X = Pos.Right (centerButton) + 5; - Top.Add (leftButton); - Top.Add (centerButton); - Top.Add (rightButton); + app.Add (leftButton); + app.Add (centerButton); + app.Add (rightButton); + + Application.Run (app); + app.Dispose (); } } diff --git a/UICatalog/Scenarios/ContentScrolling.cs b/UICatalog/Scenarios/ContentScrolling.cs index 67f61d3c8..d8f81f2a8 100644 --- a/UICatalog/Scenarios/ContentScrolling.cs +++ b/UICatalog/Scenarios/ContentScrolling.cs @@ -319,7 +319,7 @@ public class ContentScrolling : Scenario // Add demo views to show that things work correctly var textField = new TextField { X = 20, Y = 7, Width = 15, Text = "Test TextField" }; - var colorPicker = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11), Y = 10 }; + var colorPicker = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (), Y = 10 }; colorPicker.BorderStyle = LineStyle.RoundedDotted; colorPicker.ColorChanged += (s, e) => @@ -356,18 +356,9 @@ public class ContentScrolling : Scenario charMap.Accept += (s, e) => MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No"); - var buttonAnchoredRight = new Button + var buttonAnchored = new Button { - X = Pos.AnchorEnd (10), Y = 0, Text = "Button" - }; - - var labelAnchoredBottomLeft = new Label - { - AutoSize = false, - Y = Pos.AnchorEnd (3), - Width = 25, - Height = Dim.Fill (), - Text = "Label\nY=AnchorEnd(3),Height=Dim.Fill()" + X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Bottom Right" }; view.Margin.Data = "Margin"; @@ -378,7 +369,7 @@ public class ContentScrolling : Scenario view.Padding.Data = "Padding"; - view.Add (buttonAnchoredRight, textField, colorPicker, charMap, textView, labelAnchoredBottomLeft); + view.Add (buttonAnchored, textField, colorPicker, charMap, textView); var longLabel = new Label { diff --git a/UICatalog/Scenarios/DynamicMenuBar.cs b/UICatalog/Scenarios/DynamicMenuBar.cs index f6ec1616e..650e854db 100644 --- a/UICatalog/Scenarios/DynamicMenuBar.cs +++ b/UICatalog/Scenarios/DynamicMenuBar.cs @@ -614,7 +614,7 @@ public class DynamicMenuBar : Scenario _frmMenu.Add (_btnPrevious); var _btnAdd = new Button { Y = Pos.Top (_btnPrevious) + 2, Text = " Add " }; - _btnAdd.X = Pos.AnchorEnd (0) - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); + _btnAdd.X = Pos.AnchorEnd (); _frmMenu.Add (_btnAdd); var _btnNext = new Button { X = Pos.X (_btnAdd), Y = Pos.Top (_btnPrevious), Text = ">" }; diff --git a/UICatalog/Scenarios/DynamicStatusBar.cs b/UICatalog/Scenarios/DynamicStatusBar.cs index f7934024a..316e3d263 100644 --- a/UICatalog/Scenarios/DynamicStatusBar.cs +++ b/UICatalog/Scenarios/DynamicStatusBar.cs @@ -371,11 +371,11 @@ public class DynamicStatusBar : Scenario var _btnRemoveStatusBar = new Button { Y = 1, Text = "Remove a StatusBar" }; - _btnRemoveStatusBar.X = Pos.AnchorEnd (0) - (Pos.Right (_btnRemoveStatusBar) - Pos.Left (_btnRemoveStatusBar)); + _btnRemoveStatusBar.X = Pos.AnchorEnd (); _frmStatusBar.Add (_btnRemoveStatusBar); var _btnAdd = new Button { Y = Pos.Top (_btnRemoveStatusBar) + 2, Text = " Add " }; - _btnAdd.X = Pos.AnchorEnd (0) - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd)); + _btnAdd.X = Pos.AnchorEnd (0); _frmStatusBar.Add (_btnAdd); _lstItems = new ListView diff --git a/UICatalog/Scenarios/HotKeys.cs b/UICatalog/Scenarios/HotKeys.cs index 8201a140f..5b9507374 100644 --- a/UICatalog/Scenarios/HotKeys.cs +++ b/UICatalog/Scenarios/HotKeys.cs @@ -4,108 +4,102 @@ namespace UICatalog.Scenarios; [ScenarioMetadata ("HotKeys", "Demonstrates how HotKeys work.")] [ScenarioCategory ("Controls")] -[ScenarioCategory("Mouse and Keyboard")] +[ScenarioCategory ("Mouse and Keyboard")] public class HotKeys : Scenario { - public override void Init () + public override void Main () { Application.Init (); - ConfigurationManager.Themes.Theme = Theme; - ConfigurationManager.Apply (); - Top = new (); - Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]; - Top.BorderStyle = LineStyle.RoundedDotted; - Top.Title = $"{Application.QuitKey} to _Quit - Scenario: {GetName ()}"; - } - public override void Run () - { + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" + }; + var textViewLabel = new Label { Text = "_TextView:", X = 0, Y = 0 }; - Top.Add (textViewLabel); - - var textField = new TextField (){ X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 }; - Top.Add (textField); + app.Add (textViewLabel); + + var textField = new TextField { X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 }; + app.Add (textField); var viewLabel = new Label { Text = "_View:", X = 0, Y = Pos.Bottom (textField) + 1 }; - Top.Add (viewLabel); + app.Add (viewLabel); - var view = new View () { - Title = "View (_focusable)", - Text = "Text renders _Underscore", + var view = new View + { + Title = "View (_focusable)", + Text = "Text renders _Underscore", CanFocus = true, X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (view); + app.Add (view); - viewLabel = new Label { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 }; - Top.Add (viewLabel); + viewLabel = new() { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 }; + app.Add (viewLabel); - view = new View () + view = new() { Title = "View (n_ot focusable)", Text = "Text renders _Underscore", X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (view); + app.Add (view); var labelWithFrameLabel = new Label { Text = "_Label with Frame:", X = 0, Y = Pos.Bottom (view) + 1 }; - Top.Add (labelWithFrameLabel); + app.Add (labelWithFrameLabel); - var labelWithFrameFocusable = new Label () + var labelWithFrameFocusable = new Label { AutoSize = false, Title = "Label _with Frame (focusable)", CanFocus = true, X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (labelWithFrameFocusable); + app.Add (labelWithFrameFocusable); - labelWithFrameLabel = new Label { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 }; - Top.Add (labelWithFrameLabel); + labelWithFrameLabel = new() { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 }; + app.Add (labelWithFrameLabel); - var labelWithFrame = new Label () + var labelWithFrame = new Label { AutoSize = false, Title = "Label with Frame (_not focusable)", X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (labelWithFrame); + app.Add (labelWithFrame); - var buttonWithFrameLabel = new Label { Text = "_Button with Frame:", X = 0, Y = Pos.Bottom (labelWithFrame) + 1 }; - Top.Add (buttonWithFrameLabel); + app.Add (buttonWithFrameLabel); - var buttonWithFrameFocusable = new Button () + var buttonWithFrameFocusable = new Button { AutoSize = false, Title = "B_utton with Frame (focusable)", CanFocus = true, X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (buttonWithFrameFocusable); + app.Add (buttonWithFrameFocusable); - buttonWithFrameLabel = new Label { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 }; - Top.Add (buttonWithFrameLabel); + buttonWithFrameLabel = new() { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 }; + app.Add (buttonWithFrameLabel); - var buttonWithFrame = new Button () + var buttonWithFrame = new Button { AutoSize = false, Title = "Button with Frame (not focusab_le)", X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3, CanFocus = false, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (buttonWithFrame); - - + app.Add (buttonWithFrame); var checkboxWithFrameLabel = new Label { Text = "_Checkbox with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrame) + 1 }; - Top.Add (checkboxWithFrameLabel); + app.Add (checkboxWithFrameLabel); var checkboxWithFrameFocusable = new CheckBox { @@ -113,12 +107,12 @@ public class HotKeys : Scenario Title = "C_heckbox with Frame (focusable)", CanFocus = true, X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (checkboxWithFrameFocusable); + app.Add (checkboxWithFrameFocusable); - checkboxWithFrameLabel = new Label { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 }; - Top.Add (checkboxWithFrameLabel); + checkboxWithFrameLabel = new() { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 }; + app.Add (checkboxWithFrameLabel); var checkboxWithFrame = new CheckBox { @@ -126,14 +120,14 @@ public class HotKeys : Scenario Title = "Checkbox with Frame (not focusable)", X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3, CanFocus = false, - BorderStyle = LineStyle.Dashed, + BorderStyle = LineStyle.Dashed }; - Top.Add (checkboxWithFrame); + app.Add (checkboxWithFrame); + var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), Text = "_Press me!" }; + app.Add (button); - var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), Text = "_Press me!" }; - Top.Add (button); - - Application.Run (Top); + Application.Run (app); + app.Dispose (); } } diff --git a/UICatalog/Scenarios/LineCanvasExperiment.cs b/UICatalog/Scenarios/LineCanvasExperiment.cs index 651d82f56..d015cd23e 100644 --- a/UICatalog/Scenarios/LineCanvasExperiment.cs +++ b/UICatalog/Scenarios/LineCanvasExperiment.cs @@ -8,21 +8,14 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Proof of Concept")] public class LineCanvasExperiment : Scenario { - public override void Init () + public override void Main () { Application.Init (); - Top = new (); - } - /// Setup the scenario. - public override void Setup () - { - //var menu = new MenuBar (new MenuBarItem [] { - //new MenuBarItem ("_File", new MenuItem [] { - // new MenuItem ("_Quit", "", () => Application.RequestStop()), - //}) }); - - //Top.Add (menu); + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" + }; var frame1 = new FrameView { @@ -37,7 +30,7 @@ public class LineCanvasExperiment : Scenario //View.Diagnostics ^= DiagnosticFlags.FrameRuler; - Top.Add (frame1); + app.Add (frame1); var win1 = new Window { @@ -52,7 +45,7 @@ public class LineCanvasExperiment : Scenario BorderStyle = LineStyle.Heavy, SuperViewRendersLineCanvas = true }; - win1.Padding.Thickness = new Thickness (1); + win1.Padding.Thickness = new (1); frame1.Add (win1); @@ -140,9 +133,12 @@ public class LineCanvasExperiment : Scenario SuperViewRendersLineCanvas = true }; marginWindow.Margin.ColorScheme = Colors.ColorSchemes ["Dialog"]; - marginWindow.Margin.Thickness = new Thickness (1); - marginWindow.Border.Thickness = new Thickness (1, 2, 1, 1); + marginWindow.Margin.Thickness = new (1); + marginWindow.Border.Thickness = new (1, 2, 1, 1); frame1.Add (marginWindow); + + Application.Run (app); + app.Dispose (); } } diff --git a/UICatalog/Scenarios/TextAlignmentsAndDirection.cs b/UICatalog/Scenarios/TextAlignmentsAndDirection.cs index 2abe35177..52c7c5b5e 100644 --- a/UICatalog/Scenarios/TextAlignmentsAndDirection.cs +++ b/UICatalog/Scenarios/TextAlignmentsAndDirection.cs @@ -10,14 +10,21 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Text and Formatting")] public class TextAlignmentsAndDirections : Scenario { - public override void Setup () + public override void Main () { + Application.Init (); + + Window app = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" + }; + // string txt = ".\n...\n.....\nHELLO\n.....\n...\n."; // string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘"; var txt = "HELLO WORLD"; - var color1 = new ColorScheme { Normal = new Attribute (Color.Black, Color.Gray) }; - var color2 = new ColorScheme { Normal = new Attribute (Color.Black, Color.DarkGray) }; + var color1 = new ColorScheme { Normal = new (Color.Black, Color.Gray) }; + var color2 = new ColorScheme { Normal = new (Color.Black, Color.DarkGray) }; List