Browse Source

Fixed every thing but autosize scenarios??

Tig Kindel 1 year ago
parent
commit
0e49b2aa60

+ 3 - 3
Terminal.Gui/Application.cs

@@ -196,7 +196,7 @@ public static partial class Application {
 		Current = Top;
 
 		// Ensure Top's layout is up to date.
-		Current.SetRelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows)); 
+		Current.SetRelativeLayout (Driver.Bounds); 
 		
 		_cachedSupportedCultures = GetSupportedCultures ();
 		_mainThreadId = Thread.CurrentThread.ManagedThreadId;
@@ -402,7 +402,7 @@ public static partial class Application {
 		}
 
 		//if (Toplevel.LayoutStyle == LayoutStyle.Computed) {
-			Toplevel.SetRelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows));
+			Toplevel.SetRelativeLayout (Driver.Bounds);
 		//}
 		Toplevel.LayoutSubviews ();
 		Toplevel.PositionToplevels ();
@@ -714,7 +714,7 @@ public static partial class Application {
 					&& (Driver.Cols != state.Toplevel.Frame.Width || Driver.Rows != state.Toplevel.Frame.Height)
 					&& (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded)) {
 
-			state.Toplevel.Clear (new Rect (Point.Empty, new Size (Driver.Cols, Driver.Rows)));
+			state.Toplevel.Clear (Driver.Bounds);
 		}
 
 		if (state.Toplevel.NeedsDisplay ||

+ 5 - 0
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -552,6 +552,11 @@ public abstract class ConsoleDriver {
 	/// </summary>
 	public static DiagnosticFlags Diagnostics { get; set; }
 
+	/// <summary>
+	/// Gets the dimensions of the terminal.
+	/// </summary>
+	public Rect Bounds => new Rect (0, 0, Cols, Rows);
+
 	/// <summary>
 	/// Suspends the application (e.g. on Linux via SIGTSTP) and upon resume, resets the console driver.
 	/// </summary>

+ 1347 - 1420
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -11,1433 +11,1360 @@ namespace Terminal.Gui;
 /// value from the <see cref="View.Frame"/> will be used, if the value is Computed, then <see cref="View.Frame"/>
 /// will be updated from the X, Y <see cref="Pos"/> objects and the Width and Height <see cref="Dim"/> objects.
 /// </summary>
-public enum LayoutStyle
-{
-    /// <summary>
-    /// The position and size of the view are based <see cref="View.Frame"/>.
-    /// </summary>
-    Absolute,
-
-    /// <summary>
-    /// The position and size of the view will be computed based on
-    /// <see cref="View.X"/>, <see cref="View.Y"/>, <see cref="View.Width"/>, and <see cref="View.Height"/>.
-    /// <see cref="View.Frame"/> will
-    /// provide the absolute computed values.
-    /// </summary>
-    Computed
+public enum LayoutStyle {
+	/// <summary>
+	/// The position and size of the view are based <see cref="View.Frame"/>.
+	/// </summary>
+	Absolute,
+
+	/// <summary>
+	/// The position and size of the view will be computed based on
+	/// <see cref="View.X"/>, <see cref="View.Y"/>, <see cref="View.Width"/>, and <see cref="View.Height"/>.
+	/// <see cref="View.Frame"/> will
+	/// provide the absolute computed values.
+	/// </summary>
+	Computed
 }
 
-public partial class View
-{
-    bool _autoSize;
-
-    /// <summary>
-    /// Backing property for Frame - The frame for the object. Relative to the SuperView's Bounds.
-    /// </summary>
-    Rect _frame;
-
-    /// <summary>
-    /// Gets or sets location and size of the view. The frame is relative to the <see cref="SuperView"/>'s <see cref="Bounds"/>
-    /// .
-    /// </summary>
-    /// <value>
-    /// The rectangle describing the location and size of the view, in coordinates relative to the
-    /// <see cref="SuperView"/>.
-    /// </value>
-    /// <remarks>
-    ///         <para>
-    ///         Change the Frame when using the <see cref="LayoutStyle.Absolute"/> layout style to move or resize views.
-    ///         </para>
-    ///         <para>
-    ///         Altering the Frame will change <see cref="LayoutStyle"/> to <see cref="LayoutStyle.Absolute"/>.
-    ///         Additionally, <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/> will be set
-    ///         to the values of the Frame (using <see cref="Pos.PosAbsolute"/> and <see cref="Dim.DimAbsolute"/>).
-    ///         </para>
-    ///         <para>
-    ///         Altering the Frame will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/>
-    ///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    /// </remarks>
-    public virtual Rect Frame
-    {
-        get => _frame;
-        set
-        {
-            _frame = new Rect(value.X, value.Y, Math.Max(value.Width, 0), Math.Max(value.Height, 0));
-
-            // If Frame gets set, by definition, the View is now LayoutStyle.Absolute, so
-            // set all Pos/Dim to Absolute values.
-            _x = _frame.X;
-            _y = _frame.Y;
-            _width = _frame.Width;
-            _height = _frame.Height;
-            if (IsInitialized || LayoutStyle == LayoutStyle.Absolute)
-            {
-                LayoutFrames();
-                TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey();
-                SetNeedsLayout();
-                SetNeedsDisplay();
-            }
-        }
-    }
-
-    /// <summary>
-    /// The frame (specified as a <see cref="Thickness"/>) that separates a View from other SubViews of the same SuperView.
-    /// The margin offsets the <see cref="Bounds"/> from the <see cref="Frame"/>.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
-    ///         content
-    ///         and are not clipped by the View's Clip Area.
-    ///         </para>
-    ///         <para>
-    ///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
-    ///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
-    ///         of the
-    ///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
-    ///         </para>
-    /// </remarks>
-    public Frame Margin { get; private set; }
-
-    /// <summary>
-    /// The frame (specified as a <see cref="Thickness"/>) inside of the view that offsets the <see cref="Bounds"/> from the
-    /// <see cref="Margin"/>.
-    /// The Border provides the space for a visual border (drawn using line-drawing glyphs) and the Title.
-    /// The Border expands inward; in other words if `Border.Thickness.Top == 2` the border and
-    /// title will take up the first row and the second row will be filled with spaces.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         <see cref="BorderStyle"/> provides a simple helper for turning a simple border frame on or off.
-    ///         </para>
-    ///         <para>
-    ///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
-    ///         content
-    ///         and are not clipped by the View's Clip Area.
-    ///         </para>
-    ///         <para>
-    ///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
-    ///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
-    ///         of the
-    ///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
-    ///         </para>
-    /// </remarks>
-    public Frame Border { get; private set; }
-
-    /// <summary>
-    /// Gets or sets whether the view has a one row/col thick border.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         This is a helper for manipulating the view's <see cref="Border"/>. Setting this property to any value other
-    ///         than
-    ///         <see cref="LineStyle.None"/> is equivalent to setting <see cref="Border"/>'s <see cref="Frame.Thickness"/>
-    ///         to `1` and <see cref="BorderStyle"/> to the value.
-    ///         </para>
-    ///         <para>
-    ///         Setting this property to <see cref="LineStyle.None"/> is equivalent to setting <see cref="Border"/>'s
-    ///         <see cref="Frame.Thickness"/>
-    ///         to `0` and <see cref="BorderStyle"/> to <see cref="LineStyle.None"/>.
-    ///         </para>
-    ///         <para>
-    ///         For more advanced customization of the view's border, manipulate see <see cref="Border"/> directly.
-    ///         </para>
-    /// </remarks>
-    public LineStyle BorderStyle
-    {
-        get => Border?.BorderStyle ?? LineStyle.None;
-        set
-        {
-            if (Border == null)
-            {
-                throw new InvalidOperationException("Border is null; this is likely a bug.");
-            }
-            if (value != LineStyle.None)
-            {
-                Border.Thickness = new Thickness(1);
-            }
-            else
-            {
-                Border.Thickness = new Thickness(0);
-            }
-            Border.BorderStyle = value;
-            LayoutFrames();
-            SetNeedsLayout();
-        }
-    }
-
-    /// <summary>
-    /// The frame (specified as a <see cref="Thickness"/>) inside of the view that offsets the <see cref="Bounds"/> from the
-    /// <see cref="Border"/>.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
-    ///         content
-    ///         and are not clipped by the View's Clip Area.
-    ///         </para>
-    ///         <para>
-    ///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
-    ///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
-    ///         of the
-    ///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
-    ///         </para>
-    /// </remarks>
-    public Frame Padding { get; private set; }
-
-    /// <summary>
-    /// Controls how the View's <see cref="Frame"/> is computed during <see cref="LayoutSubviews"/>. If the style is set to
-    /// <see cref="LayoutStyle.Absolute"/>, LayoutSubviews does not change the <see cref="Frame"/>.
-    /// If the style is <see cref="LayoutStyle.Computed"/> the <see cref="Frame"/> is updated using
-    /// the <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/> properties.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         Setting this property to <see cref="LayoutStyle.Absolute"/> will cause <see cref="Frame"/> to determine the
-    ///         size and position of the view. <see cref="X"/> and <see cref="Y"/> will be set to <see cref="Dim.DimAbsolute"/>
-    ///         using <see cref="Frame"/>.
-    ///         </para>
-    ///         <para>
-    ///         Setting this property to <see cref="LayoutStyle.Computed"/> will cause the view to use the
-    ///         <see cref="LayoutSubviews"/> method to
-    ///         size and position of the view. If either of the <see cref="X"/> and <see cref="Y"/> properties are `null` they
-    ///         will be set to <see cref="Pos.PosAbsolute"/> using
-    ///         the current value of <see cref="Frame"/>.
-    ///         If either of the <see cref="Width"/> and <see cref="Height"/> properties are `null` they will be set to
-    ///         <see cref="Dim.DimAbsolute"/> using <see cref="Frame"/>.
-    ///         </para>
-    /// </remarks>
-    /// <value>The layout style.</value>
-    public LayoutStyle LayoutStyle
-    {
-        get
-        {
-            if (_x is Pos.PosAbsolute && _y is Pos.PosAbsolute && _width is Dim.DimAbsolute && _height is Dim.DimAbsolute)
-            {
-                return LayoutStyle.Absolute;
-            }
-            else
-            {
-                return LayoutStyle.Computed;
-            }
-        }
-        set
-        {
-            // TODO: Remove this setter and make LayoutStyle read-only for real.
-            throw new InvalidOperationException("LayoutStyle is read-only.");
-        }
-    }
-
-    /// <summary>
-    /// The bounds represent the View-relative rectangle used for this view; the area inside of the view where subviews and
-    /// content are presented.
-    /// </summary>
-    /// <value>The rectangle describing the location and size of the area where the views' subviews and content are drawn.</value>
-    /// <remarks>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value of Bounds is indeterminate until
-    ///         the
-    ///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
-    ///         called.
-    ///         </para>
-    ///         <para>
-    ///         Updates to the Bounds updates <see cref="Frame"/>, and has the same side effects as updating the
-    ///         <see cref="Frame"/>.
-    ///         </para>
-    ///         <para>
-    ///         Altering the Bounds will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/>
-    ///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    ///         <para>
-    ///         Because <see cref="Bounds"/> coordinates are relative to the upper-left corner of the <see cref="View"/>,
-    ///         the coordinates of the upper-left corner of the rectangle returned by this property are (0,0).
-    ///         Use this property to obtain the size of the area of the view for tasks such as drawing the view's contents.
-    ///         </para>
-    /// </remarks>
-    public virtual Rect Bounds
-    {
-        get
-        {
+public partial class View {
+	bool _autoSize;
+
+	/// <summary>
+	/// Backing property for Frame - The frame for the object. Relative to the SuperView's Bounds.
+	/// </summary>
+	Rect _frame;
+
+	/// <summary>
+	/// Gets or sets location and size of the view. The frame is relative to the <see cref="SuperView"/>'s <see cref="Bounds"/>
+	/// .
+	/// </summary>
+	/// <value>
+	/// The rectangle describing the location and size of the view, in coordinates relative to the
+	/// <see cref="SuperView"/>.
+	/// </value>
+	/// <remarks>
+	///         <para>
+	///         Change the Frame when using the <see cref="LayoutStyle.Absolute"/> layout style to move or resize views.
+	///         </para>
+	///         <para>
+	///         Altering the Frame will change <see cref="LayoutStyle"/> to <see cref="LayoutStyle.Absolute"/>.
+	///         Additionally, <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/> will be set
+	///         to the values of the Frame (using <see cref="Pos.PosAbsolute"/> and <see cref="Dim.DimAbsolute"/>).
+	///         </para>
+	///         <para>
+	///         Altering the Frame will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/>
+	///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	/// </remarks>
+	public virtual Rect Frame {
+		get => _frame;
+		set {
+			_frame = new Rect (value.X, value.Y, Math.Max (value.Width, 0), Math.Max (value.Height, 0));
+
+			// If Frame gets set, by definition, the View is now LayoutStyle.Absolute, so
+			// set all Pos/Dim to Absolute values.
+			_x = _frame.X;
+			_y = _frame.Y;
+			_width = _frame.Width;
+			_height = _frame.Height;
+			if (IsInitialized || LayoutStyle == LayoutStyle.Absolute) {
+				LayoutFrames ();
+				TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
+				SetNeedsLayout ();
+				SetNeedsDisplay ();
+			}
+		}
+	}
+
+	/// <summary>
+	/// The frame (specified as a <see cref="Thickness"/>) that separates a View from other SubViews of the same SuperView.
+	/// The margin offsets the <see cref="Bounds"/> from the <see cref="Frame"/>.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
+	///         content
+	///         and are not clipped by the View's Clip Area.
+	///         </para>
+	///         <para>
+	///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
+	///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
+	///         of the
+	///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
+	///         </para>
+	/// </remarks>
+	public Frame Margin { get; private set; }
+
+	/// <summary>
+	/// The frame (specified as a <see cref="Thickness"/>) inside of the view that offsets the <see cref="Bounds"/> from the
+	/// <see cref="Margin"/>.
+	/// The Border provides the space for a visual border (drawn using line-drawing glyphs) and the Title.
+	/// The Border expands inward; in other words if `Border.Thickness.Top == 2` the border and
+	/// title will take up the first row and the second row will be filled with spaces.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         <see cref="BorderStyle"/> provides a simple helper for turning a simple border frame on or off.
+	///         </para>
+	///         <para>
+	///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
+	///         content
+	///         and are not clipped by the View's Clip Area.
+	///         </para>
+	///         <para>
+	///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
+	///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
+	///         of the
+	///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
+	///         </para>
+	/// </remarks>
+	public Frame Border { get; private set; }
+
+	/// <summary>
+	/// Gets or sets whether the view has a one row/col thick border.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         This is a helper for manipulating the view's <see cref="Border"/>. Setting this property to any value other
+	///         than
+	///         <see cref="LineStyle.None"/> is equivalent to setting <see cref="Border"/>'s <see cref="Frame.Thickness"/>
+	///         to `1` and <see cref="BorderStyle"/> to the value.
+	///         </para>
+	///         <para>
+	///         Setting this property to <see cref="LineStyle.None"/> is equivalent to setting <see cref="Border"/>'s
+	///         <see cref="Frame.Thickness"/>
+	///         to `0` and <see cref="BorderStyle"/> to <see cref="LineStyle.None"/>.
+	///         </para>
+	///         <para>
+	///         For more advanced customization of the view's border, manipulate see <see cref="Border"/> directly.
+	///         </para>
+	/// </remarks>
+	public LineStyle BorderStyle {
+		get => Border?.BorderStyle ?? LineStyle.None;
+		set {
+			if (Border == null) {
+				throw new InvalidOperationException ("Border is null; this is likely a bug.");
+			}
+			if (value != LineStyle.None) {
+				Border.Thickness = new Thickness (1);
+			} else {
+				Border.Thickness = new Thickness (0);
+			}
+			Border.BorderStyle = value;
+			LayoutFrames ();
+			SetNeedsLayout ();
+		}
+	}
+
+	/// <summary>
+	/// The frame (specified as a <see cref="Thickness"/>) inside of the view that offsets the <see cref="Bounds"/> from the
+	/// <see cref="Border"/>.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         The frames (<see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>) are not part of the View's
+	///         content
+	///         and are not clipped by the View's Clip Area.
+	///         </para>
+	///         <para>
+	///         Changing the size of a frame (<see cref="Margin"/>, <see cref="Border"/>, or <see cref="Padding"/>)
+	///         will change the size of the <see cref="Frame"/> and trigger <see cref="LayoutSubviews"/> to update the layout
+	///         of the
+	///         <see cref="SuperView"/> and its <see cref="Subviews"/>.
+	///         </para>
+	/// </remarks>
+	public Frame Padding { get; private set; }
+
+	/// <summary>
+	/// Controls how the View's <see cref="Frame"/> is computed during <see cref="LayoutSubviews"/>. If the style is set to
+	/// <see cref="LayoutStyle.Absolute"/>, LayoutSubviews does not change the <see cref="Frame"/>.
+	/// If the style is <see cref="LayoutStyle.Computed"/> the <see cref="Frame"/> is updated using
+	/// the <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/> properties.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         Setting this property to <see cref="LayoutStyle.Absolute"/> will cause <see cref="Frame"/> to determine the
+	///         size and position of the view. <see cref="X"/> and <see cref="Y"/> will be set to <see cref="Dim.DimAbsolute"/>
+	///         using <see cref="Frame"/>.
+	///         </para>
+	///         <para>
+	///         Setting this property to <see cref="LayoutStyle.Computed"/> will cause the view to use the
+	///         <see cref="LayoutSubviews"/> method to
+	///         size and position of the view. If either of the <see cref="X"/> and <see cref="Y"/> properties are `null` they
+	///         will be set to <see cref="Pos.PosAbsolute"/> using
+	///         the current value of <see cref="Frame"/>.
+	///         If either of the <see cref="Width"/> and <see cref="Height"/> properties are `null` they will be set to
+	///         <see cref="Dim.DimAbsolute"/> using <see cref="Frame"/>.
+	///         </para>
+	/// </remarks>
+	/// <value>The layout style.</value>
+	public LayoutStyle LayoutStyle {
+		get {
+			if (_x is Pos.PosAbsolute && _y is Pos.PosAbsolute && _width is Dim.DimAbsolute && _height is Dim.DimAbsolute) {
+				return LayoutStyle.Absolute;
+			} else {
+				return LayoutStyle.Computed;
+			}
+		}
+		set {
+			// TODO: Remove this setter and make LayoutStyle read-only for real.
+			throw new InvalidOperationException ("LayoutStyle is read-only.");
+		}
+	}
+
+	/// <summary>
+	/// The bounds represent the View-relative rectangle used for this view; the area inside of the view where subviews and
+	/// content are presented.
+	/// </summary>
+	/// <value>The rectangle describing the location and size of the area where the views' subviews and content are drawn.</value>
+	/// <remarks>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value of Bounds is indeterminate until
+	///         the
+	///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
+	///         called.
+	///         </para>
+	///         <para>
+	///         Updates to the Bounds updates <see cref="Frame"/>, and has the same side effects as updating the
+	///         <see cref="Frame"/>.
+	///         </para>
+	///         <para>
+	///         Altering the Bounds will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/>
+	///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	///         <para>
+	///         Because <see cref="Bounds"/> coordinates are relative to the upper-left corner of the <see cref="View"/>,
+	///         the coordinates of the upper-left corner of the rectangle returned by this property are (0,0).
+	///         Use this property to obtain the size of the area of the view for tasks such as drawing the view's contents.
+	///         </para>
+	/// </remarks>
+	public virtual Rect Bounds {
+		get {
 #if DEBUG
-            if (LayoutStyle == LayoutStyle.Computed && !IsInitialized)
-            {
-                Debug.WriteLine($"WARNING: Bounds is being accessed before the View has been initialized. This is likely a bug in {this}");
-            }
+			if (LayoutStyle == LayoutStyle.Computed && !IsInitialized) {
+				Debug.WriteLine ($"WARNING: Bounds is being accessed before the View has been initialized. This is likely a bug in {this}");
+			}
 #endif // DEBUG
-            //var frameRelativeBounds = Padding?.Thickness.GetInside (Padding.Frame) ?? new Rect (default, Frame.Size);
-            var frameRelativeBounds = FrameGetInsideBounds();
-            return new Rect(default, frameRelativeBounds.Size);
-        }
-        set
-        {
-            // BUGBUG: Margin etc.. can be null (if typeof(Frame))
-            Frame = new Rect(Frame.Location,
-                new Size(
-                    value.Size.Width + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal,
-                    value.Size.Height + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical
-                )
-            );
-        }
-    }
-
-    Pos _x = Pos.At(0);
-
-    /// <summary>
-    /// Gets or sets the X position for the view (the column).
-    /// </summary>
-    /// <value>The <see cref="Pos"/> object representing the X position.</value>
-    /// <remarks>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
-    ///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
-    ///         called.
-    ///         </para>
-    ///         <para>
-    ///         Changing this property will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/> and
-    ///         <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
-    ///         <see cref="Frame"/> to be updated. If
-    ///         the new value is not of type <see cref="Pos.PosAbsolute"/> the <see cref="LayoutStyle"/> will change to
-    ///         <see cref="LayoutStyle.Computed"/>.
-    ///         </para>
-    ///         <para>
-    ///         <see langword="null"/> is the same as <c>Pos.Absolute(0)</c>.
-    ///         </para>
-    /// </remarks>
-    public Pos X
-    {
-        get => VerifyIsInitialized(_x, nameof(X));
-        set
-        {
-            _x = value ?? throw new ArgumentNullException(nameof(value), @$"{nameof(X)} cannot be null");
-            OnResizeNeeded();
-        }
-    }
-
-    Pos _y = Pos.At(0);
-
-    /// <summary>
-    /// Gets or sets the Y position for the view (the row).
-    /// </summary>
-    /// <value>The <see cref="Pos"/> object representing the Y position.</value>
-    /// <remarks>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
-    ///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
-    ///         called.
-    ///         </para>
-    ///         <para>
-    ///         Changing this property will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/> and
-    ///         <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
-    ///         <see cref="Frame"/> to be updated. If
-    ///         the new value is not of type <see cref="Pos.PosAbsolute"/> the <see cref="LayoutStyle"/> will change to
-    ///         <see cref="LayoutStyle.Computed"/>.
-    ///         </para>
-    ///         <para>
-    ///         <see langword="null"/> is the same as <c>Pos.Absolute(0)</c>.
-    ///         </para>
-    /// </remarks>
-    public Pos Y
-    {
-        get => VerifyIsInitialized(_y, nameof(Y));
-        set
-        {
-            _y = value ?? throw new ArgumentNullException(nameof(value), @$"{nameof(Y)} cannot be null");
-            OnResizeNeeded();
-        }
-    }
-
-    Dim _width = Dim.Sized(0);
-
-    /// <summary>
-    /// Gets or sets the width of the view.
-    /// </summary>
-    /// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
-    /// <remarks>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
-    ///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
-    ///         called.
-    ///         </para>
-    ///         <para>
-    ///         Changing this property will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/>
-    ///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
-    ///         <see cref="Frame"/> to be updated. If
-    ///         the new value is not of type <see cref="Dim.DimAbsolute"/> the <see cref="LayoutStyle"/> will change to
-    ///         <see cref="LayoutStyle.Computed"/>.
-    ///         </para>
-    /// </remarks>
-    public Dim Width
-    {
-        get => VerifyIsInitialized(_width, nameof(Width));
-        set
-        {
-            _width = value ?? throw new ArgumentNullException(nameof(value), @$"{nameof(Width)} cannot be null");
-
-            if (ValidatePosDim)
-            {
-                var isValidNewAutSize = AutoSize && IsValidAutoSizeWidth(_width);
-
-                if (IsAdded && AutoSize && !isValidNewAutSize)
-                {
-                    throw new InvalidOperationException("Must set AutoSize to false before set the Width.");
-                }
-            }
-            OnResizeNeeded();
-        }
-    }
-
-    Dim _height = Dim.Sized(0);
-
-    /// <summary>
-    /// Gets or sets the height of the view.
-    /// </summary>
-    /// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
-    /// <remarks>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
-    ///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
-    ///         called.
-    ///         </para>
-    ///         <para>
-    ///         Changing this property will eventually (when the view is next drawn) cause the
-    ///         <see cref="LayoutSubview(View, Rect)"/>
-    ///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
-    ///         </para>
-    ///         <para>
-    ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
-    ///         <see cref="Frame"/> to be updated. If
-    ///         the new value is not of type <see cref="Dim.DimAbsolute"/> the <see cref="LayoutStyle"/> will change to
-    ///         <see cref="LayoutStyle.Computed"/>.
-    ///         </para>
-    /// </remarks>
-    public Dim Height
-    {
-        get => VerifyIsInitialized(_height, nameof(Height));
-        set
-        {
-            _height = value ?? throw new ArgumentNullException(nameof(value), @$"{nameof(Height)} cannot be null");
-
-            if (ValidatePosDim)
-            {
-                var isValidNewAutSize = AutoSize && IsValidAutoSizeHeight(_height);
-
-                if (IsAdded && AutoSize && !isValidNewAutSize)
-                {
-                    throw new InvalidOperationException("Must set AutoSize to false before setting the Height.");
-                }
-            }
-            OnResizeNeeded();
-        }
-    }
-
-    /// <summary>
-    /// Gets or sets whether validation of <see cref="Pos"/> and <see cref="Dim"/> occurs.
-    /// </summary>
-    /// <remarks>
-    /// Setting this to <see langword="true"/> will enable validation of <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>,
-    /// and <see cref="Height"/>
-    /// during set operations and in <see cref="LayoutSubviews"/>.If invalid settings are discovered exceptions will be thrown
-    /// indicating the error.
-    /// This will impose a performance penalty and thus should only be used for debugging.
-    /// </remarks>
-    public bool ValidatePosDim { get; set; }
-
-    internal bool LayoutNeeded { get; private set; } = true;
-
-    /// <summary>
-    /// Gets or sets a flag that determines whether the View will be automatically resized to fit the <see cref="Text"/>
-    /// within <see cref="Bounds"/>
-    /// <para>
-    /// The default is <see langword="false"/>. Set to <see langword="true"/> to turn on AutoSize. If <see langword="true"/>
-    /// then
-    /// <see cref="Width"/> and <see cref="Height"/> will be used if <see cref="Text"/> can fit;
-    /// if <see cref="Text"/> won't fit the view will be resized as needed.
-    /// </para>
-    /// <para>
-    /// In addition, if <see cref="ValidatePosDim"/> is <see langword="true"/> the new values of <see cref="Width"/> and
-    /// <see cref="Height"/> must be of the same types of the existing one to avoid breaking the <see cref="Dim"/> settings.
-    /// </para>
-    /// </summary>
-    public virtual bool AutoSize
-    {
-        get => _autoSize;
-        set
-        {
-            var v = ResizeView(value);
-            TextFormatter.AutoSize = v;
-            if (_autoSize != v)
-            {
-                _autoSize = v;
-                TextFormatter.NeedsFormat = true;
-                UpdateTextFormatterText();
-                OnResizeNeeded();
-            }
-        }
-    }
-
-    /// <summary>
-    /// Event called only once when the <see cref="View"/> is being initialized for the first time.
-    /// Allows configurations and assignments to be performed before the <see cref="View"/> being shown.
-    /// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being
-    /// initialized.
-    /// </summary>
-    public event EventHandler Initialized;
-
-    /// <summary>
-    /// Helper to get the total thickness of the <see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>.
-    /// </summary>
-    /// <returns>A thickness that describes the sum of the Frames' thicknesses.</returns>
-    public Thickness GetFramesThickness()
-    {
-        var left = Margin.Thickness.Left + Border.Thickness.Left + Padding.Thickness.Left;
-        var top = Margin.Thickness.Top + Border.Thickness.Top + Padding.Thickness.Top;
-        var right = Margin.Thickness.Right + Border.Thickness.Right + Padding.Thickness.Right;
-        var bottom = Margin.Thickness.Bottom + Border.Thickness.Bottom + Padding.Thickness.Bottom;
-        return new Thickness(left, top, right, bottom);
-    }
-
-    /// <summary>
-    /// Helper to get the X and Y offset of the Bounds from the Frame. This is the sum of the Left and Top properties of
-    /// <see cref="Margin"/>, <see cref="Border"/> and <see cref="Padding"/>.
-    /// </summary>
-    public Point GetBoundsOffset() => new(Padding?.Thickness.GetInside(Padding.Frame).X ?? 0, Padding?.Thickness.GetInside(Padding.Frame).Y ?? 0);
-
-    /// <summary>
-    /// Creates the view's <see cref="Frame"/> objects. This internal method is overridden by Frame to do nothing
-    /// to prevent recursion during View construction.
-    /// </summary>
-    internal virtual void CreateFrames()
-    {
-        void ThicknessChangedHandler(object sender, EventArgs e)
-        {
-            if (IsInitialized)
-            {
-                LayoutFrames();
-            }
-            SetNeedsLayout();
-            SetNeedsDisplay();
-        }
-
-        if (Margin != null)
-        {
-            Margin.ThicknessChanged -= ThicknessChangedHandler;
-            Margin.Dispose();
-        }
-        Margin = new Frame { Id = "Margin", Thickness = new Thickness(0) };
-        Margin.ThicknessChanged += ThicknessChangedHandler;
-        Margin.Parent = this;
-
-        if (Border != null)
-        {
-            Border.ThicknessChanged -= ThicknessChangedHandler;
-            Border.Dispose();
-        }
-        Border = new Frame { Id = "Border", Thickness = new Thickness(0) };
-        Border.ThicknessChanged += ThicknessChangedHandler;
-        Border.Parent = this;
-
-        // TODO: Create View.AddAdornment
-
-        if (Padding != null)
-        {
-            Padding.ThicknessChanged -= ThicknessChangedHandler;
-            Padding.Dispose();
-        }
-        Padding = new Frame { Id = "Padding", Thickness = new Thickness(0) };
-        Padding.ThicknessChanged += ThicknessChangedHandler;
-        Padding.Parent = this;
-    }
-
-    Rect FrameGetInsideBounds()
-    {
-        if (Margin == null || Border == null || Padding == null)
-        {
-            return new Rect(default, Frame.Size);
-        }
-        var width = Math.Max(0, Frame.Size.Width - Margin.Thickness.Horizontal - Border.Thickness.Horizontal - Padding.Thickness.Horizontal);
-        var height = Math.Max(0, Frame.Size.Height - Margin.Thickness.Vertical - Border.Thickness.Vertical - Padding.Thickness.Vertical);
-        return new Rect(Point.Empty, new Size(width, height));
-    }
-
-    // Diagnostics to highlight when X or Y is read before the view has been initialized
-    Pos VerifyIsInitialized(Pos pos, string member)
-    {
+			//var frameRelativeBounds = Padding?.Thickness.GetInside (Padding.Frame) ?? new Rect (default, Frame.Size);
+			var frameRelativeBounds = FrameGetInsideBounds ();
+			return new Rect (default, frameRelativeBounds.Size);
+		}
+		set {
+			// BUGBUG: Margin etc.. can be null (if typeof(Frame))
+			Frame = new Rect (Frame.Location,
+			    new Size (
+				value.Size.Width + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal,
+				value.Size.Height + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical
+			    )
+			);
+		}
+	}
+
+	Pos _x = Pos.At (0);
+
+	/// <summary>
+	/// Gets or sets the X position for the view (the column).
+	/// </summary>
+	/// <value>The <see cref="Pos"/> object representing the X position.</value>
+	/// <remarks>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
+	///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
+	///         called.
+	///         </para>
+	///         <para>
+	///         Changing this property will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/> and
+	///         <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
+	///         <see cref="Frame"/> to be updated. If
+	///         the new value is not of type <see cref="Pos.PosAbsolute"/> the <see cref="LayoutStyle"/> will change to
+	///         <see cref="LayoutStyle.Computed"/>.
+	///         </para>
+	///         <para>
+	///         <see langword="null"/> is the same as <c>Pos.Absolute(0)</c>.
+	///         </para>
+	/// </remarks>
+	public Pos X {
+		get => VerifyIsInitialized (_x, nameof (X));
+		set {
+			_x = value ?? throw new ArgumentNullException (nameof (value), @$"{nameof (X)} cannot be null");
+			OnResizeNeeded ();
+		}
+	}
+
+	Pos _y = Pos.At (0);
+
+	/// <summary>
+	/// Gets or sets the Y position for the view (the row).
+	/// </summary>
+	/// <value>The <see cref="Pos"/> object representing the Y position.</value>
+	/// <remarks>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
+	///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
+	///         called.
+	///         </para>
+	///         <para>
+	///         Changing this property will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/> and
+	///         <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
+	///         <see cref="Frame"/> to be updated. If
+	///         the new value is not of type <see cref="Pos.PosAbsolute"/> the <see cref="LayoutStyle"/> will change to
+	///         <see cref="LayoutStyle.Computed"/>.
+	///         </para>
+	///         <para>
+	///         <see langword="null"/> is the same as <c>Pos.Absolute(0)</c>.
+	///         </para>
+	/// </remarks>
+	public Pos Y {
+		get => VerifyIsInitialized (_y, nameof (Y));
+		set {
+			_y = value ?? throw new ArgumentNullException (nameof (value), @$"{nameof (Y)} cannot be null");
+			OnResizeNeeded ();
+		}
+	}
+
+	Dim _width = Dim.Sized (0);
+
+	/// <summary>
+	/// Gets or sets the width of the view.
+	/// </summary>
+	/// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
+	/// <remarks>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
+	///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
+	///         called.
+	///         </para>
+	///         <para>
+	///         Changing this property will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/>
+	///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
+	///         <see cref="Frame"/> to be updated. If
+	///         the new value is not of type <see cref="Dim.DimAbsolute"/> the <see cref="LayoutStyle"/> will change to
+	///         <see cref="LayoutStyle.Computed"/>.
+	///         </para>
+	/// </remarks>
+	public Dim Width {
+		get => VerifyIsInitialized (_width, nameof (Width));
+		set {
+			_width = value ?? throw new ArgumentNullException (nameof (value), @$"{nameof (Width)} cannot be null");
+
+			if (ValidatePosDim) {
+				var isValidNewAutSize = AutoSize && IsValidAutoSizeWidth (_width);
+
+				if (IsAdded && AutoSize && !isValidNewAutSize) {
+					throw new InvalidOperationException ("Must set AutoSize to false before set the Width.");
+				}
+			}
+			OnResizeNeeded ();
+		}
+	}
+
+	Dim _height = Dim.Sized (0);
+
+	/// <summary>
+	/// Gets or sets the height of the view.
+	/// </summary>
+	/// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
+	/// <remarks>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value is indeterminate until the
+	///         view has been initialized (<see creft="IsInitialized"/> is true) and <see cref="LayoutSubviews"/> has been
+	///         called.
+	///         </para>
+	///         <para>
+	///         Changing this property will eventually (when the view is next drawn) cause the
+	///         <see cref="LayoutSubview(View, Rect)"/>
+	///         and <see cref="OnDrawContent(Rect)"/> methods to be called.
+	///         </para>
+	///         <para>
+	///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Absolute"/> changing this property will cause the
+	///         <see cref="Frame"/> to be updated. If
+	///         the new value is not of type <see cref="Dim.DimAbsolute"/> the <see cref="LayoutStyle"/> will change to
+	///         <see cref="LayoutStyle.Computed"/>.
+	///         </para>
+	/// </remarks>
+	public Dim Height {
+		get => VerifyIsInitialized (_height, nameof (Height));
+		set {
+			_height = value ?? throw new ArgumentNullException (nameof (value), @$"{nameof (Height)} cannot be null");
+
+			if (ValidatePosDim) {
+				var isValidNewAutSize = AutoSize && IsValidAutoSizeHeight (_height);
+
+				if (IsAdded && AutoSize && !isValidNewAutSize) {
+					throw new InvalidOperationException ("Must set AutoSize to false before setting the Height.");
+				}
+			}
+			OnResizeNeeded ();
+		}
+	}
+
+	/// <summary>
+	/// Gets or sets whether validation of <see cref="Pos"/> and <see cref="Dim"/> occurs.
+	/// </summary>
+	/// <remarks>
+	/// Setting this to <see langword="true"/> will enable validation of <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>,
+	/// and <see cref="Height"/>
+	/// during set operations and in <see cref="LayoutSubviews"/>.If invalid settings are discovered exceptions will be thrown
+	/// indicating the error.
+	/// This will impose a performance penalty and thus should only be used for debugging.
+	/// </remarks>
+	public bool ValidatePosDim { get; set; }
+
+	internal bool LayoutNeeded { get; private set; } = true;
+
+	/// <summary>
+	/// Gets or sets a flag that determines whether the View will be automatically resized to fit the <see cref="Text"/>
+	/// within <see cref="Bounds"/>
+	/// <para>
+	/// The default is <see langword="false"/>. Set to <see langword="true"/> to turn on AutoSize. If <see langword="true"/>
+	/// then
+	/// <see cref="Width"/> and <see cref="Height"/> will be used if <see cref="Text"/> can fit;
+	/// if <see cref="Text"/> won't fit the view will be resized as needed.
+	/// </para>
+	/// <para>
+	/// In addition, if <see cref="ValidatePosDim"/> is <see langword="true"/> the new values of <see cref="Width"/> and
+	/// <see cref="Height"/> must be of the same types of the existing one to avoid breaking the <see cref="Dim"/> settings.
+	/// </para>
+	/// </summary>
+	public virtual bool AutoSize {
+		get => _autoSize;
+		set {
+			var v = ResizeView (value);
+			TextFormatter.AutoSize = v;
+			if (_autoSize != v) {
+				_autoSize = v;
+				TextFormatter.NeedsFormat = true;
+				UpdateTextFormatterText ();
+				OnResizeNeeded ();
+			}
+		}
+	}
+
+	/// <summary>
+	/// Event called only once when the <see cref="View"/> is being initialized for the first time.
+	/// Allows configurations and assignments to be performed before the <see cref="View"/> being shown.
+	/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being
+	/// initialized.
+	/// </summary>
+	public event EventHandler Initialized;
+
+	/// <summary>
+	/// Helper to get the total thickness of the <see cref="Margin"/>, <see cref="Border"/>, and <see cref="Padding"/>.
+	/// </summary>
+	/// <returns>A thickness that describes the sum of the Frames' thicknesses.</returns>
+	public Thickness GetFramesThickness ()
+	{
+		var left = Margin.Thickness.Left + Border.Thickness.Left + Padding.Thickness.Left;
+		var top = Margin.Thickness.Top + Border.Thickness.Top + Padding.Thickness.Top;
+		var right = Margin.Thickness.Right + Border.Thickness.Right + Padding.Thickness.Right;
+		var bottom = Margin.Thickness.Bottom + Border.Thickness.Bottom + Padding.Thickness.Bottom;
+		return new Thickness (left, top, right, bottom);
+	}
+
+	/// <summary>
+	/// Helper to get the X and Y offset of the Bounds from the Frame. This is the sum of the Left and Top properties of
+	/// <see cref="Margin"/>, <see cref="Border"/> and <see cref="Padding"/>.
+	/// </summary>
+	public Point GetBoundsOffset () => new (Padding?.Thickness.GetInside (Padding.Frame).X ?? 0, Padding?.Thickness.GetInside (Padding.Frame).Y ?? 0);
+
+	/// <summary>
+	/// Creates the view's <see cref="Frame"/> objects. This internal method is overridden by Frame to do nothing
+	/// to prevent recursion during View construction.
+	/// </summary>
+	internal virtual void CreateFrames ()
+	{
+		void ThicknessChangedHandler (object sender, EventArgs e)
+		{
+			if (IsInitialized) {
+				LayoutFrames ();
+			}
+			SetNeedsLayout ();
+			SetNeedsDisplay ();
+		}
+
+		if (Margin != null) {
+			Margin.ThicknessChanged -= ThicknessChangedHandler;
+			Margin.Dispose ();
+		}
+		Margin = new Frame { Id = "Margin", Thickness = new Thickness (0) };
+		Margin.ThicknessChanged += ThicknessChangedHandler;
+		Margin.Parent = this;
+
+		if (Border != null) {
+			Border.ThicknessChanged -= ThicknessChangedHandler;
+			Border.Dispose ();
+		}
+		Border = new Frame { Id = "Border", Thickness = new Thickness (0) };
+		Border.ThicknessChanged += ThicknessChangedHandler;
+		Border.Parent = this;
+
+		// TODO: Create View.AddAdornment
+
+		if (Padding != null) {
+			Padding.ThicknessChanged -= ThicknessChangedHandler;
+			Padding.Dispose ();
+		}
+		Padding = new Frame { Id = "Padding", Thickness = new Thickness (0) };
+		Padding.ThicknessChanged += ThicknessChangedHandler;
+		Padding.Parent = this;
+	}
+
+	Rect FrameGetInsideBounds ()
+	{
+		if (Margin == null || Border == null || Padding == null) {
+			return new Rect (default, Frame.Size);
+		}
+		var width = Math.Max (0, Frame.Size.Width - Margin.Thickness.Horizontal - Border.Thickness.Horizontal - Padding.Thickness.Horizontal);
+		var height = Math.Max (0, Frame.Size.Height - Margin.Thickness.Vertical - Border.Thickness.Vertical - Padding.Thickness.Vertical);
+		return new Rect (Point.Empty, new Size (width, height));
+	}
+
+	// Diagnostics to highlight when X or Y is read before the view has been initialized
+	Pos VerifyIsInitialized (Pos pos, string member)
+	{
 #if DEBUG
-        if (LayoutStyle == LayoutStyle.Computed && !IsInitialized)
-        {
-            Debug.WriteLine($"WARNING: \"{this}\" has not been initialized; {member} is indeterminate {pos}. This is potentially a bug.");
-        }
+		if (LayoutStyle == LayoutStyle.Computed && !IsInitialized) {
+			Debug.WriteLine ($"WARNING: \"{this}\" has not been initialized; {member} is indeterminate {pos}. This is potentially a bug.");
+		}
 #endif // DEBUG
-        return pos;
-    }
+		return pos;
+	}
 
-    // Diagnostics to highlight when Width or Height is read before the view has been initialized
-    Dim VerifyIsInitialized(Dim dim, string member)
-    {
+	// Diagnostics to highlight when Width or Height is read before the view has been initialized
+	Dim VerifyIsInitialized (Dim dim, string member)
+	{
 #if DEBUG
-        if (LayoutStyle == LayoutStyle.Computed && !IsInitialized)
-        {
-            Debug.WriteLine($"WARNING: \"{this}\" has not been initialized; {member} is indeterminate: {dim}. This is potentially a bug.");
-        }
+		if (LayoutStyle == LayoutStyle.Computed && !IsInitialized) {
+			Debug.WriteLine ($"WARNING: \"{this}\" has not been initialized; {member} is indeterminate: {dim}. This is potentially a bug.");
+		}
 #endif // DEBUG		
-        return dim;
-    }
-
-    /// <summary>
-    /// Throws an <see cref="ArgumentException"/> if <paramref name="newValue"/> is <see cref="Pos.PosAbsolute"/> or
-    /// <see cref="Dim.DimAbsolute"/>.
-    /// Used when <see cref="ValidatePosDim"/> is turned on to verify correct <see cref="LayoutStyle.Computed"/> behavior.
-    /// </summary>
-    /// <remarks>
-    /// Does not verify if this view is Toplevel (WHY??!?).
-    /// </remarks>
-    /// <param name="prop">The property name.</param>
-    /// <param name="oldValue"></param>
-    /// <param name="newValue"></param>
-    void CheckAbsolute(string prop, object oldValue, object newValue)
-    {
-        if (!IsInitialized || !ValidatePosDim || oldValue == null || oldValue.GetType() == newValue.GetType() || this is Toplevel)
-        {
-            return;
-        }
-
-        if (oldValue.GetType() != newValue.GetType() && newValue is (Pos.PosAbsolute or Dim.DimAbsolute))
-        {
-            throw new ArgumentException($@"{prop} must not be Absolute if LayoutStyle is Computed", prop);
-        }
-    }
-
-    /// <summary>
-    /// Called whenever the view needs to be resized. Sets <see cref="Frame"/> and
-    /// triggers a <see cref="LayoutSubviews()"/> call.
-    /// </summary>
-    /// <remarks>
-    /// Can be overridden if the view resize behavior is different than the default.
-    /// </remarks>
-    protected virtual void OnResizeNeeded()
-    {
-        var actX = _x is Pos.PosAbsolute ? _x.Anchor(0) : _frame.X;
-        var actY = _y is Pos.PosAbsolute ? _y.Anchor(0) : _frame.Y;
-
-        if (AutoSize)
-        {
-            //if (TextAlignment == TextAlignment.Justified) {
-            //	throw new InvalidOperationException ("TextAlignment.Justified cannot be used with AutoSize");
-            //}
-            var s = GetAutoSize();
-            var w = _width is Dim.DimAbsolute && _width.Anchor(0) > s.Width ? _width.Anchor(0) : s.Width;
-            var h = _height is Dim.DimAbsolute && _height.Anchor(0) > s.Height ? _height.Anchor(0) : s.Height;
-            _frame = new Rect(new Point(actX, actY), new Size(w, h)); // Set frame, not Frame!
-        }
-        else
-        {
-            var w = _width is Dim.DimAbsolute ? _width.Anchor(0) : _frame.Width;
-            var h = _height is Dim.DimAbsolute ? _height.Anchor(0) : _frame.Height;
-            //// BUGBUG: v2 - ? - If layoutstyle is absolute, this overwrites the current frame h/w with 0. Hmmm...
-            //// This is needed for DimAbsolute values by setting the frame before LayoutSubViews.
-            _frame = new Rect(new Point(actX, actY), new Size(w, h)); // Set frame, not Frame!
-        }
-        //// BUGBUG: I think these calls are redundant or should be moved into just the AutoSize case
-        if (IsInitialized || LayoutStyle == LayoutStyle.Absolute)
-        {
-            SetFrameToFitText();
-            LayoutFrames();
-            TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey();
-            SetNeedsLayout();
-            SetNeedsDisplay();
-        }
-    }
-
-    internal void SetNeedsLayout()
-    {
-        if (LayoutNeeded)
-        {
-            return;
-        }
-        LayoutNeeded = true;
-        foreach (var view in Subviews)
-        {
-            view.SetNeedsLayout();
-        }
-        TextFormatter.NeedsFormat = true;
-        SuperView?.SetNeedsLayout();
-    }
-
-    /// <summary>
-    /// Indicates that the view does not need to be laid out.
-    /// </summary>
-    protected void ClearLayoutNeeded() => LayoutNeeded = false;
-
-    /// <summary>
-    /// Converts a screen-relative coordinate to a Frame-relative coordinate. Frame-relative means
-    /// relative to the View's <see cref="SuperView"/>'s <see cref="Bounds"/>.
-    /// </summary>
-    /// <returns>The coordinate relative to the <see cref="SuperView"/>'s <see cref="Bounds"/>.</returns>
-    /// <param name="x">Screen-relative column.</param>
-    /// <param name="y">Screen-relative row.</param>
-    public Point ScreenToFrame(int x, int y)
-    {
-        var superViewBoundsOffset = SuperView?.GetBoundsOffset() ?? Point.Empty;
-        var ret = new Point(x - Frame.X - superViewBoundsOffset.X, y - Frame.Y - superViewBoundsOffset.Y);
-        if (SuperView != null)
-        {
-            var superFrame = SuperView.ScreenToFrame(x - superViewBoundsOffset.X, y - superViewBoundsOffset.Y);
-            ret = new Point(superFrame.X - Frame.X, superFrame.Y - Frame.Y);
-        }
-        return ret;
-    }
-
-    /// <summary>
-    /// Converts a screen-relative coordinate to a bounds-relative coordinate.
-    /// </summary>
-    /// <returns>The coordinate relative to this view's <see cref="Bounds"/>.</returns>
-    /// <param name="x">Screen-relative column.</param>
-    /// <param name="y">Screen-relative row.</param>
-    public Point ScreenToBounds(int x, int y)
-    {
-        var screen = ScreenToFrame(x, y);
-        var boundsOffset = GetBoundsOffset();
-        return new Point(screen.X - boundsOffset.X, screen.Y - boundsOffset.Y);
-    }
-
-    /// <summary>
-    /// Converts a <see cref="Bounds"/>-relative coordinate to a screen-relative coordinate. The output is optionally clamped
-    /// to the screen dimensions.
-    /// </summary>
-    /// <param name="x"><see cref="Bounds"/>-relative column.</param>
-    /// <param name="y"><see cref="Bounds"/>-relative row.</param>
-    /// <param name="rx">Absolute column; screen-relative.</param>
-    /// <param name="ry">Absolute row; screen-relative.</param>
-    /// <param name="clamped">
-    /// If <see langword="true"/>, <paramref name="rx"/> and <paramref name="ry"/> will be clamped to the
-    /// screen dimensions (will never be negative and will always be less than <see cref="ConsoleDriver.Cols"/> and
-    /// <see cref="ConsoleDriver.Rows"/>, respectively.
-    /// </param>
-    public virtual void BoundsToScreen(int x, int y, out int rx, out int ry, bool clamped = true)
-    {
-        var boundsOffset = GetBoundsOffset();
-        rx = x + Frame.X + boundsOffset.X;
-        ry = y + Frame.Y + boundsOffset.Y;
-
-        var super = SuperView;
-        while (super != null)
-        {
-            boundsOffset = super.GetBoundsOffset();
-            rx += super.Frame.X + boundsOffset.X;
-            ry += super.Frame.Y + boundsOffset.Y;
-            super = super.SuperView;
-        }
-
-        // The following ensures that the cursor is always in the screen boundaries.
-        if (clamped)
-        {
-            ry = Math.Min(ry, Driver.Rows - 1);
-            rx = Math.Min(rx, Driver.Cols - 1);
-        }
-    }
-
-    /// <summary>
-    /// Converts a <see cref="Bounds"/>-relative region to a screen-relative region.
-    /// </summary>
-    public Rect BoundsToScreen(Rect region)
-    {
-        BoundsToScreen(region.X, region.Y, out var x, out var y, false);
-        return new Rect(x, y, region.Width, region.Height);
-    }
-
-    /// <summary>
-    /// Gets the <see cref="Frame"/> with a screen-relative location.
-    /// </summary>
-    /// <returns>The location and size of the view in screen-relative coordinates.</returns>
-    public virtual Rect FrameToScreen()
-    {
-        var ret = Frame;
-        var super = SuperView;
-        while (super != null)
-        {
-            var boundsOffset = super.GetBoundsOffset();
-            ret.X += super.Frame.X + boundsOffset.X;
-            ret.Y += super.Frame.Y + boundsOffset.Y;
-            super = super.SuperView;
-        }
-        return ret;
-    }
-
-    // TODO: Come up with a better name for this method. "SetRelativeLayout" lacks clarity and confuses. AdjustSizeAndPosition?
-    /// <summary>
-    /// Applies the view's position (<see cref="X"/>, <see cref="Y"/>) and dimension (<see cref="Width"/>, and
-    /// <see cref="Height"/>) to
-    /// <see cref="Frame"/>, given a rectangle describing the SuperView's Bounds (nominally the same as
-    /// <c>this.SuperView.Bounds</c>).
-    /// </summary>
-    /// <param name="superviewBounds">
-    /// The rectangle describing the SuperView's Bounds (nominally the same as
-    /// <c>this.SuperView.Bounds</c>).
-    /// </param>
-    internal void SetRelativeLayout(Rect superviewBounds)
-    {
-        Debug.Assert(_x != null);
-        Debug.Assert(_y != null);
-        Debug.Assert(_width != null);
-        Debug.Assert(_height != null);
-
-        int newX, newW, newY, newH;
-        var autosize = Size.Empty;
-
-        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();
-        }
-
-        // 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 Bounds
-        //   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, Rect superviewBounds, 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 current dimension (width or height)
-            //   autosize: the size to use if autosize = true
-            // This mehod is recursive if d is Dim.DimCombine
-            int GetNewDimension(Dim d, int location, int dimension, int autosize)
-            {
-                int newDimension;
-                switch (d)
-                {
-
-                    case Dim.DimCombine combine:
-                        // TODO: Move combine logic into DimCombine?
-                        var leftNewDim = GetNewDimension(combine._left, location, dimension, autosize);
-                        var 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.DimFill:
-                    case Dim.DimAbsolute:
-                    default:
-                        newDimension = Math.Max(d.Anchor(dimension - location), 0);
-                        newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
-                        break;
-                }
-
-                return newDimension;
-            }
-
-            int newDimension, newLocation;
-            var superviewDimension = width ? superviewBounds.Width : superviewBounds.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, superviewBounds, combine._left, dim, autosizeDimension);
-                    (right, newDimension) = GetNewLocationAndDimension(width, superviewBounds, 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, superviewBounds, _x, _width, autosize.Width);
-
-        // vertical/height
-        (newY, newH) = GetNewLocationAndDimension(false, superviewBounds, _y, _height, autosize.Height);
-
-        var r = new Rect(newX, newY, newW, newH);
-        if (Frame != r)
-        {
-            Frame = r;
-            // BUGBUG: Why is this AFTER setting Frame? Seems duplicative.
-            if (!SetFrameToFitText())
-            {
-                TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey();
-            }
-        }
-    }
-
-    /// <summary>
-    /// Fired after the View's <see cref="LayoutSubviews"/> method has completed.
-    /// </summary>
-    /// <remarks>
-    /// Subscribe to this event to perform tasks when the <see cref="View"/> has been resized or the layout has otherwise
-    /// changed.
-    /// </remarks>
-    public event EventHandler<LayoutEventArgs> LayoutStarted;
-
-    /// <summary>
-    /// Raises the <see cref="LayoutStarted"/> event. Called from  <see cref="LayoutSubviews"/> before any subviews have been
-    /// laid out.
-    /// </summary>
-    internal virtual void OnLayoutStarted(LayoutEventArgs args) => LayoutStarted?.Invoke(this, args);
-
-    /// <summary>
-    /// Fired after the View's <see cref="LayoutSubviews"/> method has completed.
-    /// </summary>
-    /// <remarks>
-    /// Subscribe to this event to perform tasks when the <see cref="View"/> has been resized or the layout has otherwise
-    /// changed.
-    /// </remarks>
-    public event EventHandler<LayoutEventArgs> LayoutComplete;
-
-    /// <summary>
-    /// Raises the <see cref="LayoutComplete"/> event. Called from  <see cref="LayoutSubviews"/> before all sub-views have been
-    /// laid out.
-    /// </summary>
-    internal virtual void OnLayoutComplete(LayoutEventArgs args) => LayoutComplete?.Invoke(this, args);
-
-    internal void CollectPos(Pos pos, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-    {
-        switch (pos)
-        {
-            case Pos.PosView pv:
-                // See #2461
-                //if (!from.InternalSubviews.Contains (pv.Target)) {
-                //	throw new InvalidOperationException ($"View {pv.Target} is not a subview of {from}");
-                //}
-                if (pv.Target != this)
-                {
-                    nEdges.Add((pv.Target, from));
-                }
-                return;
-            case Pos.PosCombine pc:
-                CollectPos(pc._left, from, ref nNodes, ref nEdges);
-                CollectPos(pc._right, from, ref nNodes, ref nEdges);
-                break;
-        }
-    }
-
-    internal void CollectDim(Dim dim, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-    {
-        switch (dim)
-        {
-            case Dim.DimView dv:
-                // See #2461
-                //if (!from.InternalSubviews.Contains (dv.Target)) {
-                //	throw new InvalidOperationException ($"View {dv.Target} is not a subview of {from}");
-                //}
-                if (dv.Target != this)
-                {
-                    nEdges.Add((dv.Target, from));
-                }
-                return;
-            case Dim.DimCombine dc:
-                CollectDim(dc._left, from, ref nNodes, ref nEdges);
-                CollectDim(dc._right, from, ref nNodes, ref nEdges);
-                break;
-        }
-    }
-
-    internal void CollectAll(View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-    {
-        // BUGBUG: This should really only work on initialized subviews
-        foreach (var v in from.InternalSubviews /*.Where(v => v.IsInitialized)*/)
-        {
-            nNodes.Add(v);
-            if (v.LayoutStyle != LayoutStyle.Computed)
-            {
-                continue;
-            }
-            CollectPos(v.X, v, ref nNodes, ref nEdges);
-            CollectPos(v.Y, v, ref nNodes, ref nEdges);
-            CollectDim(v.Width, v, ref nNodes, ref nEdges);
-            CollectDim(v.Height, v, ref nNodes, ref nEdges);
-        }
-    }
-
-    // https://en.wikipedia.org/wiki/Topological_sorting
-    internal static List<View> TopologicalSort(View superView, IEnumerable<View> nodes, ICollection<(View From, View To)> edges)
-    {
-        var result = new List<View>();
-
-        // Set of all nodes with no incoming edges
-        var noEdgeNodes = new HashSet<View>(nodes.Where(n => edges.All(e => !e.To.Equals(n))));
-
-        while (noEdgeNodes.Any())
-        {
-            //  remove a node n from S
-            var n = noEdgeNodes.First();
-            noEdgeNodes.Remove(n);
-
-            // add n to tail of L
-            if (n != superView)
-            {
-                result.Add(n);
-            }
-
-            // for each node m with an edge e from n to m do
-            foreach (var e in edges.Where(e => e.From.Equals(n)).ToArray())
-            {
-                var m = e.To;
-
-                // remove edge e from the graph
-                edges.Remove(e);
-
-                // if m has no other incoming edges then
-                if (edges.All(me => !me.To.Equals(m)) && m != superView)
-                {
-                    // insert m into S
-                    noEdgeNodes.Add(m);
-                }
-            }
-        }
-
-        if (!edges.Any())
-        {
-            return result;
-        }
-
-        foreach ((var from, var to) in edges)
-        {
-            if (from == to)
-            {
-                // if not yet added to the result, add it and remove from edge
-                if (result.Find(v => v == from) == null)
-                {
-                    result.Add(from);
-                }
-                edges.Remove((from, to));
-            }
-            else if (from.SuperView == to.SuperView)
-            {
-                // if 'from' is not yet added to the result, add it
-                if (result.Find(v => v == from) == null)
-                {
-                    result.Add(from);
-                }
-                // if 'to' is not yet added to the result, add it
-                if (result.Find(v => v == to) == null)
-                {
-                    result.Add(to);
-                }
-                // remove from edge
-                edges.Remove((from, to));
-            }
-            else if (from != superView?.GetTopSuperView(to, from) && !ReferenceEquals(from, to))
-            {
-                if (ReferenceEquals(from.SuperView, to))
-                {
-                    throw new InvalidOperationException($"ComputedLayout for \"{superView}\": \"{to}\" references a SubView (\"{from}\").");
-                }
-                throw new InvalidOperationException($"ComputedLayout for \"{superView}\": \"{from}\" linked with \"{to}\" was not found. Did you forget to add it to {superView}?");
-            }
-        }
-        // return L (a topologically sorted order)
-        return result;
-    } // TopologicalSort
-
-    /// <summary>
-    /// Overriden by <see cref="Frame"/> to do nothing, as the <see cref="Frame"/> does not have frames.
-    /// </summary>
-    internal virtual void LayoutFrames()
-    {
-        if (Margin == null)
-        {
-            return; // CreateFrames() has not been called yet
-        }
-
-        if (Margin.Frame.Size != Frame.Size)
-        {
-            Margin._frame = new Rect(Point.Empty, Frame.Size);
-            Margin.X = 0;
-            Margin.Y = 0;
-            Margin.Width = Frame.Size.Width;
-            Margin.Height = Frame.Size.Height;
-            Margin.SetNeedsLayout();
-            Margin.SetNeedsDisplay();
-        }
-
-        var border = Margin.Thickness.GetInside(Margin.Frame);
-        if (border != Border.Frame)
-        {
-            Border._frame = new Rect(new Point(border.Location.X, border.Location.Y), border.Size);
-            Border.X = border.Location.X;
-            Border.Y = border.Location.Y;
-            Border.Width = border.Size.Width;
-            Border.Height = border.Size.Height;
-            Border.SetNeedsLayout();
-            Border.SetNeedsDisplay();
-        }
-
-        var padding = Border.Thickness.GetInside(Border.Frame);
-        if (padding != Padding.Frame)
-        {
-            Padding._frame = new Rect(new Point(padding.Location.X, padding.Location.Y), padding.Size);
-            Padding.X = padding.Location.X;
-            Padding.Y = padding.Location.Y;
-            Padding.Width = padding.Size.Width;
-            Padding.Height = padding.Size.Height;
-            Padding.SetNeedsLayout();
-            Padding.SetNeedsDisplay();
-        }
-    }
-
-    /// <summary>
-    /// Invoked when a view starts executing or when the dimensions of the view have changed, for example in
-    /// response to the container view or terminal resizing.
-    /// </summary>
-    /// <remarks>
-    ///         <para>
-    ///         The position and dimensions of the view are indeterminate until the view has been initialized. Therefore,
-    ///         the behavior of this method is indeterminate if <see cref="IsInitialized"/> is <see langword="false"/>.
-    ///         </para>
-    ///         <para>
-    ///         Raises the <see cref="LayoutComplete"/> event) before it returns.
-    ///         </para>
-    /// </remarks>
-    public virtual void LayoutSubviews()
-    {
-        if (!IsInitialized)
-        {
-            Debug.WriteLine($"WARNING: LayoutSubviews called before view has been initialized. This is likely a bug in {this}");
-        }
-
-        if (!LayoutNeeded)
-        {
-            return;
-        }
-
-        LayoutFrames();
-
-        var oldBounds = Bounds;
-        OnLayoutStarted(new LayoutEventArgs { OldBounds = oldBounds });
-
-        TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey();
-
-        // Sort out the dependencies of the X, Y, Width, Height properties
-        var nodes = new HashSet<View>();
-        var edges = new HashSet<(View, View)>();
-        CollectAll(this, ref nodes, ref edges);
-        var ordered = TopologicalSort(SuperView, nodes, edges);
-        foreach (var v in ordered)
-        {
-            LayoutSubview(v, new Rect(GetBoundsOffset(), Bounds.Size));
-        }
-
-        // If the 'to' is rooted to 'from' and the layoutstyle is Computed it's a special-case.
-        // Use LayoutSubview with the Frame of the 'from' 
-        if (SuperView != null && GetTopSuperView() != null && LayoutNeeded && edges.Count > 0)
-        {
-            foreach ((var from, var to) in edges)
-            {
-                LayoutSubview(to, from.Frame);
-            }
-        }
-
-        LayoutNeeded = false;
-
-        OnLayoutComplete(new LayoutEventArgs { OldBounds = oldBounds });
-    }
-
-    void LayoutSubview(View v, Rect contentArea)
-    {
-        if (v.LayoutStyle == LayoutStyle.Computed)
-        {
-            v.SetRelativeLayout(contentArea);
-        }
-
-        v.LayoutSubviews();
-        v.LayoutNeeded = false;
-    }
-
-    bool ResizeView(bool autoSize)
-    {
-        if (!autoSize)
-        {
-            return false;
-        }
-
-        var boundsChanged = true;
-        var newFrameSize = GetAutoSize();
-        if (IsInitialized && newFrameSize != Frame.Size)
-        {
-            if (ValidatePosDim)
-            {
-                // BUGBUG: This ain't right, obviously.  We need to figure out how to handle this.
-                boundsChanged = ResizeBoundsToFit(newFrameSize);
-            }
-            else
-            {
-                Height = newFrameSize.Height;
-                Width = newFrameSize.Width;
-            }
-        }
-        return boundsChanged;
-    }
-
-    /// <summary>
-    /// Resizes the View to fit the specified size. Factors in the HotKey.
-    /// </summary>
-    /// <param name="size"></param>
-    /// <returns>whether the Bounds was changed or not</returns>
-    bool ResizeBoundsToFit(Size size)
-    {
-        var boundsChanged = false;
-        var canSizeW = TrySetWidth(size.Width - GetHotKeySpecifierLength(), out var rW);
-        var canSizeH = TrySetHeight(size.Height - GetHotKeySpecifierLength(false), out var rH);
-        if (canSizeW)
-        {
-            boundsChanged = true;
-            _width = rW;
-        }
-        if (canSizeH)
-        {
-            boundsChanged = true;
-            _height = rH;
-        }
-        if (boundsChanged)
-        {
-            Bounds = new Rect(Bounds.X, Bounds.Y, canSizeW ? rW : Bounds.Width, canSizeH ? rH : Bounds.Height);
-        }
-
-        return boundsChanged;
-    }
-
-    /// <summary>
-    /// Gets the Frame dimensions required to fit <see cref="Text"/> within <see cref="Bounds"/> using the text
-    /// <see cref="Direction"/> specified by the
-    /// <see cref="TextFormatter"/> property and accounting for any <see cref="HotKeySpecifier"/> characters.
-    /// </summary>
-    /// <returns>The <see cref="Size"/> of the view required to fit the text.</returns>
-    public Size GetAutoSize()
-    {
-        var x = 0;
-        var y = 0;
-        if (IsInitialized)
-        {
-            x = Bounds.X;
-            y = Bounds.Y;
-        }
-        var rect = TextFormatter.CalcRect(x, y, TextFormatter.Text, TextFormatter.Direction);
-        var newWidth = rect.Size.Width - GetHotKeySpecifierLength() + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal;
-        var newHeight = rect.Size.Height - GetHotKeySpecifierLength(false) + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical;
-        return new Size(newWidth, newHeight);
-    }
-
-    bool IsValidAutoSize(out Size autoSize)
-    {
-        var rect = TextFormatter.CalcRect(_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
-        autoSize = new Size(rect.Size.Width - GetHotKeySpecifierLength(),
-            rect.Size.Height - GetHotKeySpecifierLength(false));
-        return !(ValidatePosDim && (!(Width is Dim.DimAbsolute) || !(Height is Dim.DimAbsolute)) ||
-             _frame.Size.Width != rect.Size.Width - GetHotKeySpecifierLength() ||
-             _frame.Size.Height != rect.Size.Height - GetHotKeySpecifierLength(false));
-    }
-
-    bool IsValidAutoSizeWidth(Dim width)
-    {
-        var rect = TextFormatter.CalcRect(_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
-        var dimValue = width.Anchor(0);
-        return !(ValidatePosDim && !(width is Dim.DimAbsolute) || dimValue != rect.Size.Width - GetHotKeySpecifierLength());
-    }
-
-    bool IsValidAutoSizeHeight(Dim height)
-    {
-        var rect = TextFormatter.CalcRect(_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
-        var dimValue = height.Anchor(0);
-        return !(ValidatePosDim && !(height is Dim.DimAbsolute) || dimValue != rect.Size.Height - GetHotKeySpecifierLength(false));
-    }
-
-    /// <summary>
-    /// Determines if the View's <see cref="Width"/> can be set to a new value.
-    /// </summary>
-    /// <param name="desiredWidth"></param>
-    /// <param name="resultWidth">
-    /// Contains the width that would result if <see cref="Width"/> were set to
-    /// <paramref name="desiredWidth"/>"/>
-    /// </param>
-    /// <returns>
-    /// <see langword="true"/> if the View's <see cref="Width"/> can be changed to the specified value. False
-    /// otherwise.
-    /// </returns>
-    internal bool TrySetWidth(int desiredWidth, out int resultWidth)
-    {
-        var w = desiredWidth;
-        bool canSetWidth;
-        switch (Width)
-        {
-            case Dim.DimCombine _:
-            case Dim.DimView _:
-            case Dim.DimFill _:
-                // It's a Dim.DimCombine and so can't be assigned. Let it have it's Width anchored.
-                w = Width.Anchor(w);
-                canSetWidth = !ValidatePosDim;
-                break;
-            case Dim.DimFactor factor:
-                // Tries to get the SuperView Width otherwise the view Width.
-                var sw = SuperView != null ? SuperView.Frame.Width : w;
-                if (factor.IsFromRemaining())
-                {
-                    sw -= Frame.X;
-                }
-                w = Width.Anchor(sw);
-                canSetWidth = !ValidatePosDim;
-                break;
-            default:
-                canSetWidth = true;
-                break;
-        }
-        resultWidth = w;
-
-        return canSetWidth;
-    }
-
-    /// <summary>
-    /// Determines if the View's <see cref="Height"/> can be set to a new value.
-    /// </summary>
-    /// <param name="desiredHeight"></param>
-    /// <param name="resultHeight">
-    /// Contains the width that would result if <see cref="Height"/> were set to
-    /// <paramref name="desiredHeight"/>"/>
-    /// </param>
-    /// <returns>
-    /// <see langword="true"/> if the View's <see cref="Height"/> can be changed to the specified value. False
-    /// otherwise.
-    /// </returns>
-    internal bool TrySetHeight(int desiredHeight, out int resultHeight)
-    {
-        var h = desiredHeight;
-        bool canSetHeight;
-        switch (Height)
-        {
-            case Dim.DimCombine _:
-            case Dim.DimView _:
-            case Dim.DimFill _:
-                // It's a Dim.DimCombine and so can't be assigned. Let it have it's height anchored.
-                h = Height.Anchor(h);
-                canSetHeight = !ValidatePosDim;
-                break;
-            case Dim.DimFactor factor:
-                // Tries to get the SuperView height otherwise the view height.
-                var sh = SuperView != null ? SuperView.Frame.Height : h;
-                if (factor.IsFromRemaining())
-                {
-                    sh -= Frame.Y;
-                }
-                h = Height.Anchor(sh);
-                canSetHeight = !ValidatePosDim;
-                break;
-            default:
-                canSetHeight = true;
-                break;
-        }
-        resultHeight = h;
-
-        return canSetHeight;
-    }
-
-    /// <summary>
-    /// Finds which view that belong to the <paramref name="start"/> superview at the provided location.
-    /// </summary>
-    /// <param name="start">The superview where to look for.</param>
-    /// <param name="x">The column location in the superview.</param>
-    /// <param name="y">The row location in the superview.</param>
-    /// <param name="resx">The found view screen relative column location.</param>
-    /// <param name="resy">The found view screen relative row location.</param>
-    /// <returns>
-    /// The view that was found at the <praramref name="x"/> and <praramref name="y"/> coordinates.
-    /// <see langword="null"/> if no view was found.
-    /// </returns>
-    public static View FindDeepestView(View start, int x, int y, out int resx, out int resy)
-    {
-        resy = resx = 0;
-        if (start == null || !start.Frame.Contains(x, y))
-        {
-            return null;
-        }
-
-        var startFrame = start.Frame;
-        if (start.InternalSubviews != null)
-        {
-            var count = start.InternalSubviews.Count;
-            if (count > 0)
-            {
-                var boundsOffset = start.GetBoundsOffset();
-                var rx = x - (startFrame.X + boundsOffset.X);
-                var ry = y - (startFrame.Y + boundsOffset.Y);
-                for (var i = count - 1; i >= 0; i--)
-                {
-                    var v = start.InternalSubviews[i];
-                    if (v.Visible && v.Frame.Contains(rx, ry))
-                    {
-                        var deep = FindDeepestView(v, rx, ry, out resx, out resy);
-                        if (deep == null)
-                        {
-                            return v;
-                        }
-                        return deep;
-                    }
-                }
-            }
-        }
-        resx = x - startFrame.X;
-        resy = y - startFrame.Y;
-        return start;
-    }
+		return dim;
+	}
+
+	/// <summary>
+	/// Throws an <see cref="ArgumentException"/> if <paramref name="newValue"/> is <see cref="Pos.PosAbsolute"/> or
+	/// <see cref="Dim.DimAbsolute"/>.
+	/// Used when <see cref="ValidatePosDim"/> is turned on to verify correct <see cref="LayoutStyle.Computed"/> behavior.
+	/// </summary>
+	/// <remarks>
+	/// Does not verify if this view is Toplevel (WHY??!?).
+	/// </remarks>
+	/// <param name="prop">The property name.</param>
+	/// <param name="oldValue"></param>
+	/// <param name="newValue"></param>
+	void CheckAbsolute (string prop, object oldValue, object newValue)
+	{
+		if (!IsInitialized || !ValidatePosDim || oldValue == null || oldValue.GetType () == newValue.GetType () || this is Toplevel) {
+			return;
+		}
+
+		if (oldValue.GetType () != newValue.GetType () && newValue is (Pos.PosAbsolute or Dim.DimAbsolute)) {
+			throw new ArgumentException ($@"{prop} must not be Absolute if LayoutStyle is Computed", prop);
+		}
+	}
+
+	/// <summary>
+	/// Called whenever the view needs to be resized. Sets <see cref="Frame"/> and
+	/// triggers a <see cref="LayoutSubviews()"/> call.
+	/// </summary>
+	/// <remarks>
+	/// <para>
+	/// Sets the <see cref="Frame"/>.
+	/// </para>
+	/// <para>
+	/// Can be overridden if the view resize behavior is different than the default.
+	/// </para>
+	/// </remarks>
+	protected virtual void OnResizeNeeded ()
+	{
+		//var actX = _x is Pos.PosAbsolute ? _x.Anchor (0) : _frame.X;
+		//var actY = _y is Pos.PosAbsolute ? _y.Anchor (0) : _frame.Y;
+
+		//// TODO: Determine if this API should change Frame as it does.
+		//// TODO: Is it correct behavior? Shouldn't the Frame be changed when SetRelativeLayout
+		//// TODO: is eventually called because SetNeedsLayout get set?
+		//if (AutoSize) {
+		//	//if (TextAlignment == TextAlignment.Justified) {
+		//	//	throw new InvalidOperationException ("TextAlignment.Justified cannot be used with AutoSize");
+		//	//}
+		//	var s = GetAutoSize ();
+		//	var w = _width is Dim.DimAbsolute && _width.Anchor (0) > s.Width ? _width.Anchor (0) : s.Width;
+		//	var h = _height is Dim.DimAbsolute && _height.Anchor (0) > s.Height ? _height.Anchor (0) : s.Height;
+		//	// Set Frame to cause Pos/Dim to be set. By Definition AutoSize = true means LayoutStyleAbsolute
+		//	Frame = new Rect (new Point (actX, actY), new Size (w, h));
+		//} else {
+		//	var w = _width is Dim.DimAbsolute ? _width.Anchor (0) : _frame.Width;
+		//	var h = _height is Dim.DimAbsolute ? _height.Anchor (0) : _frame.Height;
+		//	//// BUGBUG: v2 - ? - If layoutstyle is absolute, this overwrites the current frame h/w with 0. Hmmm...
+		//	//// This is needed for DimAbsolute values by setting the frame before LayoutSubViews.
+		//	_frame = new Rect (new Point (actX, actY), new Size (w, h)); // Set frame, not Frame!
+		//}
+		// BUGBUG: I think these calls are redundant or should be moved into just the AutoSize case
+
+		SetRelativeLayout (SuperView?.Bounds ?? Application.Top?.Bounds ?? Application.Driver?.Bounds ?? new Rect (0, 0, int.MaxValue, int.MaxValue));
+		if (IsInitialized/* || LayoutStyle == LayoutStyle.Absolute*/) {
+			SetFrameToFitText ();
+			LayoutFrames ();
+			TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
+			SetNeedsLayout ();
+			SetNeedsDisplay ();
+		}
+	}
+
+	/// <summary>
+	/// Sets the internal <see cref="LayoutNeeded"/> flag for this View and all of it's
+	/// subviews and it's SuperView. The main loop will call SetRelativeLayout and LayoutSubviews
+	/// for any view with <see cref="LayoutNeeded"/> set.
+	/// </summary>
+	internal void SetNeedsLayout ()
+	{
+		if (LayoutNeeded) {
+			return;
+		}
+		LayoutNeeded = true;
+		foreach (var view in Subviews) {
+			view.SetNeedsLayout ();
+		}
+		TextFormatter.NeedsFormat = true;
+		SuperView?.SetNeedsLayout ();
+	}
+
+	/// <summary>
+	/// Indicates that the view does not need to be laid out.
+	/// </summary>
+	protected void ClearLayoutNeeded () => LayoutNeeded = false;
+
+	/// <summary>
+	/// Converts a screen-relative coordinate to a Frame-relative coordinate. Frame-relative means
+	/// relative to the View's <see cref="SuperView"/>'s <see cref="Bounds"/>.
+	/// </summary>
+	/// <returns>The coordinate relative to the <see cref="SuperView"/>'s <see cref="Bounds"/>.</returns>
+	/// <param name="x">Screen-relative column.</param>
+	/// <param name="y">Screen-relative row.</param>
+	public Point ScreenToFrame (int x, int y)
+	{
+		var superViewBoundsOffset = SuperView?.GetBoundsOffset () ?? Point.Empty;
+		var ret = new Point (x - Frame.X - superViewBoundsOffset.X, y - Frame.Y - superViewBoundsOffset.Y);
+		if (SuperView != null) {
+			var superFrame = SuperView.ScreenToFrame (x - superViewBoundsOffset.X, y - superViewBoundsOffset.Y);
+			ret = new Point (superFrame.X - Frame.X, superFrame.Y - Frame.Y);
+		}
+		return ret;
+	}
+
+	/// <summary>
+	/// Converts a screen-relative coordinate to a bounds-relative coordinate.
+	/// </summary>
+	/// <returns>The coordinate relative to this view's <see cref="Bounds"/>.</returns>
+	/// <param name="x">Screen-relative column.</param>
+	/// <param name="y">Screen-relative row.</param>
+	public Point ScreenToBounds (int x, int y)
+	{
+		var screen = ScreenToFrame (x, y);
+		var boundsOffset = GetBoundsOffset ();
+		return new Point (screen.X - boundsOffset.X, screen.Y - boundsOffset.Y);
+	}
+
+	/// <summary>
+	/// Converts a <see cref="Bounds"/>-relative coordinate to a screen-relative coordinate. The output is optionally clamped
+	/// to the screen dimensions.
+	/// </summary>
+	/// <param name="x"><see cref="Bounds"/>-relative column.</param>
+	/// <param name="y"><see cref="Bounds"/>-relative row.</param>
+	/// <param name="rx">Absolute column; screen-relative.</param>
+	/// <param name="ry">Absolute row; screen-relative.</param>
+	/// <param name="clamped">
+	/// If <see langword="true"/>, <paramref name="rx"/> and <paramref name="ry"/> will be clamped to the
+	/// screen dimensions (will never be negative and will always be less than <see cref="ConsoleDriver.Cols"/> and
+	/// <see cref="ConsoleDriver.Rows"/>, respectively.
+	/// </param>
+	public virtual void BoundsToScreen (int x, int y, out int rx, out int ry, bool clamped = true)
+	{
+		var boundsOffset = GetBoundsOffset ();
+		rx = x + Frame.X + boundsOffset.X;
+		ry = y + Frame.Y + boundsOffset.Y;
+
+		var super = SuperView;
+		while (super != null) {
+			boundsOffset = super.GetBoundsOffset ();
+			rx += super.Frame.X + boundsOffset.X;
+			ry += super.Frame.Y + boundsOffset.Y;
+			super = super.SuperView;
+		}
+
+		// The following ensures that the cursor is always in the screen boundaries.
+		if (clamped) {
+			ry = Math.Min (ry, Driver.Rows - 1);
+			rx = Math.Min (rx, Driver.Cols - 1);
+		}
+	}
+
+	/// <summary>
+	/// Converts a <see cref="Bounds"/>-relative region to a screen-relative region.
+	/// </summary>
+	public Rect BoundsToScreen (Rect region)
+	{
+		BoundsToScreen (region.X, region.Y, out var x, out var y, false);
+		return new Rect (x, y, region.Width, region.Height);
+	}
+
+	/// <summary>
+	/// Gets the <see cref="Frame"/> with a screen-relative location.
+	/// </summary>
+	/// <returns>The location and size of the view in screen-relative coordinates.</returns>
+	public virtual Rect FrameToScreen ()
+	{
+		var ret = Frame;
+		var super = SuperView;
+		while (super != null) {
+			var boundsOffset = super.GetBoundsOffset ();
+			ret.X += super.Frame.X + boundsOffset.X;
+			ret.Y += super.Frame.Y + boundsOffset.Y;
+			super = super.SuperView;
+		}
+		return ret;
+	}
+
+	// TODO: Come up with a better name for this method. "SetRelativeLayout" lacks clarity and confuses. AdjustSizeAndPosition?
+	/// <summary>
+	/// Applies the view's position (<see cref="X"/>, <see cref="Y"/>) and dimension (<see cref="Width"/>, and
+	/// <see cref="Height"/>) to
+	/// <see cref="Frame"/>, given a rectangle describing the SuperView's Bounds (nominally the same as
+	/// <c>this.SuperView.Bounds</c>).
+	/// </summary>
+	/// <param name="superviewBounds">
+	/// The rectangle describing the SuperView's Bounds (nominally the same as
+	/// <c>this.SuperView.Bounds</c>).
+	/// </param>
+	internal void SetRelativeLayout (Rect superviewBounds)
+	{
+		Debug.Assert (_x != null);
+		Debug.Assert (_y != null);
+		Debug.Assert (_width != null);
+		Debug.Assert (_height != null);
+
+		int newX, newW, newY, newH;
+		var autosize = Size.Empty;
+
+		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 ();
+		}
+
+		// 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 Bounds
+		//   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, Rect superviewBounds, 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;
+				switch (d) {
+
+				case Dim.DimCombine combine:
+					// TODO: Move combine logic into DimCombine?
+					var leftNewDim = GetNewDimension (combine._left, location, dimension, autosize);
+					var 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:
+					// DimAbsoulte.Anchor (int width) ignores width and returns n
+					newDimension = Math.Max (d.Anchor (0), 0);
+					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;
+				}
+
+				return newDimension;
+			}
+
+			int newDimension, newLocation;
+			var superviewDimension = width ? superviewBounds.Width : superviewBounds.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, superviewBounds, combine._left, dim, autosizeDimension);
+				(right, newDimension) = GetNewLocationAndDimension (width, superviewBounds, 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, superviewBounds, _x, _width, autosize.Width);
+
+		// vertical/height
+		(newY, newH) = GetNewLocationAndDimension (false, superviewBounds, _y, _height, autosize.Height);
+
+		var r = new Rect (newX, newY, newW, newH);
+		if (Frame != r) {
+			// Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
+			// the view LayoutStyle.Absolute.
+			_frame = r;
+			if (X is Pos.PosAbsolute) {
+				_x = Frame.X;
+			}
+			if (Y is Pos.PosAbsolute) {
+				_y = Frame.Y;
+			}
+			if (Width is Dim.DimAbsolute) {
+				_width = Frame.Width;
+			}
+			if (Height is Dim.DimAbsolute) {
+				_height = Frame.Height;
+			}
+
+			if (IsInitialized) {
+				//LayoutFrames ();
+				//TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
+				SetNeedsLayout ();
+				//SetNeedsDisplay ();
+			}
+			
+			// BUGBUG: Why is this AFTER setting Frame? Seems duplicative.
+			if (!SetFrameToFitText ()) {
+				TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
+			}
+		}
+	}
+
+	/// <summary>
+	/// Fired after the View's <see cref="LayoutSubviews"/> method has completed.
+	/// </summary>
+	/// <remarks>
+	/// Subscribe to this event to perform tasks when the <see cref="View"/> has been resized or the layout has otherwise
+	/// changed.
+	/// </remarks>
+	public event EventHandler<LayoutEventArgs> LayoutStarted;
+
+	/// <summary>
+	/// Raises the <see cref="LayoutStarted"/> event. Called from  <see cref="LayoutSubviews"/> before any subviews have been
+	/// laid out.
+	/// </summary>
+	internal virtual void OnLayoutStarted (LayoutEventArgs args) => LayoutStarted?.Invoke (this, args);
+
+	/// <summary>
+	/// Fired after the View's <see cref="LayoutSubviews"/> method has completed.
+	/// </summary>
+	/// <remarks>
+	/// Subscribe to this event to perform tasks when the <see cref="View"/> has been resized or the layout has otherwise
+	/// changed.
+	/// </remarks>
+	public event EventHandler<LayoutEventArgs> LayoutComplete;
+
+	/// <summary>
+	/// Raises the <see cref="LayoutComplete"/> event. Called from  <see cref="LayoutSubviews"/> before all sub-views have been
+	/// laid out.
+	/// </summary>
+	internal virtual void OnLayoutComplete (LayoutEventArgs args) => LayoutComplete?.Invoke (this, args);
+
+	internal void CollectPos (Pos pos, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
+	{
+		switch (pos) {
+		case Pos.PosView pv:
+			// See #2461
+			//if (!from.InternalSubviews.Contains (pv.Target)) {
+			//	throw new InvalidOperationException ($"View {pv.Target} is not a subview of {from}");
+			//}
+			if (pv.Target != this) {
+				nEdges.Add ((pv.Target, from));
+			}
+			return;
+		case Pos.PosCombine pc:
+			CollectPos (pc._left, from, ref nNodes, ref nEdges);
+			CollectPos (pc._right, from, ref nNodes, ref nEdges);
+			break;
+		}
+	}
+
+	internal void CollectDim (Dim dim, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
+	{
+		switch (dim) {
+		case Dim.DimView dv:
+			// See #2461
+			//if (!from.InternalSubviews.Contains (dv.Target)) {
+			//	throw new InvalidOperationException ($"View {dv.Target} is not a subview of {from}");
+			//}
+			if (dv.Target != this) {
+				nEdges.Add ((dv.Target, from));
+			}
+			return;
+		case Dim.DimCombine dc:
+			CollectDim (dc._left, from, ref nNodes, ref nEdges);
+			CollectDim (dc._right, from, ref nNodes, ref nEdges);
+			break;
+		}
+	}
+
+	internal void CollectAll (View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
+	{
+		// BUGBUG: This should really only work on initialized subviews
+		foreach (var v in from.InternalSubviews /*.Where(v => v.IsInitialized)*/) {
+			nNodes.Add (v);
+			if (v.LayoutStyle != LayoutStyle.Computed) {
+				continue;
+			}
+			CollectPos (v.X, v, ref nNodes, ref nEdges);
+			CollectPos (v.Y, v, ref nNodes, ref nEdges);
+			CollectDim (v.Width, v, ref nNodes, ref nEdges);
+			CollectDim (v.Height, v, ref nNodes, ref nEdges);
+		}
+	}
+
+	// https://en.wikipedia.org/wiki/Topological_sorting
+	internal static List<View> TopologicalSort (View superView, IEnumerable<View> nodes, ICollection<(View From, View To)> edges)
+	{
+		var result = new List<View> ();
+
+		// Set of all nodes with no incoming edges
+		var noEdgeNodes = new HashSet<View> (nodes.Where (n => edges.All (e => !e.To.Equals (n))));
+
+		while (noEdgeNodes.Any ()) {
+			//  remove a node n from S
+			var n = noEdgeNodes.First ();
+			noEdgeNodes.Remove (n);
+
+			// add n to tail of L
+			if (n != superView) {
+				result.Add (n);
+			}
+
+			// for each node m with an edge e from n to m do
+			foreach (var e in edges.Where (e => e.From.Equals (n)).ToArray ()) {
+				var m = e.To;
+
+				// remove edge e from the graph
+				edges.Remove (e);
+
+				// if m has no other incoming edges then
+				if (edges.All (me => !me.To.Equals (m)) && m != superView) {
+					// insert m into S
+					noEdgeNodes.Add (m);
+				}
+			}
+		}
+
+		if (!edges.Any ()) {
+			return result;
+		}
+
+		foreach ((var from, var to) in edges) {
+			if (from == to) {
+				// if not yet added to the result, add it and remove from edge
+				if (result.Find (v => v == from) == null) {
+					result.Add (from);
+				}
+				edges.Remove ((from, to));
+			} else if (from.SuperView == to.SuperView) {
+				// if 'from' is not yet added to the result, add it
+				if (result.Find (v => v == from) == null) {
+					result.Add (from);
+				}
+				// if 'to' is not yet added to the result, add it
+				if (result.Find (v => v == to) == null) {
+					result.Add (to);
+				}
+				// remove from edge
+				edges.Remove ((from, to));
+			} else if (from != superView?.GetTopSuperView (to, from) && !ReferenceEquals (from, to)) {
+				if (ReferenceEquals (from.SuperView, to)) {
+					throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{to}\" references a SubView (\"{from}\").");
+				}
+				throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{from}\" linked with \"{to}\" was not found. Did you forget to add it to {superView}?");
+			}
+		}
+		// return L (a topologically sorted order)
+		return result;
+	} // TopologicalSort
+
+	/// <summary>
+	/// Overriden by <see cref="Frame"/> to do nothing, as the <see cref="Frame"/> does not have frames.
+	/// </summary>
+	internal virtual void LayoutFrames ()
+	{
+		if (Margin == null) {
+			return; // CreateFrames() has not been called yet
+		}
+
+		if (Margin.Frame.Size != Frame.Size) {
+			Margin._frame = new Rect (Point.Empty, Frame.Size);
+			Margin.X = 0;
+			Margin.Y = 0;
+			Margin.Width = Frame.Size.Width;
+			Margin.Height = Frame.Size.Height;
+			Margin.SetNeedsLayout ();
+			Margin.SetNeedsDisplay ();
+		}
+
+		var border = Margin.Thickness.GetInside (Margin.Frame);
+		if (border != Border.Frame) {
+			Border._frame = new Rect (new Point (border.Location.X, border.Location.Y), border.Size);
+			Border.X = border.Location.X;
+			Border.Y = border.Location.Y;
+			Border.Width = border.Size.Width;
+			Border.Height = border.Size.Height;
+			Border.SetNeedsLayout ();
+			Border.SetNeedsDisplay ();
+		}
+
+		var padding = Border.Thickness.GetInside (Border.Frame);
+		if (padding != Padding.Frame) {
+			Padding._frame = new Rect (new Point (padding.Location.X, padding.Location.Y), padding.Size);
+			Padding.X = padding.Location.X;
+			Padding.Y = padding.Location.Y;
+			Padding.Width = padding.Size.Width;
+			Padding.Height = padding.Size.Height;
+			Padding.SetNeedsLayout ();
+			Padding.SetNeedsDisplay ();
+		}
+	}
+
+	/// <summary>
+	/// Invoked when a view starts executing or when the dimensions of the view have changed, for example in
+	/// response to the container view or terminal resizing.
+	/// </summary>
+	/// <remarks>
+	///         <para>
+	///         The position and dimensions of the view are indeterminate until the view has been initialized. Therefore,
+	///         the behavior of this method is indeterminate if <see cref="IsInitialized"/> is <see langword="false"/>.
+	///         </para>
+	///         <para>
+	///         Raises the <see cref="LayoutComplete"/> event) before it returns.
+	///         </para>
+	/// </remarks>
+	public virtual void LayoutSubviews ()
+	{
+		if (!IsInitialized) {
+			Debug.WriteLine ($"WARNING: LayoutSubviews called before view has been initialized. This is likely a bug in {this}");
+		}
+
+		if (!LayoutNeeded) {
+			return;
+		}
+
+		LayoutFrames ();
+
+		var oldBounds = Bounds;
+		OnLayoutStarted (new LayoutEventArgs { OldBounds = oldBounds });
+
+		TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
+
+		// Sort out the dependencies of the X, Y, Width, Height properties
+		var nodes = new HashSet<View> ();
+		var edges = new HashSet<(View, View)> ();
+		CollectAll (this, ref nodes, ref edges);
+		var ordered = TopologicalSort (SuperView, nodes, edges);
+		foreach (var v in ordered) {
+			LayoutSubview (v, new Rect (GetBoundsOffset (), Bounds.Size));
+		}
+
+		// If the 'to' is rooted to 'from' and the layoutstyle is Computed it's a special-case.
+		// Use LayoutSubview with the Frame of the 'from' 
+		if (SuperView != null && GetTopSuperView () != null && LayoutNeeded && edges.Count > 0) {
+			foreach ((var from, var to) in edges) {
+				LayoutSubview (to, from.Frame);
+			}
+		}
+
+		LayoutNeeded = false;
+
+		OnLayoutComplete (new LayoutEventArgs { OldBounds = oldBounds });
+	}
+
+	void LayoutSubview (View v, Rect contentArea)
+	{
+		//if (v.LayoutStyle == LayoutStyle.Computed) {
+			v.SetRelativeLayout (contentArea);
+		//}
+
+		v.LayoutSubviews ();
+		v.LayoutNeeded = false;
+	}
+
+	bool ResizeView (bool autoSize)
+	{
+		if (!autoSize) {
+			return false;
+		}
+
+		var boundsChanged = true;
+		var newFrameSize = GetAutoSize ();
+		if (IsInitialized && newFrameSize != Frame.Size) {
+			if (ValidatePosDim) {
+				// BUGBUG: This ain't right, obviously.  We need to figure out how to handle this.
+				boundsChanged = ResizeBoundsToFit (newFrameSize);
+			} else {
+				Height = newFrameSize.Height;
+				Width = newFrameSize.Width;
+			}
+		}
+		return boundsChanged;
+	}
+
+	/// <summary>
+	/// Resizes the View to fit the specified size. Factors in the HotKey.
+	/// </summary>
+	/// <param name="size"></param>
+	/// <returns>whether the Bounds was changed or not</returns>
+	bool ResizeBoundsToFit (Size size)
+	{
+		var boundsChanged = false;
+		var canSizeW = TrySetWidth (size.Width - GetHotKeySpecifierLength (), out var rW);
+		var canSizeH = TrySetHeight (size.Height - GetHotKeySpecifierLength (false), out var rH);
+		if (canSizeW) {
+			boundsChanged = true;
+			_width = rW;
+		}
+		if (canSizeH) {
+			boundsChanged = true;
+			_height = rH;
+		}
+		if (boundsChanged) {
+			Bounds = new Rect (Bounds.X, Bounds.Y, canSizeW ? rW : Bounds.Width, canSizeH ? rH : Bounds.Height);
+		}
+
+		return boundsChanged;
+	}
+
+	/// <summary>
+	/// Gets the Frame dimensions required to fit <see cref="Text"/> within <see cref="Bounds"/> using the text
+	/// <see cref="Direction"/> specified by the
+	/// <see cref="TextFormatter"/> property and accounting for any <see cref="HotKeySpecifier"/> characters.
+	/// </summary>
+	/// <returns>The <see cref="Size"/> of the view required to fit the text.</returns>
+	public Size GetAutoSize ()
+	{
+		var x = 0;
+		var y = 0;
+		if (IsInitialized) {
+			x = Bounds.X;
+			y = Bounds.Y;
+		}
+		var rect = TextFormatter.CalcRect (x, y, TextFormatter.Text, TextFormatter.Direction);
+		var newWidth = rect.Size.Width - GetHotKeySpecifierLength () + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal;
+		var newHeight = rect.Size.Height - GetHotKeySpecifierLength (false) + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical;
+		return new Size (newWidth, newHeight);
+	}
+
+	bool IsValidAutoSize (out Size autoSize)
+	{
+		var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
+		autoSize = new Size (rect.Size.Width - GetHotKeySpecifierLength (),
+		    rect.Size.Height - GetHotKeySpecifierLength (false));
+		return !(ValidatePosDim && (!(Width is Dim.DimAbsolute) || !(Height is Dim.DimAbsolute)) ||
+		     _frame.Size.Width != rect.Size.Width - GetHotKeySpecifierLength () ||
+		     _frame.Size.Height != rect.Size.Height - GetHotKeySpecifierLength (false));
+	}
+
+	bool IsValidAutoSizeWidth (Dim width)
+	{
+		var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
+		var dimValue = width.Anchor (0);
+		return !(ValidatePosDim && !(width is Dim.DimAbsolute) || dimValue != rect.Size.Width - GetHotKeySpecifierLength ());
+	}
+
+	bool IsValidAutoSizeHeight (Dim height)
+	{
+		var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection);
+		var dimValue = height.Anchor (0);
+		return !(ValidatePosDim && !(height is Dim.DimAbsolute) || dimValue != rect.Size.Height - GetHotKeySpecifierLength (false));
+	}
+
+	/// <summary>
+	/// Determines if the View's <see cref="Width"/> can be set to a new value.
+	/// </summary>
+	/// <param name="desiredWidth"></param>
+	/// <param name="resultWidth">
+	/// Contains the width that would result if <see cref="Width"/> were set to
+	/// <paramref name="desiredWidth"/>"/>
+	/// </param>
+	/// <returns>
+	/// <see langword="true"/> if the View's <see cref="Width"/> can be changed to the specified value. False
+	/// otherwise.
+	/// </returns>
+	internal bool TrySetWidth (int desiredWidth, out int resultWidth)
+	{
+		var w = desiredWidth;
+		bool canSetWidth;
+		switch (Width) {
+		case Dim.DimCombine _:
+		case Dim.DimView _:
+		case Dim.DimFill _:
+			// It's a Dim.DimCombine and so can't be assigned. Let it have it's Width anchored.
+			w = Width.Anchor (w);
+			canSetWidth = !ValidatePosDim;
+			break;
+		case Dim.DimFactor factor:
+			// Tries to get the SuperView Width otherwise the view Width.
+			var sw = SuperView != null ? SuperView.Frame.Width : w;
+			if (factor.IsFromRemaining ()) {
+				sw -= Frame.X;
+			}
+			w = Width.Anchor (sw);
+			canSetWidth = !ValidatePosDim;
+			break;
+		default:
+			canSetWidth = true;
+			break;
+		}
+		resultWidth = w;
+
+		return canSetWidth;
+	}
+
+	/// <summary>
+	/// Determines if the View's <see cref="Height"/> can be set to a new value.
+	/// </summary>
+	/// <param name="desiredHeight"></param>
+	/// <param name="resultHeight">
+	/// Contains the width that would result if <see cref="Height"/> were set to
+	/// <paramref name="desiredHeight"/>"/>
+	/// </param>
+	/// <returns>
+	/// <see langword="true"/> if the View's <see cref="Height"/> can be changed to the specified value. False
+	/// otherwise.
+	/// </returns>
+	internal bool TrySetHeight (int desiredHeight, out int resultHeight)
+	{
+		var h = desiredHeight;
+		bool canSetHeight;
+		switch (Height) {
+		case Dim.DimCombine _:
+		case Dim.DimView _:
+		case Dim.DimFill _:
+			// It's a Dim.DimCombine and so can't be assigned. Let it have it's height anchored.
+			h = Height.Anchor (h);
+			canSetHeight = !ValidatePosDim;
+			break;
+		case Dim.DimFactor factor:
+			// Tries to get the SuperView height otherwise the view height.
+			var sh = SuperView != null ? SuperView.Frame.Height : h;
+			if (factor.IsFromRemaining ()) {
+				sh -= Frame.Y;
+			}
+			h = Height.Anchor (sh);
+			canSetHeight = !ValidatePosDim;
+			break;
+		default:
+			canSetHeight = true;
+			break;
+		}
+		resultHeight = h;
+
+		return canSetHeight;
+	}
+
+	/// <summary>
+	/// Finds which view that belong to the <paramref name="start"/> superview at the provided location.
+	/// </summary>
+	/// <param name="start">The superview where to look for.</param>
+	/// <param name="x">The column location in the superview.</param>
+	/// <param name="y">The row location in the superview.</param>
+	/// <param name="resx">The found view screen relative column location.</param>
+	/// <param name="resy">The found view screen relative row location.</param>
+	/// <returns>
+	/// The view that was found at the <praramref name="x"/> and <praramref name="y"/> coordinates.
+	/// <see langword="null"/> if no view was found.
+	/// </returns>
+	public static View FindDeepestView (View start, int x, int y, out int resx, out int resy)
+	{
+		resy = resx = 0;
+		if (start == null || !start.Frame.Contains (x, y)) {
+			return null;
+		}
+
+		var startFrame = start.Frame;
+		if (start.InternalSubviews != null) {
+			var count = start.InternalSubviews.Count;
+			if (count > 0) {
+				var boundsOffset = start.GetBoundsOffset ();
+				var rx = x - (startFrame.X + boundsOffset.X);
+				var ry = y - (startFrame.Y + boundsOffset.Y);
+				for (var i = count - 1; i >= 0; i--) {
+					var v = start.InternalSubviews [i];
+					if (v.Visible && v.Frame.Contains (rx, ry)) {
+						var deep = FindDeepestView (v, rx, ry, out resx, out resy);
+						if (deep == null) {
+							return v;
+						}
+						return deep;
+					}
+				}
+			}
+		}
+		resx = x - startFrame.X;
+		resy = y - startFrame.Y;
+		return start;
+	}
 }

+ 27 - 26
Terminal.Gui/View/SuperViewChangedEventArgs.cs

@@ -1,33 +1,34 @@
 using System;
 
-namespace Terminal.Gui {
+namespace Terminal.Gui; 
+
+/// <summary>
+/// Args for events where the <see cref="View.SuperView"/> of a <see cref="View"/> is changed
+/// (e.g. <see cref="View.Removed"/> / <see cref="View.Added"/> events).
+/// </summary>
+public class SuperViewChangedEventArgs : EventArgs {
 	/// <summary>
-	/// Args for events where the <see cref="View.SuperView"/> of a <see cref="View"/> is changed
-	/// (e.g. <see cref="View.Removed"/> / <see cref="View.Added"/> events).
+	/// Creates a new instance of the <see cref="SuperViewChangedEventArgs"/> class.
 	/// </summary>
-	public class SuperViewChangedEventArgs : EventArgs
+	/// <param name="parent"></param>
+	/// <param name="child"></param>
+	public SuperViewChangedEventArgs (View parent, View child)
 	{
-		/// <summary>
-		/// Creates a new instance of the <see cref="SuperViewChangedEventArgs"/> class.
-		/// </summary>
-		/// <param name="parent"></param>
-		/// <param name="child"></param>
-		public SuperViewChangedEventArgs (View parent, View child)
-		{
-			Parent = parent;
-			Child = child;
-		}
+		Parent = parent;
+		Child = child;
+	}
 
-		/// <summary>
-		/// The parent.  For <see cref="View.Removed"/> this is the old
-		/// parent (new parent now being null).  For <see cref="View.Added"/>
-		/// it is the new parent to whom view now belongs.
-		/// </summary>
-		public View Parent { get; }
+	// TODO: Parent is the wrong name. It should be SuperView.
+	/// <summary>
+	/// The parent.  For <see cref="View.Removed"/> this is the old
+	/// parent (new parent now being null).  For <see cref="View.Added"/>
+	/// it is the new parent to whom view now belongs.
+	/// </summary>
+	public View Parent { get; }
 
-		/// <summary>
-		/// The view that is having it's <see cref="View.SuperView"/> changed
-		/// </summary>
-		public View Child { get; }
-	}
-}
+	// TODO: Child is the wrong name. It should be View.
+	/// <summary>
+	/// The view that is having it's <see cref="View.SuperView"/> changed
+	/// </summary>
+	public View Child { get; }
+}

+ 4 - 1
Terminal.Gui/Views/FileDialog.cs

@@ -368,7 +368,10 @@ namespace Terminal.Gui {
 
 		private int CalculateOkButtonPosX ()
 		{
-			return this.Bounds.Width
+			if (!IsInitialized) {
+				return 0;
+			}
+			return Bounds.Width
 				- btnOk.Bounds.Width
 				- btnCancel.Bounds.Width
 				- 1

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

@@ -99,7 +99,7 @@ public sealed class ContextMenu : IDisposable {
 		}
 		_container = Application.Current;
 		_container.Closing += Container_Closing;
-		var frame = new Rect (0, 0, View.Driver.Cols, View.Driver.Rows);
+		var frame = Application.Driver.Bounds;
 		var position = Position;
 		if (Host != null) {
 			Host.BoundsToScreen (frame.X, frame.Y, out int x, out int y);

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

@@ -1445,7 +1445,7 @@ public class MenuBar : View {
 		if (Driver == null) {
 			return Point.Empty;
 		}
-		var superViewFrame = SuperView == null ? new Rect (0, 0, Driver.Cols, Driver.Rows) : SuperView.Frame;
+		var superViewFrame = SuperView == null ? Driver.Bounds : SuperView.Frame;
 		var sv = SuperView == null ? Application.Current : SuperView;
 		var boundsOffset = sv.GetBoundsOffset ();
 		return new Point (superViewFrame.X - sv.Frame.X - boundsOffset.X,
@@ -1458,7 +1458,7 @@ public class MenuBar : View {
 	/// <returns>The location offset.</returns>
 	internal Point GetScreenOffsetFromCurrent ()
 	{
-		var screen = new Rect (0, 0, Driver.Cols, Driver.Rows);
+		var screen = Driver.Bounds;
 		var currentFrame = Application.Current.Frame;
 		var boundsOffset = Application.Top.GetBoundsOffset ();
 		return new Point (screen.X - currentFrame.X - boundsOffset.X

+ 0 - 3
Terminal.Gui/Views/Slider.cs

@@ -804,8 +804,6 @@ public class Slider<T> : View {
 		if (!IsInitialized || AutoSize == false) {
 			return;
 		}
-		// Hack???  Otherwise we can't go back to Dim.Absolute.
-		LayoutStyle = LayoutStyle.Absolute;
 		Width = 0;
 		Height = 0;
 		if (_config._sliderOrientation == Orientation.Horizontal) {
@@ -817,7 +815,6 @@ public class Slider<T> : View {
 				new Size (int.Min (SuperView.Bounds.Width - GetFramesThickness ().Horizontal, CalcThickness ()),
 					int.Min (SuperView.Bounds.Height - GetFramesThickness ().Vertical,    CalcBestLength ())));
 		}
-		LayoutStyle = LayoutStyle.Computed;
 	}
 
 	/// <summary>

+ 1 - 1
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -77,7 +77,7 @@ namespace UICatalog.Scenarios {
 				};
 
 				AutoSize = false;
-				LayoutStyle = LayoutStyle.Absolute;
+				//LayoutStyle = LayoutStyle.Absolute;
 
 				var fillText = new System.Text.StringBuilder ();
 				for (int i = 0; i < Bounds.Height; i++) {

+ 2 - 2
UICatalog/Scenarios/AllViewsTester.cs

@@ -246,7 +246,7 @@ public class AllViewsTester : Scenario {
 		var layout = view.LayoutStyle;
 
 		try {
-			view.LayoutStyle = LayoutStyle.Absolute;
+			//view.LayoutStyle = LayoutStyle.Absolute;
 
 			view.X = _xRadioGroup.SelectedItem switch {
 				0 => Pos.Percent (_xVal),
@@ -280,7 +280,7 @@ public class AllViewsTester : Scenario {
 		} catch (Exception e) {
 			MessageBox.ErrorQuery ("Exception", e.Message, "Ok");
 		} finally {
-			view.LayoutStyle = layout;
+			//view.LayoutStyle = layout;
 		}
 		UpdateTitle (view);
 	}

+ 18 - 9
UnitTests/View/DrawTests.cs

@@ -4,14 +4,16 @@ using Xunit;
 using Xunit.Abstractions;
 using Microsoft.VisualStudio.TestPlatform.Utilities;
 
-namespace Terminal.Gui.ViewsTests; 
+namespace Terminal.Gui.ViewsTests;
 
 public class DrawTests {
 	readonly ITestOutputHelper _output;
 
 	public DrawTests (ITestOutputHelper output) => _output = output;
 
-	[Fact] [AutoInitShutdown]
+	// TODO: Refactor this test to not depend on TextView etc... Make it as primitive as possible
+	[Fact]
+	[AutoInitShutdown]
 	public void Clipping_AddRune_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space ()
 	{
 		var tv = new TextView () {
@@ -29,7 +31,8 @@ public class DrawTests {
 		var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () };
 		win.Add (tv);
 		Application.Top.Add (win);
-		var lbl = new Label ("ワイドルーン。");
+		// Don't use Label. It sets AutoSize = true which is not what we're testing here.
+		var lbl = new View ("ワイドルーン。");
 		// Don't have unit tests use things that aren't absolutely critical for the test, like Dialog
 		var dg = new Window () { X = 2, Y = 2, Width = 14, Height = 3 };
 		dg.Add (lbl);
@@ -54,7 +57,8 @@ public class DrawTests {
 	}
 
 	// TODO: The tests below that use Label should use View instead.
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void Non_Bmp_ConsoleWidth_ColumnWidth_Equal_Two ()
 	{
 		string us = "\U0001d539";
@@ -102,7 +106,8 @@ public class DrawTests {
 0000000000", Application.Driver, expectedColors);
 	}
 
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void CJK_Compatibility_Ideographs_ConsoleWidth_ColumnWidth_Equal_Two ()
 	{
 		string us = "\U0000f900";
@@ -150,7 +155,8 @@ public class DrawTests {
 0000000000", Application.Driver, expectedColors);
 	}
 
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void Colors_On_TextAlignment_Right_And_Bottom ()
 	{
 		var labelRight = new Label ("Test") {
@@ -191,7 +197,8 @@ t     ", _output);
 0", Application.Driver, new Attribute [] { Colors.Base.Normal });
 	}
 
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void Draw_Negative_Bounds_Horizontal_Without_New_Lines ()
 	{
 		// BUGBUG: This previously assumed the default height of a View was 1. 
@@ -235,7 +242,8 @@ t     ", _output);
 		TestHelpers.AssertDriverContentsWithFrameAre ("", _output);
 	}
 
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void Draw_Negative_Bounds_Horizontal_With_New_Lines ()
 	{
 		var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "s\nu\nb\nV\ni\ne\nw" };
@@ -304,7 +312,8 @@ t     ", _output);
 		TestHelpers.AssertDriverContentsWithFrameAre ("", _output);
 	}
 
-	[Fact] [AutoInitShutdown]
+	[Fact]
+	[AutoInitShutdown]
 	public void Draw_Negative_Bounds_Vertical ()
 	{
 		var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "subView", TextDirection = TextDirection.TopBottom_LeftRight };

+ 21 - 2
UnitTests/View/Layout/LayoutTests.cs

@@ -248,6 +248,25 @@ public class LayoutTests {
 		top.Dispose ();
 	}
 
+	[Fact]
+	[AutoInitShutdown]
+	public void DimFill_SizedCorrectly ()
+	{
+		var view = new View () {
+			Width = Dim.Fill (),
+			Height = Dim.Fill (),
+			BorderStyle = LineStyle.Single,
+		};
+		Application.Top.Add (view);
+		var rs = Application.Begin (Application.Top);
+		((FakeDriver)Application.Driver).SetBufferSize (32, 5);
+		//view.SetNeedsLayout ();
+		Application.Top.LayoutSubviews ();
+		//view.SetRelativeLayout (new Rect (0, 0, 32, 5));
+		Assert.Equal (32, view.Frame.Width);
+		Assert.Equal (5, view.Frame.Height);
+	}
+
 	[Fact] [AutoInitShutdown]
 	public void Width_Height_SetMinWidthHeight_Narrow_Wide_Runes ()
 	{
@@ -761,7 +780,7 @@ public class LayoutTests {
 	// Was named AutoSize_Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
 	// but doesn't actually have anything to do with AutoSize.
 	[Fact]
-	public void AutoSize_Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
+	public void Pos_Validation_Do_Not_Throws_If_NewValue_Is_PosAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
 	{
 		Application.Init (new FakeDriver ());
 
@@ -781,7 +800,7 @@ public class LayoutTests {
 		t.Add (w);
 
 		t.Ready += (s, e) => {
-			v.LayoutStyle = LayoutStyle.Absolute;
+			v.Frame = new Rect (2, 2, 10, 10);
 			Assert.Equal (2, v.X = 2);
 			Assert.Equal (2, v.Y = 2);
 		};

+ 51 - 10
UnitTests/View/Layout/SetRelativeLayoutTests.cs

@@ -10,7 +10,46 @@ public class SetRelativeLayoutTests {
 	readonly ITestOutputHelper _output;
 
 	public SetRelativeLayoutTests (ITestOutputHelper output) => _output = output;
-	
+
+	[Fact]
+	public void ComputedPosDim_StayComputed ()
+	{
+		var screen = new Rect (0, 0, 10, 15);
+		var view = new View () {
+			X = 1,
+			Y = 2,
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
+		};
+
+		Assert.Equal ("Absolute(1)", view.X.ToString ());
+		Assert.Equal ("Absolute(2)", view.Y.ToString ());
+		Assert.Equal ("Fill(0)", view.Width.ToString ());
+		Assert.Equal ("Fill(0)", view.Height.ToString ());
+		view.SetRelativeLayout (screen);
+		Assert.Equal ("Fill(0)", view.Width.ToString ());
+		Assert.Equal ("Fill(0)", view.Height.ToString ());
+	}
+
+	[Fact]
+	public void AbsolutePosDim_DontChange ()
+	{
+		var screen = new Rect (0, 0, 10, 15);
+		var view = new View () {
+			X = 1,  // outside of screen +10
+			Y = 2, // outside of screen -10
+			Width = 3,
+			Height = 4
+		};
+
+		// Layout is Absolute. So the X and Y are not changed.
+		view.SetRelativeLayout (screen);
+		Assert.Equal (1, view.Frame.X);
+		Assert.Equal (2, view.Frame.Y);
+		Assert.Equal (3, view.Frame.Width);
+		Assert.Equal (4, view.Frame.Height);
+	}
+
 	[Fact]
 	public void Fill_Pos_Within_Bounds ()
 	{
@@ -64,7 +103,7 @@ public class SetRelativeLayoutTests {
 	}
 
 	[Fact]
-	public void FIll_Pos_Outside_Bounds ()
+	public void Fill_Pos_Outside_Bounds ()
 	{
 		var screen = new Rect (0, 0, 80, 25);
 		var view = new View () {
@@ -74,6 +113,7 @@ public class SetRelativeLayoutTests {
 			Height = 15
 		};
 
+		// Layout is Absolute. So the X and Y are not changed.
 		view.SetRelativeLayout (screen);
 		Assert.Equal (90, view.Frame.X);
 		Assert.Equal (-10, view.Frame.Y);
@@ -125,10 +165,10 @@ public class SetRelativeLayoutTests {
 		Assert.Equal (80, view.Frame.Width);
 		Assert.Equal (25, view.Frame.Height);
 
-		view.Width = Dim.Fill (); 
+		view.Width = Dim.Fill ();
 		view.Height = Dim.Fill ();
 		view.SetRelativeLayout (screen);
-		Assert.Equal (-41, view.Frame.X); 
+		Assert.Equal (-41, view.Frame.X);
 		Assert.Equal (-13, view.Frame.Y);
 		Assert.Equal (121, view.Frame.Width);  // 121 = screen.Width - (-Center - 41)
 		Assert.Equal (38, view.Frame.Height);
@@ -141,12 +181,12 @@ public class SetRelativeLayoutTests {
 		var view = new View () {
 			X = Pos.Center (),
 			Y = Pos.Center (),
-			Width = Dim.Fill(),
-			Height = Dim.Fill()
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
 		};
 
 		view.SetRelativeLayout (screen);
-		Assert.Equal (0, view.Frame.X); 
+		Assert.Equal (0, view.Frame.X);
 		Assert.Equal (0, view.Frame.Y);
 		Assert.Equal (80, view.Frame.Width);
 		Assert.Equal (25, view.Frame.Height);
@@ -176,14 +216,14 @@ public class SetRelativeLayoutTests {
 		view.SetRelativeLayout (screen);
 		Assert.Equal (-1, view.Frame.X);
 		Assert.Equal (0, view.Frame.Y);
-		Assert.Equal (81, view.Frame.Width); 
+		Assert.Equal (81, view.Frame.Width);
 		Assert.Equal (25, view.Frame.Height);
 
 		view.X = Pos.Center () - 2; // Fill means all the way to right. So width will be 82. (dim gets calc'd before pos).
 		view.SetRelativeLayout (screen);
 		Assert.Equal (-2, view.Frame.X);
 		Assert.Equal (0, view.Frame.Y);
-		Assert.Equal (82, view.Frame.Width); 
+		Assert.Equal (82, view.Frame.Width);
 		Assert.Equal (25, view.Frame.Height);
 
 		view.X = Pos.Center () - 3; // Fill means all the way to right. So width will be 83. (dim gets calc'd before pos).
@@ -217,7 +257,8 @@ public class SetRelativeLayoutTests {
 		Assert.Equal (23, view.Frame.Y);
 	}
 
-	[Fact] [TestRespondersDisposed]
+	[Fact]
+	[TestRespondersDisposed]
 	public void PosCombine_Plus_Absolute ()
 	{
 		var superView = new View () {

+ 522 - 13
UnitTests/View/Text/AutoSizeTextTests.cs

@@ -769,17 +769,47 @@ Y
 		Application.End (rs);
 	}
 
+	[Fact]
+	public void SetRelativeLayout_Respects_AutoSize ()
+	{
+		var view = new View (new Rect (0, 0, 10, 0)) {
+			AutoSize = true,
+		};
+		view.Text = "01234567890123456789";
+
+		Assert.True (view.AutoSize);
+		Assert.Equal (LayoutStyle.Absolute,   view.LayoutStyle);
+		Assert.Equal (new Rect (0, 0, 20, 1), view.Frame);
+		Assert.Equal ("Absolute(0)",          view.X.ToString ());
+		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
+		Assert.Equal ("Absolute(20)",         view.Width.ToString ());
+		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
+
+		view.SetRelativeLayout (new Rect (0, 0, 25, 5));
+
+		Assert.True (view.AutoSize);
+		Assert.Equal (LayoutStyle.Absolute,   view.LayoutStyle);
+		Assert.Equal (new Rect (0, 0, 20, 1), view.Frame);
+		Assert.Equal ("Absolute(0)",          view.X.ToString ());
+		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
+		Assert.Equal ("Absolute(20)",         view.Width.ToString ());
+		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
+	}
+
 	[Fact]
 	[AutoInitShutdown]
 	public void Setting_Frame_Dont_Respect_AutoSize_True_On_Layout_Absolute ()
 	{
-		var view1 = new View (new Rect (0, 0, 10, 0)) { Text = "Say Hello view1 你", AutoSize = true };
-		var view2 = new View (new Rect (0, 0, 0, 10)) {
+		var view1 = new View (new Rect (0, 0, 10, 0)) {
+			Text = "Say Hello view1 你", 
+			AutoSize = true
+		};
+		var viewTopBottom_LeftRight = new View (new Rect (0, 0, 0, 10)) {
 			Text = "Say Hello view2 你",
 			AutoSize = true,
 			TextDirection = TextDirection.TopBottom_LeftRight
 		};
-		Application.Top.Add (view1, view2);
+		Application.Top.Add (view1, viewTopBottom_LeftRight);
 
 		var rs = Application.Begin (Application.Top);
 
@@ -790,7 +820,8 @@ Y
 		Assert.Equal ("Absolute(0)", view1.Y.ToString ());
 		Assert.Equal ("Absolute(18)", view1.Width.ToString ());
 		Assert.Equal ("Absolute(1)", view1.Height.ToString ());
-		Assert.True (view2.AutoSize);
+		
+		Assert.True (viewTopBottom_LeftRight.AutoSize);
 		// BUGBUG: v2 - Autosize is broken when setting Width/Height AutoSize. Disabling test for now.
 		//Assert.Equal (LayoutStyle.Absolute, view2.LayoutStyle);
 		//Assert.Equal (new Rect (0, 0, 2, 17), view2.Frame);
@@ -811,14 +842,14 @@ Y
 		Assert.Equal ("Absolute(18)", view1.Width.ToString ());
 		Assert.Equal ("Absolute(1)", view1.Height.ToString ());
 
-		view2.Frame = new Rect (0, 0, 1, 25);
+		viewTopBottom_LeftRight.Frame = new Rect (0, 0, 1, 25);
 		Application.RunIteration (ref rs, ref firstIteration);
 
-		Assert.True (view2.AutoSize);
-		Assert.Equal (LayoutStyle.Absolute, view2.LayoutStyle);
-		Assert.Equal (new Rect (0, 0, 1, 25), view2.Frame);
-		Assert.Equal ("Absolute(0)", view2.X.ToString ());
-		Assert.Equal ("Absolute(0)", view2.Y.ToString ());
+		Assert.True (viewTopBottom_LeftRight.AutoSize);
+		Assert.Equal (LayoutStyle.Absolute, viewTopBottom_LeftRight.LayoutStyle);
+		Assert.Equal (new Rect (0, 0, 1, 25), viewTopBottom_LeftRight.Frame);
+		Assert.Equal ("Absolute(0)", viewTopBottom_LeftRight.X.ToString ());
+		Assert.Equal ("Absolute(0)", viewTopBottom_LeftRight.Y.ToString ());
 		// BUGBUG: v2 - Autosize is broken when setting Width/Height AutoSize. Disabling test for now.
 		//Assert.Equal ("Absolute(2)", view2.Width.ToString ());
 		//Assert.Equal ("Absolute(17)", view2.Height.ToString ());
@@ -1865,8 +1896,7 @@ Y
 		Assert.Equal (new Rect (0, 0, 22, 22), pos);
 		Application.End (rs);
 	}
-
-
+	
 	[Fact]
 	[AutoInitShutdown]
 	public void AutoSize_True_Width_Height_Stay_True_If_TextFormatter_Size_Fit ()
@@ -1905,7 +1935,7 @@ Y
 		Assert.Equal ("Absolute(0)", horizontalView.X.ToString ());
 		Assert.Equal ("Absolute(0)", horizontalView.Y.ToString ());
 		// BUGBUG - v2 - With v1 AutoSize = true Width/Height should always grow or keep initial value, 
-		// but in v2, autosize will be replaced by Dim.Fit. Disabling test for now.
+		
 		Assert.Equal ("Absolute(9)", horizontalView.Width.ToString ());
 		Assert.Equal ("Absolute(1)", horizontalView.Height.ToString ());
 		Assert.Equal (new Rect (0, 3, 2, 8), verticalView.Frame);
@@ -1981,4 +2011,483 @@ Y
 		Application.End (rs);
 	}
 
+
+	[Fact]
+	[AutoInitShutdown]
+	public void AutoSize_False_SetWidthHeight_With_Dim_Fill_And_Dim_Absolute_After_IsAdded_And_IsInitialized ()
+	{
+		var win = new Window (new Rect (0, 0, 30, 80));
+		var label = new Label { Width = Dim.Fill () };
+		win.Add (label);
+		Application.Top.Add (win);
+
+		Assert.True (label.IsAdded);
+
+		Assert.True (label.AutoSize);
+
+		// #3127: Before: 
+		//		 Text is empty but height=1 by default, see Label view
+		//		 BUGBUG: LayoutSubviews has not been called, so this test is not really valid (pos/dim are indeterminate, not 0)
+		//		 Not really a bug because View call OnResizeNeeded method on the SetInitialProperties method
+		// #3127: After: Text is empty Width=Dim.Fill is honored
+		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
+
+		label.Text = "First line\nSecond line";
+		Application.Top.LayoutSubviews ();
+
+		Assert.True (label.AutoSize);
+		// BUGBUG: This test is bogus: label has not been initialized. pos/dim is indeterminate!
+		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
+		Assert.False (label.IsInitialized);
+
+		var rs = Application.Begin (Application.Top);
+
+		Assert.True (label.AutoSize);
+		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
+		Assert.True (label.IsInitialized);
+
+		label.AutoSize = false;
+		// BUGBUG: Application.Refresh has nothing to do with layout! It just redraws and sets LayoutNeeded to true
+		// Application.Refresh ();
+
+		// Width should still be Dim.Fill
+		Assert.Equal ("Fill(0)", label.Width.ToString ());
+
+		// Height should be 2
+		Assert.Equal ("Absolute(2)", label.Height.ToString ());
+		Assert.Equal (2,             label.Frame.Height);
+
+		Assert.False (label.AutoSize);
+		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
+		Application.End (rs);
+	}
+
+	[Fact]
+	[AutoInitShutdown]
+	public void AutoSize_False_SetWidthHeight_With_Dim_Fill_And_Dim_Absolute_With_Initialization ()
+	{
+		var win = new Window (new Rect (0, 0, 30, 80));
+		var label = new Label { Width = Dim.Fill () };
+		win.Add (label);
+		Application.Top.Add (win);
+
+		// Text is empty but height=1 by default, see Label view
+		Assert.True (label.AutoSize);
+		Assert.Equal ("(0,0,0,1)", label.Bounds.ToString ());
+
+		var rs = Application.Begin (Application.Top);
+
+		Assert.True (label.AutoSize);
+		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
+		// and height 0 because wasn't set and the text is empty
+		// BUGBUG: Because of #2450, this test is bogus: pos/dim is indeterminate!
+		//Assert.Equal ("(0,0,28,0)", label.Bounds.ToString ());
+
+		label.Text = "First line\nSecond line";
+		Application.Refresh ();
+
+		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
+		// and height 2 because wasn't set and the text has 2 lines
+		Assert.True (label.AutoSize);
+		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
+
+		label.AutoSize = false;
+		Application.Refresh ();
+
+		// Here the SetMinWidthHeight ensuring the minimum height
+		Assert.False (label.AutoSize);
+		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
+
+		label.Text = "First changed line\nSecond changed line\nNew line";
+		Application.Refresh ();
+
+		// Here the AutoSize is false and the width 28 (Dim.Fill) and
+		// height 1 because wasn't set and SetMinWidthHeight ensuring the minimum height
+		Assert.False (label.AutoSize);
+		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
+
+		label.AutoSize = true;
+		Application.Refresh ();
+
+		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
+		// and height 3 because wasn't set and the text has 3 lines
+		Assert.True (label.AutoSize);
+		// BUGBUG: v2 - AutoSize is broken - temporarily disabling test See #2432
+		//Assert.Equal ("(0,0,28,3)", label.Bounds.ToString ());
+		Application.End (rs);
+	}
+
+
+	[Fact]
+	[AutoInitShutdown]
+	public void AutoSize_False_TextDirection_Toggle ()
+	{
+		var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
+		// View is AutoSize == true
+		var view = new View ();
+		win.Add (view);
+		Application.Top.Add (win);
+
+		var rs = Application.Begin (Application.Top);
+		((FakeDriver)Application.Driver).SetBufferSize (22, 22);
+
+		Assert.Equal (new Rect (0, 0, 22, 22), win.Frame);
+		Assert.Equal (new Rect (0, 0, 22, 22), win.Margin.Frame);
+		Assert.Equal (new Rect (0, 0, 22, 22), win.Border.Frame);
+		Assert.Equal (new Rect (1, 1, 20, 20), win.Padding.Frame);
+		Assert.False (view.AutoSize);
+		Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection);
+		Assert.Equal (Rect.Empty, view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(0)", view.Width.ToString ());
+		Assert.Equal ("Absolute(0)", view.Height.ToString ());
+		var expected = @"
+┌────────────────────┐
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.Text = "Hello World";
+		view.Width = 11;
+		view.Height = 1;
+		win.LayoutSubviews ();
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(11)", view.Width.ToString ());
+		Assert.Equal ("Absolute(1)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│Hello World         │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.AutoSize = true;
+		view.Text = "Hello Worlds";
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 12, 1), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(11)", view.Width.ToString ());
+		Assert.Equal ("Absolute(1)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│Hello Worlds        │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.TextDirection = TextDirection.TopBottom_LeftRight;
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 11, 12), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(11)", view.Width.ToString ());
+		Assert.Equal ("Absolute(1)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│H                   │
+│e                   │
+│l                   │
+│l                   │
+│o                   │
+│                    │
+│W                   │
+│o                   │
+│r                   │
+│l                   │
+│d                   │
+│s                   │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.AutoSize = false;
+		view.Height = 1;
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(11)", view.Width.ToString ());
+		Assert.Equal ("Absolute(1)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│HelloWorlds         │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.PreserveTrailingSpaces = true;
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(11)", view.Width.ToString ());
+		Assert.Equal ("Absolute(1)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│Hello World         │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.PreserveTrailingSpaces = false;
+		var f = view.Frame;
+		view.Width = f.Height;
+		view.Height = f.Width;
+		view.TextDirection = TextDirection.TopBottom_LeftRight;
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 1, 11), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(1)", view.Width.ToString ());
+		Assert.Equal ("Absolute(11)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│H                   │
+│e                   │
+│l                   │
+│l                   │
+│o                   │
+│                    │
+│W                   │
+│o                   │
+│r                   │
+│l                   │
+│d                   │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+		view.AutoSize = true;
+		Application.Refresh ();
+
+		Assert.Equal (new Rect (0, 0, 1, 12), view.Frame);
+		Assert.Equal ("Absolute(0)", view.X.ToString ());
+		Assert.Equal ("Absolute(0)", view.Y.ToString ());
+		Assert.Equal ("Absolute(1)", view.Width.ToString ());
+		Assert.Equal ("Absolute(12)", view.Height.ToString ());
+		expected = @"
+┌────────────────────┐
+│H                   │
+│e                   │
+│l                   │
+│l                   │
+│o                   │
+│                    │
+│W                   │
+│o                   │
+│r                   │
+│l                   │
+│d                   │
+│s                   │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+		Assert.Equal (new Rect (0, 0, 22, 22), pos);
+		Application.End (rs);
+	}
+
+
+	[Fact, AutoInitShutdown]
+	public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier ()
+	{
+		var text = "Say Hello 你";
+
+		// Frame: 0, 0, 12, 1
+		var horizontalView = new View () {
+			AutoSize = true,
+			HotKeySpecifier = (Rune)'_'
+		};
+		horizontalView.Text = text;
+
+		// Frame: 0, 0, 1, 12
+		var verticalView = new View () {
+			AutoSize = true,
+			HotKeySpecifier = (Rune)'_',
+			TextDirection = TextDirection.TopBottom_LeftRight
+		};
+		verticalView.Text = text;
+
+		Application.Top.Add (horizontalView, verticalView);
+		Application.Begin (Application.Top);
+		((FakeDriver)Application.Driver).SetBufferSize (50, 50);
+
+		Assert.True (horizontalView.AutoSize);
+		Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
+		Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
+		Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
+
+		Assert.True (verticalView.AutoSize);
+		// BUGBUG: v2 - Autosize is broken; disabling this test
+		Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
+		Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
+		//Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextAndHotKey ());
+		//Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
+		Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
+
+		text = "Say He_llo 你";
+		horizontalView.Text = text;
+		verticalView.Text = text;
+
+		Assert.True (horizontalView.AutoSize);
+		Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
+		Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
+		//Assert.Equal (new Size (13, 1), horizontalView.GetSizeNeededForTextAndHotKey ());
+		//Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ());
+		Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
+
+		Assert.True (verticalView.AutoSize);
+		// BUGBUG: v2 - Autosize is broken; disabling this test
+		//Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
+		//Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
+		//Assert.Equal (new Size (2, 12), verticalView.GetSizeNeededForTextAndHotKey ());
+		//Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
+		//Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
+	}
 }

+ 47 - 454
UnitTests/View/Text/TextTests.cs

@@ -33,11 +33,11 @@ public class TextTests {
 
 		Assert.Equal (5, text.Length);
 		Assert.False (view.AutoSize);
-		Assert.Equal (new Rect (0, 0, 3, 1),      view.Frame);
-		Assert.Equal (new Size (3, 1),            view.TextFormatter.Size);
+		Assert.Equal (new Rect (0, 0, 3, 1), view.Frame);
+		Assert.Equal (new Size (3, 1), view.TextFormatter.Size);
 		Assert.Equal (new List<string> { "Vie" }, view.TextFormatter.Lines);
-		Assert.Equal (new Rect (0, 0, 10, 4),     win.Frame);
-		Assert.Equal (new Rect (0, 0, 10, 4),     Application.Top.Frame);
+		Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
+		Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
 		var expected = @"
 ┌────────┐
 │Vie     │
@@ -53,8 +53,8 @@ public class TextTests {
 		view.Width = Dim.Fill () - text.Length;
 		Application.Refresh ();
 
-		Assert.Equal (new Rect (0, 0, 0, 1),             view.Frame);
-		Assert.Equal (new Size (0, 1),                   view.TextFormatter.Size);
+		Assert.Equal (new Rect (0, 0, 0, 1), view.Frame);
+		Assert.Equal (new Size (0, 1), view.TextFormatter.Size);
 		Assert.Equal (new List<string> { string.Empty }, view.TextFormatter.Lines);
 		expected = @"
 ┌────────┐
@@ -88,7 +88,7 @@ public class TextTests {
 		Assert.Equal (5, text.Length);
 		Assert.False (view.AutoSize);
 		Assert.Equal (new Rect (0, 0, 3, 1), view.Frame);
-		Assert.Equal (new Size (3, 1),       view.TextFormatter.Size);
+		Assert.Equal (new Size (3, 1), view.TextFormatter.Size);
 		Assert.Single (view.TextFormatter.Lines);
 		Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
 		Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
@@ -108,7 +108,7 @@ public class TextTests {
 		Application.Refresh ();
 
 		Assert.Equal (new Rect (0, 0, 0, 1), view.Frame);
-		Assert.Equal (new Size (0, 1),       view.TextFormatter.Size);
+		Assert.Equal (new Size (0, 1), view.TextFormatter.Size);
 		var exception = Record.Exception (() => Assert.Equal (new List<string> { string.Empty }, view.TextFormatter.Lines));
 		Assert.Null (exception);
 		expected = @"
@@ -144,11 +144,11 @@ public class TextTests {
 
 		Assert.Equal (5, text.Length);
 		Assert.False (label.AutoSize);
-		Assert.Equal (new Rect (0, 0, 3, 1),      label.Frame);
-		Assert.Equal (new Size (3, 1),            label.TextFormatter.Size);
+		Assert.Equal (new Rect (0, 0, 3, 1), label.Frame);
+		Assert.Equal (new Size (3, 1), label.TextFormatter.Size);
 		Assert.Equal (new List<string> { "Lab" }, label.TextFormatter.Lines);
-		Assert.Equal (new Rect (0, 0, 10, 4),     win.Frame);
-		Assert.Equal (new Rect (0, 0, 10, 4),     Application.Top.Frame);
+		Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
+		Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
 		var expected = @"
 ┌────────┐
 │Lab     │
@@ -165,8 +165,8 @@ public class TextTests {
 		Application.Refresh ();
 
 		Assert.False (label.AutoSize);
-		Assert.Equal (new Rect (0, 0, 0, 1),             label.Frame);
-		Assert.Equal (new Size (0, 1),                   label.TextFormatter.Size);
+		Assert.Equal (new Rect (0, 0, 0, 1), label.Frame);
+		Assert.Equal (new Size (0, 1), label.TextFormatter.Size);
 		Assert.Equal (new List<string> { string.Empty }, label.TextFormatter.Lines);
 		expected = @"
 ┌────────┐
@@ -201,7 +201,7 @@ public class TextTests {
 		Assert.Equal (5, text.Length);
 		Assert.False (label.AutoSize);
 		Assert.Equal (new Rect (0, 0, 3, 1), label.Frame);
-		Assert.Equal (new Size (3, 1),       label.TextFormatter.Size);
+		Assert.Equal (new Size (3, 1), label.TextFormatter.Size);
 		Assert.Single (label.TextFormatter.Lines);
 		Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
 		Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
@@ -221,7 +221,7 @@ public class TextTests {
 		Application.Refresh ();
 
 		Assert.Equal (new Rect (0, 0, 0, 1), label.Frame);
-		Assert.Equal (new Size (0, 1),       label.TextFormatter.Size);
+		Assert.Equal (new Size (0, 1), label.TextFormatter.Size);
 		var exception = Record.Exception (() => Assert.Equal (new List<string> { string.Empty }, label.TextFormatter.Lines));
 		Assert.Null (exception);
 		expected = @"
@@ -257,7 +257,7 @@ public class TextTests {
 		Assert.Equal (5, text.Length);
 		Assert.False (view.AutoSize);
 		Assert.Equal (new Rect (0, 0, 1, 3), view.Frame);
-		Assert.Equal (new Size (1, 3),       view.TextFormatter.Size);
+		Assert.Equal (new Size (1, 3), view.TextFormatter.Size);
 		Assert.Single (view.TextFormatter.Lines);
 		Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
 		Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
@@ -283,7 +283,7 @@ public class TextTests {
 		Application.Refresh ();
 
 		Assert.Equal (new Rect (0, 0, 1, 0), view.Frame);
-		Assert.Equal (new Size (1, 0),       view.TextFormatter.Size);
+		Assert.Equal (new Size (1, 0), view.TextFormatter.Size);
 		var exception = Record.Exception (() => Assert.Equal (new List<string> { string.Empty }, view.TextFormatter.Lines));
 		Assert.Null (exception);
 		expected = @"
@@ -325,7 +325,7 @@ public class TextTests {
 		Assert.Equal (5, text.Length);
 		Assert.False (view.AutoSize);
 		Assert.Equal (new Rect (0, 0, 2, 3), view.Frame);
-		Assert.Equal (new Size (2, 3),       view.TextFormatter.Size);
+		Assert.Equal (new Size (2, 3), view.TextFormatter.Size);
 		Assert.Single (view.TextFormatter.Lines);
 		Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
 		Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
@@ -351,7 +351,7 @@ public class TextTests {
 		Application.Refresh ();
 
 		Assert.Equal (new Rect (0, 0, 2, 0), view.Frame);
-		Assert.Equal (new Size (2, 0),       view.TextFormatter.Size);
+		Assert.Equal (new Size (2, 0), view.TextFormatter.Size);
 		var exception = Record.Exception (() => Assert.Equal (new List<string> { string.Empty }, view.TextFormatter.Lines));
 		Assert.Null (exception);
 		expected = @"
@@ -427,9 +427,10 @@ public class TextTests {
 		win.Add (label);
 		Application.Top.Add (win);
 
-		// Text is empty but height=1 by default, see Label view
+		// #3127: Before: Text is empty but height=1 by default, see Label view
+		//        After: Text is empty Dim.Fill is honored
 		Assert.False (label.AutoSize);
-		Assert.Equal ("(0,0,0,1)", label.Bounds.ToString ());
+		Assert.Equal ("(0,0,28,78)", label.Bounds.ToString ());
 
 		label.Text = "New text\nNew line";
 		Application.Top.LayoutSubviews ();
@@ -445,100 +446,6 @@ public class TextTests {
 		Application.End (rs);
 	}
 
-	[Fact]
-	[AutoInitShutdown]
-	public void AutoSize_False_SetWidthHeight_With_Dim_Fill_And_Dim_Absolute_After_IsAdded_And_IsInitialized ()
-	{
-		var win = new Window (new Rect (0, 0, 30, 80));
-		var label = new Label { Width = Dim.Fill () };
-		win.Add (label);
-		Application.Top.Add (win);
-
-		Assert.True (label.IsAdded);
-
-		// Text is empty but height=1 by default, see Label view
-		Assert.True (label.AutoSize);
-		// BUGBUG: LayoutSubviews has not been called, so this test is not really valid (pos/dim are indeterminate, not 0)
-		// Not really a bug because View call OnResizeNeeded method on the SetInitialProperties method
-		Assert.Equal ("(0,0,0,1)", label.Bounds.ToString ());
-
-		label.Text = "First line\nSecond line";
-		Application.Top.LayoutSubviews ();
-
-		Assert.True (label.AutoSize);
-		// BUGBUG: This test is bogus: label has not been initialized. pos/dim is indeterminate!
-		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
-		Assert.False (label.IsInitialized);
-
-		var rs = Application.Begin (Application.Top);
-
-		Assert.True (label.AutoSize);
-		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
-		Assert.True (label.IsInitialized);
-
-		label.AutoSize = false;
-		Application.Refresh ();
-
-		Assert.False (label.AutoSize);
-		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
-		Application.End (rs);
-	}
-
-	[Fact]
-	[AutoInitShutdown]
-	public void AutoSize_False_SetWidthHeight_With_Dim_Fill_And_Dim_Absolute_With_Initialization ()
-	{
-		var win = new Window (new Rect (0, 0, 30, 80));
-		var label = new Label { Width = Dim.Fill () };
-		win.Add (label);
-		Application.Top.Add (win);
-
-		// Text is empty but height=1 by default, see Label view
-		Assert.True (label.AutoSize);
-		Assert.Equal ("(0,0,0,1)", label.Bounds.ToString ());
-
-		var rs = Application.Begin (Application.Top);
-
-		Assert.True (label.AutoSize);
-		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
-		// and height 0 because wasn't set and the text is empty
-		// BUGBUG: Because of #2450, this test is bogus: pos/dim is indeterminate!
-		//Assert.Equal ("(0,0,28,0)", label.Bounds.ToString ());
-
-		label.Text = "First line\nSecond line";
-		Application.Refresh ();
-
-		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
-		// and height 2 because wasn't set and the text has 2 lines
-		Assert.True (label.AutoSize);
-		Assert.Equal ("(0,0,28,2)", label.Bounds.ToString ());
-
-		label.AutoSize = false;
-		Application.Refresh ();
-
-		// Here the SetMinWidthHeight ensuring the minimum height
-		Assert.False (label.AutoSize);
-		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
-
-		label.Text = "First changed line\nSecond changed line\nNew line";
-		Application.Refresh ();
-
-		// Here the AutoSize is false and the width 28 (Dim.Fill) and
-		// height 1 because wasn't set and SetMinWidthHeight ensuring the minimum height
-		Assert.False (label.AutoSize);
-		Assert.Equal ("(0,0,28,1)", label.Bounds.ToString ());
-
-		label.AutoSize = true;
-		Application.Refresh ();
-
-		// Here the AutoSize ensuring the right size with width 28 (Dim.Fill)
-		// and height 3 because wasn't set and the text has 3 lines
-		Assert.True (label.AutoSize);
-		// BUGBUG: v2 - AutoSize is broken - temporarily disabling test See #2432
-		//Assert.Equal ("(0,0,28,3)", label.Bounds.ToString ());
-		Application.End (rs);
-	}
-
 	[Fact]
 	[AutoInitShutdown]
 	public void AutoSize_False_Equal_Before_And_After_IsInitialized_With_Differents_Orders ()
@@ -576,28 +483,28 @@ public class TextTests {
 		Assert.False (view5.IsInitialized);
 		Assert.False (view1.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame);
-		Assert.Equal ("Absolute(10)",         view1.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view1.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view1.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view1.Height.ToString ());
 		Assert.False (view2.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame);
-		Assert.Equal ("Absolute(10)",         view2.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view2.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view2.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view2.Height.ToString ());
 		Assert.False (view3.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame);
-		Assert.Equal ("Absolute(10)",         view3.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view3.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view3.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view3.Height.ToString ());
 		Assert.False (view4.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame);
-		Assert.Equal ("Absolute(10)",         view4.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view4.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view4.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view4.Height.ToString ());
 		Assert.False (view5.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame);
-		Assert.Equal ("Absolute(10)",         view5.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view5.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view5.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view5.Height.ToString ());
 		Assert.False (view6.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame);
-		Assert.Equal ("Absolute(10)",         view6.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view6.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view6.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view6.Height.ToString ());
 
 		var rs = Application.Begin (Application.Top);
 
@@ -608,343 +515,29 @@ public class TextTests {
 		Assert.True (view5.IsInitialized);
 		Assert.False (view1.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame);
-		Assert.Equal ("Absolute(10)",         view1.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view1.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view1.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view1.Height.ToString ());
 		Assert.False (view2.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame);
-		Assert.Equal ("Absolute(10)",         view2.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view2.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view2.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view2.Height.ToString ());
 		Assert.False (view3.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame);
-		Assert.Equal ("Absolute(10)",         view3.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view3.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view3.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view3.Height.ToString ());
 		Assert.False (view4.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame);
-		Assert.Equal ("Absolute(10)",         view4.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view4.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view4.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view4.Height.ToString ());
 		Assert.False (view5.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame);
-		Assert.Equal ("Absolute(10)",         view5.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view5.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view5.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view5.Height.ToString ());
 		Assert.False (view6.AutoSize);
 		Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame);
-		Assert.Equal ("Absolute(10)",         view6.Width.ToString ());
-		Assert.Equal ("Absolute(5)",          view6.Height.ToString ());
+		Assert.Equal ("Absolute(10)", view6.Width.ToString ());
+		Assert.Equal ("Absolute(5)", view6.Height.ToString ());
 		Application.End (rs);
 	}
 
-	[Fact]
-	[AutoInitShutdown]
-	public void AutoSize_False_TextDirection_Toggle ()
-	{
-		var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
-		// View is AutoSize == true
-		var view = new View ();
-		win.Add (view);
-		Application.Top.Add (win);
-
-		var rs = Application.Begin (Application.Top);
-		((FakeDriver)Application.Driver).SetBufferSize (22, 22);
-
-		Assert.Equal (new Rect (0, 0, 22, 22), win.Frame);
-		Assert.Equal (new Rect (0, 0, 22, 22), win.Margin.Frame);
-		Assert.Equal (new Rect (0, 0, 22, 22), win.Border.Frame);
-		Assert.Equal (new Rect (1, 1, 20, 20), win.Padding.Frame);
-		Assert.False (view.AutoSize);
-		Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection);
-		Assert.Equal (Rect.Empty,                        view.Frame);
-		Assert.Equal ("Absolute(0)",                     view.X.ToString ());
-		Assert.Equal ("Absolute(0)",                     view.Y.ToString ());
-		Assert.Equal ("Absolute(0)",                     view.Width.ToString ());
-		Assert.Equal ("Absolute(0)",                     view.Height.ToString ());
-		var expected = @"
-┌────────────────────┐
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.Text = "Hello World";
-		view.Width = 11;
-		view.Height = 1;
-		win.LayoutSubviews ();
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(11)",         view.Width.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│Hello World         │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.AutoSize = true;
-		view.Text = "Hello Worlds";
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 12, 1), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(11)",         view.Width.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│Hello Worlds        │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.TextDirection = TextDirection.TopBottom_LeftRight;
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 11, 12), view.Frame);
-		Assert.Equal ("Absolute(0)",           view.X.ToString ());
-		Assert.Equal ("Absolute(0)",           view.Y.ToString ());
-		Assert.Equal ("Absolute(11)",          view.Width.ToString ());
-		Assert.Equal ("Absolute(1)",           view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│H                   │
-│e                   │
-│l                   │
-│l                   │
-│o                   │
-│                    │
-│W                   │
-│o                   │
-│r                   │
-│l                   │
-│d                   │
-│s                   │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.AutoSize = false;
-		view.Height = 1;
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(11)",         view.Width.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│HelloWorlds         │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.PreserveTrailingSpaces = true;
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 11, 1), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(11)",         view.Width.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│Hello World         │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.PreserveTrailingSpaces = false;
-		var f = view.Frame;
-		view.Width = f.Height;
-		view.Height = f.Width;
-		view.TextDirection = TextDirection.TopBottom_LeftRight;
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 1, 11), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Width.ToString ());
-		Assert.Equal ("Absolute(11)",         view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│H                   │
-│e                   │
-│l                   │
-│l                   │
-│o                   │
-│                    │
-│W                   │
-│o                   │
-│r                   │
-│l                   │
-│d                   │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-
-		view.AutoSize = true;
-		Application.Refresh ();
-
-		Assert.Equal (new Rect (0, 0, 1, 12), view.Frame);
-		Assert.Equal ("Absolute(0)",          view.X.ToString ());
-		Assert.Equal ("Absolute(0)",          view.Y.ToString ());
-		Assert.Equal ("Absolute(1)",          view.Width.ToString ());
-		Assert.Equal ("Absolute(12)",         view.Height.ToString ());
-		expected = @"
-┌────────────────────┐
-│H                   │
-│e                   │
-│l                   │
-│l                   │
-│o                   │
-│                    │
-│W                   │
-│o                   │
-│r                   │
-│l                   │
-│d                   │
-│s                   │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-│                    │
-└────────────────────┘
-";
-
-		pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
-		Assert.Equal (new Rect (0, 0, 22, 22), pos);
-		Application.End (rs);
-	}
 }

+ 114 - 156
UnitTests/View/ViewTests.cs

@@ -21,7 +21,7 @@ namespace Terminal.Gui.ViewTests {
 			// Parameterless
 			var r = new View ();
 			Assert.NotNull (r);
-			Assert.Equal (LayoutStyle.Computed, r.LayoutStyle);
+			Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
 			Assert.Equal ("View()(0,0,0,0)", r.ToString ());
 			Assert.False (r.CanFocus);
 			Assert.False (r.HasFocus);
@@ -29,10 +29,10 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (new Rect (0, 0, 0, 0), r.Frame);
 			Assert.Null (r.Focused);
 			Assert.Null (r.ColorScheme);
-			Assert.Null (r.Width);
-			Assert.Null (r.Height);
-			Assert.Null (r.X);
-			Assert.Null (r.Y);
+			Assert.Equal (0, r.Width);
+			Assert.Equal (0, r.Height);
+			Assert.Equal (0, r.X);
+			Assert.Equal (0, r.Y);
 			Assert.False (r.IsCurrentTop);
 			Assert.Empty (r.Id);
 			Assert.Empty (r.Subviews);
@@ -42,7 +42,7 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Null (r.MostFocused);
 			Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection);
 			r.Dispose ();
-			
+
 			// Empty Rect
 			r = new View (Rect.Empty);
 			Assert.NotNull (r);
@@ -54,10 +54,10 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (new Rect (0, 0, 0, 0), r.Frame);
 			Assert.Null (r.Focused);
 			Assert.Null (r.ColorScheme);
-			Assert.Null (r.Width);       // All view Dim are initialized now in the IsAdded setter,
-			Assert.Null (r.Height);      // avoiding Dim errors.
-			Assert.Null (r.X);           // All view Pos are initialized now in the IsAdded setter,
-			Assert.Null (r.Y);           // avoiding Pos errors.
+			Assert.Equal (0, r.Width);
+			Assert.Equal (0, r.Height);
+			Assert.Equal (0, r.X);
+			Assert.Equal (0, r.Y);
 			Assert.False (r.IsCurrentTop);
 			Assert.Empty (r.Id);
 			Assert.Empty (r.Subviews);
@@ -79,10 +79,10 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (new Rect (1, 2, 3, 4), r.Frame);
 			Assert.Null (r.Focused);
 			Assert.Null (r.ColorScheme);
-			Assert.Null (r.Width);
-			Assert.Null (r.Height);
-			Assert.Null (r.X);
-			Assert.Null (r.Y);
+			Assert.Equal (3, r.Width);
+			Assert.Equal (4, r.Height);
+			Assert.Equal (1, r.X);
+			Assert.Equal (2, r.Y);
 			Assert.False (r.IsCurrentTop);
 			Assert.Empty (r.Id);
 			Assert.Empty (r.Subviews);
@@ -96,7 +96,7 @@ namespace Terminal.Gui.ViewTests {
 			// Initializes a view with a vertical direction
 			r = new View ("Vertical View", TextDirection.TopBottom_LeftRight);
 			Assert.NotNull (r);
-			Assert.Equal (LayoutStyle.Computed, r.LayoutStyle);
+			Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
 			Assert.Equal ("View(Vertical View)(0,0,1,13)", r.ToString ());
 			Assert.False (r.CanFocus);
 			Assert.False (r.HasFocus);
@@ -104,10 +104,6 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (new Rect (0, 0, 1, 13), r.Frame);
 			Assert.Null (r.Focused);
 			Assert.Null (r.ColorScheme);
-			Assert.Null (r.Width);       // All view Dim are initialized now in the IsAdded setter,
-			Assert.Null (r.Height);      // avoiding Dim errors.
-			Assert.Null (r.X);           // All view Pos are initialized now in the IsAdded setter,
-			Assert.Null (r.Y);           // avoiding Pos errors.
 			Assert.False (r.IsCurrentTop);
 			Assert.Equal ("Vertical View", r.Id);
 			Assert.Empty (r.Subviews);
@@ -183,23 +179,23 @@ namespace Terminal.Gui.ViewTests {
 #if DEBUG_IDISPOSABLE
 			Assert.Empty (Responder.Instances);
 #endif
-			
+
 			// Default Constructor
 			view = new View ();
-			Assert.Null (view.X);
-			Assert.Null (view.Y);
-			Assert.Null (view.Width);
-			Assert.Null (view.Height);
+			Assert.Equal (0, view.X);
+			Assert.Equal (0, view.Y);
+			Assert.Equal (0, view.Width);
+			Assert.Equal (0, view.Height);
 			Assert.True (view.Frame.IsEmpty);
 			Assert.True (view.Bounds.IsEmpty);
 			view.Dispose ();
 
 			// Constructor
 			view = new View (1, 2, "");
-			Assert.Null (view.X);
-			Assert.Null (view.Y);
-			Assert.Null (view.Width);
-			Assert.Null (view.Height);
+			Assert.Equal (1, view.X);
+			Assert.Equal (2, view.Y);
+			Assert.Equal (0, view.Width);
+			Assert.Equal (0, view.Height);
 			Assert.False (view.Frame.IsEmpty);
 			Assert.True (view.Bounds.IsEmpty);
 			view.Dispose ();
@@ -259,33 +255,33 @@ namespace Terminal.Gui.ViewTests {
 		{
 			Application.Init (new FakeDriver ());
 
-			var t = new Toplevel () { Id = "0", };
+			var top = new Toplevel () { Id = "0", }; // Frame: 0, 0, 80, 25; Bounds: 0, 0, 80, 25
 
-			var w = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () };
-			var v1 = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () };
-			var v2 = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () };
-			var sv1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () };
+			var winAddedToTop = new Window () { Id = "t", Width = Dim.Fill (), Height = Dim.Fill () }; // Frame: 0, 0, 80, 25; Bounds: 0, 0, 78, 23
+			var v1AddedToWin = new View () { Id = "v1", Width = Dim.Fill (), Height = Dim.Fill () }; // Frame: 1, 1, 78, 23 (because Windows has a border)
+			var v2AddedToWin = new View () { Id = "v2", Width = Dim.Fill (), Height = Dim.Fill () }; // Frame: 1, 1, 78, 23 (because Windows has a border)
+			var svAddedTov1 = new View () { Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill () }; // Frame: 1, 1, 78, 23 (same as it's superview v1AddedToWin)
 
 			int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0;
 
-			w.Added += (s, e) => {
-				Assert.Equal (e.Parent.Frame.Width, w.Frame.Width);
-				Assert.Equal (e.Parent.Frame.Height, w.Frame.Height);
+			winAddedToTop.Added += (s, e) => {
+				Assert.Equal (e.Parent.Bounds.Width, winAddedToTop.Frame.Width);
+				Assert.Equal (e.Parent.Bounds.Height, winAddedToTop.Frame.Height);
 			};
-			v1.Added += (s, e) => {
-				Assert.Equal (e.Parent.Frame.Width, v1.Frame.Width);
-				Assert.Equal (e.Parent.Frame.Height, v1.Frame.Height);
+			v1AddedToWin.Added += (s, e) => {
+				Assert.Equal (e.Parent.Bounds.Width, v1AddedToWin.Frame.Width);
+				Assert.Equal (e.Parent.Bounds.Height, v1AddedToWin.Frame.Height);
 			};
-			v2.Added += (s, e) => {
-				Assert.Equal (e.Parent.Frame.Width, v2.Frame.Width);
-				Assert.Equal (e.Parent.Frame.Height, v2.Frame.Height);
+			v2AddedToWin.Added += (s, e) => {
+				Assert.Equal (e.Parent.Bounds.Width, v2AddedToWin.Frame.Width);
+				Assert.Equal (e.Parent.Bounds.Height, v2AddedToWin.Frame.Height);
 			};
-			sv1.Added += (s, e) => {
-				Assert.Equal (e.Parent.Frame.Width, sv1.Frame.Width);
-				Assert.Equal (e.Parent.Frame.Height, sv1.Frame.Height);
+			svAddedTov1.Added += (s, e) => {
+				Assert.Equal (e.Parent.Bounds.Width, svAddedTov1.Frame.Width);
+				Assert.Equal (e.Parent.Bounds.Height, svAddedTov1.Frame.Height);
 			};
 
-			t.Initialized += (s, e) => {
+			top.Initialized += (s, e) => {
 				tc++;
 				Assert.Equal (1, tc);
 				Assert.Equal (1, wc);
@@ -293,48 +289,61 @@ namespace Terminal.Gui.ViewTests {
 				Assert.Equal (1, v2c);
 				Assert.Equal (1, sv1c);
 
-				Assert.True (t.CanFocus);
-				Assert.True (w.CanFocus);
-				Assert.False (v1.CanFocus);
-				Assert.False (v2.CanFocus);
-				Assert.False (sv1.CanFocus);
+				Assert.True (top.CanFocus);
+				Assert.True (winAddedToTop.CanFocus);
+				Assert.False (v1AddedToWin.CanFocus);
+				Assert.False (v2AddedToWin.CanFocus);
+				Assert.False (svAddedTov1.CanFocus);
 
 				Application.Refresh ();
 			};
-			w.Initialized += (s, e) => {
+			winAddedToTop.Initialized += (s, e) => {
 				wc++;
-				Assert.Equal (t.Frame.Width, w.Frame.Width);
-				Assert.Equal (t.Frame.Height, w.Frame.Height);
+				Assert.Equal (top.Bounds.Width, winAddedToTop.Frame.Width);
+				Assert.Equal (top.Bounds.Height, winAddedToTop.Frame.Height);
 			};
-			v1.Initialized += (s, e) => {
+			v1AddedToWin.Initialized += (s, e) => {
 				v1c++;
-				Assert.Equal (t.Frame.Width, v1.Frame.Width);
-				Assert.Equal (t.Frame.Height, v1.Frame.Height);
+				// Top.Frame: 0, 0, 80, 25; Top.Bounds: 0, 0, 80, 25
+				// BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
+				// in no way should the v1AddedToWin.Frame be the same as the Top.Frame/Bounds
+				// as it is a subview of winAddedToTop, which has a border!
+				//Assert.Equal (top.Bounds.Width,  v1AddedToWin.Frame.Width);
+				//Assert.Equal (top.Bounds.Height, v1AddedToWin.Frame.Height);
 			};
-			v2.Initialized += (s, e) => {
+			v2AddedToWin.Initialized += (s, e) => {
 				v2c++;
-				Assert.Equal (t.Frame.Width, v2.Frame.Width);
-				Assert.Equal (t.Frame.Height, v2.Frame.Height);
+				// Top.Frame: 0, 0, 80, 25; Top.Bounds: 0, 0, 80, 25
+				// BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
+				// in no way should the v2AddedToWin.Frame be the same as the Top.Frame/Bounds
+				// as it is a subview of winAddedToTop, which has a border!
+				//Assert.Equal (top.Bounds.Width,  v2AddedToWin.Frame.Width);
+				//Assert.Equal (top.Bounds.Height, v2AddedToWin.Frame.Height);
 			};
-			sv1.Initialized += (s, e) => {
+			svAddedTov1.Initialized += (s, e) => {
 				sv1c++;
-				Assert.Equal (t.Frame.Width, sv1.Frame.Width);
-				Assert.Equal (t.Frame.Height, sv1.Frame.Height);
-				Assert.False (sv1.CanFocus);
-				Assert.Throws<InvalidOperationException> (() => sv1.CanFocus = true);
-				Assert.False (sv1.CanFocus);
+				// Top.Frame: 0, 0, 80, 25; Top.Bounds: 0, 0, 80, 25
+				// BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
+				// in no way should the svAddedTov1.Frame be the same as the Top.Frame/Bounds
+				// because sv1AddedTov1 is a subview of v1AddedToWin, which is a subview of
+				// winAddedToTop, which has a border!
+				//Assert.Equal (top.Bounds.Width,  svAddedTov1.Frame.Width);
+				//Assert.Equal (top.Bounds.Height, svAddedTov1.Frame.Height);
+				Assert.False (svAddedTov1.CanFocus);
+				Assert.Throws<InvalidOperationException> (() => svAddedTov1.CanFocus = true);
+				Assert.False (svAddedTov1.CanFocus);
 			};
 
-			v1.Add (sv1);
-			w.Add (v1, v2);
-			t.Add (w);
+			v1AddedToWin.Add (svAddedTov1);
+			winAddedToTop.Add (v1AddedToWin, v2AddedToWin);
+			top.Add (winAddedToTop);
 
 			Application.Iteration += (s, a) => {
 				Application.Refresh ();
-				t.Running = false;
+				top.Running = false;
 			};
 
-			Application.Run (t);
+			Application.Run (top);
 			Application.Shutdown ();
 
 			Assert.Equal (1, tc);
@@ -343,14 +352,14 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (1, v2c);
 			Assert.Equal (1, sv1c);
 
-			Assert.True (t.CanFocus);
-			Assert.True (w.CanFocus);
-			Assert.False (v1.CanFocus);
-			Assert.False (v2.CanFocus);
-			Assert.False (sv1.CanFocus);
+			Assert.True (top.CanFocus);
+			Assert.True (winAddedToTop.CanFocus);
+			Assert.False (v1AddedToWin.CanFocus);
+			Assert.False (v2AddedToWin.CanFocus);
+			Assert.False (svAddedTov1.CanFocus);
 
-			v1.CanFocus = true;
-			Assert.False (sv1.CanFocus); // False because sv1 was disposed and it isn't a subview of v1.
+			v1AddedToWin.CanFocus = true;
+			Assert.False (svAddedTov1.CanFocus); // False because sv1 was disposed and it isn't a subview of v1.
 
 		}
 
@@ -384,18 +393,18 @@ namespace Terminal.Gui.ViewTests {
 			};
 			w.Initialized += (s, e) => {
 				wc++;
-				Assert.Equal (t.Frame.Width, w.Frame.Width);
-				Assert.Equal (t.Frame.Height, w.Frame.Height);
+				Assert.Equal (t.Bounds.Width, w.Frame.Width);
+				Assert.Equal (t.Bounds.Height, w.Frame.Height);
 			};
 			v1.Initialized += (s, e) => {
 				v1c++;
-				Assert.Equal (t.Frame.Width, v1.Frame.Width);
-				Assert.Equal (t.Frame.Height, v1.Frame.Height);
+				//Assert.Equal (t.Bounds.Width, v1.Frame.Width);
+				//Assert.Equal (t.Bounds.Height, v1.Frame.Height);
 			};
 			v2.Initialized += (s, e) => {
 				v2c++;
-				Assert.Equal (t.Frame.Width, v2.Frame.Width);
-				Assert.Equal (t.Frame.Height, v2.Frame.Height);
+				//Assert.Equal (t.Bounds.Width,  v2.Frame.Width);
+				//Assert.Equal (t.Bounds.Height, v2.Frame.Height);
 			};
 			w.Add (v1, v2);
 			t.Add (w);
@@ -505,12 +514,17 @@ namespace Terminal.Gui.ViewTests {
 			var runState = Application.Begin (top);
 
 			// BUGBUG: This is a SetRelativeLayout test. It should be moved to SetRelativeLayoutTests.cs
-			view.Width = Dim.Fill ();
-			view.Height = Dim.Fill ();
-			Assert.Equal (10, view.Bounds.Width);
-			Assert.Equal (1, view.Bounds.Height);
-			view.LayoutStyle = LayoutStyle.Computed;
+			view.Width = Dim.Fill (); // Width should be 79 (Top.Width - 1)
+			Assert.Equal ("Fill(0)", view.Width.ToString ());
+			view.Height = Dim.Fill (); // Height should be 24 (Top.Height - 1)
+
+			// #3127: Before: Frame was not being set when Width and Height were set to Dim.Fill()
+			//	  After: Frame is set to the parent's Frame when Width and Height are set to Dim.Fill()
+			Assert.Equal (79, view.Bounds.Width);
+			Assert.Equal (24, view.Bounds.Height);
+			//view.LayoutStyle = LayoutStyle.Computed;
 			view.SetRelativeLayout (top.Bounds);
+			Assert.Equal ("Fill(0)", view.Width.ToString ());
 			Assert.Equal (1, view.Frame.X);
 			Assert.Equal (1, view.Frame.Y);
 			Assert.Equal (79, view.Frame.Width);
@@ -758,61 +772,6 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Equal (Rect.Empty, pos);
 		}
 
-		[Fact, AutoInitShutdown]
-		public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier ()
-		{
-			var text = "Say Hello 你";
-			var horizontalView = new View () {
-				Text = text,
-				AutoSize = true,
-				HotKeySpecifier = (Rune)'_'
-			};
-
-			var verticalView = new View () {
-				Text = text,
-				AutoSize = true,
-				HotKeySpecifier = (Rune)'_',
-				TextDirection = TextDirection.TopBottom_LeftRight
-			};
-			Application.Top.Add (horizontalView, verticalView);
-			Application.Begin (Application.Top);
-			((FakeDriver)Application.Driver).SetBufferSize (50, 50);
-
-			Assert.True (horizontalView.AutoSize);
-			Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
-			Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
-			//Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextAndHotKey ());
-			//Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ());
-			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
-
-			Assert.True (verticalView.AutoSize);
-			// BUGBUG: v2 - Autosize is broken; disabling this test
-			//Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
-			//Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
-			//Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextAndHotKey ());
-			//Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
-			Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
-
-			text = "Say He_llo 你";
-			horizontalView.Text = text;
-			verticalView.Text = text;
-
-			Assert.True (horizontalView.AutoSize);
-			Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
-			Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
-			//Assert.Equal (new Size (13, 1), horizontalView.GetSizeNeededForTextAndHotKey ());
-			//Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ());
-			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
-
-			Assert.True (verticalView.AutoSize);
-			// BUGBUG: v2 - Autosize is broken; disabling this test
-			//Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
-			//Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
-			//Assert.Equal (new Size (2, 12), verticalView.GetSizeNeededForTextAndHotKey ());
-			//Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
-			//Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
-		}
-
 		[Fact, TestRespondersDisposed]
 		public void IsAdded_Added_Removed ()
 		{
@@ -823,7 +782,7 @@ namespace Terminal.Gui.ViewTests {
 			Assert.True (view.IsAdded);
 			top.Remove (view);
 			Assert.False (view.IsAdded);
-			
+
 			top.Dispose ();
 			view.Dispose ();
 		}
@@ -831,14 +790,16 @@ namespace Terminal.Gui.ViewTests {
 		[Fact, AutoInitShutdown]
 		public void Visible_Clear_The_View_Output ()
 		{
-			var label = new Label ("Testing visibility.");
+			var view = new View ("Testing visibility.");  // use View, not Label to avoid AutoSize == true
+			Assert.Equal ("Testing visibility.".Length, view.Frame.Width);
+			Assert.Equal (1, view.Height);
 			var win = new Window ();
-			win.Add (label);
+			win.Add (view);
 			var top = Application.Top;
 			top.Add (win);
 			var rs = Application.Begin (top);
 
-			Assert.True (label.Visible);
+			Assert.True (view.Visible);
 			((FakeDriver)Application.Driver).SetBufferSize (30, 5);
 			TestHelpers.AssertDriverContentsWithFrameAre (@"
 ┌────────────────────────────┐
@@ -848,7 +809,7 @@ namespace Terminal.Gui.ViewTests {
 └────────────────────────────┘
 ", output);
 
-			label.Visible = false;
+			view.Visible = false;
 
 			bool firstIteration = false;
 			Application.RunIteration (ref rs, ref firstIteration);
@@ -1044,8 +1005,7 @@ At 0,0
 
 			view.Frame = new Rect (1, 1, 10, 1);
 			Assert.Equal (new Rect (1, 1, 10, 1), view.Frame);
-			Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
-			view.LayoutStyle = LayoutStyle.Absolute;
+			Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
 			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
 			Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplayRect);
 			top.Draw ();
@@ -1115,8 +1075,7 @@ At 0,0
 
 			view.Frame = new Rect (1, 1, 10, 1);
 			Assert.Equal (new Rect (1, 1, 10, 1), view.Frame);
-			Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
-			view.LayoutStyle = LayoutStyle.Absolute;
+			Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
 			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
 			Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplayRect);
 			view.Draw ();
@@ -1189,8 +1148,7 @@ At 0,0
 
 			view.Frame = new Rect (3, 3, 10, 1);
 			Assert.Equal (new Rect (3, 3, 10, 1), view.Frame);
-			Assert.Equal (LayoutStyle.Computed, view.LayoutStyle);
-			view.LayoutStyle = LayoutStyle.Absolute;
+			Assert.Equal (LayoutStyle.Absolute, view.LayoutStyle);
 			Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds);
 			Assert.Equal (new Rect (0, 0, 10, 1), view._needsDisplayRect);
 			top.Draw ();
@@ -1351,7 +1309,7 @@ At 0,0
 				ColorScheme = Colors.Menu,
 				Width = Dim.Fill (),
 				X = 0, // don't overcomplicate unit tests
-				Y = 0 
+				Y = 0
 			};
 
 			var button = new Button ("Press me!") {

+ 15 - 15
UnitTests/Views/Toplevel/WindowTests.cs

@@ -15,19 +15,19 @@ public class WindowTests {
 		// Parameterless
 		var r = new Window ();
 		Assert.NotNull (r);
-		Assert.Equal (string.Empty, r.Title);
+		Assert.Equal (string.Empty,         r.Title);
 		Assert.Equal (LayoutStyle.Computed, r.LayoutStyle);
-		Assert.Equal ("Window()(0,0,0,0)", r.ToString ());
+		Assert.Equal ("Window()(0,0,0,0)",  r.ToString ());
 		Assert.True (r.CanFocus);
 		Assert.False (r.HasFocus);
 		Assert.Equal (new Rect (0, 0, 0, 0), r.Bounds);
 		Assert.Equal (new Rect (0, 0, 0, 0), r.Frame);
 		Assert.Null (r.Focused);
 		Assert.NotNull (r.ColorScheme);
+		Assert.Equal (0,           r.X);
+		Assert.Equal (0,           r.Y);
 		Assert.Equal (Dim.Fill (), r.Width);
 		Assert.Equal (Dim.Fill (), r.Height);
-		Assert.Null (r.X);
-		Assert.Null (r.Y);
 		Assert.False (r.IsCurrentTop);
 		Assert.Empty (r.Id);
 		Assert.False (r.WantContinuousButtonPressed);
@@ -39,8 +39,8 @@ public class WindowTests {
 		// Empty Rect
 		r = new Window (Rect.Empty) { Title = "title" };
 		Assert.NotNull (r);
-		Assert.Equal ("title", r.Title);
-		Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
+		Assert.Equal ("title",                  r.Title);
+		Assert.Equal (LayoutStyle.Absolute,     r.LayoutStyle);
 		Assert.Equal ("Window(title)(0,0,0,0)", r.ToString ());
 		Assert.True (r.CanFocus);
 		Assert.False (r.HasFocus);
@@ -48,10 +48,10 @@ public class WindowTests {
 		Assert.Equal (new Rect (0, 0, 0, 0), r.Frame);
 		Assert.Null (r.Focused);
 		Assert.NotNull (r.ColorScheme);
-		Assert.Null (r.Width);  // All view Dim are initialized now in the IsAdded setter,
-		Assert.Null (r.Height); // avoiding Dim errors.
-		Assert.Null (r.X);      // All view Pos are initialized now in the IsAdded setter,
-		Assert.Null (r.Y);      // avoiding Pos errors.
+		Assert.Equal (0, r.X);
+		Assert.Equal (0, r.Y);
+		Assert.Equal (0, r.Width);
+		Assert.Equal (0, r.Height);
 		Assert.False (r.IsCurrentTop);
 		Assert.Equal (r.Title, r.Id);
 		Assert.False (r.WantContinuousButtonPressed);
@@ -64,7 +64,7 @@ public class WindowTests {
 		r = new Window (new Rect (1, 2, 3, 4)) { Title = "title" };
 		Assert.Equal ("title", r.Title);
 		Assert.NotNull (r);
-		Assert.Equal (LayoutStyle.Absolute, r.LayoutStyle);
+		Assert.Equal (LayoutStyle.Absolute,     r.LayoutStyle);
 		Assert.Equal ("Window(title)(1,2,3,4)", r.ToString ());
 		Assert.True (r.CanFocus);
 		Assert.False (r.HasFocus);
@@ -72,10 +72,10 @@ public class WindowTests {
 		Assert.Equal (new Rect (1, 2, 3, 4), r.Frame);
 		Assert.Null (r.Focused);
 		Assert.NotNull (r.ColorScheme);
-		Assert.Null (r.Width);
-		Assert.Null (r.Height);
-		Assert.Null (r.X);
-		Assert.Null (r.Y);
+		Assert.Equal (1, r.X);
+		Assert.Equal (2, r.Y);
+		Assert.Equal (3, r.Width);
+		Assert.Equal (4, r.Height);
 		Assert.False (r.IsCurrentTop);
 		Assert.Equal (r.Title, r.Id);
 		Assert.False (r.WantContinuousButtonPressed);