瀏覽代碼

New unit tests. Lots of fixes

Tig 1 年之前
父節點
當前提交
a3b606fe6e

+ 10 - 2
Terminal.Gui/Application/Application.cs

@@ -68,6 +68,14 @@ public static partial class Application
                       .ToList ();
     }
 
+    /// <summary>
+    ///     Gets the size of the screen. This is the size of the screen as reported by the <see cref="ConsoleDriver"/>.
+    /// </summary>
+    /// <remarks>
+    ///     If the <see cref="ConsoleDriver"/> has not been initialized, this will return a default size of 2048x2048; useful for unit tests.
+    /// </remarks>
+    public static Rectangle Screen => Driver?.Screen ?? new (0, 0, 2048, 2048);
+
     // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
     // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
     private static Toplevel _cachedRunStateToplevel;
@@ -538,7 +546,7 @@ public static partial class Application
             MoveCurrent (Current);
         }
 
-        toplevel.SetRelativeLayout (Driver.Screen.Size);
+        toplevel.SetRelativeLayout (Screen.Size);
 
         toplevel.LayoutSubviews ();
         toplevel.PositionToplevels ();
@@ -607,7 +615,7 @@ public static partial class Application
 
         // If the view is not visible within it's superview, don't position the cursor
         Rectangle mostFocusedViewport = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = Point.Empty });
-        Rectangle superViewViewport = mostFocused.SuperView?.ViewportToScreen (mostFocused.SuperView.Viewport with { Location = Point.Empty }) ?? Driver.Screen;
+        Rectangle superViewViewport = mostFocused.SuperView?.ViewportToScreen (mostFocused.SuperView.Viewport with { Location = Point.Empty }) ?? Application.Screen;
 
         if (!superViewViewport.IntersectsWith (mostFocusedViewport))
         {

+ 1 - 1
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -20,7 +20,7 @@ public abstract class ConsoleDriver
 
     // QUESTION: When non-full screen apps are supported, will this represent the app size, or will that be in Application?
     /// <summary>Gets the location and size of the terminal screen.</summary>
-    public Rectangle Screen => new (0, 0, Cols, Rows);
+    internal Rectangle Screen => new (0, 0, Cols, Rows);
 
     private Rectangle _clip;
 

+ 33 - 21
Terminal.Gui/Text/TextFormatter.cs

@@ -54,12 +54,12 @@ public class TextFormatter
     internal Size GetAutoSize ()
     {
         Size size = CalcRect (0, 0, Text, Direction, TabWidth).Size;
+
         return size with
         {
             Width = size.Width - GetHotKeySpecifierLength (),
             Height = size.Height - GetHotKeySpecifierLength (false)
         };
-
     }
     /// <summary>
     ///     Gets the width or height of the <see cref="TextFormatter.HotKeySpecifier"/> characters
@@ -112,7 +112,7 @@ public class TextFormatter
             }
         }
     }
-    
+
     /// <summary>
     ///     Determines if the viewport width will be used or only the text width will be used,
     ///     If <see langword="true"/> all the viewport area will be filled with whitespaces and the same background color
@@ -191,7 +191,7 @@ public class TextFormatter
         {
             if (AutoSize)
             {
-                _size = EnableNeedsFormat (GetAutoSize());
+                _size = EnableNeedsFormat (GetAutoSize ());
             }
             else
             {
@@ -451,9 +451,9 @@ public class TextFormatter
             }
             else
             {
-               Debug.WriteLine ($"Unsupported Alignment: {nameof (VerticalAlignment)}");
+                Debug.WriteLine ($"Unsupported Alignment: {nameof (VerticalAlignment)}");
 
-               return;
+                return;
             }
 
             int colOffset = screen.X < 0 ? Math.Abs (screen.X) : 0;
@@ -655,8 +655,20 @@ public class TextFormatter
             return Size.Empty;
         }
 
-        int width = GetLines ().Max (static line => line.GetColumns ());
-        int height = GetLines ().Count;
+        List<string> lines = GetLines ();
+
+        if (lines.Count == 0)
+        {
+            return Size.Empty;
+        }
+
+        int width = lines.Max (static line => line.GetColumns ());
+        int height = lines.Count;
+
+        if (IsVerticalDirection (Direction))
+        {
+            return new (height, width);
+        }
 
         return new (width, height);
     }
