diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 11af7dd2cd..0ae10e4677 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,8 +43,10 @@ jobs: - name: Build Release run: | dotnet-gitversion /updateprojectfiles - dotnet build --no-restore -c Release - + Import-Module ./Scripts/Terminal.Gui.PowerShell.psd1 + Build-Analyzers + dotnet build -c Release + Remove-Module Terminal.Gui.PowerShell - name: Pack run: dotnet pack -c Release --include-symbols -p:Version='${{ steps.gitversion.outputs.SemVer }}' diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index e0ab6fff61..c059a652f9 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -833,7 +833,7 @@ bool IsButtonClickedOrDoubleClicked (MouseFlags flag) /// private static Attribute MakeColor (short foreground, short background) { - var v = (short)(foreground | (background << 4)); + var v = (short)((ushort)foreground | (background << 4)); // TODO: for TrueColor - Use InitExtendedPair Curses.InitColorPair (v, foreground, background); diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 896487ac30..21991f4485 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -2344,11 +2344,9 @@ private void CheckWinChange () internal class WindowsClipboard : ClipboardBase { - private const uint _cfUnicodeText = 13; + private const uint CF_UNICODE_TEXT = 13; - public WindowsClipboard () { IsSupported = IsClipboardFormatAvailable (_cfUnicodeText); } - - public override bool IsSupported { get; } + public override bool IsSupported { get; } = IsClipboardFormatAvailable (CF_UNICODE_TEXT); protected override string GetClipboardDataImpl () { @@ -2359,7 +2357,7 @@ protected override string GetClipboardDataImpl () return string.Empty; } - nint handle = GetClipboardData (_cfUnicodeText); + nint handle = GetClipboardData (CF_UNICODE_TEXT); if (handle == nint.Zero) { @@ -2431,7 +2429,7 @@ protected override void SetClipboardDataImpl (string text) GlobalUnlock (target); } - if (SetClipboardData (_cfUnicodeText, hGlobal) == default (nint)) + if (SetClipboardData (CF_UNICODE_TEXT, hGlobal) == default (nint)) { ThrowWin32 (); } diff --git a/Terminal.Gui/Drawing/Justification.cs b/Terminal.Gui/Drawing/Justification.cs index 16c76c372c..f1fba56a83 100644 --- a/Terminal.Gui/Drawing/Justification.cs +++ b/Terminal.Gui/Drawing/Justification.cs @@ -96,7 +96,7 @@ public class Justifier public int ContainerSize { get; set; } /// - /// Gets or sets whether puts a space is placed between items. Default is . If , a space will be + /// Gets or sets whether puts a space is placed between items. Default is . If , a space will be /// placed between each item, which is useful for justifying text. /// public bool PutSpaceBetweenItems { get; set; } @@ -118,6 +118,7 @@ public int [] Justify (int [] sizes) /// /// The sizes of the items to justify. /// The justification style. + /// /// The size of the container. /// The locations of the items, from left to right. public static int [] Justify (Justification justification, bool putSpaceBetweenItems, int containerSize, int [] sizes) diff --git a/Terminal.Gui/Text/TextFormatter.cs b/Terminal.Gui/Text/TextFormatter.cs index 5d60ba89ad..925f89a389 100644 --- a/Terminal.Gui/Text/TextFormatter.cs +++ b/Terminal.Gui/Text/TextFormatter.cs @@ -662,7 +662,7 @@ public Size FormatAndGetSize () /// /// /// If the text needs to be formatted (if is ) - /// will be called and upon return + /// will be called and upon return /// will be . /// /// diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 4178e63ef6..5a03664520 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -670,9 +670,10 @@ public virtual void LayoutSubviews () CheckDimAuto (); - LayoutAdornments (); + var contentSize = ContentSize.GetValueOrDefault (); + OnLayoutStarted (new (contentSize)); - OnLayoutStarted (new (ContentSize.GetValueOrDefault ())); + LayoutAdornments (); SetTextFormatterSize (); @@ -684,7 +685,7 @@ public virtual void LayoutSubviews () foreach (View v in ordered) { - LayoutSubview (v, Viewport.Size); + LayoutSubview (v, contentSize); } // If the 'to' is rooted to 'from' it's a special-case. @@ -699,7 +700,7 @@ public virtual void LayoutSubviews () LayoutNeeded = false; - OnLayoutComplete (new (ContentSize.GetValueOrDefault ())); + OnLayoutComplete (new (contentSize)); } private void LayoutSubview (View v, Size contentSize) diff --git a/Terminal.sln.DotSettings b/Terminal.sln.DotSettings index 3bc1fab5d4..ca15b55838 100644 --- a/Terminal.sln.DotSettings +++ b/Terminal.sln.DotSettings @@ -387,6 +387,7 @@ <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> diff --git a/UnitTests/View/FindDeepestViewTests.cs b/UnitTests/View/FindDeepestViewTests.cs index 8f99e095cc..67687702d9 100644 --- a/UnitTests/View/FindDeepestViewTests.cs +++ b/UnitTests/View/FindDeepestViewTests.cs @@ -8,7 +8,7 @@ namespace Terminal.Gui.ViewTests; /// Tests View.FindDeepestView /// /// -public class FindDeepestViewTests (ITestOutputHelper output) +public class FindDeepestViewTests () { [Theory] [InlineData (0, 0, 0, 0, 0, -1, -1, null)] @@ -249,7 +249,6 @@ public void Returns_Null_If_Not_Visible_And_SubView_Visible (int testX, int test [InlineData (2, 3, true)] [InlineData (5, 6, true)] - [InlineData (2, 3, true)] [InlineData (6, 7, true)] public void Returns_Correct_If_Start_Has_Adornments (int testX, int testY, bool expectedSubViewFound) { @@ -303,15 +302,14 @@ public void Returns_Correct_If_Start_Has_Offset_Viewport (int offset, int testX, } [Theory] + [InlineData (9, 9, true)] [InlineData (0, 0, false)] [InlineData (1, 1, false)] - [InlineData (9, 9, true)] [InlineData (10, 10, false)] [InlineData (7, 8, false)] [InlineData (1, 2, false)] [InlineData (2, 3, false)] [InlineData (5, 6, false)] - [InlineData (2, 3, false)] [InlineData (6, 7, false)] public void Returns_Correct_If_Start_Has_Adornment_WithSubview (int testX, int testY, bool expectedSubViewFound) { @@ -365,7 +363,7 @@ public void Returns_Adornment_If_Start_Has_Adornments (int testX, int testY, Typ start.Add (subview); var found = View.FindDeepestView (start, testX, testY); - Assert.Equal (expectedAdornmentType, found.GetType ()); + Assert.Equal (expectedAdornmentType, found!.GetType ()); } // Test that FindDeepestView works if the subview has positive Adornments @@ -379,7 +377,6 @@ public void Returns_Adornment_If_Start_Has_Adornments (int testX, int testY, Typ [InlineData (1, 2, false)] [InlineData (5, 6, false)] - [InlineData (2, 3, true)] [InlineData (2, 3, true)] public void Returns_Correct_If_SubView_Has_Adornments (int testX, int testY, bool expectedSubViewFound) { @@ -533,6 +530,6 @@ public void Returns_Correct_With_NestedSubViews (int testX, int testY, int expec start.Add (subviews [0]); var found = View.FindDeepestView (start, testX, testY); - Assert.Equal (expectedSubViewFound, subviews.IndexOf (found)); + Assert.Equal (expectedSubViewFound, subviews.IndexOf (found!)); } } diff --git a/UnitTests/View/Layout/LayoutTests.cs b/UnitTests/View/Layout/LayoutTests.cs index 94267b4081..2f00865a09 100644 --- a/UnitTests/View/Layout/LayoutTests.cs +++ b/UnitTests/View/Layout/LayoutTests.cs @@ -115,66 +115,65 @@ public void TopologicalSort_Recursive_Ref () sub2.Dispose (); } - //[Fact] - //[AutoInitShutdown] - //public void TrySetHeight_ForceValidatePosDim () - //{ - // var top = new View { X = 0, Y = 0, Height = 20 }; - - // var v = new View { Height = Dim.Fill (), ValidatePosDim = true }; - // top.Add (v); - - // Assert.False (v.TrySetHeight (10, out int rHeight)); - // Assert.Equal (10, rHeight); - - // v.Height = Dim.Fill (1); - // Assert.False (v.TrySetHeight (10, out rHeight)); - // Assert.Equal (9, rHeight); - - // v.Height = 0; - // Assert.True (v.TrySetHeight (10, out rHeight)); - // Assert.Equal (10, rHeight); - // Assert.False (v.IsInitialized); - - // var toplevel = new Toplevel (); - // toplevel.Add (top); - // Application.Begin (toplevel); - - // Assert.True (v.IsInitialized); - - // v.Height = 15; - // Assert.True (v.TrySetHeight (5, out rHeight)); - // Assert.Equal (5, rHeight); - //} - - //[Fact] - //[AutoInitShutdown] - //public void TrySetWidth_ForceValidatePosDim () - //{ - // var top = new View { X = 0, Y = 0, Width = 80 }; - - // var v = new View { Width = Dim.Fill (), ValidatePosDim = true }; - // top.Add (v); - - // Assert.False (v.TrySetWidth (70, out int rWidth)); - // Assert.Equal (70, rWidth); - - // v.Width = Dim.Fill (1); - // Assert.False (v.TrySetWidth (70, out rWidth)); - // Assert.Equal (69, rWidth); - - // v.Width = 0; - // Assert.True (v.TrySetWidth (70, out rWidth)); - // Assert.Equal (70, rWidth); - // Assert.False (v.IsInitialized); - - // var toplevel = new Toplevel (); - // toplevel.Add (top); - // Application.Begin (toplevel); - - // Assert.True (v.IsInitialized); - // v.Width = 75; - // Assert.True (v.TrySetWidth (60, out rWidth)); - // Assert.Equal (60, rWidth); - //} + [Fact] + public void LayoutSubviews_Uses_ContentSize () + { + var superView = new View () + { + Width = 5, + Height = 5, + ContentSize = new (10, 10) + }; + var view = new View () + { + X = Pos.Center () + }; + superView.Add (view); + + superView.LayoutSubviews (); + + Assert.Equal (5, view.Frame.X); + superView.Dispose (); + } + + // Test OnLayoutStarted/OnLayoutComplete - ensure that they are called at right times + [Fact] + public void LayoutSubviews_LayoutStarted_Complete () + { + var superView = new View (); + var view = new View (); + superView.Add (view); + superView.BeginInit (); + superView.EndInit (); + + var layoutStarted = false; + var layoutComplete = false; + + var borderLayoutStarted = false; + var borderLayoutComplete = false; + + view.LayoutStarted += (sender, e) => layoutStarted = true; + view.LayoutComplete += (sender, e) => layoutComplete = true; + + view.Border.LayoutStarted += (sender, e) => + { + Assert.True (layoutStarted); + borderLayoutStarted = true; + }; + view.Border.LayoutComplete += (sender, e) => + { + Assert.True (layoutStarted); + Assert.False (layoutComplete); + borderLayoutComplete = true; + }; + + superView.LayoutSubviews (); + + Assert.True (borderLayoutStarted); + Assert.True (borderLayoutComplete); + + Assert.True (layoutStarted); + Assert.True (layoutComplete); + superView.Dispose (); + } } diff --git a/UnitTests/View/Layout/ViewportTests.cs b/UnitTests/View/Layout/ViewportTests.cs index cd576c2105..a4fa24c265 100644 --- a/UnitTests/View/Layout/ViewportTests.cs +++ b/UnitTests/View/Layout/ViewportTests.cs @@ -248,7 +248,7 @@ public void Set_Viewport_ValidValue_UpdatesViewport (int viewWidth, int viewHeig view.Viewport = newViewport; // Assert - Assert.Equal (new Rectangle(expectedX, expectedY, viewWidth, viewHeight), view.Viewport); + Assert.Equal (new Rectangle (expectedX, expectedY, viewWidth, viewHeight), view.Viewport); } [Theory] @@ -321,18 +321,9 @@ public void Set_Viewport_NegativeValue_NotAllowedBySettings () } [Theory] - [InlineData (0, 0, 0)] - [InlineData (1, 0, 0)] - [InlineData (-1, 0, 0)] - [InlineData (10, 0, 0)] - [InlineData (11, 0, 0)] - - [InlineData (0, 1, 1)] - [InlineData (1, 1, 1)] - [InlineData (-1, 1, 1)] - [InlineData (10, 1, 1)] - [InlineData (11, 1, 1)] - public void GetViewportOffset_Returns_Offset_From_Frame (int frameX, int adornmentThickness, int expectedOffset) + [InlineData (0, 0)] + [InlineData (1, 1)] + public void GetViewportOffset_Returns_Offset_From_Frame (int adornmentThickness, int expectedOffset) { View view = new () { diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index e7e0fc5d9e..e03090a3dd 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -378,7 +378,7 @@ public void WantContinuousButtonPressed_False_Button_Press_Release_DoesNotClick Assert.Equal (0, clickedCount); me.Handled = false; - me.Flags =clicked; + me.Flags = clicked; view.NewMouseEvent (me); Assert.Equal (1, clickedCount); @@ -387,11 +387,11 @@ public void WantContinuousButtonPressed_False_Button_Press_Release_DoesNotClick [Theory] - [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)] - [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] - [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] - [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] - public void WantContinuousButtonPressed_True_Button_Clicked_Clicks (MouseFlags pressed, MouseFlags released, MouseFlags clicked) + [InlineData (MouseFlags.Button1Clicked)] + [InlineData (MouseFlags.Button2Clicked)] + [InlineData (MouseFlags.Button3Clicked)] + [InlineData (MouseFlags.Button4Clicked)] + public void WantContinuousButtonPressed_True_Button_Clicked_Clicks (MouseFlags clicked) { var me = new MouseEvent (); @@ -405,7 +405,7 @@ public void WantContinuousButtonPressed_True_Button_Clicked_Clicks (MouseFlags p var clickedCount = 0; view.MouseClick += (s, e) => clickedCount++; - + me.Flags = clicked; view.NewMouseEvent (me); Assert.Equal (1, clickedCount); @@ -414,11 +414,11 @@ public void WantContinuousButtonPressed_True_Button_Clicked_Clicks (MouseFlags p } [Theory] - [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)] - [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] - [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] - [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] - public void WantContinuousButtonPressed_True_Button_Press_Release_Clicks (MouseFlags pressed, MouseFlags released, MouseFlags clicked) + [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released)] + [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released)] + [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released)] + [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released)] + public void WantContinuousButtonPressed_True_Button_Press_Release_Clicks (MouseFlags pressed, MouseFlags released) { var me = new MouseEvent ();