ソースを参照

Merge pull request #3410 from tig/v2_481-AnchorEnd

Fixes #481. Adds `Pos.AnchorEnd ()` (no param) to automatically account for the view's dimension.
Tig 1 年間 前
コミット
c1cac7290c

+ 342 - 194
Terminal.Gui/View/Layout/PosDim.cs

@@ -1,4 +1,6 @@
-namespace Terminal.Gui;
+using static Terminal.Gui.Dialog;
+
+namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
 ///     Describes the position of a <see cref="View"/> which can be an absolute value, a percentage, centered, or
 ///     Describes the position of a <see cref="View"/> which can be an absolute value, a percentage, centered, or
@@ -43,7 +45,7 @@
 ///             </item>
 ///             </item>
 ///             <item>
 ///             <item>
 ///                 <term>
 ///                 <term>
-///                     <see cref="Pos.Anchor(int)"/>
+///                     <see cref="Pos.AnchorEnd()"/>
 ///                 </term>
 ///                 </term>
 ///                 <description>
 ///                 <description>
 ///                     Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of
 ///                     Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of
@@ -125,20 +127,36 @@
 public class Pos
 public class Pos
 {
 {
     /// <summary>
     /// <summary>
-    ///     Creates a <see cref="Pos"/> 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 <see cref="Pos"/> 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
+    ///     <see cref="Pos.AnchorEnd(int)"/>,
+    ///     with an offset equivalent to the View's respective dimension.
+    /// </summary>
+    /// <returns>The <see cref="Pos"/> object anchored to the end (the bottom or the right side) minus the View's dimension.</returns>
+    /// <example>
+    ///     This sample shows how align a <see cref="Button"/> to the bottom-right the SuperView.
+    ///     <code>
+    /// anchorButton.X = Pos.AnchorEnd ();
+    /// anchorButton.Y = Pos.AnchorEnd ();
+    /// </code>
+    /// </example>
+    public static Pos AnchorEnd () { return new PosAnchorEnd (); }
+
+    /// <summary>
+    ///     Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of the SuperView,
+    ///     useful to flush the layout from the right or bottom. See also <see cref="Pos.AnchorEnd()"/>, which uses the view
+    ///     dimension to ensure the view is fully visible.
     /// </summary>
     /// </summary>
     /// <returns>The <see cref="Pos"/> object anchored to the end (the bottom or the right side).</returns>
     /// <returns>The <see cref="Pos"/> object anchored to the end (the bottom or the right side).</returns>
     /// <param name="offset">The view will be shifted left or up by the amount specified.</param>
     /// <param name="offset">The view will be shifted left or up by the amount specified.</param>
     /// <example>
     /// <example>
-    ///     This sample shows how align a <see cref="Button"/> to the bottom-right of a <see cref="View"/>.
+    ///     This sample shows how align a 10 column wide <see cref="Button"/> to the bottom-right the SuperView.
     ///     <code>
     ///     <code>
-    /// // See Issue #502 
-    /// anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
-    /// anchorButton.Y = Pos.AnchorEnd (1);
+    /// anchorButton.X = Pos.AnchorEnd (10);
+    /// anchorButton.Y = 1
     /// </code>
     /// </code>
     /// </example>
     /// </example>
-    public static Pos AnchorEnd (int offset = 0)
+    public static Pos AnchorEnd (int offset)
     {
     {
         if (offset < 0)
         if (offset < 0)
         {
         {
@@ -153,25 +171,17 @@ public class Pos
     /// <param name="n">The value to convert to the <see cref="Pos"/>.</param>
     /// <param name="n">The value to convert to the <see cref="Pos"/>.</param>
     public static Pos At (int n) { return new PosAbsolute (n); }
     public static Pos At (int n) { return new PosAbsolute (n); }
 
 
-    /// <summary>
-    ///     Creates a <see cref="Pos"/> object that tracks the Bottom (Y+Height) coordinate of the specified
-    ///     <see cref="View"/>
-    /// </summary>
-    /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
-    /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos Bottom (View view) { return new PosView (view, 3); }
-
     /// <summary>Creates a <see cref="Pos"/> object that can be used to center the <see cref="View"/>.</summary>
     /// <summary>Creates a <see cref="Pos"/> object that can be used to center the <see cref="View"/>.</summary>
     /// <returns>The center Pos.</returns>
     /// <returns>The center Pos.</returns>
     /// <example>
     /// <example>
-    ///     This creates a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height, and
+    ///     This creates a <see cref="TextView"/> centered horizontally, is 50% of the way down, is 30% the height, and
     ///     is 80% the width of the <see cref="View"/> it added to.
     ///     is 80% the width of the <see cref="View"/> it added to.
     ///     <code>
     ///     <code>
     ///  var textView = new TextView () {
     ///  var textView = new TextView () {
-    /// 	X = Pos.Center (),
-    /// 	Y = Pos.Percent (50),
-    /// 	Width = Dim.Percent (80),
-    ///  	Height = Dim.Percent (30),
+    ///     X = Pos.Center (),
+    ///     Y = Pos.Percent (50),
+    ///     Width = Dim.Percent (80),
+    ///     Height = Dim.Percent (30),
     ///  };
     ///  };
     ///  </code>
     ///  </code>
     /// </example>
     /// </example>
@@ -197,11 +207,6 @@ public class Pos
     /// <returns>A hash code for the current object.</returns>
     /// <returns>A hash code for the current object.</returns>
     public override int GetHashCode () { return Anchor (0).GetHashCode (); }
     public override int GetHashCode () { return Anchor (0).GetHashCode (); }
 
 
-    /// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
-    /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
-    /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos Left (View view) { return new PosView (view, 0); }
-
     /// <summary>Adds a <see cref="Terminal.Gui.Pos"/> to a <see cref="Terminal.Gui.Pos"/>, yielding a new <see cref="Pos"/>.</summary>
     /// <summary>Adds a <see cref="Terminal.Gui.Pos"/> to a <see cref="Terminal.Gui.Pos"/>, yielding a new <see cref="Pos"/>.</summary>
     /// <param name="left">The first <see cref="Terminal.Gui.Pos"/> to add.</param>
     /// <param name="left">The first <see cref="Terminal.Gui.Pos"/> to add.</param>
     /// <param name="right">The second <see cref="Terminal.Gui.Pos"/> to add.</param>
     /// <param name="right">The second <see cref="Terminal.Gui.Pos"/> to add.</param>
@@ -214,7 +219,11 @@ public class Pos
         }
         }
 
 
         var newPos = new PosCombine (true, left, right);
         var newPos = new PosCombine (true, left, right);
-        SetPosCombine (left, newPos);
+
+        if (left is PosView view)
+        {
+            view.Target.SetNeedsLayout ();
+        }
 
 
         return newPos;
         return newPos;
     }
     }
@@ -239,75 +248,109 @@ public class Pos
         }
         }
 
 
         var newPos = new PosCombine (false, left, right);
         var newPos = new PosCombine (false, left, right);
-        SetPosCombine (left, newPos);
+
+        if (left is PosView view)
+        {
+            view.Target.SetNeedsLayout ();
+        }
 
 
         return newPos;
         return newPos;
     }
     }
 
 
     /// <summary>Creates a percentage <see cref="Pos"/> object</summary>
     /// <summary>Creates a percentage <see cref="Pos"/> object</summary>
     /// <returns>The percent <see cref="Pos"/> object.</returns>
     /// <returns>The percent <see cref="Pos"/> object.</returns>
-    /// <param name="n">A value between 0 and 100 representing the percentage.</param>
+    /// <param name="percent">A value between 0 and 100 representing the percentage.</param>
     /// <example>
     /// <example>
-    ///     This creates a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height, and
+    ///     This creates a <see cref="TextField"/> centered horizontally, is 50% of the way down, is 30% the height, and
     ///     is 80% the width of the <see cref="View"/> it added to.
     ///     is 80% the width of the <see cref="View"/> it added to.
     ///     <code>
     ///     <code>
-    ///  var textView = new TextView () {
-    /// 	X = Pos.Center (),
-    /// 	Y = Pos.Percent (50),
-    /// 	Width = Dim.Percent (80),
-    ///  	Height = Dim.Percent (30),
+    ///  var textView = new TextField {
+    ///      X = Pos.Center (),
+    ///      Y = Pos.Percent (50),
+    ///      Width = Dim.Percent (80),
+    ///      Height = Dim.Percent (30),
     ///  };
     ///  };
     ///  </code>
     ///  </code>
     /// </example>
     /// </example>
-    public static Pos Percent (float n)
+    public static Pos Percent (float percent)
     {
     {
-        if (n is < 0 or > 100)
+        if (percent is < 0 or > 100)
         {
         {
-            throw new ArgumentException ("Percent value must be between 0 and 100");
+            throw new ArgumentException ("Percent value must be between 0 and 100.");
         }
         }
 
 
-        return new PosFactor (n / 100);
+        return new PosFactor (percent / 100);
     }
     }
 
 
-    /// <summary>
-    ///     Creates a <see cref="Pos"/> object that tracks the Right (X+Width) coordinate of the specified
-    ///     <see cref="View"/>.
-    /// </summary>
+    /// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos Right (View view) { return new PosView (view, 2); }
+    public static Pos Top (View view) { return new PosView (view, Side.Top); }
 
 
     /// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
     /// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos Top (View view) { return new PosView (view, 1); }
+    public static Pos Y (View view) { return new PosView (view, Side.Top); }
 
 
     /// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
     /// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos X (View view) { return new PosView (view, 0); }
+    public static Pos Left (View view) { return new PosView (view, Side.Left); }
 
 
-    /// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
+    /// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
     /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
-    public static Pos Y (View view) { return new PosView (view, 1); }
+    public static Pos X (View view) { return new PosView (view, Side.Left); }
 
 
-    internal virtual int Anchor (int width) { return 0; }
+    /// <summary>
+    ///     Creates a <see cref="Pos"/> object that tracks the Bottom (Y+Height) coordinate of the specified
+    ///     <see cref="View"/>
+    /// </summary>
+    /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
+    /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
+    public static Pos Bottom (View view) { return new PosView (view, Side.Bottom); }
 
 
-    private static void SetPosCombine (Pos left, PosCombine newPos)
-    {
-        var view = left as PosView;
+    /// <summary>
+    ///     Creates a <see cref="Pos"/> object that tracks the Right (X+Width) coordinate of the specified
+    ///     <see cref="View"/>.
+    /// </summary>
+    /// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
+    /// <param name="view">The <see cref="View"/>  that will be tracked.</param>
+    public static Pos Right (View view) { return new PosView (view, Side.Right); }
 
 
-        if (view is { })
-        {
-            view.Target.SetNeedsLayout ();
-        }
-    }
+    /// <summary>
+    ///     Gets a position that is anchored to a certain point in the layout. This method is typically used
+    ///     internally by the layout system to determine where a View should be positioned.
+    /// </summary>
+    /// <param name="width">The width of the area where the View is being positioned (Superview.ContentSize).</param>
+    /// <returns>
+    ///     An integer representing the calculated position. The way this position is calculated depends on the specific
+    ///     subclass of Pos that is used. For example, PosAbsolute returns a fixed position, PosAnchorEnd returns a
+    ///     position that is anchored to the end of the layout, and so on.
+    /// </returns>
+    internal virtual int Anchor (int width) { return 0; }
 
 
-    internal class PosAbsolute : Pos
+    /// <summary>
+    ///     Calculates and returns the position of a <see cref="View"/> object. It takes into account the dimension of the
+    ///     superview and the dimension of the view itself.
+    /// </summary>
+    /// <param name="superviewDimension">
+    ///     The dimension of the superview. This could be the width for x-coordinate calculation or the
+    ///     height for y-coordinate calculation.
+    /// </param>
+    /// <param name="dim">The dimension of the View. It could be the current width or height.</param>
+    /// <param name="autosize">Obsolete; to be deprecated.</param>
+    /// <param name="autoSize">Obsolete; to be deprecated.</param>
+    /// <returns>
+    ///     The calculated position of the View. The way this position is calculated depends on the specific subclass of Pos
+    ///     that
+    ///     is used.
+    /// </returns>
+    internal virtual int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize) { return Anchor (superviewDimension); }
+
+    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 bool Equals (object other) { return other is PosAbsolute abs && abs._n == _n; }
         public override int GetHashCode () { return _n.GetHashCode (); }
         public override int GetHashCode () { return _n.GetHashCode (); }
         public override string ToString () { return $"Absolute({_n})"; }
         public override string ToString () { return $"Absolute({_n})"; }
@@ -317,30 +360,58 @@ public class Pos
     internal class PosAnchorEnd : Pos
     internal class PosAnchorEnd : Pos
     {
     {
         private readonly int _offset;
         private readonly int _offset;
+        public PosAnchorEnd () { UseDimForOffset = true; }
         public PosAnchorEnd (int offset) { _offset = offset; }
         public PosAnchorEnd (int offset) { _offset = offset; }
         public override bool Equals (object other) { return other is PosAnchorEnd anchorEnd && anchorEnd._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 int GetHashCode () { return _offset.GetHashCode (); }
-        public override string ToString () { return $"AnchorEnd({_offset})"; }
-        internal override int Anchor (int width) { return width - _offset; }
+
+        /// <summary>
+        ///     If true, the offset is the width of the view, if false, the offset is the offset value.
+        /// </summary>
+        internal bool UseDimForOffset { get; set; }
+
+        public override string ToString () { return UseDimForOffset ? "AnchorEnd()" : $"AnchorEnd({_offset})"; }
+
+        internal override int Anchor (int width)
+        {
+            if (UseDimForOffset)
+            {
+                return width;
+            }
+
+            return width - _offset;
+        }
+
+        internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
+        {
+            int newLocation = Anchor (superviewDimension);
+
+            if (UseDimForOffset)
+            {
+                newLocation -= dim.Anchor (superviewDimension);
+            }
+
+            return newLocation;
+        }
     }
     }
 
 
     internal class PosCenter : Pos
     internal class PosCenter : Pos
     {
     {
         public override string ToString () { return "Center"; }
         public override string ToString () { return "Center"; }
         internal override int Anchor (int width) { return width / 2; }
         internal override int Anchor (int width) { return width / 2; }
-    }
-
-    internal class PosCombine : Pos
-    {
-        internal bool _add;
-        internal Pos _left, _right;
 
 
-        public PosCombine (bool add, Pos left, Pos right)
+        internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
         {
         {
-            _left = left;
-            _right = right;
-            _add = add;
+            int newDimension = Math.Max (dim.Calculate (0, superviewDimension, autosize, autoSize), 0);
+
+            return Anchor (superviewDimension - newDimension);
         }
         }
+    }
+
+    internal class PosCombine (bool add, Pos left, Pos right) : Pos
+    {
+        internal bool _add = add;
+        internal Pos _left = left, _right = right;
 
 
         public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
         public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
 
 
@@ -356,12 +427,25 @@ public class Pos
 
 
             return la - ra;
             return la - ra;
         }
         }
+
+        internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
+        {
+            int newDimension = dim.Calculate (0, superviewDimension, autosize, autoSize);
+            int left = _left.Calculate (superviewDimension, dim, autosize, autoSize);
+            int right = _right.Calculate (superviewDimension, dim, autosize, autoSize);
+
+            if (_add)
+            {
+                return left + right;
+            }
+
+            return left - right;
+        }
     }
     }
 
 