@@ -1666,13 +1678,13 @@ public class TextFormatter
     private static string PerformCorrectFormatDirection (TextDirection textDirection, string line)
     {
         return textDirection switch
-               {
-                   TextDirection.RightLeft_BottomTop
-                       or TextDirection.RightLeft_TopBottom
-                       or TextDirection.BottomTop_LeftRight
-                       or TextDirection.BottomTop_RightLeft => StringExtensions.ToString (line.EnumerateRunes ().Reverse ()),
-                   _ => line
-               };
+        {
+            TextDirection.RightLeft_BottomTop
+                or TextDirection.RightLeft_TopBottom
+                or TextDirection.BottomTop_LeftRight
+                or TextDirection.BottomTop_RightLeft => StringExtensions.ToString (line.EnumerateRunes ().Reverse ()),
+            _ => line
+        };
     }
 
     private static List<Rune> PerformCorrectFormatDirection (TextDirection textDirection, List<Rune> runes)
@@ -1683,13 +1695,13 @@ public class TextFormatter
     private static List<string> PerformCorrectFormatDirection (TextDirection textDirection, List<string> lines)
     {
         return textDirection switch
-               {
-                   TextDirection.TopBottom_RightLeft
-                       or TextDirection.LeftRight_BottomTop
-                       or TextDirection.RightLeft_BottomTop
-                       or TextDirection.BottomTop_RightLeft => lines.ToArray ().Reverse ().ToList (),
-                   _ => lines
-               };
+        {
+            TextDirection.TopBottom_RightLeft
+                or TextDirection.LeftRight_BottomTop
+                or TextDirection.RightLeft_BottomTop
+                or TextDirection.BottomTop_RightLeft => lines.ToArray ().Reverse ().ToList (),
+            _ => lines
+        };
     }
 
     /// <summary>Returns the number of lines needed to render the specified text given the width.</summary>

+ 12 - 5
Terminal.Gui/View/Layout/DimAuto.cs

@@ -63,19 +63,25 @@ public class DimAuto () : Dim
         var maxCalculatedSize = 0;
 
         int autoMin = MinimumContentDim?.GetAnchor (superviewContentSize) ?? 0;
-        int autoMax = MaximumContentDim?.GetAnchor (superviewContentSize) ?? (dimension == Dimension.Width ? Application.Driver.Screen.Width : Application.Driver.Screen.Height);
+        int screen = dimension == Dimension.Width ? Application.Screen.Width * 4 : Application.Screen.Height * 4;
+        int autoMax = MaximumContentDim?.GetAnchor (superviewContentSize) ?? screen;
 
         if (Style.FastHasFlags (DimAutoStyle.Text))
         {
             if (dimension == Dimension.Width)
             {
-                //us.TextFormatter.Size = us.GetContentSize ();
+                us.TextFormatter.Size = new (autoMax, 2048);
                 textSize = int.Max (autoMin, us.TextFormatter.FormatAndGetSize ().Width);
+                us.TextFormatter.Size = new Size (textSize, 2048);
             }
             else
             {
-                us.TextFormatter.Size = us.GetContentSize () with { Height = Application.Driver.Screen.Height };
+                if (us.TextFormatter.Size.Width == 0)
+                {
+                    us.TextFormatter.Size = us.TextFormatter.GetAutoSize ();
+                }
                 textSize = int.Max (autoMin, us.TextFormatter.FormatAndGetSize ().Height);
+                us.TextFormatter.Size = us.TextFormatter.Size with { Height = textSize };
             }
         }
 
@@ -629,15 +635,16 @@ public class DimAuto () : Dim
 
         // ************** We now definitively know `us.ContentSize` ***************
 
+        int oppositeScreen = dimension == Dimension.Width ? Application.Screen.Height * 4 : Application.Screen.Width * 4 ;
         foreach (var v in us.Subviews)
         {
             if (dimension == Dimension.Width)
             {
-                v.SetRelativeLayout (new Size (max, Application.Driver.Screen.Width));
+                v.SetRelativeLayout (new Size (max, oppositeScreen));
             }
             else
             {
-                v.SetRelativeLayout (new Size (Application.Driver.Screen.Height, max));
+                v.SetRelativeLayout (new Size (oppositeScreen, max));
             }
         }
 

+ 2 - 1
Terminal.Gui/View/Layout/PosCenter.cs

@@ -13,8 +13,9 @@ public class PosCenter : Pos
 
     internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
     {
+        // Protect against negative dimensions
         int newDimension = Math.Max (dim.Calculate (0, superviewDimension, us, dimension), 0);
 
-        return GetAnchor (superviewDimension - newDimension);
+        return superviewDimension / 2 - newDimension / 2;
     }
 }

+ 2 - 2
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -737,10 +737,10 @@ public partial class View
 
         // Determine our container's ContentSize - 
         //  First try SuperView.Viewport, then Application.Top, then Driver.Viewport.
-        //  Finally, if none of those are valid, use int.MaxValue (for Unit tests).
+        //  Finally, if none of those are valid, use 2048 (for Unit tests).
         Size superViewContentSize = SuperView is { IsInitialized: true } ? SuperView.GetContentSize () :
                            Application.Top is { } && Application.Top != this && Application.Top.IsInitialized ? Application.Top.GetContentSize () :
-                           Application.Driver?.Screen.Size ?? new (int.MaxValue, int.MaxValue);
+                           Application.Screen.Size;
 
         SetTextFormatterSize ();
 

+ 3 - 11
Terminal.Gui/View/ViewText.cs

@@ -1,5 +1,7 @@
 #nullable enable
 
+using static Unix.Terminal.Curses;
+
 namespace Terminal.Gui;
 
 public partial class View
@@ -159,17 +161,6 @@ public partial class View
         }
     }
 
-    /// <summary>
-    ///     Gets the dimensions required for <see cref="Text"/> ignoring a <see cref="TextFormatter.HotKeySpecifier"/>.
-    /// </summary>
-    /// <returns></returns>
-    internal Size GetSizeNeededForTextWithoutHotKey ()
-    {
-        return new Size (
-                         TextFormatter.Size.Width - TextFormatter.GetHotKeySpecifierLength (),
-                         TextFormatter.Size.Height - TextFormatter.GetHotKeySpecifierLength (false));
-    }
-
     /// <summary>
     ///     Internal API. Sets <see cref="TextFormatter"/>.Size to the current <see cref="Viewport"/> size, adjusted for
     ///     <see cref="TextFormatter.HotKeySpecifier"/>.
@@ -196,6 +187,7 @@ public partial class View
         if ((widthAuto is { } && widthAuto.Style.FastHasFlags (DimAutoStyle.Text))
             || (heightAuto is { } && heightAuto.Style.FastHasFlags (DimAutoStyle.Text)))
         {
+            // BUGBUG: This ignores wordwrap and other formatting options.
             size = TextFormatter.GetAutoSize ();
 
             if (widthAuto is null || !widthAuto.Style.FastHasFlags (DimAutoStyle.Text))

+ 1 - 1
Terminal.Gui/Views/Menu/ContextMenu.cs

@@ -144,7 +144,7 @@ public sealed class ContextMenu : IDisposable
         _container = Application.Current;
         _container.Closing += Container_Closing;
         _container.Deactivate += Container_Deactivate;
-        Rectangle frame = Application.Driver.Screen;
+        Rectangle frame = Application.Screen;
         Point position = Position;
 
         if (Host is { })

+ 1 - 1
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -619,7 +619,7 @@ public class MenuBar : View, IDesignable
             return Point.Empty;
         }
 
-        Rectangle superViewFrame = SuperView is null ? Driver.Screen : SuperView.Frame;
+        Rectangle superViewFrame = SuperView is null ? Application.Screen : SuperView.Frame;
         View sv = SuperView is null ? Application.Current : SuperView;
 
         if (sv is null)

+ 1 - 8
Terminal.Gui/Views/MessageBox.cs