-    internal class PosFactor : Pos
+    internal class PosFactor (float factor) : Pos
     {
     {
-        private readonly float _factor;
-        public PosFactor (float n) { _factor = n; }
+        private readonly float _factor = factor;
         public override bool Equals (object other) { return other is PosFactor f && f._factor == _factor; }
         public override bool Equals (object other) { return other is PosFactor f && f._factor == _factor; }
         public override int GetHashCode () { return _factor.GetHashCode (); }
         public override int GetHashCode () { return _factor.GetHashCode (); }
         public override string ToString () { return $"Factor({_factor})"; }
         public override string ToString () { return $"Factor({_factor})"; }
@@ -369,78 +453,77 @@ public class Pos
     }
     }
 
 
     // Helper class to provide dynamic value by the execution of a function that returns an integer.
     // Helper class to provide dynamic value by the execution of a function that returns an integer.
-    internal class PosFunc : Pos
+    internal class PosFunc (Func<int> n) : Pos
     {
     {
-        private readonly Func<int> _function;
-        public PosFunc (Func<int> n) { _function = n; }
+        private readonly Func<int> _function = n;
         public override bool Equals (object other) { return other is PosFunc f && f._function () == _function (); }
         public override bool Equals (object other) { return other is PosFunc f && f._function () == _function (); }
         public override int GetHashCode () { return _function.GetHashCode (); }
         public override int GetHashCode () { return _function.GetHashCode (); }
         public override string ToString () { return $"PosFunc({_function ()})"; }
         public override string ToString () { return $"PosFunc({_function ()})"; }
         internal override int Anchor (int width) { return _function (); }
         internal override int Anchor (int width) { return _function (); }
     }
     }
 
 
-    internal class PosView : Pos
+    /// <summary>
+    /// Describes which side of the view to use for the position.
+    /// </summary>
+    public enum Side
     {
     {
-        public readonly View Target;
-
-        private readonly int side;
+        /// <summary>
+        /// The left (X) side of the view.
+        /// </summary>
+        Left = 0,
+
+        /// <summary>
+        /// The top (Y) side of the view.
+        /// </summary>
+        Top = 1,
+
+        /// <summary>
+        /// The right (X + Width) side of the view.
+        /// </summary>
+        Right = 2,
+
+        /// <summary>
+        /// The bottom (Y + Height) side of the view.
+        /// </summary>
+        Bottom = 3
+    }
 
 
-        public PosView (View view, int side)
-        {
-            Target = view;
-            this.side = side;
-        }
+    internal class PosView (View view, Side side) : Pos
+    {
+        public readonly View Target = view;
 
 
         public override bool Equals (object other) { return other is PosView abs && abs.Target == Target; }
         public override bool Equals (object other) { return other is PosView abs && abs.Target == Target; }
         public override int GetHashCode () { return Target.GetHashCode (); }
         public override int GetHashCode () { return Target.GetHashCode (); }
 
 
         public override string ToString ()
         public override string ToString ()
         {
         {
-            string tside;
-
-            switch (side)
+            string sideString = side switch
             {
             {
-                case 0:
-                    tside = "x";
-
-                    break;
-                case 1:
-                    tside = "y";
-
-                    break;
-                case 2:
-                    tside = "right";
-
-                    break;
-                case 3:
-                    tside = "bottom";
-
-                    break;
-                default:
-                    tside = "unknown";
-
-                    break;
-            }
-
-            if (Target is null)
+                Side.Left => "left",
+                Side.Top => "top",
+                Side.Right => "right",
+                Side.Bottom => "bottom",
+                _ => "unknown"
+            };
+
+            if (Target == null)
             {
             {
                 throw new NullReferenceException (nameof (Target));
                 throw new NullReferenceException (nameof (Target));
             }
             }
 
 
-            return $"View(side={tside},target={Target})";
+            return $"View(side={sideString},target={Target})";
         }
         }
 
 
         internal override int Anchor (int width)
         internal override int Anchor (int width)
         {
         {
-            switch (side)
+            return side switch
             {
             {
-                case 0: return Target.Frame.X;
-                case 1: return Target.Frame.Y;
-                case 2: return Target.Frame.Right;
-                case 3: return Target.Frame.Bottom;
-                default:
-                    return 0;
-            }
+                Side.Left => Target.Frame.X,
+                Side.Top => Target.Frame.Y,
+                Side.Right => Target.Frame.Right,
+                Side.Bottom => Target.Frame.Bottom,
+                _ => 0
+            };
         }
         }
     }
     }
 }
 }
@@ -486,8 +569,8 @@ public class Pos
 ///                     <see cref="Dim.Fill(int)"/>
 ///                     <see cref="Dim.Fill(int)"/>
 ///                 </term>
 ///                 </term>
 ///                 <description>
 ///                 <description>
-///                     Creates a <see cref="Dim"/> object that fills the dimension, leaving the specified number
-///                     of columns for a margin.
+///                     Creates a <see cref="Dim"/> object that fills the dimension from the View's X position
+///                     to the end of the super view's width, leaving the specified number of columns for a margin.
 ///                 </description>
 ///                 </description>
 ///             </item>
 ///             </item>
 ///             <item>
 ///             <item>
@@ -545,11 +628,11 @@ public class Dim
     /// <summary>Creates a <see cref="Dim"/> object that tracks the Height of the specified <see cref="View"/>.</summary>
     /// <summary>Creates a <see cref="Dim"/> object that tracks the Height of the specified <see cref="View"/>.</summary>
     /// <returns>The height <see cref="Dim"/> of the other <see cref="View"/>.</returns>
     /// <returns>The height <see cref="Dim"/> of the other <see cref="View"/>.</returns>
     /// <param name="view">The view that will be tracked.</param>
     /// <param name="view">The view that will be tracked.</param>
-    public static Dim Height (View view) { return new DimView (view, 0); }
+    public static Dim Height (View view) { return new DimView (view, Dimension.Height); }
 
 
-    /// <summary>Adds a <see cref="Terminal.Gui.Dim"/> to a <see cref="Terminal.Gui.Dim"/>, yielding a new <see cref="Dim"/>.</summary>
-    /// <param name="left">The first <see cref="Terminal.Gui.Dim"/> to add.</param>
-    /// <param name="right">The second <see cref="Terminal.Gui.Dim"/> to add.</param>
+    /// <summary>Adds a <see cref="Dim"/> to a <see cref="Dim"/>, yielding a new <see cref="Dim"/>.</summary>
+    /// <param name="left">The first <see cref="Dim"/> to add.</param>
+    /// <param name="right">The second <see cref="Dim"/> to add.</param>
     /// <returns>The <see cref="Dim"/> that is the sum of the values of <c>left</c> and <c>right</c>.</returns>
     /// <returns>The <see cref="Dim"/> that is the sum of the values of <c>left</c> and <c>right</c>.</returns>
     public static Dim operator + (Dim left, Dim right)
     public static Dim operator + (Dim left, Dim right)
     {
     {
@@ -559,7 +642,7 @@ public class Dim
         }
         }
 
 
         var newDim = new DimCombine (true, left, right);
         var newDim = new DimCombine (true, left, right);
-        SetDimCombine (left, newDim);
+        (left as DimView)?.Target.SetNeedsLayout ();
 
 
         return newDim;
         return newDim;
     }
     }
@@ -570,11 +653,11 @@ public class Dim
     public static implicit operator Dim (int n) { return new DimAbsolute (n); }
     public static implicit operator Dim (int n) { return new DimAbsolute (n); }
 
 
     /// <summary>
     /// <summary>
-    ///     Subtracts a <see cref="Terminal.Gui.Dim"/> from a <see cref="Terminal.Gui.Dim"/>, yielding a new
+    ///     Subtracts a <see cref="Dim"/> from a <see cref="Dim"/>, yielding a new
     ///     <see cref="Dim"/>.
     ///     <see cref="Dim"/>.
     /// </summary>
     /// </summary>
-    /// <param name="left">The <see cref="Terminal.Gui.Dim"/> to subtract from (the minuend).</param>
-    /// <param name="right">The <see cref="Terminal.Gui.Dim"/> to subtract (the subtrahend).</param>
+    /// <param name="left">The <see cref="Dim"/> to subtract from (the minuend).</param>
+    /// <param name="right">The <see cref="Dim"/> to subtract (the subtrahend).</param>
     /// <returns>The <see cref="Dim"/> that is the <c>left</c> minus <c>right</c>.</returns>
     /// <returns>The <see cref="Dim"/> that is the <c>left</c> minus <c>right</c>.</returns>
     public static Dim operator - (Dim left, Dim right)
     public static Dim operator - (Dim left, Dim right)
     {
     {
@@ -584,38 +667,40 @@ public class Dim
         }
         }
 
 
         var newDim = new DimCombine (false, left, right);
         var newDim = new DimCombine (false, left, right);
-        SetDimCombine (left, newDim);
+        (left as DimView)?.Target.SetNeedsLayout ();
 
 
         return newDim;
         return newDim;
     }
     }
 
 
     /// <summary>Creates a percentage <see cref="Dim"/> object that is a percentage of the width or height of the SuperView.</summary>
     /// <summary>Creates a percentage <see cref="Dim"/> object that is a percentage of the width or height of the SuperView.</summary>
     /// <returns>The percent <see cref="Dim"/> object.</returns>
     /// <returns>The percent <see cref="Dim"/> object.</returns>
-    /// <param name="n">A value between 0 and 100 representing the percentage.</param>
-    /// <param name="r">
-    ///     If <c>true</c> the Percent is computed based on the remaining space after the X/Y anchor positions. If
-    ///     <c>false</c> is computed based on the whole original space.
+    /// <param name="percent">A value between 0 and 100 representing the percentage.</param>
+    /// <param name="usePosition">
+    ///     If <see langword="true"/> the dimension is computed using the View's position (<see cref="View.X"/> or
+    ///     <see cref="View.Y"/>).
+    ///     If <see langword="false"/> the dimension is computed using the View's <see cref="View.ContentSize"/>.
     /// </param>
     /// </param>
     /// <example>
     /// <example>
-    ///     This initializes a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height,
-    ///     and is 80% the width of the <see cref="View"/> it added to.
+    ///     This initializes a <see cref="TextField"/> that will be centered horizontally, is 50% of the way down, is 30% the
+    ///     height,
+    ///     and is 80% the width of the SuperView.
     ///     <code>
     ///     <code>
-    ///  var textView = new TextView () {
-    /// 	X = Pos.Center (),
-    /// 	Y = Pos.Percent (50),
-    /// 	Width = Dim.Percent (80),
-    ///  	Height = Dim.Percent (30),
+    ///  var textView = new TextField {
+    ///     X = Pos.Center (),
+    ///     Y = Pos.Percent (50),
+    ///     Width = Dim.Percent (80),
+    ///     Height = Dim.Percent (30),
     ///  };
     ///  };
     ///  </code>
     ///  </code>
     /// </example>
     /// </example>
-    public static Dim Percent (float n, bool r = false)
+    public static Dim Percent (float percent, bool usePosition = false)
     {
     {
-        if (n is < 0 or > 100)
+        if (percent is < 0 or > 100)
         {
         {
             throw new ArgumentException ("Percent value must be between 0 and 100");
             throw new ArgumentException ("Percent value must be between 0 and 100");
         }
         }
 
 
-        return new DimFactor (n / 100, r);
+        return new DimFactor (percent / 100, usePosition);
     }
     }
 
 
     /// <summary>Creates an Absolute <see cref="Dim"/> from the specified integer value.</summary>
     /// <summary>Creates an Absolute <see cref="Dim"/> from the specified integer value.</summary>
@@ -626,34 +711,63 @@ public class Dim
     /// <summary>Creates a <see cref="Dim"/> object that tracks the Width of the specified <see cref="View"/>.</summary>
     /// <summary>Creates a <see cref="Dim"/> object that tracks the Width of the specified <see cref="View"/>.</summary>
     /// <returns>The width <see cref="Dim"/> of the other <see cref="View"/>.</returns>
     /// <returns>The width <see cref="Dim"/> of the other <see cref="View"/>.</returns>
     /// <param name="view">The view that will be tracked.</param>
     /// <param name="view">The view that will be tracked.</param>
-    public static Dim Width (View view) { return new DimView (view, 1); }
+    public static Dim Width (View view) { return new DimView (view, Dimension.Width); }
 
 
+    /// <summary>
+    ///     Gets a dimension that is anchored to a certain point in the layout.
+    ///     This method is typically used internally by the layout system to determine the size of a View.
+    /// </summary>
+    /// <param name="width">The width of the area where the View is being sized (Superview.ContentSize).</param>
+    /// <returns>
+    ///     An integer representing the calculated dimension. The way this dimension is calculated depends on the specific
+    ///     subclass of Dim that is used. For example, DimAbsolute returns a fixed dimension, DimFactor returns a
+    ///     dimension that is a certain percentage of the super view's size, and so on.
+    /// </returns>
     internal virtual int Anchor (int width) { return 0; }
     internal virtual int Anchor (int width) { return 0; }
 
 
-    // BUGBUG: newPos is never used.
-    private static void SetDimCombine (Dim left, DimCombine newPos) { (left as DimView)?.Target.SetNeedsLayout (); }
+    /// <summary>
+    ///     Calculates and returns the dimension of a <see cref="View"/> object. It takes into account the location of the
+    ///     <see cref="View"/>, its current size, and whether it should automatically adjust its size based on its content.
+    /// </summary>
+    /// <param name="location">
+    ///     The starting point from where the size calculation begins. It could be the left edge for width calculation or the
+    ///     top edge for height calculation.
+    /// </param>
+    /// <param name="dimension">The current size of the View. It could be the current width or height.</param>
+    /// <param name="autosize">Obsolete; To be deprecated.</param>
+    /// <param name="autoSize">Obsolete; To be deprecated.</param>
+    /// <returns>
+    ///     The calculated size of the View. The way this size is calculated depends on the specific subclass of Dim that
+    ///     is used.
+    /// </returns>
+    internal virtual int Calculate (int location, int dimension, int autosize, bool autoSize)
+    {
+        int newDimension = Math.Max (Anchor (dimension - location), 0);
 
 
-    internal class DimAbsolute : Dim
+        return autoSize && autosize > newDimension ? autosize : newDimension;
+    }
+
+    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 bool Equals (object other) { return other is DimAbsolute abs && abs._n == _n; }
         public override int GetHashCode () { return _n.GetHashCode (); }
         public override int GetHashCode () { return _n.GetHashCode (); }
         public override string ToString () { return $"Absolute({_n})"; }
         public override string ToString () { return $"Absolute({_n})"; }
         internal override int Anchor (int width) { return _n; }
         internal override int Anchor (int width) { return _n; }
-    }
-
-    internal class DimCombine : Dim
-    {
-        internal bool _add;
-        internal Dim _left, _right;
 
 
-        public DimCombine (bool add, Dim left, Dim right)
+        internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
         {
         {
-            _left = left;
-            _right = right;
-            _add = add;
+            // DimAbsolute.Anchor (int width) ignores width and returns n
+            int newDimension = Math.Max (Anchor (0), 0);
+
+            return autoSize && autosize > newDimension ? autosize : newDimension;
         }
         }
+    }
+
+    internal class DimCombine (bool add, Dim left, Dim right) : Dim
+    {
+        internal bool _add = add;
+        internal Dim _left = left, _right = right;
 
 
         public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
         public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
 
 
@@ -669,30 +783,49 @@ public class Dim
 
 
             return la - ra;
             return la - ra;
         }
         }
-    }
 
 
-    internal class DimFactor : Dim
-    {
-        private readonly float _factor;
-        private readonly bool _remaining;
-
-        public DimFactor (float n, bool r = false)
+        internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
         {
         {
-            _factor = n;
-            _remaining = r;
+            int leftNewDim = _left.Calculate (location, dimension, autosize, autoSize);
+            int rightNewDim = _right.Calculate (location, dimension, autosize, autoSize);
+
+            int newDimension;
+
+            if (_add)
+            {
+                newDimension = leftNewDim + rightNewDim;
+            }
+            else
+            {
+                newDimension = Math.Max (0, leftNewDim - rightNewDim);
+            }
+
+            return autoSize && autosize > newDimension ? autosize : newDimension;
         }
         }
+    }
+
+    internal class DimFactor (float factor, bool remaining = false) : Dim
+    {
+        private readonly float _factor = factor;
+        private readonly bool _remaining = remaining;
 
 
         public override bool Equals (object other) { return other is DimFactor f && f._factor == _factor && f._remaining == _remaining; }
         public override bool Equals (object other) { return other is DimFactor f && f._factor == _factor && f._remaining == _remaining; }
         public override int GetHashCode () { return _factor.GetHashCode (); }
         public override int GetHashCode () { return _factor.GetHashCode (); }
         public bool IsFromRemaining () { return _remaining; }
         public bool IsFromRemaining () { return _remaining; }
         public override string ToString () { return $"Factor({_factor},{_remaining})"; }
         public override string ToString () { return $"Factor({_factor},{_remaining})"; }
         internal override int Anchor (int width) { return (int)(width * _factor); }
         internal override int Anchor (int width) { return (int)(width * _factor); }
+
+        internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
+        {
+            int newDimension = _remaining ? Math.Max (Anchor (dimension - location), 0) : Anchor (dimension);
+
+            return autoSize && autosize > newDimension ? autosize : newDimension;
+        }
     }
     }
 
 
-    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 bool Equals (object other) { return other is DimFill fill && fill._margin == _margin; }
         public override int GetHashCode () { return _margin.GetHashCode (); }
         public override int GetHashCode () { return _margin.GetHashCode (); }
         public override string ToString () { return $"Fill({_margin})"; }
         public override string ToString () { return $"Fill({_margin})"; }
@@ -700,21 +833,36 @@ public class Dim
     }
     }
 
 
     // Helper class to provide dynamic value by the execution of a function that returns an integer.
     // Helper class to provide dynamic value by the execution of a function that returns an integer.
-    internal class DimFunc : Dim
+    internal class DimFunc (Func<int> n) : Dim
     {
     {
-        private readonly Func<int> _function;
-        public DimFunc (Func<int> n) { _function = n; }
+        private readonly Func<int> _function = n;
         public override bool Equals (object other) { return other is DimFunc f && f._function () == _function (); }
         public override bool Equals (object other) { return other is DimFunc f && f._function () == _function (); }
         public override int GetHashCode () { return _function.GetHashCode (); }
         public override int GetHashCode () { return _function.GetHashCode (); }
         public override string ToString () { return $"DimFunc({_function ()})"; }
         public override string ToString () { return $"DimFunc({_function ()})"; }
         internal override int Anchor (int width) { return _function (); }
         internal override int Anchor (int width) { return _function (); }
     }
     }
 
 
+    /// <summary>
+    /// 
+    /// </summary>
+    public enum Dimension
+    {
+        /// <summary>
+        /// The height dimension.
+        /// </summary>
+        Height = 0,
+
+        /// <summary>
+        /// The width dimension.
+        /// </summary>
+        Width = 1
+    }
+
     internal class DimView : Dim
     internal class DimView : Dim
     {
     {
-        private readonly int _side;
+        private readonly Dimension _side;
 
 
-        public DimView (View view, int side)
+        internal DimView (View view, Dimension side)
         {
         {
             Target = view;
             Target = view;
             _side = side;
             _side = side;
@@ -726,29 +874,29 @@ public class Dim
 
 
         public override string ToString ()
         public override string ToString ()
         {
         {
-            if (Target is null)
+            if (Target == null)
             {
             {
                 throw new NullReferenceException ();
                 throw new NullReferenceException ();
             }
             }
 
 
-            string tside = _side switch
-                           {
-                               0 => "Height",
-                               1 => "Width",
-                               _ => "unknown"
-                           };
+            string sideString = _side switch
+            {
+                Dimension.Height => "Height",
+                Dimension.Width => "Width",
+                _ => "unknown"
+            };
 
 
-            return $"View({tside},{Target})";
+            return $"View({sideString},{Target})";
         }
         }
 
 
         internal override int Anchor (int width)
         internal override int Anchor (int width)
         {
         {
             return _side switch
             return _side switch
-                   {
-                       0 => Target.Frame.Height,
-                       1 => Target.Frame.Width,
-                       _ => 0
-                   };
+            {
+                Dimension.Height => Target.Frame.Height,
+                Dimension.Width => Target.Frame.Width,
+                _ => 0
+            };
         }
         }
     }
     }
 }
 }

+ 37 - 181
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -1,5 +1,4 @@
 using System.Diagnostics;
 using System.Diagnostics;
-using System.IO.Compression;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
@@ -88,11 +87,13 @@ public partial class View
 
 
     private void SetFrame (Rectangle frame)
     private void SetFrame (Rectangle frame)
     {
     {
-        Rectangle oldViewport  = Rectangle.Empty;
+        var oldViewport = Rectangle.Empty;
+
         if (IsInitialized)
         if (IsInitialized)
         {
         {
             oldViewport = Viewport;
             oldViewport = Viewport;
         }
         }
+
         // This is the only place where _frame should be set directly. Use Frame = or SetFrame instead.
         // This is the only place where _frame should be set directly. Use Frame = or SetFrame instead.
         _frame = frame;
         _frame = frame;
 
 
@@ -113,7 +114,7 @@ public partial class View
                 // Adornments don't have SuperViews; use Adornment.FrameToScreen override
                 // Adornments don't have SuperViews; use Adornment.FrameToScreen override
                 // which will give us the screen coordinates of the parent
                 // which will give us the screen coordinates of the parent
 
 
-                var parentScreen = adornment.FrameToScreen ();
+                Rectangle parentScreen = adornment.FrameToScreen ();
 
 
                 // Now add our Frame location
                 // Now add our Frame location
                 parentScreen.Offset (screen.X, screen.Y);
                 parentScreen.Offset (screen.X, screen.Y);
@@ -142,7 +143,7 @@ public partial class View
     {
     {
         if (SuperView is null)
         if (SuperView is null)
         {
         {
-            return new Point (x - Frame.X, y - Frame.Y);
+            return new (x - Frame.X, y - Frame.Y);
         }
         }
 
 
         Point superViewViewportOffset = SuperView.GetViewportOffsetFromFrame ();
         Point superViewViewportOffset = SuperView.GetViewportOffsetFromFrame ();
@@ -242,7 +243,8 @@ public partial class View
     /// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
     /// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>.
+    ///         The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>
+    ///         .
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
     ///         If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
@@ -283,8 +285,8 @@ public partial class View
             if (IsAdded && AutoSize && !isValidNewAutoSize)
             if (IsAdded && AutoSize && !isValidNewAutoSize)
             {
             {
                 Debug.WriteLine (
                 Debug.WriteLine (
-                                                     @$"Must set AutoSize to false before setting the {nameof (Height)}."
-                                                    );
+                                 @$"Must set AutoSize to false before setting the {nameof (Height)}."
+                                );
                 AutoSize = false;
                 AutoSize = false;
             }
             }
 
 
@@ -299,7 +301,8 @@ public partial class View
     /// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
     /// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>.
+    ///         The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>
+    ///         .
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
     ///         If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
@@ -330,7 +333,7 @@ public partial class View
 
 
             if (AutoSize)
             if (AutoSize)
             {
             {
-                Debug.WriteLine($@"Must set AutoSize to false before setting {nameof(Width)}.");
+                Debug.WriteLine ($@"Must set AutoSize to false before setting {nameof (Width)}.");
                 AutoSize = false;
                 AutoSize = false;
             }
             }
 
 
@@ -338,7 +341,7 @@ public partial class View
 
 
             if (IsAdded && AutoSize && !isValidNewAutoSize)
             if (IsAdded && AutoSize && !isValidNewAutoSize)
             {
             {
-                Debug.WriteLine($@"Must set AutoSize to false before setting {nameof(Width)}.");
+                Debug.WriteLine ($@"Must set AutoSize to false before setting {nameof (Width)}.");
                 AutoSize = false;
                 AutoSize = false;
             }
             }
 
 
@@ -656,6 +659,7 @@ public partial class View
             int startOffsetY = y - (start.Frame.Y + viewportOffset.Y);
             int startOffsetY = y - (start.Frame.Y + viewportOffset.Y);
 
 
             View? subview = null;
             View? subview = null;
+
             for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
             for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
             {
             {
                 if (start.InternalSubviews [i].Visible
                 if (start.InternalSubviews [i].Visible
@@ -750,8 +754,8 @@ public partial class View
         }
         }
 
 
         //System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
         //System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
-        bool menuVisible = false;
-        bool statusVisible = false;
+        var menuVisible = false;
+        var statusVisible = false;
 
 
         if (viewToMove?.SuperView is null || viewToMove == Application.Top || viewToMove?.SuperView == Application.Top)
         if (viewToMove?.SuperView is null || viewToMove == Application.Top || viewToMove?.SuperView == Application.Top)
         {
         {
@@ -907,6 +911,7 @@ public partial class View
 
 
         OnLayoutComplete (new (ContentSize));
         OnLayoutComplete (new (ContentSize));
     }
     }
+
     private void LayoutSubview (View v, Size contentSize)
     private void LayoutSubview (View v, Size contentSize)
     {
     {
         v.SetRelativeLayout (contentSize);
         v.SetRelativeLayout (contentSize);
@@ -964,6 +969,7 @@ public partial class View
             SetNeedsLayout ();
             SetNeedsLayout ();
         }
         }
     }
     }
+
     internal bool LayoutNeeded { get; private set; } = true;
     internal bool LayoutNeeded { get; private set; } = true;
 
 
     /// <summary>
     /// <summary>
@@ -995,11 +1001,11 @@ public partial class View
     ///     <see cref="Height"/>).
     ///     <see cref="Height"/>).
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
-    /// <para>
-    /// If <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, or <see cref="Height"/> are
-    /// absolute, they will be updated to reflect the new size and position of the view. Otherwise, they
-    /// are left unchanged.
-    /// </para>
+    ///     <para>
+    ///         If <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, or <see cref="Height"/> are
+    ///         absolute, they will be updated to reflect the new size and position of the view. Otherwise, they
+    ///         are left unchanged.
+    ///     </para>
     /// </remarks>
     /// </remarks>
     /// <param name="superviewContentSize">
     /// <param name="superviewContentSize">
     ///     The size of the SuperView's content (nominally the same as <c>this.SuperView.ContentSize</c>).
     ///     The size of the SuperView's content (nominally the same as <c>this.SuperView.ContentSize</c>).
@@ -1011,175 +1017,25 @@ public partial class View
         Debug.Assert (_width is { });
         Debug.Assert (_width is { });
         Debug.Assert (_height is { });
         Debug.Assert (_height is { });
 
 
-        int newX, newW, newY, newH;
-        var autosize = Size.Empty;
+        var autoSize = Size.Empty;
 
 
         if (AutoSize)
         if (AutoSize)
         {
         {
-            // Note this is global to this function and used as such within the local functions defined
-            // below. In v2 AutoSize will be re-factored to not need to be dealt with in this function.
-            autosize = GetAutoSize ();
+            autoSize = GetAutoSize ();
         }
         }
 
 
-        // TODO: Since GetNewLocationAndDimension does not depend on View, it can be moved into PosDim.cs
-        // TODO: to make architecture more clean. Do this after DimAuto is implemented and the 
-        // TODO: View.AutoSize stuff is removed.
-
-        // Returns the new dimension (width or height) and location (x or y) for the View given
-        //   the superview's Viewport
-        //   the current Pos (View.X or View.Y)
-        //   the current Dim (View.Width or View.Height)
-        // This method is called recursively if pos is Pos.PosCombine
-        (int newLocation, int newDimension) GetNewLocationAndDimension (
-            bool width,
-            Size superviewContentSize,
-            Pos pos,
-            Dim dim,
-            int autosizeDimension
-        )
-        {
-            // Gets the new dimension (width or height, dependent on `width`) of the given Dim given:
-            //   location: the current location (x or y)
-            //   dimension: the new dimension (width or height) (if relevant for Dim type)
-            //   autosize: the size to use if autosize = true
-            // This method is recursive if d is Dim.DimCombine
-            int GetNewDimension (Dim d, int location, int dimension, int autosize)
-            {
-                int newDimension;
+        int newX = _x.Calculate (superviewContentSize.Width, _width, autoSize.Width, AutoSize);
+        int newW = _width.Calculate (newX, superviewContentSize.Width, autoSize.Width, AutoSize);
+        int newY = _y.Calculate (superviewContentSize.Height, _height, autoSize.Height, AutoSize);
+        int newH = _height.Calculate (newY, superviewContentSize.Height, autoSize.Height, AutoSize);
 
 
-                switch (d)
-                {
-                    case Dim.DimCombine combine:
-                        // TODO: Move combine logic into DimCombine?
-                        int leftNewDim = GetNewDimension (combine._left, location, dimension, autosize);
-                        int rightNewDim = GetNewDimension (combine._right, location, dimension, autosize);
-
-                        if (combine._add)
-                        {
-                            newDimension = leftNewDim + rightNewDim;
-                        }
-                        else
-                        {
-                            newDimension = leftNewDim - rightNewDim;
-                        }
-
-                        newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
-
-                        break;
-
-                    case Dim.DimFactor factor when !factor.IsFromRemaining ():
-                        newDimension = d.Anchor (dimension);
-                        newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
-
-                        break;
-
-                    case Dim.DimAbsolute:
-                        // DimAbsolute.Anchor (int width) ignores width and returns n
-                        newDimension = Math.Max (d.Anchor (0), 0);
-
-                        // BUGBUG: AutoSize does two things: makes text fit AND changes the view's dimensions
-                        newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
-
-                        break;
-
-                    case Dim.DimFill:
-                    default:
-                        newDimension = Math.Max (d.Anchor (dimension - location), 0);
-                        newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
-
-                        break;
-                }
+        Rectangle newFrame = new (newX, newY, newW, newH);
 
 
-                return newDimension;
-            }
-
-            int newDimension, newLocation;
-            int superviewDimension = width ? superviewContentSize.Width : superviewContentSize.Height;
-
-            // Determine new location
-            switch (pos)
-            {
-                case Pos.PosCenter posCenter:
-                    // For Center, the dimension is dependent on location, but we need to force getting the dimension first
-                    // using a location of 0
-                    newDimension = Math.Max (GetNewDimension (dim, 0, superviewDimension, autosizeDimension), 0);
-                    newLocation = posCenter.Anchor (superviewDimension - newDimension);
-
-                    newDimension = Math.Max (
-                                             GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
-                                             0
-                                            );
-
-                    break;
-
-                case Pos.PosCombine combine:
-                    // TODO: Move combine logic into PosCombine?
-                    int left, right;
-
-                    (left, newDimension) = GetNewLocationAndDimension (
-                                                                       width,
-                                                                       superviewContentSize,
-                                                                       combine._left,
-                                                                       dim,
-                                                                       autosizeDimension
-                                                                      );
-
-                    (right, newDimension) = GetNewLocationAndDimension (
-                                                                        width,
-                                                                        superviewContentSize,
-                                                                        combine._right,
-                                                                        dim,
-                                                                        autosizeDimension
-                                                                       );
-
-                    if (combine._add)
-                    {
-                        newLocation = left + right;
-                    }
-                    else
-                    {
-                        newLocation = left - right;
-                    }
-
-                    newDimension = Math.Max (
-                                             GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
-                                             0
-                                            );
-
-                    break;
-
-                case Pos.PosAnchorEnd:
-                case Pos.PosAbsolute:
-                case Pos.PosFactor:
-                case Pos.PosFunc:
-                case Pos.PosView:
-                default:
-                    newLocation = pos?.Anchor (superviewDimension) ?? 0;
-
-                    newDimension = Math.Max (
-                                             GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
-                                             0
-                                            );
-
-                    break;
-            }
-
-            return (newLocation, newDimension);
-        }
-
-        // horizontal/width
-        (newX, newW) = GetNewLocationAndDimension (true, superviewContentSize, _x, _width, autosize.Width);
-
-        // vertical/height
-        (newY, newH) = GetNewLocationAndDimension (false, superviewContentSize, _y, _height, autosize.Height);
-
-        Rectangle r = new (newX, newY, newW, newH);
-
-        if (Frame != r)
+        if (Frame != newFrame)
         {
         {
             // Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
             // Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
             // the view LayoutStyle.Absolute.
             // the view LayoutStyle.Absolute.
-            SetFrame (r);
+            SetFrame (newFrame);
 
 
             if (_x is Pos.PosAbsolute)
             if (_x is Pos.PosAbsolute)
             {
             {
@@ -1207,18 +1063,18 @@ public partial class View
 
 
         if (AutoSize)
         if (AutoSize)
         {
         {
-            if (autosize.Width == 0 || autosize.Height == 0)
+            if (autoSize.Width == 0 || autoSize.Height == 0)
             {
             {
                 // Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
                 // Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
                 // the view LayoutStyle.Absolute.
                 // the view LayoutStyle.Absolute.
-                SetFrame (_frame with { Size = autosize });
+                SetFrame (_frame with { Size = autoSize });
 
 
-                if (autosize.Width == 0)
+                if (autoSize.Width == 0)
                 {
                 {
                     _width = 0;
                     _width = 0;
                 }
                 }
 
 
-                if (autosize.Height == 0)
+                if (autoSize.Height == 0)
                 {
                 {
                     _height = 0;
                     _height = 0;
                 }
                 }
@@ -1432,4 +1288,4 @@ public partial class View
     public bool ValidatePosDim { get; set; }
     public bool ValidatePosDim { get; set; }
 
 
     #endregion
     #endregion
-}
+}

+ 9 - 8
UICatalog/Scenarios/Adornments.cs

@@ -38,7 +38,7 @@ public class Adornments : Scenario
         app.Add (window);
         app.Add (window);
 
 
         var tf1 = new TextField { Width = 10, Text = "TextField" };
         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.BorderStyle = LineStyle.RoundedDotted;
 
 
         color.ColorChanged += (s, e) =>
         color.ColorChanged += (s, e) =>
@@ -68,15 +68,16 @@ public class Adornments : Scenario
         };
         };
         label.Border.Thickness = new (1, 3, 1, 1);
         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,
             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";
         window.Margin.Data = "Margin";
@@ -94,7 +95,7 @@ public class Adornments : Scenario
 
 
         };
         };
         longLabel.TextFormatter.WordWrap = true;
         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; };
         editor.Initialized += (s, e) => { editor.ViewToEdit = window; };
 
 

+ 4 - 4
UICatalog/Scenarios/AllViewsTester.cs

@@ -147,7 +147,7 @@ public class AllViewsTester : Scenario
                                      };
                                      };
         _settingsPane.Add (_computedCheckBox);
         _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
         _locationFrame = new FrameView
         {
         {
@@ -179,7 +179,7 @@ public class AllViewsTester : Scenario
 
 
         _locationFrame.Add (_xRadioGroup);
         _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:" };
         label = new Label { X = Pos.Right (_xRadioGroup) + 1, Y = 0, Text = "Y:" };
         _locationFrame.Add (label);
         _locationFrame.Add (label);
         _yText = new TextField { X = Pos.Right (label) + 1, Y = 0, Width = 4, Text = $"{_yVal}" };
         _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
             view.X = _xRadioGroup.SelectedItem switch
                      {
                      {
                          0 => Pos.Percent (_xVal),
                          0 => Pos.Percent (_xVal),
-                         1 => Pos.AnchorEnd (_xVal),
+                         1 => Pos.AnchorEnd (),
                          2 => Pos.Center (),
                          2 => Pos.Center (),
                          3 => Pos.At (_xVal),
                          3 => Pos.At (_xVal),
                          _ => view.X
                          _ => view.X
@@ -397,7 +397,7 @@ public class AllViewsTester : Scenario
             view.Y = _yRadioGroup.SelectedItem switch
             view.Y = _yRadioGroup.SelectedItem switch
                      {
                      {
                          0 => Pos.Percent (_yVal),
                          0 => Pos.Percent (_yVal),
-                         1 => Pos.AnchorEnd (_yVal),
+                         1 => Pos.AnchorEnd (),
                          2 => Pos.Center (),
                          2 => Pos.Center (),
                          3 => Pos.At (_yVal),
                          3 => Pos.At (_yVal),
                          _ => view.Y
                          _ => view.Y

+ 2 - 2
UICatalog/Scenarios/Animation.cs

@@ -34,12 +34,12 @@ public class Animation : Scenario
 
 
         win.Add (imageView);
         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);
         win.Add (lbl);
 
 
         var lbl2 = new Label
         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);
         win.Add (lbl2);
 
 

+ 21 - 11
UICatalog/Scenarios/BasicColors.cs

@@ -8,8 +8,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Text and Formatting")]
 [ScenarioCategory ("Text and Formatting")]
 public class BasicColors : Scenario
 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 vx = 30;
         var x = 30;
         var x = 30;
         var y = 14;
         var y = 14;
@@ -31,7 +38,7 @@ public class BasicColors : Scenario
                 Text = bg.ToString (),
                 Text = bg.ToString (),
                 TextDirection = TextDirection.TopBottom_LeftRight
                 TextDirection = TextDirection.TopBottom_LeftRight
             };
             };
-            Win.Add (vl);
+            app.Add (vl);
 
 
             var hl = new Label
             var hl = new Label
             {
             {
@@ -44,7 +51,7 @@ public class BasicColors : Scenario
                 ColorScheme = new ColorScheme { Normal = attr },
                 ColorScheme = new ColorScheme { Normal = attr },
                 Text = bg.ToString ()
                 Text = bg.ToString ()
             };
             };
-            Win.Add (hl);
+            app.Add (hl);
             vx++;
             vx++;
 
 
             foreach (ColorName fg in colors)
             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 ()
                     ColorScheme = new ColorScheme { Normal = c }, X = x, Y = y, Text = t [^1].ToString ()
                 };
                 };
-                Win.Add (l);
+                app.Add (l);
                 x++;
                 x++;
             }
             }
 
 
@@ -64,24 +71,24 @@ public class BasicColors : Scenario
             y++;
             y++;
         }
         }
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (36), Text = "Mouse over to get the Attribute:" }
                  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 };
         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 = "  " };
         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 };
         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 = "  " };
         var viewBackground = new View { X = Pos.AnchorEnd (2), Y = 4, ColorScheme = new ColorScheme (), Text = "  " };