@@ -391,16 +391,13 @@ public static class MessageBox
             {
                 int buttonHeight = buttonList.Count > 0 ? buttonList [0].Frame.Height : 0;
                 Debug.Assert (d.TextFormatter.WordWrap);
-                d.TextFormatter.Size = new Size (d.GetContentSize ().Width, Application.Driver.Screen.Height);
+                d.TextFormatter.Size = new Size (d.GetContentSize ().Width, Application.Screen.Height);
                 Size textSize = d.TextFormatter.GetAutoSize ();
                 textSize.Height += buttonHeight;
 
                 if (textSize != d.TextFormatter.Size)
                 {
-                    //d.TextFormatter.Size = textSize;
-                    //d.SetContentSize (textSize);
                     d.SetNeedsLayout ();
-                    //d.SetRelativeLayout (Application.Driver.Screen.Size);
                 }
             }
         };
@@ -412,10 +409,6 @@ public static class MessageBox
         d.TextFormatter.WordWrap = wrapMessage;
         d.TextFormatter.MultiLine = !wrapMessage;
 
-        // Add two lines to push buttons down two rows
-        // BUGBUG: The " " are here due to a bug in TextFormater.Format that strips trailing newlines when .Wordwrap = true
-       // d.Text += Environment.NewLine + " " + Environment.NewLine + " ";
-
         d.ColorScheme = new ColorScheme (d.ColorScheme)
         {
             Focus = d.ColorScheme.Normal

+ 0 - 1
UICatalog/Scenarios/MessageBoxes.cs

@@ -47,7 +47,6 @@ public class MessageBoxes : Scenario
         {
             X = 0,
             Y = Pos.Bottom (label),
-
             Width = Dim.Width (label),
             Height = 1,
             TextAlignment = Alignment.End,

+ 5 - 5
UnitTests/View/DrawTests.cs

@@ -394,7 +394,7 @@ public class DrawTests (ITestOutputHelper _output)
         var view = new View { Width = 2, Height = 2, BorderStyle = LineStyle.Single };
         view.BeginInit ();
         view.EndInit ();
-        view.SetRelativeLayout (Application.Driver.Screen.Size);
+        view.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 2, 2), view.Frame);
         Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -419,7 +419,7 @@ public class DrawTests (ITestOutputHelper _output)
         view.Border.Thickness = new Thickness (1, 1, 1, 0);
         view.BeginInit ();
         view.EndInit ();
-        view.SetRelativeLayout (Application.Driver.Screen.Size);
+        view.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 2, 1), view.Frame);
         Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -437,7 +437,7 @@ public class DrawTests (ITestOutputHelper _output)
         view.Border.Thickness = new Thickness (0, 1, 1, 1);
         view.BeginInit ();
         view.EndInit ();
-        view.SetRelativeLayout (Application.Driver.Screen.Size);
+        view.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 1, 2), view.Frame);
         Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -462,7 +462,7 @@ public class DrawTests (ITestOutputHelper _output)
         view.Border.Thickness = new Thickness (1, 1, 0, 1);
         view.BeginInit ();
         view.EndInit ();
-        view.SetRelativeLayout (Application.Driver.Screen.Size);
+        view.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 1, 2), view.Frame);
         Assert.Equal (Rectangle.Empty, view.Viewport);
@@ -488,7 +488,7 @@ public class DrawTests (ITestOutputHelper _output)
 
         view.BeginInit ();
         view.EndInit ();
-        view.SetRelativeLayout (Application.Driver.Screen.Size);
+        view.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 2, 1), view.Frame);
         Assert.Equal (Rectangle.Empty, view.Viewport);

+ 235 - 63
UnitTests/View/Layout/Dim.AutoTests.cs