-        Win.Add (viewBackground);
+        app.Add (viewBackground);
 
 
         Application.MouseEvent += (s, e) =>
         Application.MouseEvent += (s, e) =>
                                   {
                                   {
@@ -103,5 +110,8 @@ public class BasicColors : Scenario
                                               new ColorScheme (viewBackground.ColorScheme) { Normal = new Attribute (back, back) };
                                               new ColorScheme (viewBackground.ColorScheme) { Normal = new Attribute (back, back) };
                                       }
                                       }
                                   };
                                   };
+
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 2 - 2
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
         // This is the default button (IsDefault = true); if user presses ENTER in the TextField
         // the scenario will quit
         // 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 ();
         defaultButton.Accept += (s, e) => Application.RequestStop ();
         main.Add (defaultButton);
         main.Add (defaultButton);
 
 
@@ -459,7 +459,7 @@ public class Buttons : Scenario
             _up = new ()
             _up = new ()
             {
             {
                 AutoSize = false,
                 AutoSize = false,
-                X = Pos.AnchorEnd (1),
+                X = Pos.AnchorEnd (),
                 Y = Pos.Top (_number),
                 Y = Pos.Top (_number),
                 Height = 1,
                 Height = 1,
                 Width = 1,
                 Width = 1,

+ 23 - 17
UICatalog/Scenarios/ColorPicker.cs

@@ -24,42 +24,45 @@ public class ColorPickers : Scenario
     private ColorPicker foregroundColorPicker;
     private ColorPicker foregroundColorPicker;
 
 
     /// <summary>Setup the scenario.</summary>
     /// <summary>Setup the scenario.</summary>
-    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.
         // Foreground ColorPicker.
         foregroundColorPicker = new ColorPicker { Title = "Foreground Color", BorderStyle = LineStyle.Single };
         foregroundColorPicker = new ColorPicker { Title = "Foreground Color", BorderStyle = LineStyle.Single };
         foregroundColorPicker.ColorChanged += ForegroundColor_ColorChanged;
         foregroundColorPicker.ColorChanged += ForegroundColor_ColorChanged;
-        Win.Add (foregroundColorPicker);
+        app.Add (foregroundColorPicker);
 
 
         _foregroundColorLabel = new Label
         _foregroundColorLabel = new Label
         {
         {
             X = Pos.Left (foregroundColorPicker), Y = Pos.Bottom (foregroundColorPicker) + 1
             X = Pos.Left (foregroundColorPicker), Y = Pos.Bottom (foregroundColorPicker) + 1
         };
         };
-        Win.Add (_foregroundColorLabel);
+        app.Add (_foregroundColorLabel);
 
 
         // Background ColorPicker.
         // Background ColorPicker.
         backgroundColorPicker = new ColorPicker
         backgroundColorPicker = new ColorPicker
         {
         {
             Title = "Background Color",
             Title = "Background Color",
-            // TODO: Replace with Pos.AnchorEnd () when #2900 is done
-            X = Pos.AnchorEnd ((8 * 4) + 2), // 8 box * 4 width + 2 for border
+            X = Pos.AnchorEnd (),
             BoxHeight = 1,
             BoxHeight = 1,
             BoxWidth = 4,
             BoxWidth = 4,
-            BorderStyle = LineStyle.Single
+            BorderStyle = LineStyle.Single,
         };
         };
 
 
-        //backgroundColorPicker.X = Pos.AnchorEnd () - (Pos.Right (backgroundColorPicker) - Pos.Left (backgroundColorPicker));
         backgroundColorPicker.ColorChanged += BackgroundColor_ColorChanged;
         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 () - (Pos.Right (_backgroundColorLabel) - Pos.Left (_backgroundColorLabel));
-        _backgroundColorLabel.Y = Pos.Bottom (backgroundColorPicker) + 1;
-        Win.Add (_backgroundColorLabel);
+        app.Add (_backgroundColorLabel);
 
 
         // Demo Label.
         // Demo Label.
         _demoView = new View
         _demoView = new View
@@ -74,12 +77,15 @@ public class ColorPickers : Scenario
             Height = 5,
             Height = 5,
             Width = 20
             Width = 20
         };
         };
-        Win.Add (_demoView);
+        app.Add (_demoView);
 
 
         // Set default colors.
         // Set default colors.
         foregroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Foreground.GetClosestNamedColor ();
         foregroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Foreground.GetClosestNamedColor ();
         backgroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Background.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 ();
     }
     }
 
 
     /// <summary>Fired when background color is changed.</summary>
     /// <summary>Fired when background color is changed.</summary>

+ 46 - 45
UICatalog/Scenarios/ComputedLayout.cs

@@ -13,17 +13,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Layout")]
 [ScenarioCategory ("Layout")]
 public class ComputedLayout : Scenario
 public class ComputedLayout : Scenario
 {
 {
-    public override void Init ()
+    public override void Main ()
     {
     {
         Application.Init ();
         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
         // Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width
         const string rule = "|123456789";
         const string rule = "|123456789";
 
 
@@ -38,7 +36,7 @@ public class ComputedLayout : Scenario
             Text = rule
             Text = rule
         };
         };
 
 
-        Top.Add (horizontalRuler);
+        app.Add (horizontalRuler);
 
 
         // Demonstrate using Dim to create a vertical ruler that always measures the parent window's height
         // 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";
         const string vrule = "|\n1\n2\n3\n4\n5\n6\n7\n8\n9\n";
@@ -54,7 +52,7 @@ public class ComputedLayout : Scenario
             Text = vrule
             Text = vrule
         };
         };
 
 
-        Top.LayoutComplete += (s, a) =>
+        app.LayoutComplete += (s, a) =>
                                           {
                                           {
                                               horizontalRuler.Text =
                                               horizontalRuler.Text =
                                                   rule.Repeat ((int)Math.Ceiling (horizontalRuler.Viewport.Width / (double)rule.Length)) [
                                                   rule.Repeat ((int)Math.Ceiling (horizontalRuler.Viewport.Width / (double)rule.Length)) [
@@ -65,15 +63,15 @@ public class ComputedLayout : Scenario
                                                       [..(verticalRuler.Viewport.Height * 2)];
                                                       [..(verticalRuler.Viewport.Height * 2)];
                                           };
                                           };
 
 
-        Top.Add (verticalRuler);
+        app.Add (verticalRuler);
 
 
         // Demonstrate At - Using Pos.At to locate a view in an absolute location
         // 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) };
         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
         // Throw in a literal absolute - Should function identically to above
         var absoluteButton = new Button { Text = "X = 30, Y = 1", X = 30, Y = 1 };
         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
         // Demonstrate using Dim to create a window that fills the parent with a margin
         var margin = 10;
         var margin = 10;
@@ -84,7 +82,7 @@ public class ComputedLayout : Scenario
                                   subWin.Title =
                                   subWin.Title =
                                       $"{subWin.GetType ().Name} {{X={subWin.X},Y={subWin.Y},Width={subWin.Width},Height={subWin.Height}}}";
                                       $"{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 i = 1;
         var txt = "Resize the terminal to see computed layout in action.";
         var txt = "Resize the terminal to see computed layout in action.";
@@ -209,7 +207,7 @@ public class ComputedLayout : Scenario
                        }
                        }
                       );
                       );
         frameView.Add (labelList.ToArray ());
         frameView.Add (labelList.ToArray ());
-        Top.Add (frameView);
+        app.Add (frameView);
 
 
         frameView = new FrameView
         frameView = new FrameView
         {
         {
@@ -223,7 +221,7 @@ public class ComputedLayout : Scenario
                                      fv.Title =
                                      fv.Title =
                                          $"{frameView.GetType ().Name} {{X={fv.X},Y={fv.Y},Width={fv.Width},Height={fv.Height}}}";
                                          $"{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
         // Demonstrate Dim & Pos using percentages - a TextField that is 30% height and 80% wide
         var textView = new TextView
         var textView = new TextView
@@ -237,7 +235,7 @@ public class ComputedLayout : Scenario
 
 
         textView.Text =
         textView.Text =
             "This TextView should horizontally & vertically centered and \n10% of the screeen height, and 80% of its width.";
             "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
         var oddballButton = new Button
         {
         {
@@ -245,7 +243,7 @@ public class ComputedLayout : Scenario
             X = Pos.Center (),
             X = Pos.Center (),
             Y = Pos.Bottom (textView) + 1
             Y = Pos.Bottom (textView) + 1
         };
         };
-        Top.Add (oddballButton);
+        app.Add (oddballButton);
 
 
         #region Issue2358
         #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
         // 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) };
         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) };
         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) };
         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) };
         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) };
         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)
         // 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
         // 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),
             X = Pos.Center () + Pos.Center () - Pos.Percent (50),
             Y = Pos.Bottom (oddballButton)
             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)
         // 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
         // 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),
             X = Pos.Percent (50) + Pos.Center () - Pos.Percent (50),
             Y = Pos.Bottom (oddballButton)
             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)
         // 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
         // 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),
             X = Pos.Center () + Pos.Percent (50) - Pos.Percent (50),
             Y = Pos.Bottom (oddballButton)
             Y = Pos.Bottom (oddballButton)
         };
         };
-        Top.Add (oddballButton);
+        app.Add (oddballButton);
 
 
         #endregion
         #endregion
 
 
@@ -306,29 +304,29 @@ public class ComputedLayout : Scenario
             X = Pos.Center () + Pos.Center () - Pos.Percent (50),
             X = Pos.Center () + Pos.Center () - Pos.Percent (50),
             Y = Pos.Bottom (oddballButton)
             Y = Pos.Bottom (oddballButton)
         };
         };
-        Top.Add (oddballButton);
+        app.Add (oddballButton);
 
 
         // This demonstrates combining Percents)
         // This demonstrates combining Percents)
         oddballButton = new Button
         oddballButton = new Button
         {
         {
             Text = "Percent(40) + Percent(10)", X = Pos.Percent (40) + Pos.Percent (10), Y = Pos.Bottom (oddballButton)
             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
         // 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 ()};
+        anchorButton.X = Pos.AnchorEnd ();
 
 
         anchorButton.Accept += (s, e) =>
         anchorButton.Accept += (s, e) =>
                                 {
                                 {
                                     // This demonstrates how to have a dynamically sized button
                                     // This demonstrates how to have a dynamically sized button
                                     // Each time the button is clicked the button's text gets longer
                                     // 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. 
                                     // get updated. 
                                     anchorButton.Text += "!";
                                     anchorButton.Text += "!";
-                                    Top.LayoutSubviews ();
+                                    app.LayoutSubviews ();
                                 };
                                 };
-        Top.Add (anchorButton);
+        app.Add (anchorButton);
 
 
         // Demonstrate AnchorEnd(n) 
         // Demonstrate AnchorEnd(n) 
         // This is intentionally convoluted to illustrate potential bugs.
         // This is intentionally convoluted to illustrate potential bugs.
@@ -342,7 +340,7 @@ public class ComputedLayout : Scenario
             X = 5,
             X = 5,
             Y = Pos.AnchorEnd (2)
             Y = Pos.AnchorEnd (2)
         };
         };
-        Top.Add (anchorEndLabel1);
+        app.Add (anchorEndLabel1);
 
 
         // Demonstrate DimCombine (via AnchorEnd(n) - 1)
         // Demonstrate DimCombine (via AnchorEnd(n) - 1)
         // This is intentionally convoluted to illustrate potential bugs.
         // This is intentionally convoluted to illustrate potential bugs.
@@ -357,22 +355,22 @@ public class ComputedLayout : Scenario
             X = 5,
             X = 5,
             Y = Pos.AnchorEnd (2) - 1 // Pos.Combine
             Y = Pos.AnchorEnd (2) - 1 // Pos.Combine
         };
         };
-        Top.Add (anchorEndLabel2);
+        app.Add (anchorEndLabel2);
 
 
         // Show positioning vertically using Pos.AnchorEnd via Pos.Combine
         // Show positioning vertically using Pos.AnchorEnd via Pos.Combine
         var leftButton = new Button
         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) =>
         leftButton.Accept += (s, e) =>
                               {
                               {
                                   // This demonstrates how to have a dynamically sized button
                                   // This demonstrates how to have a dynamically sized button
                                   // Each time the button is clicked the button's text gets longer
                                   // 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. 
                                   // get updated. 
                                   leftButton.Text += "!";
                                   leftButton.Text += "!";
-                                  Top.LayoutSubviews ();
+                                  app.LayoutSubviews ();
                               };
                               };
 
 
         // show positioning vertically using Pos.AnchorEnd
         // show positioning vertically using Pos.AnchorEnd
@@ -385,10 +383,10 @@ public class ComputedLayout : Scenario
                                 {
                                 {
                                     // This demonstrates how to have a dynamically sized button
                                     // This demonstrates how to have a dynamically sized button
                                     // Each time the button is clicked the button's text gets longer
                                     // 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. 
                                     // get updated. 
                                     centerButton.Text += "!";
                                     centerButton.Text += "!";
-                                    Top.LayoutSubviews ();
+                                    app.LayoutSubviews ();
                                 };
                                 };
 
 
         // show positioning vertically using another window and Pos.Bottom
         // 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
                                    // This demonstrates how to have a dynamically sized button
                                    // Each time the button is clicked the button's text gets longer
                                    // 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. 
                                    // get updated. 
                                    rightButton.Text += "!";
                                    rightButton.Text += "!";
-                                   Top.LayoutSubviews ();
+                                   app.LayoutSubviews ();
                                };
                                };
 
 
         // Center three buttons with 5 spaces between them
         // Center three buttons with 5 spaces between them
         leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
         leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
         rightButton.X = Pos.Right (centerButton) + 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 ();
     }
     }
 }
 }

+ 4 - 13
UICatalog/Scenarios/ContentScrolling.cs

@@ -321,7 +321,7 @@ public class ContentScrolling : Scenario
         // Add demo views to show that things work correctly
         // Add demo views to show that things work correctly
         var textField = new TextField { X = 20, Y = 7, Width = 15, Text = "Test TextField" };
         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.BorderStyle = LineStyle.RoundedDotted;
 
 
         colorPicker.ColorChanged += (s, e) =>
         colorPicker.ColorChanged += (s, e) =>
@@ -358,18 +358,9 @@ public class ContentScrolling : Scenario
         charMap.Accept += (s, e) =>
         charMap.Accept += (s, e) =>
                               MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
                               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";
         view.Margin.Data = "Margin";
@@ -380,7 +371,7 @@ public class ContentScrolling : Scenario
 
 
         view.Padding.Data = "Padding";
         view.Padding.Data = "Padding";
 
 
-        view.Add (buttonAnchoredRight, textField, colorPicker, charMap, textView, labelAnchoredBottomLeft);
+        view.Add (buttonAnchored, textField, colorPicker, charMap, textView);
 
 
         var longLabel = new Label
         var longLabel = new Label
         {
         {

+ 2 - 2
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -604,7 +604,7 @@ public class DynamicMenuBar : Scenario
 
 
             var _btnRemoveMenuBar = new Button { Y = 1, Text = "Remove a MenuBar" };
             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);
             _frmMenu.Add (_btnRemoveMenuBar);
 
 
             var _btnPrevious = new Button
             var _btnPrevious = new Button
@@ -614,7 +614,7 @@ public class DynamicMenuBar : Scenario
             _frmMenu.Add (_btnPrevious);
             _frmMenu.Add (_btnPrevious);
 
 
             var _btnAdd = new Button { Y = Pos.Top (_btnPrevious) + 2, Text = " Add  " };
             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 ();
             _frmMenu.Add (_btnAdd);
             _frmMenu.Add (_btnAdd);
 
 
             var _btnNext = new Button { X = Pos.X (_btnAdd), Y = Pos.Top (_btnPrevious), Text = ">" };
             var _btnNext = new Button { X = Pos.X (_btnAdd), Y = Pos.Top (_btnPrevious), Text = ">" };

+ 2 - 2
UICatalog/Scenarios/DynamicStatusBar.cs

@@ -371,11 +371,11 @@ public class DynamicStatusBar : Scenario
 
 
             var _btnRemoveStatusBar = new Button { Y = 1, Text = "Remove a StatusBar" };
             var _btnRemoveStatusBar = new Button { Y = 1, Text = "Remove a StatusBar" };
 
 
-            _btnRemoveStatusBar.X = Pos.AnchorEnd () - (Pos.Right (_btnRemoveStatusBar) - Pos.Left (_btnRemoveStatusBar));
+            _btnRemoveStatusBar.X = Pos.AnchorEnd ();
             _frmStatusBar.Add (_btnRemoveStatusBar);
             _frmStatusBar.Add (_btnRemoveStatusBar);
 
 
             var _btnAdd = new Button { Y = Pos.Top (_btnRemoveStatusBar) + 2, Text = " Add  " };
             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);
             _frmStatusBar.Add (_btnAdd);
             _frmStatusBar.Add (_btnAdd);
 
 
             _lstItems = new ListView
             _lstItems = new ListView

+ 52 - 58
UICatalog/Scenarios/HotKeys.cs

@@ -4,108 +4,102 @@ namespace UICatalog.Scenarios;
 
 
 [ScenarioMetadata ("HotKeys", "Demonstrates how HotKeys work.")]
 [ScenarioMetadata ("HotKeys", "Demonstrates how HotKeys work.")]
 [ScenarioCategory ("Controls")]
 [ScenarioCategory ("Controls")]
-[ScenarioCategory("Mouse and Keyboard")]
+[ScenarioCategory ("Mouse and Keyboard")]
 public class HotKeys : Scenario
 public class HotKeys : Scenario
 {
 {
-    public override void Init ()
+    public override void Main ()
     {
     {
         Application.Init ();
         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 };
         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 };
         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,
             CanFocus = true,
             X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
             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)",
             Title = "View (n_ot focusable)",
             Text = "Text renders _Underscore",
             Text = "Text renders _Underscore",
             X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
             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 };
         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,
             AutoSize = false,
             Title = "Label _with Frame (focusable)",
             Title = "Label _with Frame (focusable)",
             CanFocus = true,
             CanFocus = true,
             X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
             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,
             AutoSize = false,
             Title = "Label with Frame (_not focusable)",
             Title = "Label with Frame (_not focusable)",
             X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
             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 };
         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,
             AutoSize = false,
             Title = "B_utton with Frame (focusable)",
             Title = "B_utton with Frame (focusable)",
             CanFocus = true,
             CanFocus = true,
             X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
             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,
             AutoSize = false,
             Title = "Button with Frame (not focusab_le)",
             Title = "Button with Frame (not focusab_le)",
             X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
             X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
             CanFocus = false,
             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 };
         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
         var checkboxWithFrameFocusable = new CheckBox
         {
         {
@@ -113,12 +107,12 @@ public class HotKeys : Scenario
             Title = "C_heckbox with Frame (focusable)",
             Title = "C_heckbox with Frame (focusable)",
             CanFocus = true,
             CanFocus = true,
             X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
             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
         var checkboxWithFrame = new CheckBox
         {
         {
@@ -126,14 +120,14 @@ public class HotKeys : Scenario
             Title = "Checkbox with Frame (not focusable)",
             Title = "Checkbox with Frame (not focusable)",
             X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
             X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
             CanFocus = false,
             CanFocus = false,
-            BorderStyle = LineStyle.Dashed,
+            BorderStyle = LineStyle.Dashed
         };
         };
-        Top.Add (checkboxWithFrame);
-
+        app.Add (checkboxWithFrame);
 
 
-        var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), Text = "_Press me!" };
-        Top.Add (button);
+        var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), Text = "_Press me!" };
+        app.Add (button);
 
 
-        Application.Run (Top);
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 12 - 16
UICatalog/Scenarios/LineCanvasExperiment.cs

@@ -8,21 +8,14 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Proof of Concept")]
 [ScenarioCategory ("Proof of Concept")]
 public class LineCanvasExperiment : Scenario
 public class LineCanvasExperiment : Scenario
 {
 {
-    public override void Init ()
+    public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        Top = new ();
-    }
-
-    /// <summary>Setup the scenario.</summary>
-    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
         var frame1 = new FrameView
         {
         {
@@ -37,7 +30,7 @@ public class LineCanvasExperiment : Scenario
 
 
         //View.Diagnostics ^= DiagnosticFlags.FrameRuler;
         //View.Diagnostics ^= DiagnosticFlags.FrameRuler;
 
 
-        Top.Add (frame1);
+        app.Add (frame1);
 
 
         var win1 = new Window
         var win1 = new Window
         {
         {
@@ -52,7 +45,7 @@ public class LineCanvasExperiment : Scenario
             BorderStyle = LineStyle.Heavy,
             BorderStyle = LineStyle.Heavy,
             SuperViewRendersLineCanvas = true
             SuperViewRendersLineCanvas = true
         };
         };
-        win1.Padding.Thickness = new Thickness (1);
+        win1.Padding.Thickness = new (1);
 
 
         frame1.Add (win1);
         frame1.Add (win1);
 
 
@@ -140,9 +133,12 @@ public class LineCanvasExperiment : Scenario
             SuperViewRendersLineCanvas = true
             SuperViewRendersLineCanvas = true
         };
         };
         marginWindow.Margin.ColorScheme = Colors.ColorSchemes ["Dialog"];
         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);
         frame1.Add (marginWindow);
+
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 2 - 2
UICatalog/Scenarios/Scrolling.cs