@@ -976,8 +976,9 @@ public class DimAutoTests (ITestOutputHelper output)
     public void DimAutoStyle_Content_IgnoresSubviews_When_ContentSize_Is_Set ()
     {
         var view = new View ();
-        var subview = new View () {
-                Frame = new Rectangle (50, 50, 1, 1)
+        var subview = new View ()
+        {
+            Frame = new Rectangle (50, 50, 1, 1)
         };
         view.SetContentSize (new (10, 5));
 
@@ -1045,27 +1046,34 @@ public class DimAutoTests (ITestOutputHelper output)
     [InlineData (1, 50, 51)]
     [InlineData (0, 25, 25)]
     [InlineData (-1, 50, 49)]
-    public void With_Subview_Using_DimFactor (int subViewOffset, int dimFactor, int expectedSize)
+    public void With_Subview_Using_DimPercent (int subViewOffset, int percent, int expectedSize)
     {
-        var view = new View () { Width = 100, Height = 100 };
+        var view = new View ()
+        {
+            Width = 100, Height = 100
+        };
         var subview = new View ()
         {
             X = subViewOffset,
             Y = subViewOffset,
-            Width = Dim.Percent (dimFactor),
-            Height = Dim.Percent (dimFactor)
+            Width = Dim.Percent (percent),
+            Height = Dim.Percent (percent)
         };
         view.Add (subview);
 
-        subview.SetRelativeLayout (new (100, 100));
-
-        var dim = Dim.Auto (DimAutoStyle.Content);
-
-        int calculatedWidth = dim.Calculate (0, 100, view, Dimension.Width);
-        int calculatedHeight = dim.Calculate (0, 100, view, Dimension.Height);
+        view.BeginInit ();
+        view.EndInit ();
 
-        Assert.Equal (expectedSize, calculatedWidth);
-        Assert.Equal (expectedSize, calculatedHeight);
+        // Assuming the calculation is done after layout
+        int calculatedX = subview.X.Calculate (100, subview.Width, subview, Dimension.Width);
+        int calculatedY = subview.Y.Calculate (100, subview.Height, subview, Dimension.Height);
+        int calculatedWidth = subview.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = subview.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (20, calculatedWidth); // subview's width
+        Assert.Equal (10, calculatedHeight); // subview's height
+        Assert.Equal (50, calculatedX);  // 50% of 100 (Width)
+        Assert.Equal (50, calculatedY);  // 50% of 100 (Height) 
     }
 
     [Theory]
@@ -1090,7 +1098,7 @@ public class DimAutoTests (ITestOutputHelper output)
         };
         view.Add (subview);
         //view.LayoutSubviews ();
-        view.SetRelativeLayout(new (200,200));
+        view.SetRelativeLayout (new (200, 200));
 
         Assert.Equal (expectedSize, view.Frame.Width);
     }
@@ -1136,72 +1144,226 @@ public class DimAutoTests (ITestOutputHelper output)
 
     // Testing all Pos combinations
 