@@ -122,10 +122,10 @@ public class Scrolling : Scenario
                        );
                        );
 
 
         // Demonstrate AnchorEnd - Button is anchored to bottom/right
         // 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)
         // 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) =>
         anchorButton.Accept += (s, e) =>
                                {
                                {

+ 34 - 24
UICatalog/Scenarios/TextAlignmentsAndDirection.cs

@@ -10,14 +10,21 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Text and Formatting")]
 [ScenarioCategory ("Text and Formatting")]
 public class TextAlignmentsAndDirections : Scenario
 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...\n.....\nHELLO\n.....\n...\n.";
         // string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘";
         // string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘";
         var txt = "HELLO WORLD";
         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<Label> txts = new (); // single line
         List<Label> txts = new (); // single line
         List<Label> mtxts = new (); // multi line
         List<Label> mtxts = new (); // multi line
@@ -125,14 +132,14 @@ public class TextAlignmentsAndDirections : Scenario
         txts.Add (txtLabelHR);
         txts.Add (txtLabelHR);
         txts.Add (txtLabelHJ);
         txts.Add (txtLabelHJ);
 
 
-        Win.Add (labelHL);
-        Win.Add (txtLabelHL);
-        Win.Add (labelHC);
-        Win.Add (txtLabelHC);
-        Win.Add (labelHR);
-        Win.Add (txtLabelHR);
-        Win.Add (labelHJ);
-        Win.Add (txtLabelHJ);
+        app.Add (labelHL);
+        app.Add (txtLabelHL);
+        app.Add (labelHC);
+        app.Add (txtLabelHC);
+        app.Add (labelHR);
+        app.Add (txtLabelHR);
+        app.Add (labelHJ);
+        app.Add (txtLabelHJ);
 
 
         // Vertical Single-Line
         // Vertical Single-Line
 
 
@@ -245,14 +252,14 @@ public class TextAlignmentsAndDirections : Scenario
         txts.Add (txtLabelVB);
         txts.Add (txtLabelVB);
         txts.Add (txtLabelVJ);
         txts.Add (txtLabelVJ);
 
 
-        Win.Add (labelVT);
-        Win.Add (txtLabelVT);
-        Win.Add (labelVM);
-        Win.Add (txtLabelVM);
-        Win.Add (labelVB);
-        Win.Add (txtLabelVB);
-        Win.Add (labelVJ);
-        Win.Add (txtLabelVJ);
+        app.Add (labelVT);
+        app.Add (txtLabelVT);
+        app.Add (labelVM);
+        app.Add (txtLabelVM);
+        app.Add (labelVB);
+        app.Add (txtLabelVB);
+        app.Add (labelVJ);
+        app.Add (txtLabelVJ);
 
 
         // Multi-Line
         // Multi-Line
 
 
@@ -410,7 +417,7 @@ public class TextAlignmentsAndDirections : Scenario
         container.Add (txtLabelBC);
         container.Add (txtLabelBC);
         container.Add (txtLabelBR);
         container.Add (txtLabelBR);
 
 
-        Win.Add (container);
+        app.Add (container);
 
 
         // Edit Text
         // Edit Text
 
 
@@ -437,7 +444,7 @@ public class TextAlignmentsAndDirections : Scenario
                                    }
                                    }
                                };
                                };
 
 
-        Win.KeyUp += (s, m) =>
+        app.KeyUp += (s, m) =>
                      {
                      {
                          foreach (Label v in txts)
                          foreach (Label v in txts)
                          {
                          {
@@ -452,7 +459,7 @@ public class TextAlignmentsAndDirections : Scenario
 
 
         editText.SetFocus ();
         editText.SetFocus ();
 
 
-        Win.Add (editText);
+        app.Add (editText);
 
 
         // JUSTIFY CHECKBOX
         // JUSTIFY CHECKBOX
 
 
@@ -494,7 +501,7 @@ public class TextAlignmentsAndDirections : Scenario
                                        }
                                        }
                                    };
                                    };
 
 
-        Win.Add (justifyCheckbox);
+        app.Add (justifyCheckbox);
 
 
         // Direction Options
         // Direction Options
 
 
@@ -518,6 +525,9 @@ public class TextAlignmentsAndDirections : Scenario
                                                     }
                                                     }
                                                 };
                                                 };
 
 
-        Win.Add (directionOptions);
+        app.Add (directionOptions);
+
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 61 - 49
UICatalog/Scenarios/TrueColors.cs

@@ -7,8 +7,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Colors")]
 [ScenarioCategory ("Colors")]
 public class TrueColors : Scenario
 public class TrueColors : Scenario
 {
 {
-    public override void Setup ()
+    public override void Main ()
     {
     {
+        Application.Init ();
+
+        Window app = new ()
+        {
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+        };
+
         var x = 2;
         var x = 2;
         var y = 1;
         var y = 1;
 
 
@@ -18,7 +25,7 @@ public class TrueColors : Scenario
         {
         {
             X = x, Y = y++, Text = $"Current driver is {Application.Driver.GetType ().Name}"
             X = x, Y = y++, Text = $"Current driver is {Application.Driver.GetType ().Name}"
         };
         };
-        Win.Add (lblDriverName);
+        app.Add (lblDriverName);
         y++;
         y++;
 
 
         var cbSupportsTrueColor = new CheckBox
         var cbSupportsTrueColor = new CheckBox
@@ -29,7 +36,7 @@ public class TrueColors : Scenario
             CanFocus = false,
             CanFocus = false,
             Text = "Driver supports true color "
             Text = "Driver supports true color "
         };
         };
-        Win.Add (cbSupportsTrueColor);
+        app.Add (cbSupportsTrueColor);
 
 
         var cbUseTrueColor = new CheckBox
         var cbUseTrueColor = new CheckBox
         {
         {
@@ -40,53 +47,53 @@ public class TrueColors : Scenario
             Text = "Force 16 colors"
             Text = "Force 16 colors"
         };
         };
         cbUseTrueColor.Toggled += (_, evt) => { Application.Force16Colors = evt.NewValue ?? false; };
         cbUseTrueColor.Toggled += (_, evt) => { Application.Force16Colors = evt.NewValue ?? false; };
-        Win.Add (cbUseTrueColor);
+        app.Add (cbUseTrueColor);
 
 
         y += 2;
         y += 2;
-        SetupGradient ("Red gradient", x, ref y, i => new Color (i, 0));
-        SetupGradient ("Green gradient", x, ref y, i => new Color (0, i));
-        SetupGradient ("Blue gradient", x, ref y, i => new Color (0, 0, i));
-        SetupGradient ("Yellow gradient", x, ref y, i => new Color (i, i));
-        SetupGradient ("Magenta gradient", x, ref y, i => new Color (i, 0, i));
-        SetupGradient ("Cyan gradient", x, ref y, i => new Color (0, i, i));
-        SetupGradient ("Gray gradient", x, ref y, i => new Color (i, i, i));
-
-        Win.Add (
+        SetupGradient ("Red gradient", x, ref y, i => new (i, 0));
+        SetupGradient ("Green gradient", x, ref y, i => new (0, i));
+        SetupGradient ("Blue gradient", x, ref y, i => new (0, 0, i));
+        SetupGradient ("Yellow gradient", x, ref y, i => new (i, i));
+        SetupGradient ("Magenta gradient", x, ref y, i => new (i, 0, i));
+        SetupGradient ("Cyan gradient", x, ref y, i => new (0, i, i));
+        SetupGradient ("Gray gradient", x, ref y, i => new (i, i, i));
+
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 2, Text = "Mouse over to get the gradient view color:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 2, Text = "Mouse over to get the gradient view color:" }
                 );
                 );
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 4, Text = "Red:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 4, Text = "Red:" }
                 );
                 );
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 5, Text = "Green:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 5, Text = "Green:" }
                 );
                 );
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 6, Text = "Blue:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 6, Text = "Blue:" }
                 );
                 );
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 8, Text = "Darker:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 8, Text = "Darker:" }
                 );
                 );
 
 
-        Win.Add (
+        app.Add (
                  new Label { X = Pos.AnchorEnd (44), Y = 9, Text = "Lighter:" }
                  new Label { X = Pos.AnchorEnd (44), Y = 9, Text = "Lighter:" }
                 );
                 );
 
 
         var lblRed = new Label { X = Pos.AnchorEnd (32), Y = 4, Text = "na" };
         var lblRed = new Label { X = Pos.AnchorEnd (32), Y = 4, Text = "na" };
-        Win.Add (lblRed);
+        app.Add (lblRed);
         var lblGreen = new Label { X = Pos.AnchorEnd (32), Y = 5, Text = "na" };
         var lblGreen = new Label { X = Pos.AnchorEnd (32), Y = 5, Text = "na" };
-        Win.Add (lblGreen);
+        app.Add (lblGreen);
         var lblBlue = new Label { X = Pos.AnchorEnd (32), Y = 6, Text = "na" };
         var lblBlue = new Label { X = Pos.AnchorEnd (32), Y = 6, Text = "na" };
-        Win.Add (lblBlue);
+        app.Add (lblBlue);
 
 
         var lblDarker = new Label { X = Pos.AnchorEnd (32), Y = 8, Text = "     " };
         var lblDarker = new Label { X = Pos.AnchorEnd (32), Y = 8, Text = "     " };
-        Win.Add (lblDarker);
+        app.Add (lblDarker);
 
 
         var lblLighter = new Label { X = Pos.AnchorEnd (32), Y = 9, Text = "    " };
         var lblLighter = new Label { X = Pos.AnchorEnd (32), Y = 9, Text = "    " };
-        Win.Add (lblLighter);
+        app.Add (lblLighter);
 
 
         Application.MouseEvent += (s, e) =>
         Application.MouseEvent += (s, e) =>
                                   {
                                   {
@@ -94,16 +101,17 @@ public class TrueColors : Scenario
                                       {
                                       {
                                           return;
                                           return;
                                       }
                                       }
+
                                       if (e.Flags == MouseFlags.Button1Clicked)
                                       if (e.Flags == MouseFlags.Button1Clicked)
                                       {
                                       {
                                           Attribute normal = e.View.GetNormalColor ();
                                           Attribute normal = e.View.GetNormalColor ();
-                                          
-                                          lblLighter.ColorScheme = new ColorScheme(e.View.ColorScheme)
+
+                                          lblLighter.ColorScheme = new (e.View.ColorScheme)
                                           {
                                           {
-                                              Normal = new Attribute (
-                                                                      normal.Foreground,
-                                                                      normal.Background.GetHighlightColor ()
-                                                                     )
+                                              Normal = new (
+                                                            normal.Foreground,
+                                                            normal.Background.GetHighlightColor ()
+                                                           )
                                           };
                                           };
                                       }
                                       }
                                       else
                                       else
@@ -114,31 +122,35 @@ public class TrueColors : Scenario
                                           lblBlue.Text = normal.Foreground.B.ToString ();
                                           lblBlue.Text = normal.Foreground.B.ToString ();
                                       }
                                       }
                                   };
                                   };
-    }
+        Application.Run (app);
+        app.Dispose ();
 
 
-    private void SetupGradient (string name, int x, ref int y, Func<int, Color> colorFunc)
-    {
-        var gradient = new Label { X = x, Y = y++, Text = name };
-        Win.Add (gradient);
+        return;
 
 
-        for (int dx = x, i = 0; i <= 256; i += 4)
+        void SetupGradient (string name, int x, ref int y, Func<int, Color> colorFunc)
         {
         {
-            var l = new Label
+            var gradient = new Label { X = x, Y = y++, Text = name };
+            app.Add (gradient);
+
+            for (int dx = x, i = 0; i <= 256; i += 4)
             {
             {
-                X = dx++,
-                Y = y,
-                ColorScheme = new ColorScheme
+                var l = new Label
                 {
                 {
-                    Normal = new Attribute (
-                                            colorFunc (Math.Clamp (i, 0, 255)),
-                                            colorFunc (Math.Clamp (i, 0, 255))
-                                           )
-                },
-                Text = " "
-            };
-            Win.Add (l);
+                    X = dx++,
+                    Y = y,
+                    ColorScheme = new()
+                    {
+                        Normal = new (
+                                      colorFunc (Math.Clamp (i, 0, 255)),
+                                      colorFunc (Math.Clamp (i, 0, 255))
+                                     )
+                    },
+                    Text = " "
+                };
+                app.Add (l);
+            }
+
+            y += 2;
         }
         }
-
-        y += 2;
     }
     }
 }
 }

+ 16 - 16
UICatalog/Scenarios/ViewExperiments.cs

@@ -9,17 +9,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Proof of Concept")]
 [ScenarioCategory ("Proof of Concept")]
 public class ViewExperiments : Scenario
 public class ViewExperiments : Scenario
 {
 {
-    public override void Init ()
+    public override void Main ()
     {
     {
         Application.Init ();
         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 ()}"
+        };
+
         var containerLabel = new Label
         var containerLabel = new Label
         {
         {
             X = 0,
             X = 0,
@@ -28,7 +26,7 @@ public class ViewExperiments : Scenario
             Width = Dim.Fill (),
             Width = Dim.Fill (),
             Height = 3
             Height = 3
         };
         };
-        Top.Add (containerLabel);
+        app.Add (containerLabel);
 
 
         var view = new View
         var view = new View
         {
         {
@@ -41,7 +39,7 @@ public class ViewExperiments : Scenario
             Id = "DaView"
             Id = "DaView"
         };
         };
 
 
-        //Top.Add (view);
+        //app.Add (view);
 
 
         view.Margin.Thickness = new Thickness (2, 2, 2, 2);
         view.Margin.Thickness = new Thickness (2, 2, 2, 2);
         view.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
         view.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
@@ -199,8 +197,7 @@ public class ViewExperiments : Scenario
         };
         };
         view.Add (edit);
         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 = new TextField { Text = "AnchorEnd ();AnchorEnd ()", X = Pos.AnchorEnd(), Y = Pos.AnchorEnd (), Width = 30, Height = 1 };
         view.Add (edit);
         view.Add (edit);
 
 
         edit = new TextField
         edit = new TextField
@@ -217,9 +214,9 @@ public class ViewExperiments : Scenario
                                {
                                {
                                    containerLabel.Text =
                                    containerLabel.Text =
                                        $"Container.Frame: {
                                        $"Container.Frame: {
-                                           Top.Frame
+                                           app.Frame
                                        } .Bounds: {
                                        } .Bounds: {
-                                           Top.Viewport
+                                           app.Viewport
                                        }\nView.Frame: {
                                        }\nView.Frame: {
                                            view.Frame
                                            view.Frame
                                        } .Viewport: {
                                        } .Viewport: {
@@ -244,11 +241,14 @@ public class ViewExperiments : Scenario
             ViewToEdit = view
             ViewToEdit = view
         };
         };
 
 
-        Top.Add (editor);
+        app.Add (editor);
         view.X = 36;
         view.X = 36;
         view.Y = 4;
         view.Y = 4;
         view.Width = Dim.Fill ();
         view.Width = Dim.Fill ();
         view.Height = Dim.Fill ();
         view.Height = Dim.Fill ();
-        Top.Add (view);
+        app.Add (view);
+
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 35 - 44
UICatalog/Scenarios/WindowsAndFrameViews.cs

@@ -8,8 +8,15 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Layout")]
 [ScenarioCategory ("Layout")]
 public class WindowsAndFrameViews : Scenario
 public class WindowsAndFrameViews : Scenario
 {
 {
-    public override void Setup ()
+    public override void Main ()
     {
     {
+        Application.Init ();
+
+        Window app = new ()
+        {
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+        };
+
         static int About ()
         static int About ()
         {
         {
             return MessageBox.Query (
             return MessageBox.Query (
@@ -26,11 +33,7 @@ public class WindowsAndFrameViews : Scenario
         // list of Windows we create
         // list of Windows we create
         List<View> listWin = new ();
         List<View> listWin = new ();
 
 
-        //Ignore the Win that UI Catalog created and create a new one
-        Top.Remove (Win);
-        Win?.Dispose ();
-
-        Win = new Window
+        var win = new Window
         {
         {
             Title = $"{listWin.Count} - Scenario: {GetName ()}",
             Title = $"{listWin.Count} - Scenario: {GetName ()}",
             X = Pos.Center (),
             X = Pos.Center (),
@@ -39,8 +42,8 @@ public class WindowsAndFrameViews : Scenario
             Height = 10,
             Height = 10,
             ColorScheme = Colors.ColorSchemes ["Dialog"]
             ColorScheme = Colors.ColorSchemes ["Dialog"]
         };
         };
-        Win.Padding.Thickness = new Thickness (padding);
-        Win.Margin.Thickness = new Thickness (margin);
+        win.Padding.Thickness = new (padding);
+        win.Margin.Thickness = new (margin);
 
 
         var paddingButton = new Button
         var paddingButton = new Button
         {
         {
@@ -50,21 +53,21 @@ public class WindowsAndFrameViews : Scenario
             Text = $"Padding of container is {padding}"
             Text = $"Padding of container is {padding}"
         };
         };
         paddingButton.Accept += (s, e) => About ();
         paddingButton.Accept += (s, e) => About ();
-        Win.Add (paddingButton);
+        win.Add (paddingButton);
 
 
-        Win.Add (
+        win.Add (
                  new Button
                  new Button
                  {
                  {
                      X = Pos.Center (),
                      X = Pos.Center (),
-                     Y = Pos.AnchorEnd (1),
+                     Y = Pos.AnchorEnd (),
                      ColorScheme = Colors.ColorSchemes ["Error"],
                      ColorScheme = Colors.ColorSchemes ["Error"],
                      Text = "Press ME! (Y = Pos.AnchorEnd(1))"
                      Text = "Press ME! (Y = Pos.AnchorEnd(1))"
                  }
                  }
                 );
                 );
-        Top.Add (Win);
+        app.Add (win);
 
 
         // add it to our list
         // add it to our list
-        listWin.Add (Win);
+        listWin.Add (win);
 
 
         // create 3 more Windows in a loop, adding them Application.Top
         // create 3 more Windows in a loop, adding them Application.Top
         // Each with a
         // Each with a
@@ -75,9 +78,9 @@ public class WindowsAndFrameViews : Scenario
         // 
         // 
         for (var pad = 0; pad < 3; pad++)
         for (var pad = 0; pad < 3; pad++)
         {
         {
-            Window win = null;
+            Window loopWin = null;
 
 
-            win = new Window
+            loopWin = new()
             {
             {
                 Title = $"{listWin.Count} - Window Loop - padding = {pad}",
                 Title = $"{listWin.Count} - Window Loop - padding = {pad}",
                 X = margin,
                 X = margin,
@@ -85,9 +88,9 @@ public class WindowsAndFrameViews : Scenario
                 Width = Dim.Fill (margin),
                 Width = Dim.Fill (margin),
                 Height = contentHeight + pad * 2 + 2
                 Height = contentHeight + pad * 2 + 2
             };
             };
-            win.Padding.Thickness = new Thickness (pad);
+            loopWin.Padding.Thickness = new (pad);
 
 
-            win.ColorScheme = Colors.ColorSchemes ["Dialog"];
+            loopWin.ColorScheme = Colors.ColorSchemes ["Dialog"];
 
 
             var pressMeButton = new Button
             var pressMeButton = new Button
             {
             {
@@ -95,8 +98,8 @@ public class WindowsAndFrameViews : Scenario
             };
             };
 
 
             pressMeButton.Accept += (s, e) =>
             pressMeButton.Accept += (s, e) =>
-                                         MessageBox.ErrorQuery (win.Title, "Neat?", "Yes", "No");
-            win.Add (pressMeButton);
+                                        MessageBox.ErrorQuery (loopWin.Title, "Neat?", "Yes", "No");
+            loopWin.Add (pressMeButton);
 
 
             var subWin = new Window
             var subWin = new Window
             {
             {
@@ -110,9 +113,9 @@ public class WindowsAndFrameViews : Scenario
             };
             };
 
 
             subWin.Add (
             subWin.Add (
-                        new TextField { Y = 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Edit me! " + win.Title }
+                        new TextField { Y = 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Edit me! " + loopWin.Title }
                        );
                        );
-            win.Add (subWin);
+            loopWin.Add (subWin);
 
 
             var frameView = new FrameView
             var frameView = new FrameView
             {
             {
@@ -128,27 +131,15 @@ public class WindowsAndFrameViews : Scenario
             frameView.Add (
             frameView.Add (
                            new TextField { Y = 1, Text = "Edit Me!" }
                            new TextField { Y = 1, Text = "Edit Me!" }
                           );
                           );
-            win.Add (frameView);
+            loopWin.Add (frameView);
 
 
-            Top.Add (win);
-            listWin.Add (win);
+            app.Add (loopWin);
+            listWin.Add (loopWin);
         }
         }
 
 
-        // Add a FrameView (frame) to Application.Top
-        // Position it at Bottom, using the list of Windows we created above.
-        // Fill it with
-        //   a label
-        //   a SubWindow containing (subWinofFV)
-        //      a TextField
-        //	    two checkboxes
-        //   a Sub FrameView containing (subFrameViewofFV)
-        //      a TextField
-        //      two CheckBoxes	
-        //   a checkbox
-        //   a checkbox
         FrameView frame = null;
         FrameView frame = null;
 
 
-        frame = new FrameView
+        frame = new()
         {
         {
             X = margin,
             X = margin,
             Y = Pos.Bottom (listWin.Last ()) + margin / 2,
             Y = Pos.Bottom (listWin.Last ()) + margin / 2,
@@ -199,22 +190,22 @@ public class WindowsAndFrameViews : Scenario
 
 
         subFrameViewofFV.Add (new CheckBox { Y = 1, Text = "Check me" });
         subFrameViewofFV.Add (new CheckBox { Y = 1, Text = "Check me" });
 
 
-        // BUGBUG: This checkbox is not shown even though frameViewFV has 3 rows in 
-        // its client area. #522
         subFrameViewofFV.Add (new CheckBox { Y = 2, Text = "Or, Check me" });
         subFrameViewofFV.Add (new CheckBox { Y = 2, Text = "Or, Check me" });
 
 
         frame.Add (
         frame.Add (
-                   new CheckBox { X = 0, Y = Pos.AnchorEnd (1), Text = "Btn1 (Y = Pos.AnchorEnd (1))" }
+                   new CheckBox { X = 0, Y = Pos.AnchorEnd (), Text = "Btn1 (Y = Pos.AnchorEnd ())" }
                   );
                   );
-        var c = new CheckBox { Y = Pos.AnchorEnd (1), Text = "Btn2 (Y = Pos.AnchorEnd (1))" };
-        c.X = Pos.AnchorEnd () - (Pos.Right (c) - Pos.Left (c));
+        var c = new CheckBox { X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Btn2 (Y = Pos.AnchorEnd ())" };
         frame.Add (c);
         frame.Add (c);
 
 
         frame.Add (subFrameViewofFV);
         frame.Add (subFrameViewofFV);
 
 
-        Top.Add (frame);
+        app.Add (frame);
         listWin.Add (frame);
         listWin.Add (frame);
 
 
-        Top.ColorScheme = Colors.ColorSchemes ["Base"];
+        app.ColorScheme = Colors.ColorSchemes ["Base"];
+
+        Application.Run (app);
+        app.Dispose ();
     }
     }
 }
 }

+ 297 - 0
UnitTests/View/Layout/AnchorEndTests.cs

@@ -0,0 +1,297 @@
+using Xunit.Abstractions;
+using static Terminal.Gui.Pos;
+
+namespace Terminal.Gui.ViewTests;
+
+public class AnchorEndTests (ITestOutputHelper output)
+{
+    [Fact]
+    public void PosAnchorEnd_Constructor ()
+    {
+        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<PosAnchorEnd> (pos);
+    }
+
+    [Fact]
+    public void AnchorEnd_Negative_Throws ()
+    {
+        Pos pos;
+        int n = -1;
+        Assert.Throws<ArgumentException> (() => 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)]
+    [InlineData (25, 10, 0)]
+    [InlineData (26, 10, -1)]
+    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);
+    }
+
+    // UseDimForOffset tests
+
+    [Fact]
+    public void AnchorEnd_UseDimForOffset_CreatesCorrectInstance ()
+    {
+        var pos = Pos.AnchorEnd ();
+        Assert.IsType<PosAnchorEnd> (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)]
+    [InlineData (9, 16)]
+    [InlineData (11, 14)]
+    [InlineData (25, 0)]
+    [InlineData (26, -1)]
+    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 = dim,
+            Height = 1
+        };
+        superView.Add (view);
+        superView.BeginInit ();
+        superView.EndInit ();
+
+        // Act
+        superView.LayoutSubviews ();
+
+        // Assert
+        Assert.Equal (expectedXPosition, view.Frame.X);
+    }
+
+    [Theory]
+    [InlineData (0, 25)]
+    [InlineData (10, 23)]
+    [InlineData (50, 13)]
+    [InlineData (100, 0)]
+    public void AnchorEnd_UseDimForOffset_DimPercent_PositionsViewOffsetByDim (int percent, int expectedXPosition)
+    {
+        // Arrange
+        var superView = new View { Width = 25, Height = 25 };
+        var view = new View
+        {
+            X = Pos.AnchorEnd (),
+            Width = Dim.Percent ( percent),
+            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]
+    [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);
+    }
+
+}

+ 55 - 2
UnitTests/View/Layout/DimTests.cs

@@ -1,6 +1,8 @@
 using System.Globalization;
 using System.Globalization;
 using System.Text;
 using System.Text;
 using Xunit.Abstractions;
 using Xunit.Abstractions;
+using static Terminal.Gui.Dim;
+
 
 
 // Alias Console to MockConsole so we don't accidentally use Console
 // Alias Console to MockConsole so we don't accidentally use Console
 using Console = Terminal.Gui.FakeConsole;
 using Console = Terminal.Gui.FakeConsole;
@@ -22,6 +24,57 @@ public class DimTests
         Thread.CurrentThread.CurrentUICulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;
     }
     }
 
 
+    [Fact]
+    public void DimAbsolute_GetDimension_ReturnsCorrectValue ()
+    {
+        var dim = new DimAbsolute (10);
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (10, result);
+    }
+
+    [Fact]
+    public void DimCombine_GetDimension_ReturnsCorrectValue ()
+    {
+        var dim1 = new DimAbsolute (10);
+        var dim2 = new DimAbsolute (20);
+        var dim = dim1 + dim2;
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (30, result);
+    }
+
+    [Fact]
+    public void DimFactor_GetDimension_ReturnsCorrectValue ()
+    {
+        var dim = new DimFactor (0.5f);
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (50, result);
+    }
+
+    [Fact]
+    public void DimFill_GetDimension_ReturnsCorrectValue ()
+    {
+        var dim = Dim.Fill ();
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (100, result);
+    }
+
+    [Fact]
+    public void DimFunc_GetDimension_ReturnsCorrectValue ()
+    {
+        var dim = new DimFunc (() => 10);
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (10, result);
+    }
+
+    [Fact]
+    public void DimView_GetDimension_ReturnsCorrectValue ()
+    {
+        var view = new View { Width = 10 };
+        var dim = new DimView (view, Dimension.Width);
+        var result = dim.Calculate (0, 100, 50, false);
+        Assert.Equal (10, result);
+    }
+
     // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
     // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
     // A new test that does not depend on Application is needed.
     // A new test that does not depend on Application is needed.
     [Fact]
     [Fact]
@@ -508,9 +561,9 @@ public class DimTests
         Assert.Equal (20, dimCombine.Anchor (100));
         Assert.Equal (20, dimCombine.Anchor (100));
 
 
         var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
         var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
-        var dimViewHeight = new Dim.DimView (view, 0);
+        var dimViewHeight = new Dim.DimView (view, Dimension.Height);
         Assert.Equal (1, dimViewHeight.Anchor (0));
         Assert.Equal (1, dimViewHeight.Anchor (0));
-        var dimViewWidth = new Dim.DimView (view, 1);
+        var dimViewWidth = new Dim.DimView (view, Dimension.Width);
         Assert.Equal (20, dimViewWidth.Anchor (0));
         Assert.Equal (20, dimViewWidth.Anchor (0));
 
 
         view.Dispose ();
         view.Dispose ();

+ 90 - 187
UnitTests/View/Layout/PosTests.cs

@@ -1,165 +1,65 @@
 using Xunit.Abstractions;
 using Xunit.Abstractions;
-
-// Alias Console to MockConsole so we don't accidentally use Console
+using static Terminal.Gui.Dim;
+using static Terminal.Gui.Pos;
 
 
 namespace Terminal.Gui.ViewTests;
 namespace Terminal.Gui.ViewTests;
 
 
-public class PosTests
+public class PosTests (ITestOutputHelper output)
 {
 {
-    private readonly ITestOutputHelper _output;
-    public PosTests (ITestOutputHelper output) { _output = output; }
-
     [Fact]
     [Fact]
-    public void AnchorEnd_Equal ()
+    public void PosAbsolute_GetLocation_ReturnsExpectedValue ()
     {
     {
-        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 posAbsolute = new PosAbsolute (5);
+        var result = posAbsolute.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (5, result);
     }
     }
 
 
-    // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
-    // TODO: A new test that calls SetRelativeLayout directly is needed.
     [Fact]
     [Fact]
-    [AutoInitShutdown]
-    public void AnchorEnd_Equal_Inside_Window ()
+    public void PosAnchorEnd_GetLocation_ReturnsExpectedValue ()
     {
     {
-        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);
+        var posAnchorEnd = new PosAnchorEnd (5);
+        var result = posAnchorEnd.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (5, result);
     }
     }
 
 
-    // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
-    // TODO: A new test that calls SetRelativeLayout directly is needed.
     [Fact]
     [Fact]
-    [AutoInitShutdown]
-    public void AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
+    public void PosCenter_GetLocation_ReturnsExpectedValue ()
     {
     {
-        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);
+        var posCenter = new PosCenter ();
+        var result = posCenter.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (4, result);
     }
     }
 
 
     [Fact]
     [Fact]
-    public void AnchorEnd_Negative_Throws ()
+    public void PosCombine_GetLocation_ReturnsExpectedValue ()
     {
     {
-        Pos pos;
-        int n = -1;
-        Assert.Throws<ArgumentException> (() => pos = Pos.AnchorEnd (n));
+        var posCombine = new PosCombine (true, new PosAbsolute (5), new PosAbsolute (3));
+        var result = posCombine.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (8, result);
     }
     }
 
 
     [Fact]
     [Fact]
-    public void AnchorEnd_SetsValue ()
+    public void PosFactor_GetLocation_ReturnsExpectedValue ()
     {
     {
-        var n = 0;
-        Pos pos = Pos.AnchorEnd ();
-        Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
-
-        n = 5;
-        pos = Pos.AnchorEnd (n);
-        Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
+        var posFactor = new PosFactor (0.5f);
+        var result = posFactor.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (5, result);
     }
     }
 
 
-    // This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests.
     [Fact]
     [Fact]
-    [SetupFakeDriver]
-    public void AnchorEnd_View_And_Button ()
+    public void PosFunc_GetLocation_ReturnsExpectedValue ()
     {
     {
-        ((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 () - 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
-        };
+        var posFunc = new PosFunc (() => 5);
+        var result = posFunc.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (5, result);
+    }
 
 
-        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 PosView_GetLocation_ReturnsExpectedValue ()
+    {
+        var posView = new PosView (new View { Frame = new Rectangle (5, 5, 10, 10) }, 0);
+        var result = posView.Calculate (10, new DimAbsolute (2), 1, false);
+        Assert.Equal (5, result);
     }
     }
 
 
     [Fact]
     [Fact]
@@ -201,28 +101,28 @@ public class PosTests
         Pos pos = Pos.Left (v);
         Pos pos = Pos.Left (v);
 
 
         Assert.Equal (
         Assert.Equal (
-                      $"View(side=x,target=View(V){v.Frame})",
+                      $"View(side=left,target=View(V){v.Frame})",
                       pos.ToString ()
                       pos.ToString ()
                      );
                      );
 
 
         pos = Pos.X (v);
         pos = Pos.X (v);
 
 
         Assert.Equal (
         Assert.Equal (
-                      $"View(side=x,target=View(V){v.Frame})",
+                      $"View(side=left,target=View(V){v.Frame})",
                       pos.ToString ()
                       pos.ToString ()
                      );
                      );
 
 
         pos = Pos.Top (v);
         pos = Pos.Top (v);
 
 
         Assert.Equal (
         Assert.Equal (
-                      $"View(side=y,target=View(V){v.Frame})",
+                      $"View(side=top,target=View(V){v.Frame})",
                       pos.ToString ()
                       pos.ToString ()
                      );
                      );
 
 
         pos = Pos.Y (v);
         pos = Pos.Y (v);
 
 
         Assert.Equal (
         Assert.Equal (
-                      $"View(side=y,target=View(V){v.Frame})",
+                      $"View(side=top,target=View(V){v.Frame})",
                       pos.ToString ()
                       pos.ToString ()
                      );
                      );
 
 
@@ -291,19 +191,19 @@ public class PosTests
         Assert.Equal (posCombine._right, posAbsolute);
         Assert.Equal (posCombine._right, posAbsolute);
         Assert.Equal (20, posCombine.Anchor (100));
         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._left, posAbsolute);
         Assert.Equal (posCombine._right, posFactor);
         Assert.Equal (posCombine._right, posFactor);
         Assert.Equal (20, posCombine.Anchor (100));
         Assert.Equal (20, posCombine.Anchor (100));
 
 
-        var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
-        var posViewX = new Pos.PosView (view, 0);
+        var view = new View { Frame = new (20, 10, 20, 1) };
+        var posViewX = new Pos.PosView (view, Pos.Side.Left);
         Assert.Equal (20, posViewX.Anchor (0));
         Assert.Equal (20, posViewX.Anchor (0));
-        var posViewY = new Pos.PosView (view, 1);
+        var posViewY = new Pos.PosView (view, Pos.Side.Top);
         Assert.Equal (10, posViewY.Anchor (0));
         Assert.Equal (10, posViewY.Anchor (0));
-        var posRight = new Pos.PosView (view, 2);
+        var posRight = new Pos.PosView (view, Pos.Side.Right);
         Assert.Equal (40, posRight.Anchor (0));
         Assert.Equal (40, posRight.Anchor (0));
-        var posViewBottom = new Pos.PosView (view, 3);
+        var posViewBottom = new Pos.PosView (view, Pos.Side.Bottom);
         Assert.Equal (11, posViewBottom.Anchor (0));
         Assert.Equal (11, posViewBottom.Anchor (0));
 
 
         view.Dispose ();
         view.Dispose ();
@@ -339,6 +239,7 @@ public class PosTests
             Application.End (rs);
             Application.End (rs);
 
 
             Application.Top.Dispose ();
             Application.Top.Dispose ();
+
             // Shutdown must be called to safely clean up Application if Init has been called
             // Shutdown must be called to safely clean up Application if Init has been called
             Application.Shutdown ();
             Application.Shutdown ();
         }
         }
@@ -513,6 +414,7 @@ public class PosTests
         Assert.Equal (20, count);
         Assert.Equal (20, count);
 
 
         top.Dispose ();
         top.Dispose ();
+
         // Shutdown must be called to safely clean up Application if Init has been called
         // Shutdown must be called to safely clean up Application if Init has been called
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
@@ -582,6 +484,7 @@ public class PosTests
         Assert.Equal (0, count);
         Assert.Equal (0, count);
 
 
         top.Dispose ();
         top.Dispose ();
+
         // Shutdown must be called to safely clean up Application if Init has been called
         // Shutdown must be called to safely clean up Application if Init has been called
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
@@ -619,7 +522,7 @@ public class PosTests
         var super = new View { Width = 10, Height = 10, Text = "super" };
         var super = new View { Width = 10, Height = 10, Text = "super" };
         var view1 = new View { Width = 2, Height = 2, Text = "view1" };
         var view1 = new View { Width = 2, Height = 2, Text = "view1" };
         var view2 = new View { Width = 2, Height = 2, Text = "view2" };
         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.Add (view1, view2);
         super.BeginInit ();
         super.BeginInit ();
@@ -627,9 +530,9 @@ public class PosTests
 
 
         Exception exception = Record.Exception (super.LayoutSubviews);
         Exception exception = Record.Exception (super.LayoutSubviews);
         Assert.Null (exception);
         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 ();
         super.Dispose ();
     }
     }
@@ -714,21 +617,21 @@ public class PosTests
         Pos pos;
         Pos pos;
 
 
         // Pos.Left
         // Pos.Left
-        side = "x";
+        side = "left";
         testInt = 0;
         testInt = 0;
         testRect = Rectangle.Empty;
         testRect = Rectangle.Empty;
-        pos = Pos.Left (new View ());
+        pos = Pos.Left (new ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
         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 ());
         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 ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
 
 
         // Pos.Left(win) + 0
         // Pos.Left(win) + 0
-        pos = Pos.Left (new View { Frame = testRect }) + testInt;
+        pos = Pos.Left (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -738,7 +641,7 @@ public class PosTests
         testInt = 1;
         testInt = 1;
 
 
         // Pos.Left(win) +1
         // Pos.Left(win) +1
-        pos = Pos.Left (new View { Frame = testRect }) + testInt;
+        pos = Pos.Left (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -748,7 +651,7 @@ public class PosTests
         testInt = -1;
         testInt = -1;
 
 
         // Pos.Left(win) -1
         // Pos.Left(win) -1
-        pos = Pos.Left (new View { Frame = testRect }) - testInt;
+        pos = Pos.Left (new() { Frame = testRect }) - testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -756,21 +659,21 @@ public class PosTests
                      );
                      );
 
 
         // Pos.X
         // Pos.X
-        side = "x";
+        side = "left";
         testInt = 0;
         testInt = 0;
         testRect = Rectangle.Empty;
         testRect = Rectangle.Empty;
-        pos = Pos.X (new View ());
+        pos = Pos.X (new ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
         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 ());
         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 ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
 
 
         // Pos.X(win) + 0
         // Pos.X(win) + 0
-        pos = Pos.X (new View { Frame = testRect }) + testInt;
+        pos = Pos.X (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -780,7 +683,7 @@ public class PosTests
         testInt = 1;
         testInt = 1;
 
 
         // Pos.X(win) +1
         // Pos.X(win) +1
-        pos = Pos.X (new View { Frame = testRect }) + testInt;
+        pos = Pos.X (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -790,7 +693,7 @@ public class PosTests
         testInt = -1;
         testInt = -1;
 
 
         // Pos.X(win) -1
         // Pos.X(win) -1
-        pos = Pos.X (new View { Frame = testRect }) - testInt;
+        pos = Pos.X (new() { Frame = testRect }) - testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -798,21 +701,21 @@ public class PosTests
                      );
                      );
 
 
         // Pos.Top
         // Pos.Top
-        side = "y";
+        side = "top";
         testInt = 0;
         testInt = 0;
         testRect = Rectangle.Empty;
         testRect = Rectangle.Empty;
-        pos = Pos.Top (new View ());
+        pos = Pos.Top (new ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
         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 ());
         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 ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
 
 
         // Pos.Top(win) + 0
         // Pos.Top(win) + 0
-        pos = Pos.Top (new View { Frame = testRect }) + testInt;
+        pos = Pos.Top (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -822,7 +725,7 @@ public class PosTests
         testInt = 1;
         testInt = 1;
 
 
         // Pos.Top(win) +1
         // Pos.Top(win) +1
-        pos = Pos.Top (new View { Frame = testRect }) + testInt;
+        pos = Pos.Top (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -832,7 +735,7 @@ public class PosTests
         testInt = -1;
         testInt = -1;
 
 
         // Pos.Top(win) -1
         // Pos.Top(win) -1
-        pos = Pos.Top (new View { Frame = testRect }) - testInt;
+        pos = Pos.Top (new() { Frame = testRect }) - testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -840,21 +743,21 @@ public class PosTests
                      );
                      );
 
 
         // Pos.Y
         // Pos.Y
-        side = "y";
+        side = "top";
         testInt = 0;
         testInt = 0;
         testRect = Rectangle.Empty;
         testRect = Rectangle.Empty;
-        pos = Pos.Y (new View ());
+        pos = Pos.Y (new ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
         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 ());
         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 ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
 
 
         // Pos.Y(win) + 0
         // Pos.Y(win) + 0
-        pos = Pos.Y (new View { Frame = testRect }) + testInt;
+        pos = Pos.Y (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -864,7 +767,7 @@ public class PosTests
         testInt = 1;
         testInt = 1;
 
 
         // Pos.Y(win) +1
         // Pos.Y(win) +1
-        pos = Pos.Y (new View { Frame = testRect }) + testInt;
+        pos = Pos.Y (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -874,7 +777,7 @@ public class PosTests
         testInt = -1;
         testInt = -1;
 
 
         // Pos.Y(win) -1
         // Pos.Y(win) -1
-        pos = Pos.Y (new View { Frame = testRect }) - testInt;
+        pos = Pos.Y (new() { Frame = testRect }) - testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -885,18 +788,18 @@ public class PosTests
         side = "bottom";
         side = "bottom";
         testRect = Rectangle.Empty;
         testRect = Rectangle.Empty;
         testInt = 0;
         testInt = 0;
-        pos = Pos.Bottom (new View ());
+        pos = Pos.Bottom (new ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
         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 ());
         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 ());
         Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
 
 
         // Pos.Bottom(win) + 0
         // Pos.Bottom(win) + 0
-        pos = Pos.Bottom (new View { Frame = testRect }) + testInt;
+        pos = Pos.Bottom (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -906,7 +809,7 @@ public class PosTests
         testInt = 1;
         testInt = 1;
 
 
         // Pos.Bottom(win) +1
         // Pos.Bottom(win) +1
-        pos = Pos.Bottom (new View { Frame = testRect }) + testInt;
+        pos = Pos.Bottom (new() { Frame = testRect }) + testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
@@ -916,7 +819,7 @@ public class PosTests
         testInt = -1;
         testInt = -1;
 
 
         // Pos.Bottom(win) -1
         // Pos.Bottom(win) -1
-        pos = Pos.Bottom (new View { Frame = testRect }) - testInt;
+        pos = Pos.Bottom (new() { Frame = testRect }) - testInt;
 
 
         Assert.Equal (
         Assert.Equal (
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
                       $"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",

+ 1 - 1
UnitTests/View/Layout/SetRelativeLayoutTests.cs

@@ -405,7 +405,7 @@ public class SetRelativeLayoutTests
     {
     {
         var screen = new Size (30, 1);
         var screen = new Size (30, 1);
         var view = new View { Text = "abc", AutoSize = true }; // BUGBUG: AutoSize or Width must be set
         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; }
         int GetViewWidth () { return view.Frame.Width; }
 
 

+ 2 - 2
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 btn = new Button { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true };
         var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}";
         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 () };
         var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
         win.Add (btn);
         win.Add (btn);

+ 2 - 2
UnitTests/Views/CheckBoxTests.cs

@@ -77,7 +77,7 @@ public class CheckBoxTests
     {
     {
         var checkBox = new CheckBox { Y = Pos.Center (), Text = "C_heck this out 你" };
         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 你" };
         var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" };
         win.Add (checkBox);
         win.Add (checkBox);
@@ -121,7 +121,7 @@ public class CheckBoxTests
     {
     {
         var checkBox = new CheckBox { Y = Pos.Center (), Text = "Check this out 你" };
         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 你" };
         var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" };
         win.Add (checkBox);
         win.Add (checkBox);

+ 1 - 1
UnitTests/Views/LabelTests.cs

@@ -92,7 +92,7 @@ public class LabelTests
     public void AutoSize_Stays_True_AnchorEnd ()
     public void AutoSize_Stays_True_AnchorEnd ()
     {
     {
         var label = new Label { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true };
         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 () };
         var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
         win.Add (label);
         win.Add (label);

+ 1 - 1
docfx/docs/layout.md

@@ -55,7 +55,7 @@ The [Pos](~/api/Terminal.Gui.Pos.yml) is the type of `View.X` and `View.Y` and s
 
 
 * Absolute position, by passing an integer - `Pos.Absolute(n)`.
 * Absolute position, by passing an integer - `Pos.Absolute(n)`.
 * Percentage of the parent's view size - `Pos.Percent(percent)`.
 * Percentage of the parent's view size - `Pos.Percent(percent)`.
-* Anchored from the end of the dimension - `Pos.AnchorEnd(margin)`.
+* Anchored from the end of the dimension - `Pos.AnchorEnd()`.
 * Centered, using `Pos.Center()`.
 * Centered, using `Pos.Center()`.
 * The `Pos.Left(otherView)`, `Pos.Top(otherView)`, `Pos.Bottom(otherView)`, `Pos.Right(otherView)` positions of another view.
 * The `Pos.Left(otherView)`, `Pos.Top(otherView)`, `Pos.Bottom(otherView)`, `Pos.Right(otherView)` positions of another view.
 
 

+ 1 - 0
docfx/docs/newinv2.md

@@ -24,6 +24,7 @@ The entire library has been reviewed and simplified. As a result, the API is mor
 * *Adornments* - 
 * *Adornments* - 
 * *Built-in Scrolling/Virtual Content Area* - In v1, to have a view a user could scroll required either a bespoke scrolling implementation, inheriting from `ScrollView`, or managing the complexity of `ScrollBarView` directly. In v2, the base-View class supports scrolling inherently. The area of a view visible to the user at a given moment was previously a rectangle called `Bounds`. `Bounds.Location` was always `Point.Empty`. In v2 the visible area is a rectangle called `Viewport` which is a protal into the Views content, which can be bigger (or smaller) than the area visible to the user. Causing a view to scroll is as simple as changing `View.Viewport.Location`. The View's content described by `View.ContentSize`. See [Layout](layout.md) for details.
 * *Built-in Scrolling/Virtual Content Area* - In v1, to have a view a user could scroll required either a bespoke scrolling implementation, inheriting from `ScrollView`, or managing the complexity of `ScrollBarView` directly. In v2, the base-View class supports scrolling inherently. The area of a view visible to the user at a given moment was previously a rectangle called `Bounds`. `Bounds.Location` was always `Point.Empty`. In v2 the visible area is a rectangle called `Viewport` which is a protal into the Views content, which can be bigger (or smaller) than the area visible to the user. Causing a view to scroll is as simple as changing `View.Viewport.Location`. The View's content described by `View.ContentSize`. See [Layout](layout.md) for details.
 * *Computed Layout Improvements* - 
 * *Computed Layout Improvements* - 
+* *`Pos.AnchorEnd ()`* - New to v2 is `Pos.AnchorEnd ()` (with no parameters) which allows a view to be anchored to the right or bottom of the Superview. 
 * *`Dim.Auto`* - 
 * *`Dim.Auto`* - 
 * ...	
 * ...