-    [Fact]
-    public void With_Subview_At_PosAt ()
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 21, 11)]
+    [InlineData (1, 21, 1, 11, 21, 11)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosAbsolute (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
     {
-        var view = new View ();
-        var subview = new View () { X = Pos.Absolute (10), Y = Pos.Absolute (5), Width = 20, Height = 10 };
+        var view = new View ()
+        {
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
+        };
+        var subview = new View ()
+        {
+            X = Pos.Absolute (10),
+            Y = Pos.Absolute (5),
+            Width = 20,
+            Height = 10
+        };
         view.Add (subview);
 
-        var dimWidth = Dim.Auto ();
-        var dimHeight = Dim.Auto ();
+        // Assuming the calculation is done after layout
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
 
-        int calculatedWidth = dimWidth.Calculate (0, 100, view, Dimension.Width);
-        int calculatedHeight = dimHeight.Calculate (0, 100, view, Dimension.Height);
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
 
-        // Expecting the size to include the subview's position and size
-        Assert.Equal (30, calculatedWidth); // 10 (X position) + 20 (Width)
-        Assert.Equal (15, calculatedHeight); // 5 (Y position) + 10 (Height)
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
     }
 
-    [Fact (Skip = "TextOnly")]
-    public void With_Subview_At_PosPercent ()
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 20, 10)]
+    [InlineData (1, 21, 1, 11, 20, 10)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosPercent (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
     {
-        var view = new View () { Width = 100, Height = 100 };
-        var subview = new View () { X = Pos.Percent (50), Y = Pos.Percent (50), Width = 20, Height = 10 };
+        var view = new View ()
+        {
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
+        };
+        var subview = new View ()
+        {
+            X = Pos.Percent (50),
+            Y = Pos.Percent (50),
+            Width = 20,
+            Height = 10
+        };
         view.Add (subview);
 
-        var dimWidth = Dim.Auto ();
-        var dimHeight = Dim.Auto ();
-
         // Assuming the calculation is done after layout
-        int calculatedWidth = dimWidth.Calculate (0, 100, view, Dimension.Width);
-        int calculatedHeight = dimHeight.Calculate (0, 100, view, Dimension.Height);
-
-        // Expecting the size to include the subview's position as a percentage of the parent view's size plus the subview's size
-        Assert.Equal (70, calculatedWidth); // 50% of 100 (Width) + 20
-        Assert.Equal (60, calculatedHeight); // 50% of 100 (Height) + 10
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
+
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
+
+        view.BeginInit ();
+        view.EndInit ();
+        // subview should be at 50% in the parent view
+        Assert.Equal ((int)(view.Viewport.Width * .50), subview.Frame.X);
+        Assert.Equal ((int)(view.Viewport.Height * .50), subview.Frame.Y);
     }
 
-    [Fact (Skip = "TextOnly")]
-    public void With_Subview_At_PosCenter ()
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 21, 11)]
+    [InlineData (1, 21, 1, 11, 21, 11)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosPercent_Combine (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
     {
-        var view = new View () { Width = 100, Height = 100 };
-        var subview = new View () { X = Pos.Center (), Y = Pos.Center (), Width = 20, Height = 10 };
+        var view = new View ()
+        {
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
+        };
+        var subview = new View ()
+        {
+            X = Pos.Percent (50) + 1,
+            Y = 1 + Pos.Percent (50),
+            Width = 20,
+            Height = 10
+        };
         view.Add (subview);
 
-        var dimWidth = Dim.Auto ();
-        var dimHeight = Dim.Auto ();
-
         // Assuming the calculation is done after layout
-        int calculatedWidth = dimWidth.Calculate (0, 100, view, Dimension.Width);
-        int calculatedHeight = dimHeight.Calculate (0, 100, view, Dimension.Height);
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
+
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
+
+        view.BeginInit ();
+        view.EndInit ();
+        // subview should be at 50% in the parent view
+        Assert.Equal ((int)(view.Viewport.Width * .50) + 1, subview.Frame.X);
+        Assert.Equal ((int)(view.Viewport.Height * .50) + 1, subview.Frame.Y);
+    }
+
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 21, 11)]
+    [InlineData (1, 21, 1, 11, 21, 11)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosCenter (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
+    {
+        var view = new View ()
+        {
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
+        };
+        var subview = new View ()
+        {
+            X = Pos.Center (),
+            Y = Pos.Center (),
+            Width = 20,
+            Height = 10
+        };
+        view.Add (subview);
 
-        // Expecting the size to include the subview's position at the center of the parent view plus the subview's size
-        Assert.Equal (70, calculatedWidth); // Centered in 100 (Width) + 20
-        Assert.Equal (60, calculatedHeight); // Centered in 100 (Height) + 10
+        // Assuming the calculation is done after layout
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
+
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
+
+        view.BeginInit ();
+        view.EndInit ();
+        // subview should be centered in the parent view + 1
+        Assert.Equal (view.Viewport.Width / 2 - subview.Frame.Width / 2, subview.Frame.X);
+        Assert.Equal (view.Viewport.Height / 2 - subview.Frame.Height / 2, subview.Frame.Y);
     }
 
-    [Fact]
-    public void With_Subview_At_PosAnchorEnd ()
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 18, 0, 8, 18, 8)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 21, 11)]
+    [InlineData (1, 21, 1, 11, 21, 11)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosCenter_Combine (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
     {
-        var dimWidth = Dim.Auto ();
-        var dimHeight = Dim.Auto ();
+        var view = new View ()
+        {
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
+        };
 
+        var subview = new View ()
+        {
+            X = Pos.Center () + 1,
+            Y = 1 + Pos.Center (),
+            Width = 20,
+            Height = 10
+        };
+        view.Add (subview);
+
+        // Assuming the calculation is done after layout
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
+
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
+
+        view.BeginInit ();
+        view.EndInit ();
+        // subview should be centered in the parent view + 1
+        Assert.Equal (view.Viewport.Width / 2 - subview.Frame.Width / 2 + 1, subview.Frame.X);
+        Assert.Equal (view.Viewport.Height / 2 - subview.Frame.Height / 2 + 1, subview.Frame.Y);
+    }
+
+    [Theory]
+    [InlineData (0, 0, 0, 0, 0, 0)]
+    [InlineData (0, 19, 0, 9, 19, 9)]
+    [InlineData (0, 18, 0, 8, 18, 8)]
+    [InlineData (0, 20, 0, 10, 20, 10)]
+    [InlineData (0, 21, 0, 11, 20, 10)]
+    [InlineData (1, 21, 1, 11, 20, 10)]
+    [InlineData (100, 21, 100, 11, 21, 11)]
+    public void With_Subview_Using_PosAnchorEnd (int minWidth, int maxWidth, int minHeight, int maxHeight, int expectedWidth, int expectedHeight)
+    {
         var view = new View ()
         {
-            Width = dimWidth,
-            Height = dimHeight
+            Width = Dim.Auto (minimumContentDim: minWidth, maximumContentDim: maxWidth),
+            Height = Dim.Auto (minimumContentDim: minHeight, maximumContentDim: maxHeight)
         };
 
         var subview = new View ()
@@ -1214,12 +1376,22 @@ public class DimAutoTests (ITestOutputHelper output)
         view.Add (subview);
 
         // Assuming the calculation is done after layout
-        int calculatedWidth = dimWidth.Calculate (0, 100, view, Dimension.Width);
-        int calculatedHeight = dimHeight.Calculate (0, 100, view, Dimension.Height);
-
-        // Expecting the size to include the subview's position at the end of the parent view minus the offset plus the subview's size
-        Assert.Equal (20, calculatedWidth);
-        Assert.Equal (10, calculatedHeight);
+        int calculatedX = view.X.Calculate (100, view.Width, view, Dimension.Width);
+        int calculatedY = view.Y.Calculate (100, view.Height, view, Dimension.Height);
+        int calculatedWidth = view.Width.Calculate (0, 100, view, Dimension.Width);
+        int calculatedHeight = view.Height.Calculate (0, 100, view, Dimension.Height);
+
+        Assert.Equal (expectedWidth, calculatedWidth);
+        Assert.Equal (expectedHeight, calculatedHeight);
+
+        Assert.Equal (0, calculatedX);
+        Assert.Equal (0, calculatedY);
+
+        view.BeginInit ();
+        view.EndInit ();
+        // subview should be at the end of the view
+        Assert.Equal (view.Viewport.Width - subview.Frame.Width, subview.Frame.X);
+        Assert.Equal (view.Viewport.Height - subview.Frame.Height, subview.Frame.Y);
     }
 
     [Fact]

+ 23 - 4
UnitTests/View/Layout/Pos.CenterTests.cs

@@ -51,12 +51,31 @@ public class PosCenterTests (ITestOutputHelper output)
         Assert.IsType<PosCenter> (pos);
     }
 
-    [Fact]
-    public void PosCenter_Calculate_ReturnsExpectedValue ()
+    [Theory]
+    [InlineData (10, 2, 4)]
+    [InlineData (10, 10, 0)]
+    [InlineData (10, 11, 0)]
+    [InlineData (10, 12, -1)]
+    [InlineData (19, 20, -1)]
+    public void PosCenter_Calculate_ReturnsExpectedValue (int superviewDimension, int width, int expectedX)
     {
         var posCenter = new PosCenter ();
-        int result = posCenter.Calculate (10, new DimAbsolute (2), null, Dimension.None);
-        Assert.Equal (4, result);
+        int result = posCenter.Calculate (superviewDimension, new DimAbsolute (width), null!, Dimension.Width);
+        Assert.Equal (expectedX, result);
+    }
+
+
+    [Fact]
+    public void PosCenter_Bigger_Than_SuperView ()
+    {
+        var superView = new View { Width = 10, Height = 10 };
+        var view = new View { X = Center (), Y = Center (), Width = 20, Height = 20 };
+        superView.Add (view);
+        superView.BeginInit();
+        superView.EndInit();
+
+        Assert.Equal (-5, view.Frame.Left);
+        Assert.Equal (-5, view.Frame.Top);
     }
 
     [Theory]

+ 14 - 0
UnitTests/View/Layout/Pos.PercentTests.cs

@@ -7,6 +7,20 @@ public class PosPercentTests (ITestOutputHelper output)
 {
     private readonly ITestOutputHelper _output = output;
 
+    [Theory]
+    [InlineData (50, 10, 2, 5)]
+    [InlineData (50, 10, 10, 5)]
+    [InlineData (50, 10, 11, 5)]
+    [InlineData (50, 10, 12, 5)]
+    [InlineData (50, 19, 20, 9)]
+    public void PosPercent_Calculate_ReturnsExpectedValue (int percent, int superviewDimension, int width, int expectedX)
+    {
+        var posPercent = new PosPercent (percent);
+        int result = posPercent.Calculate (superviewDimension, new DimAbsolute (width), null!, Dimension.Width);
+        Assert.Equal (expectedX, result);
+    }
+
+
     // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
     // TODO: A new test that calls SetRelativeLayout directly is needed.
     [Theory]

+ 1 - 50
UnitTests/View/TextTests.cs

@@ -778,56 +778,7 @@ Y
         Application.End (rs);
         top.Dispose ();
     }
-
-    [Fact]
-    [AutoInitShutdown]
-    public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier ()
-    {
-        var text = "Say Hello 你";
-
-        // Frame: 0, 0, 12, 1
-        var horizontalView = new View
-        {
-            Width = Dim.Auto (), Height = Dim.Auto ()
-        };
-        horizontalView.TextFormatter.HotKeySpecifier = (Rune)'_';
-        horizontalView.Text = text;
-
-        // Frame: 0, 0, 1, 12
-        var verticalView = new View
-        {
-            Width = Dim.Auto (), Height = Dim.Auto (), TextDirection = TextDirection.TopBottom_LeftRight
-        };
-        verticalView.Text = text;
-        verticalView.TextFormatter.HotKeySpecifier = (Rune)'_';
-
-        var top = new Toplevel ();
-        top.Add (horizontalView, verticalView);
-        Application.Begin (top);
-        ((FakeDriver)Application.Driver).SetBufferSize (50, 50);
-
-        Assert.Equal (new (0, 0, 12, 1), horizontalView.Frame);
-        Assert.Equal (new (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
-        Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
-
-        Assert.Equal (new (0, 0, 2, 11), verticalView.Frame);
-        Assert.Equal (new (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
-        Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
-
-        text = "012345678你";
-        horizontalView.Text = text;
-        verticalView.Text = text;
-
-        Assert.Equal (new (0, 0, 11, 1), horizontalView.Frame);
-        Assert.Equal (new (11, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
-        Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
-
-        Assert.Equal (new (0, 0, 2, 10), verticalView.Frame);
-        Assert.Equal (new (2, 10), verticalView.GetSizeNeededForTextWithoutHotKey ());
-        Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
-        top.Dispose ();
-    }
-
+    
     [Theory]
     [AutoInitShutdown]
     [InlineData (true)]

+ 2 - 2
UnitTests/View/ViewTests.cs

@@ -833,10 +833,10 @@ At 0,0
             TextDirection = TextDirection.TopBottom_LeftRight,
             Width = Dim.Auto (),
             Height = Dim.Auto ()
-        }; // BUGBUG: AutoSize or Height need be set
+        };
+        r.TextFormatter.WordWrap = false;
         Assert.NotNull (r);
 
-        // BUGBUG: IsInitialized must be true to process calculation
         r.BeginInit ();
         r.EndInit ();
         Assert.False (r.CanFocus);

+ 1 - 1
UnitTests/Views/LabelTests.cs

@@ -473,7 +473,7 @@ e
         var label = new Label { BorderStyle = LineStyle.Single, Text = "Test" };
         label.BeginInit ();
         label.EndInit ();
-        label.SetRelativeLayout (Application.Driver.Screen.Size);
+        label.SetRelativeLayout (Application.Screen.Size);
 
         Assert.Equal (new (0, 0, 4, 1), label.Viewport);
         Assert.Equal (new (0, 0, 6, 3), label.Frame);

+ 1 - 1
UnitTests/Views/TextViewTests.cs

@@ -6900,7 +6900,7 @@ This is the second line.
                                                      );
 
         ((FakeDriver)Application.Driver).SetBufferSize (6, 25);
-        tv.SetRelativeLayout (Application.Driver.Screen.Size);
+        tv.SetRelativeLayout (Application.Screen.Size);
         tv.Draw ();
         Assert.Equal (new Point (4, 2), tv.CursorPosition);
         Assert.Equal (new Point (12, 0), cp);