瀏覽代碼

Merge branch 'v1_setrelativelayout_improvement' into v2

Tig Kindel 2 年之前
父節點
當前提交
5c659110bf

+ 40 - 40
Terminal.Gui/Core/Border.cs

@@ -651,9 +651,9 @@ namespace Terminal.Gui {
 
 			// Draw the upper BorderThickness
 			for (int r = frame.Y - drawMarginFrame - sumThickness.Top;
-				r < frame.Y - drawMarginFrame - padding.Top; r++) {
+				r > 0 && r < frame.Y - drawMarginFrame - padding.Top; r++) {
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -661,9 +661,9 @@ namespace Terminal.Gui {
 
 			// Draw the left BorderThickness
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c < frame.X - drawMarginFrame - padding.Left; c++) {
+					c > 0 && c < frame.X - drawMarginFrame - padding.Left; c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -671,9 +671,9 @@ namespace Terminal.Gui {
 
 			// Draw the right BorderThickness
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
 				for (int c = frame.Right + drawMarginFrame + padding.Right;
-					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -681,9 +681,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower BorderThickness
 			for (int r = frame.Bottom + drawMarginFrame + padding.Bottom;
-				r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c > 0 && c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -693,9 +693,9 @@ namespace Terminal.Gui {
 
 			// Draw the upper Padding
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r < frame.Y - drawMarginFrame; r++) {
+				r > 0 && r < frame.Y - drawMarginFrame; r++) {
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -703,9 +703,9 @@ namespace Terminal.Gui {
 
 			// Draw the left Padding
 			for (int r = frame.Y - drawMarginFrame;
-				r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c < frame.X - drawMarginFrame; c++) {
+					c > 0 && c < frame.X - drawMarginFrame; c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -713,9 +713,9 @@ namespace Terminal.Gui {
 
 			// Draw the right Padding
 			for (int r = frame.Y - drawMarginFrame;
-				r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
 				for (int c = frame.Right + drawMarginFrame;
-					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -723,9 +723,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower Padding
 			for (int r = frame.Bottom + drawMarginFrame;
-				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -825,9 +825,9 @@ namespace Terminal.Gui {
 
 			// Draw the upper BorderThickness
 			for (int r = frame.Y;
-				r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
+				r > 0 && r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
 				for (int c = frame.X;
-					c < Math.Min (frame.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -835,9 +835,9 @@ namespace Terminal.Gui {
 
 			// Draw the left BorderThickness
 			for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
-				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X;
-					c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
+					c > 0 && c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -845,9 +845,9 @@ namespace Terminal.Gui {
 
 			// Draw the right BorderThickness
 			for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
-				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
 				for (int c = Math.Max (frame.Right - borderThickness.Right, frame.X);
-					c < Math.Min (frame.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -855,9 +855,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower BorderThickness
 			for (int r = Math.Max (frame.Bottom - borderThickness.Bottom, frame.Y);
-				r < Math.Min (frame.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom, driver.Rows); r++) {
 				for (int c = frame.X;
-					c < Math.Min (frame.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -867,9 +867,9 @@ namespace Terminal.Gui {
 
 			// Draw the upper Padding
 			for (int r = frame.Y + borderThickness.Top;
-				r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
+				r > 0 && r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
 				for (int c = frame.X + borderThickness.Left;
-					c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -877,9 +877,9 @@ namespace Terminal.Gui {
 
 			// Draw the left Padding
 			for (int r = frame.Y + sumThickness.Top;
-				r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X + borderThickness.Left;
-					c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
+					c > 0 && c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -887,9 +887,9 @@ namespace Terminal.Gui {
 
 			// Draw the right Padding
 			for (int r = frame.Y + sumThickness.Top;
-				r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
 				for (int c = Math.Max (frame.Right - sumThickness.Right, frame.X + sumThickness.Left);
-					c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
+					c > 0 && c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -897,9 +897,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower Padding
 			for (int r = Math.Max (frame.Bottom - sumThickness.Bottom, frame.Y + borderThickness.Top);
-				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X + borderThickness.Left;
-					c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
+					c > 0 && c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -926,9 +926,9 @@ namespace Terminal.Gui {
 
 				// Draw the upper Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r < frame.Y; r++) {
+					r > 0 && r < frame.Y; r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -936,9 +936,9 @@ namespace Terminal.Gui {
 
 				// Draw the left Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c < frame.X; c++) {
+						c > 0 && c < frame.X; c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -946,9 +946,9 @@ namespace Terminal.Gui {
 
 				// Draw the right Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = frame.Right;
-						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -956,9 +956,9 @@ namespace Terminal.Gui {
 
 				// Draw the lower Effect3D
 				for (int r = frame.Bottom;
-					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}

+ 14 - 14
Terminal.Gui/Core/PosDim.cs

@@ -52,7 +52,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Pos.PosFunc({function ()})";
+				return $"PosFunc({function ()})";
 			}
 
 			public override int GetHashCode () => function.GetHashCode ();
@@ -85,7 +85,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Pos.Factor({factor})";
+				return $"Factor({factor})";
 			}
 
 			public override int GetHashCode () => factor.GetHashCode ();
@@ -135,7 +135,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Pos.AnchorEnd(margin={n})";
+				return $"AnchorEnd({n})";
 			}
 		}
 
@@ -174,7 +174,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return "Pos.Center";
+				return "Center";
 			}
 		}
 
@@ -209,7 +209,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Pos.Absolute({n})";
+				return $"Absolute({n})";
 			}
 
 			internal override int Anchor (int width)
@@ -244,7 +244,7 @@ namespace Terminal.Gui {
 
 		internal class PosCombine : Pos {
 			internal Pos left, right;
-			bool add;
+			internal bool add;
 			public PosCombine (bool add, Pos left, Pos right)
 			{
 				this.left = left;
@@ -264,7 +264,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Pos.Combine({left.ToString ()}{(add ? '+' : '-')}{right.ToString ()})";
+				return $"Combine({left}{(add ? '+' : '-')}{right})";
 			}
 
 		}
@@ -345,7 +345,7 @@ namespace Terminal.Gui {
 				case 3: tside = "bottom"; break;
 				default: tside = "unknown"; break;
 				}
-				return $"Pos.View(side={tside}, target={Target.ToString ()})";
+				return $"View({tside},{Target.ToString()})";
 			}
 
 			public override int GetHashCode () => Target.GetHashCode ();
@@ -442,7 +442,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Dim.DimFunc({function ()})";
+				return $"DimFunc({function ()})";
 			}
 
 			public override int GetHashCode () => function.GetHashCode ();
@@ -482,7 +482,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Dim.Factor(factor={factor}, remaining={remaining})";
+				return $"Factor({factor},{remaining})";
 			}
 
 			public override int GetHashCode () => factor.GetHashCode ();
@@ -522,7 +522,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Dim.Absolute({n})";
+				return $"Absolute({n})";
 			}
 
 			internal override int Anchor (int width)
@@ -541,7 +541,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Dim.Fill(margin={margin})";
+				return $"Fill({margin})";
 			}
 
 			internal override int Anchor (int width)
@@ -613,7 +613,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Dim.Combine({left.ToString ()}{(add ? '+' : '-')}{right.ToString ()})";
+				return $"Combine({left}{(add ? '+' : '-')}{right})";
 			}
 
 		}
@@ -691,7 +691,7 @@ namespace Terminal.Gui {
 				case 1: tside = "Width"; break;
 				default: tside = "unknown"; break;
 				}
-				return $"DimView(side={tside}, target={Target.ToString ()})";
+				return $"DimView({tside},{Target.ToString ()})";
 			}
 
 			public override int GetHashCode () => Target.GetHashCode ();

+ 221 - 205
Terminal.Gui/Core/View.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics;
 using System.Linq;
 using System.Reflection;
 using NStack;
@@ -1109,8 +1110,15 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public void Clear ()
 		{
-			var h = Frame.Height;
-			var w = Frame.Width;
+			Rect containerBounds = GetContainerBounds ();
+			Rect viewBounds = Bounds;
+			if (!containerBounds.IsEmpty) {
+				viewBounds.Width = Math.Min (viewBounds.Width, containerBounds.Width);
+				viewBounds.Height = Math.Min (viewBounds.Height, containerBounds.Height);
+			}
+
+			var h = viewBounds.Height;
+			var w = viewBounds.Width;
 			for (var line = 0; line < h; line++) {
 				Move (0, line);
 				for (var col = 0; col < w; col++)
@@ -1517,6 +1525,7 @@ namespace Terminal.Gui {
 			if (!IgnoreBorderPropertyOnRedraw && Border != null) {
 				Border.DrawContent (this);
 				boundsAdjustedForBorder = new Rect (bounds.X + 1, bounds.Y + 1, Math.Max (0, bounds.Width - 2), Math.Max(0, bounds.Height - 2));
+				boundsAdjustedForBorder = Bounds;// new Rect (bounds.X + 1, bounds.Y + 1, Math.Max (bounds.Width, bounds.Width - 2), Math.Max (bounds.Height, bounds.Height - 2));
 			} else if (ustring.IsNullOrEmpty (TextFormatter.Text) &&
 				(GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") &&
 				(!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) {
@@ -1545,8 +1554,9 @@ namespace Terminal.Gui {
 				foreach (var view in subviews) {
 					if (!view.NeedDisplay.IsEmpty || view.ChildNeedsDisplay || view.LayoutNeeded) {
 						if (view.Frame.IntersectsWith (clipRect) && (view.Frame.IntersectsWith (boundsAdjustedForBorder) || boundsAdjustedForBorder.X < 0 || bounds.Y < 0)) {
-							if (view.LayoutNeeded)
+							if (view.LayoutNeeded) {
 								view.LayoutSubviews ();
+							}
 
 							// Draw the subview
 							// Use the view's bounds (view-relative; Location will always be (0,0)
@@ -2176,162 +2186,119 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Sets the View's <see cref="Frame"/> to the relative coordinates if its container, given the <see cref="Frame"/> for its container.
+		/// Sets the View's <see cref="Frame"/> to the frame-relative coordinates if its container. The
+		/// container size and location are specified by <paramref name="superviewFrame"/> and are relative to the
+		/// View's superview.
 		/// </summary>
-		/// <param name="hostFrame">The screen-relative frame for the host.</param>
-		/// <remarks>
-		/// Reminder: <see cref="Frame"/> is superview-relative; <see cref="Bounds"/> is view-relative.
-		/// </remarks>
-		internal void SetRelativeLayout (Rect hostFrame)
+		/// <param name="superviewFrame">The supserview-relative rectangle describing View's container (nominally the 
+		/// same as <c>this.SuperView.Frame</c>).</param>
+		internal void SetRelativeLayout (Rect superviewFrame)
 		{
-			int actW, actH, actX, actY;
-			var s = Size.Empty;
+			int newX, newW, newY, newH;
+			var autosize = Size.Empty;
 
 			if (AutoSize) {
-				s = GetAutoSize ();
-			}
-
-			if (x is Pos.PosCenter) {
-				if (width == null) {
-					actW = AutoSize ? s.Width : hostFrame.Width;
-				} else {
-					actW = width.Anchor (hostFrame.Width);
-					actW = AutoSize && s.Width > actW ? s.Width : actW;
-				}
-				actX = x.Anchor (hostFrame.Width - actW);
-			} else {
-				actX = x?.Anchor (hostFrame.Width) ?? 0;
-
-				actW = Math.Max (CalculateActualWidth (width, hostFrame, actX, s), 0);
+				// 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 ();
 			}
 
-			if (y is Pos.PosCenter) {
-				if (height == null) {
-					actH = AutoSize ? s.Height : hostFrame.Height;
-				} else {
-					actH = height.Anchor (hostFrame.Height);
-					actH = AutoSize && s.Height > actH ? s.Height : actH;
-				}
-				actY = y.Anchor (hostFrame.Height - actH);
-			} else {
-				actY = y?.Anchor (hostFrame.Height) ?? 0;
+			// Returns the new dimension (width or height) and location (x or y) for the View given
+			//   the superview's Frame.X or Frame.Y
+			//   the superview's width or height
+			//   the current Pos (View.X or View.Y)
+			//   the current Dim (View.Width or View.Height)
+			(int newLocation, int newDimension) GetNewLocationAndDimension (int superviewLocation, int superviewDimension, Pos pos, Dim dim, int autosizeDimension)
+			{
+				int newDimension, newLocation;
 
-				actH = Math.Max (CalculateActualHight (height, hostFrame, actY, s), 0);
-			}
+				switch (pos) {
+				case Pos.PosCenter:
+					if (dim == null) {
+						newDimension = AutoSize ? autosizeDimension : superviewDimension;
+					} else {
+						newDimension = dim.Anchor (superviewDimension);
+						newDimension = AutoSize && autosizeDimension > newDimension ? autosizeDimension : newDimension;
+					}
+					newLocation = pos.Anchor (superviewDimension - newDimension);
+					break;
 
-			var r = new Rect (actX, actY, actW, actH);
-			if (Frame != r) {
-				Frame = r;
-				if (!SetMinWidthHeight ())
-					TextFormatter.Size = GetBoundsTextFormatterSize ();
-			}
-		}
+				case Pos.PosCombine:
+					var combine = pos as Pos.PosCombine;
+					int left, right;
+					(left, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.left, dim, autosizeDimension);
+					(right, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.right, dim, autosizeDimension);
+					if (combine.add) {
+						newLocation = left + right;
+					} else {
+						newLocation = left - right;
+					}
+					newDimension = Math.Max (CalculateNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0);
+					break;
 
-		private int CalculateActualWidth (Dim width, Rect hostFrame, int actX, Size s)
-		{
-			int actW;
-			switch (width) {
-			case null:
-				actW = AutoSize ? s.Width : hostFrame.Width;
-				break;
-			case Dim.DimCombine combine:
-				int leftActW = CalculateActualWidth (combine.left, hostFrame, actX, s);
-				int rightActW = CalculateActualWidth (combine.right, hostFrame, actX, s);
-				if (combine.add) {
-					actW = leftActW + rightActW;
-				} else {
-					actW = leftActW - rightActW;
+				case Pos.PosAbsolute:
+				case Pos.PosAnchorEnd:
+				case Pos.PosFactor:
+				case Pos.PosFunc:
+				case Pos.PosView:
+				default:
+					newLocation = pos?.Anchor (superviewDimension) ?? 0;
+					newDimension = Math.Max (CalculateNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0);
+					break;
 				}
-				actW = AutoSize && s.Width > actW ? s.Width : actW;
-				break;
-			case Dim.DimFactor factor when !factor.IsFromRemaining ():
-				actW = width.Anchor (hostFrame.Width);
-				actW = AutoSize && s.Width > actW ? s.Width : actW;
-				break;
-			default:
-				actW = Math.Max (width.Anchor (hostFrame.Width - actX), 0);
-				actW = AutoSize && s.Width > actW ? s.Width : actW;
-				break;
+				return (newLocation, newDimension);
 			}
 
-			return actW;
-		}
-
-		private int CalculateActualHight (Dim height, Rect hostFrame, int actY, Size s)
-		{
-			int actH;
-			switch (height) {
-			case null:
-				actH = AutoSize ? s.Height : hostFrame.Height;
-				break;
-			case Dim.DimCombine combine:
-				int leftActH = CalculateActualHight (combine.left, hostFrame, actY, s);
-				int rightActH = CalculateActualHight (combine.right, hostFrame, actY, s);
-				if (combine.add) {
-					actH = leftActH + rightActH;
-				} else {
-					actH = leftActH - rightActH;
+			// Recursively calculates the new dimension (width or height) of the given Dim given:
+			//   the current location (x or y)
+			//   the current dimennsion (width or height)
+			int CalculateNewDimension (Dim d, int location, int dimension, int autosize)
+			{
+				int newDimension;
+				switch (d) {
+				case null:
+					newDimension = AutoSize ? autosize : dimension;
+					break;
+				case Dim.DimCombine combine:
+					int leftNewDim = CalculateNewDimension (combine.left, location, dimension, autosize);
+					int rightNewDim = CalculateNewDimension (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:
+				default:
+					newDimension = Math.Max (d.Anchor (dimension - location), 0);
+					newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
+					break;
 				}
-				actH = AutoSize && s.Height > actH ? s.Height : actH;
-				break;
-			case Dim.DimFactor factor when !factor.IsFromRemaining ():
-				actH = height.Anchor (hostFrame.Height);
-				actH = AutoSize && s.Height > actH ? s.Height : actH;
-				break;
-			default:
-				actH = Math.Max (height.Anchor (hostFrame.Height - actY), 0);
-				actH = AutoSize && s.Height > actH ? s.Height : actH;
-				break;
-			}
-
-			return actH;
-		}
-
-		// https://en.wikipedia.org/wiki/Topological_sorting
-		List<View> TopologicalSort (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 != this?.SuperView)
-					result.Add (n);
+				return newDimension;
+			}
 
-				// 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);
+			// horiztonal
+			(newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, Width, autosize.Width);
 
-					// if m has no other incoming edges then
-					if (edges.All (me => !me.To.Equals (m)) && m != this?.SuperView) {
-						// insert m into S
-						noEdgeNodes.Add (m);
-					}
-				}
-			}
+			// vertical
+			(newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, Height, autosize.Height);
 
-			if (edges.Any ()) {
-				(var from, var to) = edges.First ();
-				if (from != Application.Top) {
-					if (!ReferenceEquals (from, to)) {
-						throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {this}?");
-					} else {
-						throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + this);
-					}
+			var r = new Rect (newX, newY, newW, newH);
+			if (Frame != r) {
+				Frame = r;
+				if (!SetMinWidthHeight ()) {
+					TextFormatter.Size = GetBoundsTextFormatterSize ();
 				}
 			}
-
-			// return L (a topologically sorted order)
-			return result;
 		}
 
 		/// <summary>
@@ -2383,6 +2350,107 @@ namespace Terminal.Gui {
 			LayoutComplete?.Invoke (args);
 		}
 
+		internal void CollectPos (Pos pos, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
+		{
+			switch (pos) {
+			case Pos.PosView pv:
+				if (pv.Target != this) {
+					nEdges.Add ((pv.Target, from));
+				}
+				foreach (var v in from.InternalSubviews) {
+					CollectAll (v, ref nNodes, ref nEdges);
+				}
+				return;
+			case Pos.PosCombine pc:
+				foreach (var v in from.InternalSubviews) {
+					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:
+				if (dv.Target != this) {
+					nEdges.Add ((dv.Target, from));
+				}
+				foreach (var v in from.InternalSubviews) {
+					CollectAll (v, ref nNodes, ref nEdges);
+				}
+				return;
+			case Dim.DimCombine dc:
+				foreach (var v in from.InternalSubviews) {
+					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)
+		{
+			foreach (var v in from.InternalSubviews) {
+				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 ()) {
+				(var from, var to) = edges.First ();
+				if (from != Application.Top) {
+					if (!ReferenceEquals (from, to)) {
+						throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {superView}?");
+					} else {
+						throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + superView);
+					}
+				}
+			}
+			// return L (a topologically sorted order)
+			return result;
+		} // TopologicalSort
+		
+		
 		/// <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.
@@ -2401,69 +2469,11 @@ namespace Terminal.Gui {
 
 			TextFormatter.Size = GetBoundsTextFormatterSize ();
 
-
 			// Sort out the dependencies of the X, Y, Width, Height properties
 			var nodes = new HashSet<View> ();
 			var edges = new HashSet<(View, View)> ();
-
-			void CollectPos (Pos pos, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-			{
-				switch (pos) {
-				case Pos.PosView pv:
-					if (pv.Target != this) {
-						nEdges.Add ((pv.Target, from));
-					}
-					foreach (var v in from.InternalSubviews) {
-						CollectAll (v, ref nNodes, ref nEdges);
-					}
-					return;
-				case Pos.PosCombine pc:
-					foreach (var v in from.InternalSubviews) {
-						CollectPos (pc.left, from, ref nNodes, ref nEdges);
-						CollectPos (pc.right, from, ref nNodes, ref nEdges);
-					}
-					break;
-				}
-			}
-
-			void CollectDim (Dim dim, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-			{
-				switch (dim) {
-				case Dim.DimView dv:
-					if (dv.Target != this) {
-						nEdges.Add ((dv.Target, from));
-					}
-					foreach (var v in from.InternalSubviews) {
-						CollectAll (v, ref nNodes, ref nEdges);
-					}
-					return;
-				case Dim.DimCombine dc:
-					foreach (var v in from.InternalSubviews) {
-						CollectDim (dc.left, from, ref nNodes, ref nEdges);
-						CollectDim (dc.right, from, ref nNodes, ref nEdges);
-					}
-					break;
-				}
-			}
-
-			void CollectAll (View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
-			{
-				foreach (var v in from.InternalSubviews) {
-					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);
-				}
-			}
-
 			CollectAll (this, ref nodes, ref edges);
-
-			var ordered = TopologicalSort (nodes, edges);
-
+			var ordered = View.TopologicalSort (SuperView, nodes, edges);
 			foreach (var v in ordered) {
 				if (v.LayoutStyle == LayoutStyle.Computed) {
 					v.SetRelativeLayout (Frame);
@@ -2473,9 +2483,12 @@ namespace Terminal.Gui {
 				v.LayoutNeeded = false;
 			}
 
+			// If our SuperView is Application.Top and the layoutstyle is Computed it's a special-cass.
+			// Use SetRelativeaLayout with the Frame of the Application.Top
 			if (SuperView != null && SuperView == Application.Top && LayoutNeeded
 			    && ordered.Count == 0 && LayoutStyle == LayoutStyle.Computed) {
-				SetRelativeLayout (SuperView.Frame);
+				Debug.Assert (Application.Top.Frame.Location == Point.Empty);
+				SetRelativeLayout (Application.Top.Frame);
 			}
 
 			LayoutNeeded = false;
@@ -2758,9 +2771,11 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Gets the size to fit all text if <see cref="AutoSize"/> is true.
+		/// Gets the dimensions required to fit <see cref="Text"/> 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"/></returns>
+		/// <returns>The <see cref="Size"/> required to fit the text.</returns>
 		public Size GetAutoSize ()
 		{
 			var rect = TextFormatter.CalcRect (Bounds.X, Bounds.Y, TextFormatter.Text, TextFormatter.Direction);
@@ -2795,10 +2810,11 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Get the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> length.
+		/// Gets the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> characters in the <see cref="Text"/> property.
 		/// </summary>
-		/// <param name="isWidth"><see langword="true"/> if is the width (default) <see langword="false"/> if is the height.</param>
-		/// <returns>The length of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.</returns>
+		/// <param name="isWidth">If <see langword="true"/> (the default) the width required for the hotkey specifier is returned. Otherwise the height is returned.</param>
+		/// <returns>The number of characters required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>. If the text direction specified
+		/// by <see cref="TextDirection"/> does not match the <paramref name="isWidth"/> parameter, <c>0</c> is returned.</returns>
 		public int GetHotKeySpecifierLength (bool isWidth = true)
 		{
 			if (isWidth) {
@@ -2813,7 +2829,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Gets the bounds size from a <see cref="Terminal.Gui.TextFormatter.Size"/>.
+		/// Gets the <see cref="TextFormatter.Size"/> minus the size required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.
 		/// </summary>
 		/// <returns>The bounds size minus the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> length.</returns>
 		public Size GetTextFormatterBoundsSize ()

+ 1 - 0
Terminal.Gui/Terminal.Gui.csproj

@@ -63,6 +63,7 @@
   </ItemGroup>
   <PropertyGroup>
     <TargetFrameworks>net472;netstandard2.0;net6.0</TargetFrameworks>
+    <LangVersion>9</LangVersion>
     <RootNamespace>Terminal.Gui</RootNamespace>
     <AssemblyName>Terminal.Gui</AssemblyName>
     <LangVersion>8</LangVersion>

+ 2 - 2
UICatalog/Scenario.cs

@@ -205,8 +205,8 @@ namespace UICatalog {
 		}
 
 		/// <summary>
-		/// Runs the <see cref="Scenario"/>. Override to start the <see cref="Scenario"/> using a <see cref="Toplevel"/> different than `Top`.
-		/// 
+		/// Runs the <see cref="Scenario"/>. Override to start the <see cref="Scenario"/> 
+		/// using a <see cref="Toplevel"/> different than `Top`.
 		/// </summary>
 		/// <remarks>
 		/// Overrides that do not call the base.<see cref="Run"/>, must call <see cref="Application.Shutdown"/> before returning.

+ 0 - 313
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -1,313 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using Terminal.Gui;
-
-namespace UICatalog.Scenarios {
-	[ScenarioMetadata (Name: "ASCIICustomButtonTest", Description: "ASCIICustomButton sample")]
-	[ScenarioCategory ("Controls")]
-	public class ASCIICustomButtonTest : Scenario {
-		private static bool smallerWindow;
-		private ScrollViewTestWindow scrollViewTestWindow;
-		private MenuItem miSmallerWindow;
-
-		public override void Init (ColorScheme colorScheme)
-		{
-			Application.Init ();
-			scrollViewTestWindow = new ScrollViewTestWindow ();
-			var menu = new MenuBar (new MenuBarItem [] {
-				new MenuBarItem("Window Size", new MenuItem [] {
-					miSmallerWindow = new MenuItem ("Smaller Window", "", ChangeWindowSize) {
-						CheckType = MenuItemCheckStyle.Checked
-					},
-					null,
-					new MenuItem("Quit", "",() => Application.RequestStop(),null,null, Key.Q | Key.CtrlMask)
-				})
-			});
-			Application.Top.Add (menu, scrollViewTestWindow);
-			Application.Run ();
-		}
-
-		private void ChangeWindowSize ()
-		{
-			smallerWindow = (bool)(miSmallerWindow.Checked = !miSmallerWindow.Checked);
-			scrollViewTestWindow.Dispose ();
-			Application.Top.Remove (scrollViewTestWindow);
-			scrollViewTestWindow = new ScrollViewTestWindow ();
-			Application.Top.Add (scrollViewTestWindow);
-		}
-
-		public override void Run ()
-		{
-		}
-
-		public class ASCIICustomButton : Button {
-			public string Description => $"Description of: {id}";
-
-			public event Action<ASCIICustomButton> PointerEnter;
-
-			private Label fill;
-			private FrameView border;
-			private string id;
-
-			public ASCIICustomButton (string text, Pos x, Pos y, int width, int height) : base (text)
-			{
-				CustomInitialize ("", text, x, y, width, height);
-			}
-
-			public ASCIICustomButton (string id, string text, Pos x, Pos y, int width, int height) : base (text)
-			{
-				CustomInitialize (id, text, x, y, width, height);
-			}
-
-			private void CustomInitialize (string id, string text, Pos x, Pos y, int width, int height)
-			{
-				this.id = id;
-				X = x;
-				Y = y;
-
-				Frame = new Rect {
-					Width = width,
-					Height = height
-				};
-
-				border = new FrameView () {
-					Width = width,
-					Height = height
-				};
-
-				AutoSize = false;
-
-				var fillText = new System.Text.StringBuilder ();
-				for (int i = 0; i < Bounds.Height; i++) {
-					if (i > 0) {
-						fillText.AppendLine ("");
-					}
-					for (int j = 0; j < Bounds.Width; j++) {
-						fillText.Append ("█");
-					}
-				}
-
-				fill = new Label (fillText.ToString ()) {
-					Visible = false,
-					CanFocus = false
-				};
-
-				var title = new Label (text) {
-					X = Pos.Center (),
-					Y = Pos.Center (),
-				};
-
-				border.MouseClick += This_MouseClick;
-				border.Subviews [0].MouseClick += This_MouseClick;
-				fill.MouseClick += This_MouseClick;
-				title.MouseClick += This_MouseClick;
-
-				Add (border, fill, title);
-			}
-
-			private void This_MouseClick (MouseEventArgs obj)
-			{
-				OnMouseEvent (obj.MouseEvent);
-			}
-
-			public override bool OnMouseEvent (MouseEvent mouseEvent)
-			{
-				Debug.WriteLine ($"{mouseEvent.Flags}");
-				if (mouseEvent.Flags == MouseFlags.Button1Clicked) {
-					if (!HasFocus && SuperView != null) {
-						if (!SuperView.HasFocus) {
-							SuperView.SetFocus ();
-						}
-						SetFocus ();
-						SetNeedsDisplay ();
-					}
-
-					OnClicked ();
-					return true;
-				}
-				return base.OnMouseEvent (mouseEvent);
-			}
-
-			public override bool OnEnter (View view)
-			{
-				border.Visible = false;
-				fill.Visible = true;
-				PointerEnter.Invoke (this);
-				view = this;
-				return base.OnEnter (view);
-			}
-
-			public override bool OnLeave (View view)
-			{
-				border.Visible = true;
-				fill.Visible = false;
-				if (view == null)
-					view = this;
-				return base.OnLeave (view);
-			}
-		}
-
-		public class ScrollViewTestWindow : Window {
-			private List<Button> buttons;
-			private const int BUTTONS_ON_PAGE = 7;
-			private const int BUTTON_HEIGHT = 3;
-
-			private ScrollView scrollView;
-			private ASCIICustomButton selected;
-
-			public ScrollViewTestWindow ()
-			{
-				Title = "ScrollViewTestWindow";
-
-				Label titleLabel = null;
-				if (smallerWindow) {
-					Width = 80;
-					Height = 25;
-
-					scrollView = new ScrollView () {
-						X = 3,
-						Y = 1,
-						Width = 24,
-						Height = BUTTONS_ON_PAGE * BUTTON_HEIGHT,
-						ShowVerticalScrollIndicator = true,
-						ShowHorizontalScrollIndicator = false
-					};
-				} else {
-					Width = Dim.Fill ();
-					Height = Dim.Fill ();
-
-					titleLabel = new Label ("DOCUMENTS") {
-						X = 0,
-						Y = 0
-					};
-
-					scrollView = new ScrollView () {
-						X = 0,
-						Y = 1,
-						Width = 27,
-						Height = BUTTONS_ON_PAGE * BUTTON_HEIGHT,
-						ShowVerticalScrollIndicator = true,
-						ShowHorizontalScrollIndicator = false
-					};
-				}
-
-				scrollView.ClearKeybindings ();
-
-				buttons = new List<Button> ();
-				Button prevButton = null;
-				int count = 20;
-				for (int j = 0; j < count; j++) {
-					Pos yPos = prevButton == null ? 0 : Pos.Bottom (prevButton);
-					var button = new ASCIICustomButton (j.ToString (), $"section {j}", 0, yPos, 25, BUTTON_HEIGHT);
-					button.Id = $"button{j}";
-					button.Clicked += Button_Clicked;
-					button.PointerEnter += Button_PointerEnter;
-					button.MouseClick += Button_MouseClick;
-					button.KeyPress += Button_KeyPress;
-					scrollView.Add (button);
-					buttons.Add (button);
-					prevButton = button;
-				}
-
-				var closeButton = new ASCIICustomButton ("close", "Close", 0, Pos.Bottom (prevButton), 25, BUTTON_HEIGHT);
-				closeButton.Clicked += Button_Clicked;
-				closeButton.PointerEnter += Button_PointerEnter;
-				closeButton.MouseClick += Button_MouseClick;
-				closeButton.KeyPress += Button_KeyPress;
-				scrollView.Add (closeButton);
-				buttons.Add (closeButton);
-
-				var pages = buttons.Count / BUTTONS_ON_PAGE;
-				if (buttons.Count % BUTTONS_ON_PAGE > 0)
-					pages++;
-
-				scrollView.ContentSize = new Size (25, pages * BUTTONS_ON_PAGE * BUTTON_HEIGHT);
-				if (smallerWindow) {
-					Add (scrollView);
-				} else {
-					Add (titleLabel, scrollView);
-				}
-			}
-
-			private void Button_KeyPress (KeyEventEventArgs obj)
-			{
-				switch (obj.KeyEvent.Key) {
-				case Key.End:
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						 -(scrollView.ContentSize.Height - scrollView.Frame.Height
-						 + (scrollView.ShowHorizontalScrollIndicator ? 1 : 0)));
-					obj.Handled = true;
-					return;
-				case Key.Home:
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X, 0);
-					obj.Handled = true;
-					return;
-				case Key.PageDown:
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						 Math.Max (scrollView.ContentOffset.Y - scrollView.Frame.Height,
-						 -(scrollView.ContentSize.Height - scrollView.Frame.Height
-						 + (scrollView.ShowHorizontalScrollIndicator ? 1 : 0))));
-					obj.Handled = true;
-					return;
-				case Key.PageUp:
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						 Math.Min (scrollView.ContentOffset.Y + scrollView.Frame.Height, 0));
-					obj.Handled = true;
-					return;
-				}
-			}
-
-			private void Button_MouseClick (MouseEventArgs obj)
-			{
-				if (obj.MouseEvent.Flags == MouseFlags.WheeledDown) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						scrollView.ContentOffset.Y - BUTTON_HEIGHT);
-					obj.Handled = true;
-				} else if (obj.MouseEvent.Flags == MouseFlags.WheeledUp) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						Math.Min (scrollView.ContentOffset.Y + BUTTON_HEIGHT, 0));
-					obj.Handled = true;
-				}
-			}
-
-			private void Button_Clicked ()
-			{
-				MessageBox.Query ("Button clicked.", $"'{selected.Text}' clicked!", "Ok");
-				if (selected.Text == "Close") {
-					Application.RequestStop ();
-				}
-			}
-
-			private void Button_PointerEnter (ASCIICustomButton obj)
-			{
-				bool? moveDown;
-				if (obj.Frame.Y > selected?.Frame.Y) {
-					moveDown = true;
-				} else if (obj.Frame.Y < selected?.Frame.Y) {
-					moveDown = false;
-				} else {
-					moveDown = null;
-				}
-				var offSet = selected != null ? obj.Frame.Y - selected.Frame.Y + (-scrollView.ContentOffset.Y % BUTTON_HEIGHT) : 0;
-				selected = obj;
-				if (moveDown == true && selected.Frame.Y + scrollView.ContentOffset.Y + BUTTON_HEIGHT >= scrollView.Frame.Height && offSet != BUTTON_HEIGHT) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						Math.Min (scrollView.ContentOffset.Y - BUTTON_HEIGHT, -(selected.Frame.Y - scrollView.Frame.Height + BUTTON_HEIGHT)));
-				} else if (moveDown == true && selected.Frame.Y + scrollView.ContentOffset.Y >= scrollView.Frame.Height) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						scrollView.ContentOffset.Y - BUTTON_HEIGHT);
-				} else if (moveDown == true && selected.Frame.Y + scrollView.ContentOffset.Y < 0) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						-selected.Frame.Y);
-				} else if (moveDown == false && selected.Frame.Y < -scrollView.ContentOffset.Y) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						Math.Max (scrollView.ContentOffset.Y + BUTTON_HEIGHT, selected.Frame.Y));
-				} else if (moveDown == false && selected.Frame.Y + scrollView.ContentOffset.Y > scrollView.Frame.Height) {
-					scrollView.ContentOffset = new Point (scrollView.ContentOffset.X,
-						 -(selected.Frame.Y - scrollView.Frame.Height + BUTTON_HEIGHT));
-				}
-			}
-		}
-	}
-}

+ 65 - 65
UICatalog/Scenarios/Borders.cs

@@ -19,8 +19,6 @@ namespace UICatalog.Scenarios {
 			var effect3D = true;
 
 			var smartPanel = new PanelView () {
-				X = Pos.Center () - 38,
-				Y = Pos.Center () - 3,
 				Width = 24,
 				Height = 13,
 				Border = new Border () {
@@ -71,9 +69,7 @@ namespace UICatalog.Scenarios {
 			//	Height = 13
 			//};
 
-			var smartView = new Label () {
-				X = Pos.Center () + 10,
-				Y = Pos.Center () + 2,
+			var smartLabel = new Label () {
 				Border = new Border () {
 					BorderStyle = borderStyle,
 					DrawMarginFrame = drawMarginFrame,
@@ -88,7 +84,7 @@ namespace UICatalog.Scenarios {
 				Text = "This is a test\nwithout a \nPanelView",
 				TextAlignment = TextAlignment.Centered
 			};
-			smartView.Border.Child = smartView;
+			smartLabel.Border.Child = smartLabel;
 
 			Win.Add (new Label ("Padding:") {
 				X = Pos.Center () - 23,
@@ -105,16 +101,16 @@ namespace UICatalog.Scenarios {
 						int.Parse (e.NewText.ToString ()), smartPanel.Child.Border.Padding.Right,
 						smartPanel.Child.Border.Padding.Bottom);
 
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
+					smartLabel.Border.Padding = new Thickness (smartLabel.Border.Padding.Left,
+						int.Parse (e.NewText.ToString ()), smartLabel.Border.Padding.Right,
+						smartLabel.Border.Padding.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			paddingTopEdit.Text = $"{smartView.Border.Padding.Top}";
+			paddingTopEdit.Text = $"{smartLabel.Border.Padding.Top}";
 
 			Win.Add (paddingTopEdit);
 
@@ -129,16 +125,16 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.Padding.Top, smartPanel.Child.Border.Padding.Right,
 						smartPanel.Child.Border.Padding.Bottom);
 
-					smartView.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
+					smartLabel.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
+						smartLabel.Border.Padding.Top, smartLabel.Border.Padding.Right,
+						smartLabel.Border.Padding.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			paddingLeftEdit.Text = $"{smartView.Border.Padding.Left}";
+			paddingLeftEdit.Text = $"{smartLabel.Border.Padding.Left}";
 			Win.Add (paddingLeftEdit);
 
 			var paddingRightEdit = new TextField ("") {
@@ -152,16 +148,16 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
 						smartPanel.Child.Border.Padding.Bottom);
 
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Bottom);
+					smartLabel.Border.Padding = new Thickness (smartLabel.Border.Padding.Left,
+						smartLabel.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
+						smartLabel.Border.Padding.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			paddingRightEdit.Text = $"{smartView.Border.Padding.Right}";
+			paddingRightEdit.Text = $"{smartLabel.Border.Padding.Right}";
 			Win.Add (paddingRightEdit);
 
 			var paddingBottomEdit = new TextField ("") {
@@ -175,8 +171,8 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.Padding.Top, smartPanel.Child.Border.Padding.Right,
 						int.Parse (e.NewText.ToString ()));
 
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
+					smartLabel.Border.Padding = new Thickness (smartLabel.Border.Padding.Left,
+						smartLabel.Border.Padding.Top, smartLabel.Border.Padding.Right,
 						int.Parse (e.NewText.ToString ()));
 				} catch {
 					if (!e.NewText.IsEmpty) {
@@ -184,16 +180,16 @@ namespace UICatalog.Scenarios {
 					}
 				}
 			};
-			paddingBottomEdit.Text = $"{smartView.Border.Padding.Bottom}";
+			paddingBottomEdit.Text = $"{smartLabel.Border.Padding.Bottom}";
 			Win.Add (paddingBottomEdit);
 
 			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Center () - 35,
+				X = Pos.Left(paddingLeftEdit),
 				Y = 5
 			};
 			replacePadding.Clicked += () => {
 				smartPanel.Child.Border.Padding = new Thickness (smartPanel.Child.Border.Padding.Top);
-				smartView.Border.Padding = new Thickness (smartView.Border.Padding.Top);
+				smartLabel.Border.Padding = new Thickness (smartLabel.Border.Padding.Top);
 				if (paddingTopEdit.Text.IsEmpty) {
 					paddingTopEdit.Text = "0";
 				}
@@ -203,7 +199,7 @@ namespace UICatalog.Scenarios {
 
 			var cbUseUsePanelFrame = new CheckBox ("UsePanelFrame") {
 				X = Pos.X (replacePadding),
-				Y = Pos.Y (replacePadding) + 3,
+				Y = Pos.Y (replacePadding) + 1,
 				Checked = smartPanel.UsePanelFrame
 			};
 			cbUseUsePanelFrame.Toggled += (e) => smartPanel.UsePanelFrame = (bool)!e;
@@ -224,16 +220,16 @@ namespace UICatalog.Scenarios {
 						int.Parse (e.NewText.ToString ()), smartPanel.Child.Border.BorderThickness.Right,
 						smartPanel.Child.Border.BorderThickness.Bottom);
 
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
+					smartLabel.Border.BorderThickness = new Thickness (smartLabel.Border.BorderThickness.Left,
+						int.Parse (e.NewText.ToString ()), smartLabel.Border.BorderThickness.Right,
+						smartLabel.Border.BorderThickness.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			borderTopEdit.Text = $"{smartView.Border.BorderThickness.Top}";
+			borderTopEdit.Text = $"{smartLabel.Border.BorderThickness.Top}";
 
 			Win.Add (borderTopEdit);
 
@@ -248,16 +244,16 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.BorderThickness.Top, smartPanel.Child.Border.BorderThickness.Right,
 						smartPanel.Child.Border.BorderThickness.Bottom);
 
-					smartView.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
+					smartLabel.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
+						smartLabel.Border.BorderThickness.Top, smartLabel.Border.BorderThickness.Right,
+						smartLabel.Border.BorderThickness.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			borderLeftEdit.Text = $"{smartView.Border.BorderThickness.Left}";
+			borderLeftEdit.Text = $"{smartLabel.Border.BorderThickness.Left}";
 			Win.Add (borderLeftEdit);
 
 			var borderRightEdit = new TextField ("") {
@@ -271,16 +267,16 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
 						smartPanel.Child.Border.BorderThickness.Bottom);
 
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Bottom);
+					smartLabel.Border.BorderThickness = new Thickness (smartLabel.Border.BorderThickness.Left,
+						smartLabel.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
+						smartLabel.Border.BorderThickness.Bottom);
 				} catch {
 					if (!e.NewText.IsEmpty) {
 						e.Cancel = true;
 					}
 				}
 			};
-			borderRightEdit.Text = $"{smartView.Border.BorderThickness.Right}";
+			borderRightEdit.Text = $"{smartLabel.Border.BorderThickness.Right}";
 			Win.Add (borderRightEdit);
 
 			var borderBottomEdit = new TextField ("") {
@@ -294,8 +290,8 @@ namespace UICatalog.Scenarios {
 						smartPanel.Child.Border.BorderThickness.Top, smartPanel.Child.Border.BorderThickness.Right,
 						int.Parse (e.NewText.ToString ()));
 
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
+					smartLabel.Border.BorderThickness = new Thickness (smartLabel.Border.BorderThickness.Left,
+						smartLabel.Border.BorderThickness.Top, smartLabel.Border.BorderThickness.Right,
 						int.Parse (e.NewText.ToString ()));
 				} catch {
 					if (!e.NewText.IsEmpty) {
@@ -303,16 +299,16 @@ namespace UICatalog.Scenarios {
 					}
 				}
 			};
-			borderBottomEdit.Text = $"{smartView.Border.BorderThickness.Bottom}";
+			borderBottomEdit.Text = $"{smartLabel.Border.BorderThickness.Bottom}";
 			Win.Add (borderBottomEdit);
 
 			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Center () + 1,
+				X = Pos.Left(borderLeftEdit),
 				Y = 5
 			};
 			replaceBorder.Clicked += () => {
 				smartPanel.Child.Border.BorderThickness = new Thickness (smartPanel.Child.Border.BorderThickness.Top);
-				smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Top);
+				smartLabel.Border.BorderThickness = new Thickness (smartLabel.Border.BorderThickness.Top);
 				if (borderTopEdit.Text.IsEmpty) {
 					borderTopEdit.Text = "0";
 				}
@@ -328,21 +324,21 @@ namespace UICatalog.Scenarios {
 
 				X = 2,
 				Y = 1,
-				SelectedItem = (int)smartView.Border.BorderStyle
+				SelectedItem = (int)smartLabel.Border.BorderStyle
 			};
 			Win.Add (rbBorderStyle);
 
-			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartView.Border.DrawMarginFrame) {
+			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartLabel.Border.DrawMarginFrame) {
 				X = Pos.AnchorEnd (20),
 				Y = 0,
 				Width = 5
 			};
 			cbDrawMarginFrame.Toggled += (e) => {
 				try {
-					smartPanel.Child.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
-					smartView.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
-					if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-						cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
+					smartPanel.Child.Border.DrawMarginFrame = cbDrawMarginFrame.Checked;
+					smartLabel.Border.DrawMarginFrame = cbDrawMarginFrame.Checked;
+					if (cbDrawMarginFrame.Checked != smartLabel.Border.DrawMarginFrame) {
+						cbDrawMarginFrame.Checked = smartLabel.Border.DrawMarginFrame;
 					}
 				} catch { }
 			};
@@ -350,14 +346,14 @@ namespace UICatalog.Scenarios {
 
 			rbBorderStyle.SelectedItemChanged += (e) => {
 				smartPanel.Child.Border.BorderStyle = (BorderStyle)e.SelectedItem;
-				smartView.Border.BorderStyle = (BorderStyle)e.SelectedItem;
-				smartView.SetNeedsDisplay ();
-				if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-					cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
+				smartLabel.Border.BorderStyle = (BorderStyle)e.SelectedItem;
+				smartLabel.SetNeedsDisplay ();
+				if (cbDrawMarginFrame.Checked != smartLabel.Border.DrawMarginFrame) {
+					cbDrawMarginFrame.Checked = smartLabel.Border.DrawMarginFrame;
 				}
 			};
 
-			var cbEffect3D = new CheckBox ("Draw 3D effects", smartView.Border.Effect3D) {
+			var cbEffect3D = new CheckBox ("Draw 3D effects", smartLabel.Border.Effect3D) {
 				X = Pos.AnchorEnd (20),
 				Y = 1,
 				Width = 5
@@ -383,15 +379,15 @@ namespace UICatalog.Scenarios {
 					smartPanel.Child.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
 						smartPanel.Child.Border.Effect3DOffset.Y);
 
-					smartView.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Effect3DOffset.Y);
+					smartLabel.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
+						smartLabel.Border.Effect3DOffset.Y);
 				} catch {
 					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
 						e.Cancel = true;
 					}
 				}
 			};
-			effect3DOffsetX.Text = $"{smartView.Border.Effect3DOffset.X}";
+			effect3DOffsetX.Text = $"{smartLabel.Border.Effect3DOffset.X}";
 			Win.Add (effect3DOffsetX);
 
 			Win.Add (new Label ("Y:") {
@@ -409,7 +405,7 @@ namespace UICatalog.Scenarios {
 					smartPanel.Child.Border.Effect3DOffset = new Point (smartPanel.Child.Border.Effect3DOffset.X,
 						int.Parse (e.NewText.ToString ()));
 
-					smartView.Border.Effect3DOffset = new Point (smartView.Border.Effect3DOffset.X,
+					smartLabel.Border.Effect3DOffset = new Point (smartLabel.Border.Effect3DOffset.X,
 						int.Parse (e.NewText.ToString ()));
 				} catch {
 					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
@@ -417,13 +413,13 @@ namespace UICatalog.Scenarios {
 					}
 				}
 			};
-			effect3DOffsetY.Text = $"{smartView.Border.Effect3DOffset.Y}";
+			effect3DOffsetY.Text = $"{smartLabel.Border.Effect3DOffset.Y}";
 			Win.Add (effect3DOffsetY);
 
 			cbEffect3D.Toggled += (e) => {
 				try {
-					smartPanel.Child.Border.Effect3D = smartView.Border.Effect3D = effect3DOffsetX.Enabled =
-						effect3DOffsetY.Enabled = (bool)cbEffect3D.Checked;
+					smartPanel.Child.Border.Effect3D = smartLabel.Border.Effect3D = effect3DOffsetX.Enabled =
+						effect3DOffsetY.Enabled = cbEffect3D.Checked;
 				} catch { }
 			};
 
@@ -437,10 +433,10 @@ namespace UICatalog.Scenarios {
 
 				X = 2,
 				Y = 6,
-				SelectedItem = (int)smartView.Border.Background
+				SelectedItem = (int)smartLabel.Border.Background
 			};
 			rbBackground.SelectedItemChanged += (e) => {
-				smartPanel.Child.Border.Background = smartView.Border.Background = (Color)e.SelectedItem;
+				smartPanel.Child.Border.Background = smartLabel.Border.Background = (Color)e.SelectedItem;
 			};
 			Win.Add (rbBackground);
 
@@ -454,17 +450,21 @@ namespace UICatalog.Scenarios {
 
 				X = Pos.AnchorEnd (18),
 				Y = 6,
-				SelectedItem = (int)smartView.Border.BorderBrush
+				SelectedItem = (int)smartLabel.Border.BorderBrush
 			};
 			rbBorderBrush.SelectedItemChanged += (e) => {
-				smartPanel.Child.Border.BorderBrush = smartView.Border.BorderBrush = (Color)e.SelectedItem;
+				smartPanel.Child.Border.BorderBrush = smartLabel.Border.BorderBrush = (Color)e.SelectedItem;
 			};
 			Win.Add (rbBorderBrush);
 
+			smartPanel.X = Pos.Left (paddingLeftEdit);
+			smartPanel.Y = Pos.Top (smartLabel);
 			Win.Add (smartPanel);
-			Win.Add (smartView);
-
+			smartLabel.X = Pos.Left (borderLeftEdit);
+			smartLabel.Y = Pos.Bottom (cbUseUsePanelFrame) + 5;
+			Win.Add (smartLabel);
 			Win.BringSubviewToFront (smartPanel);
+
 		}
 	}
 }

+ 5 - 3
UICatalog/Scenarios/BordersOnFrameView.cs

@@ -20,7 +20,7 @@ namespace UICatalog.Scenarios {
 
 			var smartView = new FrameView () {
 				X = Pos.Center (),
-				Y = Pos.Center () - 7,
+				Y = 0, // Y is set below 
 				Width = 40,
 				Height = 20,
 				Border = new Border () {
@@ -142,7 +142,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (paddingBottomEdit);
 
 			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Center () - 35,
+				X = Pos.Left (paddingLeftEdit),
 				Y = 5
 			};
 			replacePadding.Clicked += () => {
@@ -236,7 +236,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (borderBottomEdit);
 
 			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Center () + 1,
+				X = Pos.Left (borderLeftEdit),
 				Y = 5
 			};
 			replaceBorder.Clicked += () => {
@@ -248,6 +248,8 @@ namespace UICatalog.Scenarios {
 			};
 			Win.Add (replaceBorder);
 
+			smartView.Y = Pos.Bottom (replaceBorder) + 1;
+
 			Win.Add (new Label ("BorderStyle:"));
 
 			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();

+ 5 - 3
UICatalog/Scenarios/BordersOnToplevel.cs

@@ -20,7 +20,7 @@ namespace UICatalog.Scenarios {
 
 			var smartView = new Border.ToplevelContainer () {
 				X = Pos.Center (),
-				Y = Pos.Center () - 7,
+				Y = 0, // Y is set below 
 				Width = 40,
 				Height = 20,
 				Border = new Border () {
@@ -142,7 +142,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (paddingBottomEdit);
 
 			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Center () - 35,
+				X = Pos.Left(paddingLeftEdit),
 				Y = 5
 			};
 			replacePadding.Clicked += () => {
@@ -236,7 +236,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (borderBottomEdit);
 
 			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Center () + 1,
+				X = Pos.Left(borderLeftEdit),
 				Y = 5
 			};
 			replaceBorder.Clicked += () => {
@@ -248,6 +248,8 @@ namespace UICatalog.Scenarios {
 			};
 			Win.Add (replaceBorder);
 
+			smartView.Y = Pos.Bottom (replaceBorder) + 1;
+
 			Win.Add (new Label ("BorderStyle:"));
 
 			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();

+ 4 - 3
UICatalog/Scenarios/BordersOnWindow.cs

@@ -20,7 +20,6 @@ namespace UICatalog.Scenarios {
 
 			var smartView = new Window () {
 				X = Pos.Center (),
-				Y = Pos.Center () - 7,
 				Width = 40,
 				Height = 20,
 				Border = new Border () {
@@ -142,7 +141,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (paddingBottomEdit);
 
 			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Center () - 35,
+				X = Pos.Left (paddingLeftEdit),
 				Y = 5
 			};
 			replacePadding.Clicked += () => {
@@ -236,7 +235,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (borderBottomEdit);
 
 			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Center () + 1,
+				X = Pos.Left (borderLeftEdit),
 				Y = 5
 			};
 			replaceBorder.Clicked += () => {
@@ -250,6 +249,8 @@ namespace UICatalog.Scenarios {
 
 			Win.Add (new Label ("BorderStyle:"));
 
+			smartView.Y = Pos.Bottom (replaceBorder) + 1;
+
 			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();
 			var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
 				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {

+ 149 - 59
UICatalog/Scenarios/ComputedLayout.cs

@@ -17,39 +17,31 @@ namespace UICatalog.Scenarios {
 	[ScenarioCategory ("Layout")]
 	public class ComputedLayout : Scenario {
 
+		public override void Init (ColorScheme colorScheme)
+		{
+			Application.Init ();
+			Application.Top.ColorScheme = colorScheme;
+		}
+
 		public override void Setup ()
 		{
-			var menu = new MenuBar (new MenuBarItem [] {
-				new MenuBarItem ("_Settings", new MenuItem [] {
-					null,
-					new MenuItem ("_Quit", "", () => Quit()),
-				}),
-			});
-			Application.Top.Add (menu);
-
-			var statusBar = new StatusBar (new StatusItem [] {
-				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
-			});
-			Application.Top.Add (statusBar);
-
-			//Top.LayoutStyle = LayoutStyle.Computed;
 			// Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width
-			// BUGBUG: Dim.Fill returns too big a value sometimes.
 			const string rule = "|123456789";
 			var horizontalRuler = new Label ("") {
+				AutoSize = false,
 				X = 0,
 				Y = 0,
-				Width = Dim.Fill (),  // FIXED: I don't think this should be needed; DimFill() should respect container's frame. X does.
+				Width = Dim.Fill (),
 				ColorScheme = Colors.Error
 			};
 
-			Win.Add (horizontalRuler);
+			Application.Top.Add (horizontalRuler);
 
 			// Demonstrate using Dim to create a vertical ruler that always measures the parent window's height
-			// TODO: Either build a custom control for this or implement linewrap in Label #352
 			const string vrule = "|\n1\n2\n3\n4\n5\n6\n7\n8\n9\n";
 
 			var verticalRuler = new Label ("") {
+				AutoSize = false,
 				X = 0,
 				Y = 0,
 				Width = 1,
@@ -57,29 +49,37 @@ namespace UICatalog.Scenarios {
 				ColorScheme = Colors.Error
 			};
 
-			Win.LayoutComplete += (a) => {
+			Application.Top.LayoutComplete += (a) => {
 				horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)];
-				verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height * 2)];
+				verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height*2)];
 			};
 
-			Win.Add (verticalRuler);
+			Application.Top.Add (verticalRuler);
 
-			// Demonstrate At - Absolute Layout using Pos
-			var absoluteButton = new Button ("Absolute At(2,1)") {
+			// Demonstrate At - Using Pos.At to locate a view in an absolute location
+			var atButton = new Button ("At(2,1)") {
 				X = Pos.At (2),
 				Y = Pos.At (1)
 			};
-			Win.Add (absoluteButton);
+			Application.Top.Add (atButton);
+
+			// Throw in a literal absolute - Should funciton identically to above
+			var absoluteButton = new Button ("X = 30, Y = 1") {
+				X = 30,
+				Y = 1
+			};
+			Application.Top.Add (absoluteButton);
 
 			// Demonstrate using Dim to create a window that fills the parent with a margin
 			int margin = 10;
-			var subWin = new Window ($"Centered Sub Window with {margin} character margin") {
+			var subWin = new Window () {
 				X = Pos.Center (),
 				Y = 2,
 				Width = Dim.Fill (margin),
 				Height = 7
 			};
-			Win.Add (subWin);
+			subWin.Title = $"{subWin.GetType().Name} {{X={subWin.X},Y={subWin.Y},Width={subWin.Width},Height={subWin.Height}}}";
+			Application.Top.Add (subWin);
 
 			int i = 1;
 			string txt = "Resize the terminal to see computed layout in action.";
@@ -92,13 +92,13 @@ namespace UICatalog.Scenarios {
 			subWin.Add (labelList.ToArray ());
 
 			// #522 repro?
-			var frameView = new FrameView ($"Centered FrameView with {margin} character margin") {
-				X = Pos.Center (),
+			var frameView = new FrameView () {
+				X = 2, //Pos.Center (),
 				Y = Pos.Bottom (subWin),
-				Width = Dim.Fill (margin),
+				Width = 30,
 				Height = 7
 			};
-			Win.Add (frameView);
+			frameView.Title = $"{frameView.GetType ().Name} {{X={frameView.X},Y={frameView.Y},Width={frameView.Width},Height={frameView.Height}}}";
 			i = 1;
 			labelList = new List<Label> ();
 			labelList.Add (new Label ($"The lines below show different TextAlignments"));
@@ -107,73 +107,164 @@ namespace UICatalog.Scenarios {
 			labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Centered, Width = Dim.Fill (), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()), ColorScheme = Colors.Dialog });
 			labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Justified, Width = Dim.Fill (), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()), ColorScheme = Colors.Dialog });
 			frameView.Add (labelList.ToArray ());
+			Application.Top.Add (frameView);
+
+			frameView = new FrameView () {
+				X = Pos.Right(frameView),
+				Y = Pos.Top (frameView),
+				Width = Dim.Fill(),
+				Height = 7,
+			};
+			frameView.Title = $"{frameView.GetType ().Name} {{X={frameView.X},Y={frameView.Y},Width={frameView.Width},Height={frameView.Height}}}";
+			Application.Top.Add (frameView);
 
 			// Demonstrate Dim & Pos using percentages - a TextField that is 30% height and 80% wide
 			var textView = new TextView () {
 				X = Pos.Center (),
 				Y = Pos.Percent (50),
 				Width = Dim.Percent (80),
-				Height = Dim.Percent (30),
+				Height = Dim.Percent (10),
 				ColorScheme = Colors.TopLevel,
 			};
-			textView.Text = "This text view should be half-way down the terminal,\n20% of its height, and 80% of its width.";
-			Win.Add (textView);
+			textView.Text = $"This TextView should horizontally & vertically centered and \n10% of the screeen height, and 80% of its width.";
+			Application.Top.Add (textView);
+
+			var oddballButton = new Button ("These buttons demo convoluted PosCombine scenarios") {
+				X = Pos.Center (),
+				Y = Pos.Bottom (textView) + 1
+			};
+			Application.Top.Add (oddballButton);
+
+			#region Issue2358
+			// Demonstrate odd-ball Combine scenarios
+			// Until https://github.com/gui-cs/Terminal.Gui/issues/2358 is fixed these won't work right
+
+			oddballButton = new Button ("Center + 0") {
+				X = Pos.Center () + 0,
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			oddballButton = new Button ("Center + 1") {
+				X = Pos.Center () + 1,
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			oddballButton = new Button ("0 + Center") {
+				X = 0 + Pos.Center (),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			oddballButton = new Button ("1 + Center") {
+				X = 1 + Pos.Center (),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
+			// The `- Pos.Percent(5)` is there so at least something is visible
+			oddballButton = new Button ("Center + Center - Percent(50)") {
+				X = Pos.Center () + Pos.Center () - Pos.Percent(50),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
+			// The `- Pos.Percent(5)` is there so at least something is visible
+			oddballButton = new Button ("Percent(50) + Center - Percent(50)") {
+				X = Pos.Percent (50) + Pos.Center () - Pos.Percent (50),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
+			// The `- Pos.Percent(5)` is there so at least something is visible
+			oddballButton = new Button ("Center + Percent(50) - Percent(50)") {
+				X = Pos.Center () + Pos.Percent (50) - Pos.Percent (50),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			#endregion
+			// This demonstrates nonsense: Same as At(0)
+			oddballButton = new Button ("Center - Center - Percent(50)") {
+				X = Pos.Center () + Pos.Center () - Pos.Percent (50),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
+
+			// This demonstrates combining Percents)
+			oddballButton = new Button ("Percent(40) + Percent(10)") {
+				X = Pos.Percent (40) + Pos.Percent(10),
+				Y = Pos.Bottom (oddballButton)
+			};
+			Application.Top.Add (oddballButton);
 
 			// Demonstrate AnchorEnd - Button is anchored to bottom/right
-			var anchorButton = new Button ("Anchor End") {
+			var anchorButton = new Button ("Button using AnchorEnd") {
 				Y = Pos.AnchorEnd () - 1,
 			};
-			// TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
 			anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
 			anchorButton.Clicked += () => {
 				// Ths demonstrates how to have a dynamically sized button
 				// Each time the button is clicked the button's text gets longer
-				// The call to Win.LayoutSubviews causes the Computed layout to
+				// The call to Application.Top.LayoutSubviews causes the Computed layout to
 				// get updated. 
 				anchorButton.Text += "!";
-				Win.LayoutSubviews ();
+				Application.Top.LayoutSubviews ();
 			};
-			Win.Add (anchorButton);
-
+			Application.Top.Add (anchorButton);
 
-			// Centering multiple controls horizontally. 
+			// Demonstrate AnchorEnd(n) 
 			// This is intentionally convoluted to illustrate potential bugs.
-			var bottomLabel = new Label ("This should be the 2nd to last line (Bug #xxx).") {
+			var anchorEndLabel1 = new Label ("This Label should be the 2nd to last line (AnchorEnd (2)).") {
 				TextAlignment = Terminal.Gui.TextAlignment.Centered,
 				ColorScheme = Colors.Menu,
-				Width = Dim.Fill (),
-				X = Pos.Center (),
-				Y = Pos.AnchorEnd () - 2 // FIXED: -2 should be two lines above border; but it has to be -4
+				Width = Dim.Fill (5),
+				X = 5,
+				Y = Pos.AnchorEnd (2)
+			};
+			Application.Top.Add (anchorEndLabel1);
+
+			// Demonstrate DimCombine (via AnchorEnd(n) - 1)
+			// This is intentionally convoluted to illustrate potential bugs.
+			var anchorEndLabel2 = new TextField ("This TextField should be the 3rd to last line (AnchorEnd (2) - 1).") {
+				TextAlignment = Terminal.Gui.TextAlignment.Left,
+				ColorScheme = Colors.Menu,
+				Width = Dim.Fill (5),
+				X = 5,
+				Y = Pos.AnchorEnd (2) - 1 // Pos.Combine
 			};
-			Win.Add (bottomLabel);
+			Application.Top.Add (anchorEndLabel2);
 
-			// Show positioning vertically using Pos.Bottom 
-			// BUGBUG: -1 should be just above border; but it has to be -3
+			// Show positioning vertically using Pos.AnchorEnd via Pos.Combine
 			var leftButton = new Button ("Left") {
-				Y = Pos.AnchorEnd () - 1
+				Y = Pos.AnchorEnd () - 1 // Pos.Combine
 			};
 			leftButton.Clicked += () => {
 				// Ths demonstrates how to have a dynamically sized button
 				// Each time the button is clicked the button's text gets longer
-				// The call to Win.LayoutSubviews causes the Computed layout to
+				// The call to Application.Top.LayoutSubviews causes the Computed layout to
 				// get updated. 
 				leftButton.Text += "!";
-				Win.LayoutSubviews ();
+				Application.Top.LayoutSubviews ();
 			};
 
 
 			// show positioning vertically using Pos.AnchorEnd
 			var centerButton = new Button ("Center") {
 				X = Pos.Center (),
-				Y = Pos.AnchorEnd () - 1
+				Y = Pos.AnchorEnd (1)  // Pos.AnchorEnd(1)
 			};
 			centerButton.Clicked += () => {
 				// Ths demonstrates how to have a dynamically sized button
 				// Each time the button is clicked the button's text gets longer
-				// The call to Win.LayoutSubviews causes the Computed layout to
+				// The call to Application.Top.LayoutSubviews causes the Computed layout to
 				// get updated. 
 				centerButton.Text += "!";
-				Win.LayoutSubviews ();
+				Application.Top.LayoutSubviews ();
 			};
 
 			// show positioning vertically using another window and Pos.Bottom
@@ -183,20 +274,19 @@ namespace UICatalog.Scenarios {
 			rightButton.Clicked += () => {
 				// Ths demonstrates how to have a dynamically sized button
 				// Each time the button is clicked the button's text gets longer
-				// The call to Win.LayoutSubviews causes the Computed layout to
+				// The call to Application.Top.LayoutSubviews causes the Computed layout to
 				// get updated. 
 				rightButton.Text += "!";
-				Win.LayoutSubviews ();
+				Application.Top.LayoutSubviews ();
 			};
 
 			// Center three buttons with 5 spaces between them
-			// TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
 			leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
 			rightButton.X = Pos.Right (centerButton) + 5;
 
-			Win.Add (leftButton);
-			Win.Add (centerButton);
-			Win.Add (rightButton);
+			Application.Top.Add (leftButton);
+			Application.Top.Add (centerButton);
+			Application.Top.Add (rightButton);
 		}
 
 		public override void Run ()

+ 23 - 2
UICatalog/Scenarios/Generic.cs

@@ -1,13 +1,34 @@
-using Terminal.Gui;
+using System.Data;
+using Terminal.Gui;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "Generic", Description: "Generic sample - A template for creating new Scenarios")]
 	[ScenarioCategory ("Controls")]
 	public class MyScenario : Scenario {
+		public override void Init (ColorScheme colorScheme)
+		{
+			// The base `Scenario.Init` implementation:
+			//  - Calls `Application.Init ()`
+			//  - Adds a full-screen Window to Application.Top with a title
+			//    that reads "Press <hotkey> to Quit". Access this Window with `this.Win`.
+			//  - Sets the ColorScheme property of `this.Win` to `colorScheme`.
+			// To overrride this, implement an override of `Init`.
+			base.Init (colorScheme);
+
+			// A common, alternate, implementation where `this.Win` is not used:
+			//   Application.Init ();
+			//   Application.Top.ColorScheme = colorScheme;
+		}
+
 		public override void Setup ()
 		{
-			// Put your scenario code here, e.g.
+			// Put scenario code here (in a real app, this would be the code
+			// that would setup the app before `Application.Run` is called`).
+			// With a Scenario, after UI Catalog calls `Scenario.Setup` it calls
+			// `Scenario.Run` which calls `Application.Run`.
+			// Example:
 			var button = new Button ("Press me!") {
+				AutoSize = false,
 				X = Pos.Center (),
 				Y = Pos.Center (),
 			};

+ 72 - 287
UnitTests/Core/BorderTests.cs

@@ -1,19 +1,15 @@
 using System;
-using System.Reflection.Emit;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using Xunit;
-using Xunit.Abstractions;
 using Rune = System.Rune;
 
 namespace Terminal.Gui.CoreTests {
 	public class BorderTests {
-		readonly ITestOutputHelper output;
-
-		public BorderTests (ITestOutputHelper output)
-		{
-			this.output = output;
-		}
-
-		[Fact, AutoInitShutdown]
+		[Fact]
+		[AutoInitShutdown]
 		public void Constructor_Defaults ()
 		{
 			var b = new Border ();
@@ -49,7 +45,8 @@ namespace Terminal.Gui.CoreTests {
 			Assert.False (b.DrawMarginFrame);
 		}
 
-		[Fact, AutoInitShutdown]
+		[Fact]
+		[AutoInitShutdown]
 		public void ActualWidth_ActualHeight ()
 		{
 			var v = new View (new Rect (5, 10, 60, 20), "", new Border ());
@@ -84,229 +81,68 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Equal (new Thickness (5, 5, 5, 5), b.GetSumThickness ());
 		}
 
-		//[Fact]
-		//[AutoInitShutdown]
-		//public void DrawContent_With_Child_Border ()
-		//{
-		//	var top = Application.Top;
-		//	var driver = (FakeDriver)Application.Driver;
-
-		//	var label = new Label () {
-		//		X = Pos.Center (),
-		//		Y = Pos.Center (),
-		//		Border = new Border () {
-		//			BorderStyle = BorderStyle.Single,
-		//			Padding = new Thickness (2),
-		//			BorderThickness = new Thickness (2),
-		//			BorderBrush = Color.Red,
-		//			Background = Color.BrightGreen,
-		//			Effect3D = true,
-		//			Effect3DOffset = new Point (2, -3)
-		//		},
-		//		ColorScheme = Colors.TopLevel,
-		//		Text = "This is a test"
-		//	};
-		//	label.Border.Child = label;
-		//	top.Add (label);
-
-		//	top.LayoutSubviews ();
-		//	label.Redraw (label.Bounds);
-
-		//	var frame = label.Frame;
-		//	var drawMarginFrame = label.Border.DrawMarginFrame ? 1 : 0;
-		//	var sumThickness = label.Border.GetSumThickness ();
-		//	var padding = label.Border.Padding;
-		//	var effect3DOffset = label.Border.Effect3DOffset;
-		//	var borderStyle = label.Border.BorderStyle;
-
-		//	// Check the upper BorderThickness
-		//	for (int r = frame.Y - drawMarginFrame - sumThickness.Top;
-		//		r < frame.Y - drawMarginFrame - padding.Top; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-		//			c < frame.Right + drawMarginFrame + sumThickness.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.Red, color.Background);
-		//		}
-		//	}
-
-		//	// Check the left BorderThickness
-		//	for (int r = frame.Y - drawMarginFrame - padding.Top;
-		//		r < frame.Bottom + drawMarginFrame + padding.Bottom; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-		//			c < frame.X - drawMarginFrame - padding.Left; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.Red, color.Background);
-		//		}
-		//	}
-
-		//	// Check the right BorderThickness
-		//	for (int r = frame.Y - drawMarginFrame - padding.Top;
-		//		r < frame.Bottom + drawMarginFrame + padding.Bottom; r++) {
-		//		for (int c = frame.Right + drawMarginFrame + padding.Right;
-		//			c < frame.Right + drawMarginFrame - sumThickness.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.Red, color.Background);
-		//		}
-		//	}
-
-		//	// Check the lower BorderThickness
-		//	for (int r = frame.Bottom + drawMarginFrame + padding.Bottom;
-		//		r < frame.Bottom + drawMarginFrame + sumThickness.Bottom; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-		//			c < frame.Right + drawMarginFrame + sumThickness.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.Red, color.Background);
-		//		}
-		//	}
-
-		//	// Check the upper Padding
-		//	for (int r = frame.Y - drawMarginFrame - padding.Top;
-		//		r < frame.Y - drawMarginFrame; r++) {
-		//		for (int c = frame.X - drawMarginFrame - padding.Left;
-		//			c < frame.Right + drawMarginFrame + padding.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.BrightGreen, color.Background);
-		//		}
-		//	}
-
-		//	// Check the left Padding
-		//	for (int r = frame.Y - drawMarginFrame;
-		//		r < frame.Bottom + drawMarginFrame; r++) {
-		//		for (int c = frame.X - drawMarginFrame - padding.Left;
-		//			c < frame.X - drawMarginFrame; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.BrightGreen, color.Background);
-		//		}
-		//	}
-
-		//	// Check the right Padding
-		//	for (int r = frame.Y - drawMarginFrame;
-		//		r < frame.Bottom + drawMarginFrame; r++) {
-		//		for (int c = frame.Right + drawMarginFrame;
-		//			c < frame.Right + drawMarginFrame - padding.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.BrightGreen, color.Background);
-		//		}
-		//	}
-
-		//	// Check the lower Padding
-		//	for (int r = frame.Bottom + drawMarginFrame;
-		//		r < frame.Bottom + drawMarginFrame + padding.Bottom; r++) {
-		//		for (int c = frame.X - drawMarginFrame - padding.Left;
-		//			c < frame.Right + drawMarginFrame + padding.Right; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.BrightGreen, color.Background);
-		//		}
-		//	}
-
-		//	Rune hLine = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.HLine : (borderStyle == BorderStyle.Double ? driver.HDLine : ' ')) : ' ';
-		//	Rune vLine = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.VLine : (borderStyle == BorderStyle.Double ? driver.VDLine : ' ')) : ' ';
-		//	Rune uRCorner = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.URCorner : (borderStyle == BorderStyle.Double ? driver.URDCorner : ' ')) : ' ';
-		//	Rune uLCorner = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.ULCorner : (borderStyle == BorderStyle.Double ? driver.ULDCorner : ' ')) : ' ';
-		//	Rune lLCorner = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.LLCorner : (borderStyle == BorderStyle.Double ? driver.LLDCorner : ' ')) : ' ';
-		//	Rune lRCorner = drawMarginFrame > 0 ? (borderStyle == BorderStyle.Single
-		//		? driver.LRCorner : (borderStyle == BorderStyle.Double ? driver.LRDCorner : ' ')) : ' ';
-
-		//	var text = "";
-		//	// Check the MarginFrame
-		//	for (int r = frame.Y - drawMarginFrame;
-		//		r < frame.Bottom + drawMarginFrame; r++) {
-		//		for (int c = frame.X - drawMarginFrame;
-		//			c <= frame.Right + drawMarginFrame - 1; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			var rune = (Rune)driver.Contents [r, c, 0];
-		//			Assert.Equal (Color.Black, color.Background);
-		//			if (c == frame.X - drawMarginFrame && r == frame.Y - drawMarginFrame) {
-		//				Assert.Equal (uLCorner, rune);
-		//			} else if (c == frame.Right && r == frame.Y - drawMarginFrame) {
-		//				Assert.Equal (uRCorner, rune);
-		//			} else if (c == frame.X - drawMarginFrame && r == frame.Bottom) {
-		//				Assert.Equal (lLCorner, rune);
-		//			} else if (c == frame.Right && r == frame.Bottom) {
-		//				Assert.Equal (lRCorner, rune);
-		//			} else if (c >= frame.X && (r == frame.Y - drawMarginFrame
-		//				|| r == frame.Bottom)) {
-		//				Assert.Equal (hLine, rune);
-		//			} else if ((c == frame.X - drawMarginFrame || c == frame.Right)
-		//				&& r >= frame.Y && r <= frame.Bottom - drawMarginFrame) {
-		//				Assert.Equal (vLine, rune);
-		//			} else {
-		//				text += rune.ToString ();
-		//			}
-		//		}
-		//	}
-		//	Assert.Equal ("This is a test", text.Trim ());
-
-		//	// Check the upper Effect3D
-		//	for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
-		//		r < frame.Y - drawMarginFrame - sumThickness.Top; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
-		//			c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.DarkGray, color.Background);
-		//		}
-		//	}
-
-		//	// Check the left Effect3D
-		//	for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
-		//		r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
-		//			c < frame.X - drawMarginFrame - sumThickness.Left; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.DarkGray, color.Background);
-		//		}
-		//	}
-
-		//	// Check the right Effect3D
-		//	for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
-		//		r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
-		//		for (int c = frame.Right + drawMarginFrame + sumThickness.Right;
-		//			c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.DarkGray, color.Background);
-		//		}
-		//	}
-
-		//	// Check the lower Effect3D
-		//	for (int r = frame.Bottom + drawMarginFrame + sumThickness.Bottom;
-		//		r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
-		//		for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
-		//			c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.DarkGray, color.Background);
-		//		}
-		//	}
-
-		//	// Check the Child frame
-		//	for (int r = frame.Y; r < frame.Y + frame.Height; r++) {
-		//		for (int c = frame.X; c < frame.X + frame.Width; c++) {
-
-		//			var color = (Attribute)driver.Contents [r, c, 1];
-		//			Assert.Equal (Color.BrightGreen, color.Foreground);
-		//			Assert.Equal (Color.Black, color.Background);
-		//		}
-		//	}
-		//}
-
-		[Fact, AutoInitShutdown]
+	}
+				}
+			}
+			Assert.Equal ("This is a test", text.Trim ());
+
+			// Check the upper Effect3D
+			for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
+				r < frame.Y - drawMarginFrame - sumThickness.Top; r++) {
+				for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
+					c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
+
+					var color = (Attribute)driver.Contents [r, c, 1];
+					Assert.Equal (Color.DarkGray, color.Background);
+				}
+			}
+
+			// Check the left Effect3D
+			for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
+				r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
+				for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
+					c < frame.X - drawMarginFrame - sumThickness.Left; c++) {
+
+					var color = (Attribute)driver.Contents [r, c, 1];
+					Assert.Equal (Color.DarkGray, color.Background);
+				}
+			}
+
+			// Check the right Effect3D
+			for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
+				r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
+				for (int c = frame.Right + drawMarginFrame + sumThickness.Right;
+					c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
+
+					var color = (Attribute)driver.Contents [r, c, 1];
+					Assert.Equal (Color.DarkGray, color.Background);
+				}
+			}
+
+			// Check the lower Effect3D
+			for (int r = frame.Bottom + drawMarginFrame + sumThickness.Bottom;
+				r < frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y; r++) {
+				for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
+					c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
+
+					var color = (Attribute)driver.Contents [r, c, 1];
+					Assert.Equal (Color.DarkGray, color.Background);
+				}
+			}
+
+			// Check the Child frame
+			for (int r = frame.Y; r < frame.Y + frame.Height; r++) {
+				for (int c = frame.X; c < frame.X + frame.Width; c++) {
+
+					var color = (Attribute)driver.Contents [r, c, 1];
+					Assert.Equal (Color.BrightGreen, color.Foreground);
+					Assert.Equal (Color.Black, color.Background);
+				}
+			}
+		}
+
+		[Fact]
+		[AutoInitShutdown]
 		public void DrawContent_With_Parent_Border ()
 		{
 			var top = Application.Top;
@@ -542,7 +378,8 @@ namespace Terminal.Gui.CoreTests {
 			}
 		}
 
-		[Fact, AutoInitShutdown]
+		[Fact]
+		[AutoInitShutdown]
 		public void BorderOnControlWithNoChildren ()
 		{
 			var label = new TextField ("Loading...") {
@@ -558,57 +395,5 @@ namespace Terminal.Gui.CoreTests {
 
 			Assert.Null (Record.Exception (() => label.Redraw (label.Bounds)));
 		}
-
-		[Fact, AutoInitShutdown]
-		public void BorderStyle_And_DrawMarginFrame_Gets_Sets ()
-		{
-			var lblTop = new Label ("At 0,0");
-			var lblFrame = new Label ("Centered") { X = Pos.Center (), Y = Pos.Center () };
-			var frame = new FrameView () { Y = 1, Width = 20, Height = 3 };
-			var lblFill = new Label () { Width = Dim.Fill(),Height = Dim.Fill(), Visible = false };
-			var fillText = new System.Text.StringBuilder ();
-			for (int i = 0; i < frame.Bounds.Height; i++) {
-				if (i > 0) {
-					fillText.AppendLine ("");
-				}
-				for (int j = 0; j < frame.Bounds.Width; j++) {
-					fillText.Append ("█");
-				}
-			}
-			lblFill.Text = fillText.ToString ();
-			frame.Add (lblFill, lblFrame);
-			var lblBottom = new Label ("At 0,4") { Y = 4 };
-			Application.Top.Add (lblTop, frame, lblBottom);
-			Application.Begin (Application.Top);
-
-			Assert.Equal (BorderStyle.Single, frame.Border.BorderStyle);
-			Assert.True (frame.Border.DrawMarginFrame);
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-At 0,0              
-┌──────────────────┐
-│     Centered     │
-└──────────────────┘
-At 0,4              ", output);
-
-			frame.Border.BorderStyle = BorderStyle.None;
-			Application.Refresh ();
-			Assert.True (frame.Border.DrawMarginFrame);
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-At 0,0        
-              
-      Centered
-              
-At 0,4        ", output);
-
-			frame.Border.DrawMarginFrame = false;
-			lblFill.Visible = true;
-			Application.Refresh ();
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-At 0,0              
-████████████████████
-██████Centered██████
-████████████████████
-At 0,4              ", output);
-		}
 	}
 }

+ 1424 - 0
UnitTests/Core/LayoutTests.cs

@@ -0,0 +1,1424 @@
+using NStack;
+using System;
+using System.Collections.Generic;
+using System.Xml.Linq;
+using Terminal.Gui.Graphs;
+using Xunit;
+using Xunit.Abstractions;
+//using GraphViewTests = Terminal.Gui.Views.GraphViewTests;
+
+// Alias Console to MockConsole so we don't accidentally use Console
+using Console = Terminal.Gui.FakeConsole;
+
+namespace Terminal.Gui.CoreTests {
+	public class LayoutTests {
+		readonly ITestOutputHelper output;
+
+		public LayoutTests (ITestOutputHelper output)
+		{
+			this.output = output;
+		}
+
+		[Fact]
+		public void TopologicalSort_Missing_Add ()
+		{
+			var root = new View ();
+			var sub1 = new View ();
+			root.Add (sub1);
+			var sub2 = new View ();
+			sub1.Width = Dim.Width (sub2);
+
+			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
+
+			sub2.Width = Dim.Width (sub1);
+
+			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
+		}
+
+		[Fact]
+		public void TopologicalSort_Recursive_Ref ()
+		{
+			var root = new View ();
+			var sub1 = new View ();
+			root.Add (sub1);
+			var sub2 = new View ();
+			root.Add (sub2);
+			sub2.Width = Dim.Width (sub2);
+			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
+		}
+
+		[Fact, AutoInitShutdown]
+		public void SetWidth_CanSetWidth_ForceValidatePosDim ()
+		{
+			var top = new View () {
+				X = 0,
+				Y = 0,
+				Width = 80,
+			};
+
+			var v = new View () {
+				Width = Dim.Fill (),
+				ForceValidatePosDim = true
+			};
+			top.Add (v);
+
+			Assert.False (v.SetWidth (70, out int rWidth));
+			Assert.Equal (70, rWidth);
+
+			v.Width = Dim.Fill (1);
+			Assert.False (v.SetWidth (70, out rWidth));
+			Assert.Equal (69, rWidth);
+
+			v.Width = null;
+			Assert.True (v.SetWidth (70, out rWidth));
+			Assert.Equal (70, rWidth);
+			Assert.False (v.IsInitialized);
+
+			Application.Top.Add (top);
+			Application.Begin (Application.Top);
+
+			Assert.True (v.IsInitialized);
+			v.Width = Dim.Fill (1);
+			Assert.Throws<ArgumentException> (() => v.Width = 75);
+			v.LayoutStyle = LayoutStyle.Absolute;
+			v.Width = 75;
+			Assert.True (v.SetWidth (60, out rWidth));
+			Assert.Equal (60, rWidth);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void SetHeight_CanSetHeight_ForceValidatePosDim ()
+		{
+			var top = new View () {
+				X = 0,
+				Y = 0,
+				Height = 20
+			};
+
+			var v = new View () {
+				Height = Dim.Fill (),
+				ForceValidatePosDim = true
+			};
+			top.Add (v);
+
+			Assert.False (v.SetHeight (10, out int rHeight));
+			Assert.Equal (10, rHeight);
+
+			v.Height = Dim.Fill (1);
+			Assert.False (v.SetHeight (10, out rHeight));
+			Assert.Equal (9, rHeight);
+
+			v.Height = null;
+			Assert.True (v.SetHeight (10, out rHeight));
+			Assert.Equal (10, rHeight);
+			Assert.False (v.IsInitialized);
+
+			Application.Top.Add (top);
+			Application.Begin (Application.Top);
+
+			Assert.True (v.IsInitialized);
+
+			v.Height = Dim.Fill (1);
+			Assert.Throws<ArgumentException> (() => v.Height = 15);
+			v.LayoutStyle = LayoutStyle.Absolute;
+			v.Height = 15;
+			Assert.True (v.SetHeight (5, out rHeight));
+			Assert.Equal (5, rHeight);
+		}
+
+		[Fact]
+		public void GetCurrentWidth_CanSetWidth ()
+		{
+			var top = new View () {
+				X = 0,
+				Y = 0,
+				Width = 80,
+			};
+
+			var v = new View () {
+				Width = Dim.Fill ()
+			};
+			top.Add (v);
+
+			Assert.False (v.AutoSize);
+			Assert.True (v.GetCurrentWidth (out int cWidth));
+			Assert.Equal (80, cWidth);
+
+			v.Width = Dim.Fill (1);
+			Assert.True (v.GetCurrentWidth (out cWidth));
+			Assert.Equal (79, cWidth);
+
+			v.AutoSize = true;
+
+			Assert.True (v.GetCurrentWidth (out cWidth));
+			Assert.Equal (79, cWidth);
+		}
+
+		[Fact]
+		public void GetCurrentHeight_CanSetHeight ()
+		{
+			var top = new View () {
+				X = 0,
+				Y = 0,
+				Height = 20
+			};
+
+			var v = new View () {
+				Height = Dim.Fill ()
+			};
+			top.Add (v);
+
+			Assert.False (v.AutoSize);
+			Assert.True (v.GetCurrentHeight (out int cHeight));
+			Assert.Equal (20, cHeight);
+
+			v.Height = Dim.Fill (1);
+			Assert.True (v.GetCurrentHeight (out cHeight));
+			Assert.Equal (19, cHeight);
+
+			v.AutoSize = true;
+
+			Assert.True (v.GetCurrentHeight (out cHeight));
+			Assert.Equal (19, cHeight);
+		}
+
+		[Fact]
+		public void AutoSize_False_If_Text_Emmpty ()
+		{
+			var view1 = new View ();
+			var view2 = new View ("");
+			var view3 = new View () { Text = "" };
+
+			Assert.False (view1.AutoSize);
+			Assert.False (view2.AutoSize);
+			Assert.False (view3.AutoSize);
+		}
+
+		[Fact]
+		public void AutoSize_False_If_Text_Is_Not_Emmpty ()
+		{
+			var view1 = new View ();
+			view1.Text = "Hello World";
+			var view2 = new View ("Hello World");
+			var view3 = new View () { Text = "Hello World" };
+
+			Assert.False (view1.AutoSize);
+			Assert.False (view2.AutoSize);
+			Assert.False (view3.AutoSize);
+		}
+
+		[Fact]
+		public void AutoSize_True_Label_If_Text_Emmpty ()
+		{
+			var label1 = new Label ();
+			var label2 = new Label ("");
+			var label3 = new Label () { Text = "" };
+
+			Assert.True (label1.AutoSize);
+			Assert.True (label2.AutoSize);
+			Assert.True (label3.AutoSize);
+		}
+
+		[Fact]
+		public void AutoSize_True_Label_If_Text_Is_Not_Emmpty ()
+		{
+			var label1 = new Label ();
+			label1.Text = "Hello World";
+			var label2 = new Label ("Hello World");
+			var label3 = new Label () { Text = "Hello World" };
+
+			Assert.True (label1.AutoSize);
+			Assert.True (label2.AutoSize);
+			Assert.True (label3.AutoSize);
+		}
+
+		[Fact]
+		public void AutoSize_False_ResizeView_Is_Always_False ()
+		{
+			var label = new Label () { AutoSize = false };
+
+			label.Text = "New text";
+
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=0,Height=1}", label.Bounds.ToString ());
+		}
+
+		[Fact]
+		public void AutoSize_True_ResizeView_With_Dim_Absolute ()
+		{
+			var label = new Label ();
+
+			label.Text = "New text";
+
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=8,Height=1}", label.Bounds.ToString ());
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_False_ResizeView_With_Dim_Fill_After_IsInitialized ()
+		{
+			var win = new Window (new Rect (0, 0, 30, 80), "");
+			var label = new Label () { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill () };
+			win.Add (label);
+			Application.Top.Add (win);
+
+			// Text is empty so height=0
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=0,Height=0}", label.Bounds.ToString ());
+
+			label.Text = "New text\nNew line";
+			Application.Top.LayoutSubviews ();
+
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=78}", label.Bounds.ToString ());
+			Assert.False (label.IsInitialized);
+
+			Application.Begin (Application.Top);
+			Assert.True (label.IsInitialized);
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=78}", label.Bounds.ToString ());
+		}
+
+		[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 so height=0
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=0,Height=0}", label.Bounds.ToString ());
+
+			label.Text = "First line\nSecond line";
+			Application.Top.LayoutSubviews ();
+
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=2}", label.Bounds.ToString ());
+			Assert.False (label.IsInitialized);
+
+			Application.Begin (Application.Top);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=2}", label.Bounds.ToString ());
+			Assert.True (label.IsInitialized);
+
+			label.AutoSize = false;
+			Application.Refresh ();
+
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=1}", label.Bounds.ToString ());
+		}
+
+		[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 so height=0
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=0,Height=0}", label.Bounds.ToString ());
+
+			Application.Begin (Application.Top);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=0}", label.Bounds.ToString ());
+
+			label.Text = "First line\nSecond line";
+			Application.Refresh ();
+
+			// Here the AutoSize ensuring the right size
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=2}", label.Bounds.ToString ());
+
+			label.AutoSize = false;
+			Application.Refresh ();
+
+			// Here the SetMinWidthHeight ensuring the minimum height
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=1}", label.Bounds.ToString ());
+
+			label.Text = "First changed line\nSecond changed line\nNew line";
+			Application.Refresh ();
+
+			Assert.False (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=1}", label.Bounds.ToString ());
+
+			label.AutoSize = true;
+			Application.Refresh ();
+
+			Assert.True (label.AutoSize);
+			Assert.Equal ("{X=0,Y=0,Width=28,Height=3}", label.Bounds.ToString ());
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_True_Setting_With_Height_Horizontal ()
+		{
+			var label = new Label ("Hello") { Width = 10, Height = 2 };
+			var viewX = new View ("X") { X = Pos.Right (label) };
+			var viewY = new View ("Y") { Y = Pos.Bottom (label) };
+
+			Application.Top.Add (label, viewX, viewY);
+			Application.Begin (Application.Top);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 2), label.Frame);
+
+			var expected = @"
+Hello     X
+           
+Y          
+";
+
+			var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 11, 3), pos);
+
+			label.AutoSize = false;
+			Application.Refresh ();
+
+			Assert.False (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 2), label.Frame);
+
+			expected = @"
+Hello     X
+           
+Y          
+";
+
+			pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 11, 3), pos);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_True_Setting_With_Height_Vertical ()
+		{
+			var label = new Label ("Hello") { Width = 2, Height = 10, TextDirection = TextDirection.TopBottom_LeftRight };
+			var viewX = new View ("X") { X = Pos.Right (label) };
+			var viewY = new View ("Y") { Y = Pos.Bottom (label) };
+
+			Application.Top.Add (label, viewX, viewY);
+			Application.Begin (Application.Top);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 2, 10), label.Frame);
+
+			var expected = @"
+H X
+e  
+l  
+l  
+o  
+   
+   
+   
+   
+   
+Y  
+";
+
+			var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 3, 11), pos);
+
+			label.AutoSize = false;
+			Application.Refresh ();
+
+			Assert.False (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 2, 10), label.Frame);
+
+			expected = @"
+H X
+e  
+l  
+l  
+o  
+   
+   
+   
+   
+   
+Y  
+";
+
+			pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 3, 11), pos);
+		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void Excess_Text_Is_Erased_When_The_Width_Is_Reduced ()
+		{
+			var lbl = new Label ("123");
+			Application.Top.Add (lbl);
+			Application.Begin (Application.Top);
+
+			Assert.True (lbl.AutoSize);
+			Assert.Equal ("123 ", GetContents ());
+
+			lbl.Text = "12";
+
+			lbl.SuperView.Redraw (lbl.SuperView.NeedDisplay);
+
+			Assert.Equal ("12  ", GetContents ());
+
+			string GetContents ()
+			{
+				var text = "";
+				for (int i = 0; i < 4; i++) {
+					text += (char)Application.Driver.Contents [0, i, 0];
+				}
+				return text;
+			}
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Width_Height_SetMinWidthHeight_Narrow_Wide_Runes ()
+		{
+			var text = $"First line{Environment.NewLine}Second line";
+			var horizontalView = new View () {
+				Width = 20,
+				Text = text
+			};
+			var verticalView = new View () {
+				Y = 3,
+				Height = 20,
+				Text = text,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var win = new Window () {
+				Width = Dim.Fill (),
+				Height = Dim.Fill (),
+				Text = "Window"
+			};
+			win.Add (horizontalView, verticalView);
+			Application.Top.Add (win);
+			Application.Begin (Application.Top);
+			((FakeDriver)Application.Driver).SetBufferSize (32, 32);
+
+			Assert.False (horizontalView.AutoSize);
+			Assert.False (verticalView.AutoSize);
+			Assert.Equal (new Rect (0, 0, 20, 1), horizontalView.Frame);
+			Assert.Equal (new Rect (0, 3, 1, 20), verticalView.Frame);
+			var expected = @"
+┌──────────────────────────────┐
+│First line Second li          │
+│                              │
+│                              │
+│F                             │
+│i                             │
+│r                             │
+│s                             │
+│t                             │
+│                              │
+│l                             │
+│i                             │
+│n                             │
+│e                             │
+│                              │
+│S                             │
+│e                             │
+│c                             │
+│o                             │
+│n                             │
+│d                             │
+│                              │
+│l                             │
+│i                             │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+└──────────────────────────────┘
+";
+
+			var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 32, 32), pos);
+
+			verticalView.Text = $"最初の行{Environment.NewLine}二行目";
+			Application.Top.Redraw (Application.Top.Bounds);
+			Assert.Equal (new Rect (0, 3, 2, 20), verticalView.Frame);
+			expected = @"
+┌──────────────────────────────┐
+│First line Second li          │
+│                              │
+│                              │
+│最                            │
+│初                            │
+│の                            │
+│行                            │
+│                              │
+│二                            │
+│行                            │
+│目                            │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+│                              │
+└──────────────────────────────┘
+";
+
+			pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 32, 32), pos);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void TextDirection_Toggle ()
+		{
+			var view = new View ();
+			var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () };
+			win.Add (view);
+			Application.Top.Add (win);
+
+			Application.Begin (Application.Top);
+			((FakeDriver)Application.Driver).SetBufferSize (22, 22);
+
+			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;
+			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(0)", 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(0)", 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(0)", 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(11)", 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);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Width_Height_AutoSize_True_Stay_True_If_TextFormatter_Size_Fit ()
+		{
+			var text = $"Fi_nish 終";
+			var horizontalView = new View () {
+				AutoSize = true,
+				HotKeySpecifier = '_',
+				Text = text
+			};
+			var verticalView = new View () {
+				Y = 3,
+				AutoSize = true,
+				HotKeySpecifier = '_',
+				Text = text,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var win = new Window () {
+				Width = Dim.Fill (),
+				Height = Dim.Fill (),
+				Text = "Window"
+			};
+			win.Add (horizontalView, verticalView);
+			Application.Top.Add (win);
+			Application.Begin (Application.Top);
+			((FakeDriver)Application.Driver).SetBufferSize (22, 22);
+
+			Assert.True (horizontalView.AutoSize);
+			Assert.True (verticalView.AutoSize);
+			Assert.Equal (new Size (10, 1), horizontalView.TextFormatter.Size);
+			Assert.Equal (new Size (2, 9), verticalView.TextFormatter.Size);
+			Assert.Equal (new Rect (0, 0, 9, 1), horizontalView.Frame);
+			Assert.Equal ("Absolute(0)", horizontalView.X.ToString ());
+			Assert.Equal ("Absolute(0)", horizontalView.Y.ToString ());
+			Assert.Equal ("Absolute(9)", horizontalView.Width.ToString ());
+			Assert.Equal ("Absolute(1)", horizontalView.Height.ToString ());
+			Assert.Equal (new Rect (0, 3, 2, 8), verticalView.Frame);
+			Assert.Equal ("Absolute(0)", verticalView.X.ToString ());
+			Assert.Equal ("Absolute(3)", verticalView.Y.ToString ());
+			Assert.Equal ("Absolute(2)", verticalView.Width.ToString ());
+			Assert.Equal ("Absolute(8)", verticalView.Height.ToString ());
+			var expected = @"
+┌────────────────────┐
+│Finish 終           │
+│                    │
+│                    │
+│F                   │
+│i                   │
+│n                   │
+│i                   │
+│s                   │
+│h                   │
+│                    │
+│終                  │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+			var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 22, 22), pos);
+
+			verticalView.Text = $"最初_の行二行目";
+			Application.Top.Redraw (Application.Top.Bounds);
+			Assert.True (horizontalView.AutoSize);
+			Assert.True (verticalView.AutoSize);
+			// height was initialized with 8 and is kept as minimum
+			Assert.Equal (new Rect (0, 3, 2, 8), verticalView.Frame);
+			Assert.Equal ("Absolute(0)", verticalView.X.ToString ());
+			Assert.Equal ("Absolute(3)", verticalView.Y.ToString ());
+			Assert.Equal ("Absolute(2)", verticalView.Width.ToString ());
+			Assert.Equal ("Absolute(8)", verticalView.Height.ToString ());
+			expected = @"
+┌────────────────────┐
+│Finish 終           │
+│                    │
+│                    │
+│最                  │
+│初                  │
+│の                  │
+│行                  │
+│二                  │
+│行                  │
+│目                  │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+│                    │
+└────────────────────┘
+";
+
+			pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (0, 0, 22, 22), pos);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_Stays_True_Center_HotKeySpecifier ()
+		{
+			var btn = new Button () {
+				X = Pos.Center (),
+				Y = Pos.Center (),
+				Text = "Say He_llo 你"
+			};
+
+			var win = new Window () {
+				Width = Dim.Fill (),
+				Height = Dim.Fill (),
+				Title = "Test Demo 你"
+			};
+			win.Add (btn);
+			Application.Top.Add (win);
+
+			Assert.True (btn.AutoSize);
+
+			Application.Begin (Application.Top);
+			((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+			var expected = @"
+┌ Test Demo 你 ──────────────┐
+│                            │
+│      [ Say Hello 你 ]      │
+│                            │
+└────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+
+			Assert.True (btn.AutoSize);
+			btn.Text = "Say He_llo 你 changed";
+			Assert.True (btn.AutoSize);
+			Application.Refresh ();
+			expected = @"
+┌ Test Demo 你 ──────────────┐
+│                            │
+│  [ Say Hello 你 changed ]  │
+│                            │
+└────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_False_Equal_Before_And_After_IsInitialized_With_Differents_Orders ()
+		{
+			var view1 = new View () { Text = "Say Hello view1 你", AutoSize = false, Width = 10, Height = 5 };
+			var view2 = new View () { Text = "Say Hello view2 你", Width = 10, Height = 5, AutoSize = false };
+			var view3 = new View () { AutoSize = false, Width = 10, Height = 5, Text = "Say Hello view3 你" };
+			var view4 = new View () {
+				Text = "Say Hello view4 你",
+				AutoSize = false,
+				Width = 10,
+				Height = 5,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var view5 = new View () {
+				Text = "Say Hello view5 你",
+				Width = 10,
+				Height = 5,
+				AutoSize = false,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var view6 = new View () {
+				AutoSize = false,
+				Width = 10,
+				Height = 5,
+				TextDirection = TextDirection.TopBottom_LeftRight,
+				Text = "Say Hello view6 你",
+			};
+			Application.Top.Add (view1, view2, view3, view4, view5, view6);
+
+			Assert.False (view1.IsInitialized);
+			Assert.False (view2.IsInitialized);
+			Assert.False (view3.IsInitialized);
+			Assert.False (view4.IsInitialized);
+			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.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.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.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.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.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 ());
+
+			Application.Begin (Application.Top);
+
+			Assert.True (view1.IsInitialized);
+			Assert.True (view2.IsInitialized);
+			Assert.True (view3.IsInitialized);
+			Assert.True (view4.IsInitialized);
+			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.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.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.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.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.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 ());
+		}
+
+		[Fact, AutoInitShutdown]
+		public void AutoSize_True_Equal_Before_And_After_IsInitialized_With_Differents_Orders ()
+		{
+			var view1 = new View () { Text = "Say Hello view1 你", AutoSize = true, Width = 10, Height = 5 };
+			var view2 = new View () { Text = "Say Hello view2 你", Width = 10, Height = 5, AutoSize = true };
+			var view3 = new View () { AutoSize = true, Width = 10, Height = 5, Text = "Say Hello view3 你" };
+			var view4 = new View () {
+				Text = "Say Hello view4 你",
+				AutoSize = true,
+				Width = 10,
+				Height = 5,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var view5 = new View () {
+				Text = "Say Hello view5 你",
+				Width = 10,
+				Height = 5,
+				AutoSize = true,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			var view6 = new View () {
+				AutoSize = true,
+				Width = 10,
+				Height = 5,
+				TextDirection = TextDirection.TopBottom_LeftRight,
+				Text = "Say Hello view6 你",
+			};
+			Application.Top.Add (view1, view2, view3, view4, view5, view6);
+
+			Assert.False (view1.IsInitialized);
+			Assert.False (view2.IsInitialized);
+			Assert.False (view3.IsInitialized);
+			Assert.False (view4.IsInitialized);
+			Assert.False (view5.IsInitialized);
+			Assert.True (view1.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view1.Frame);
+			Assert.Equal ("Absolute(10)", view1.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view1.Height.ToString ());
+			Assert.True (view2.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view2.Frame);
+			Assert.Equal ("Absolute(10)", view2.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view2.Height.ToString ());
+			Assert.True (view3.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view3.Frame);
+			Assert.Equal ("Absolute(10)", view3.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view3.Height.ToString ());
+			Assert.True (view4.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view4.Frame);
+			Assert.Equal ("Absolute(10)", view4.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view4.Height.ToString ());
+			Assert.True (view5.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view5.Frame);
+			Assert.Equal ("Absolute(10)", view5.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view5.Height.ToString ());
+			Assert.True (view6.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view6.Frame);
+			Assert.Equal ("Absolute(10)", view6.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view6.Height.ToString ());
+
+			Application.Begin (Application.Top);
+
+			Assert.True (view1.IsInitialized);
+			Assert.True (view2.IsInitialized);
+			Assert.True (view3.IsInitialized);
+			Assert.True (view4.IsInitialized);
+			Assert.True (view5.IsInitialized);
+			Assert.True (view1.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view1.Frame);
+			Assert.Equal ("Absolute(10)", view1.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view1.Height.ToString ());
+			Assert.True (view2.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view2.Frame);
+			Assert.Equal ("Absolute(10)", view2.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view2.Height.ToString ());
+			Assert.True (view3.AutoSize);
+			Assert.Equal (new Rect (0, 0, 18, 5), view3.Frame);
+			Assert.Equal ("Absolute(10)", view3.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view3.Height.ToString ());
+			Assert.True (view4.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view4.Frame);
+			Assert.Equal ("Absolute(10)", view4.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view4.Height.ToString ());
+			Assert.True (view5.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view5.Frame);
+			Assert.Equal ("Absolute(10)", view5.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view5.Height.ToString ());
+			Assert.True (view6.AutoSize);
+			Assert.Equal (new Rect (0, 0, 10, 17), view6.Frame);
+			Assert.Equal ("Absolute(10)", view6.Width.ToString ());
+			Assert.Equal ("Absolute(5)", view6.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)) {
+				Text = "Say Hello view2 你",
+				AutoSize = true,
+				TextDirection = TextDirection.TopBottom_LeftRight
+			};
+			Application.Top.Add (view1, view2);
+
+			var rs = Application.Begin (Application.Top);
+
+			Assert.True (view1.AutoSize);
+			Assert.Equal (LayoutStyle.Absolute, view1.LayoutStyle);
+			Assert.Equal (new Rect (0, 0, 18, 1), view1.Frame);
+			Assert.Equal ("Absolute(0)", view1.X.ToString ());
+			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.Equal (LayoutStyle.Absolute, view2.LayoutStyle);
+			Assert.Equal (new Rect (0, 0, 2, 17), view2.Frame);
+			Assert.Equal ("Absolute(0)", view2.X.ToString ());
+			Assert.Equal ("Absolute(0)", view2.Y.ToString ());
+			Assert.Equal ("Absolute(2)", view2.Width.ToString ());
+			Assert.Equal ("Absolute(17)", view2.Height.ToString ());
+
+			view1.Frame = new Rect (0, 0, 25, 4);
+			bool firstIteration = false;
+			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
+
+			Assert.True (view1.AutoSize);
+			Assert.Equal (LayoutStyle.Absolute, view1.LayoutStyle);
+			Assert.Equal (new Rect (0, 0, 25, 4), view1.Frame);
+			Assert.Equal ("Absolute(0)", view1.X.ToString ());
+			Assert.Equal ("Absolute(0)", view1.Y.ToString ());
+			Assert.Equal ("Absolute(18)", view1.Width.ToString ());
+			Assert.Equal ("Absolute(1)", view1.Height.ToString ());
+
+			view2.Frame = new Rect (0, 0, 1, 25);
+			Application.RunMainLoopIteration (ref rs, true, 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.Equal ("Absolute(2)", view2.Width.ToString ());
+			Assert.Equal ("Absolute(17)", view2.Height.ToString ());
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Pos_Dim_Are_Null_If_Not_Initialized_On_Constructor_IsAdded_False ()
+		{
+			var top = Application.Top;
+			var view1 = new View ();
+			Assert.False (view1.IsAdded);
+			Assert.Null (view1.X);
+			Assert.Null (view1.Y);
+			Assert.Null (view1.Width);
+			Assert.Null (view1.Height);
+			top.Add (view1);
+			Assert.True (view1.IsAdded);
+			Assert.Equal ("Absolute(0)", view1.X.ToString ());
+			Assert.Equal ("Absolute(0)", view1.Y.ToString ());
+			Assert.Equal ("Absolute(0)", view1.Width.ToString ());
+			Assert.Equal ("Absolute(0)", view1.Height.ToString ());
+
+			var view2 = new View () {
+				X = Pos.Center (),
+				Y = Pos.Center (),
+				Width = Dim.Fill (),
+				Height = Dim.Fill ()
+			};
+			Assert.False (view2.IsAdded);
+			Assert.Equal ("Center", view2.X.ToString ());
+			Assert.Equal ("Center", view2.Y.ToString ());
+			Assert.Equal ("Fill(0)", view2.Width.ToString ());
+			Assert.Equal ("Fill(0)", view2.Height.ToString ());
+			top.Add (view2);
+			Assert.True (view2.IsAdded);
+			Assert.Equal ("Center", view2.X.ToString ());
+			Assert.Equal ("Center", view2.Y.ToString ());
+			Assert.Equal ("Fill(0)", view2.Width.ToString ());
+			Assert.Equal ("Fill(0)", view2.Height.ToString ());
+		}
+
+		[Fact]
+		public void SetRelativeLayout_PosCombine_Center_Plus_Absolute ()
+		{
+			var superView = new View () {
+				AutoSize = false,
+				Width = 10,
+				Height = 10
+			};
+
+			var testView = new View () {
+				AutoSize = false,
+				X = Pos.Center (),
+				Y = Pos.Center (),
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (4, testView.Frame.X);
+			Assert.Equal (4, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = Pos.Center () + 1,
+				Y = Pos.Center () + 1,
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (5, testView.Frame.X);
+			Assert.Equal (5, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = 1 + Pos.Center (),
+				Y = 1 + Pos.Center (),
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (5, testView.Frame.X);
+			Assert.Equal (5, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = 1 + Pos.Percent (50),
+				Y = Pos.Percent (50) + 1,
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (6, testView.Frame.X);
+			Assert.Equal (6, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = Pos.Percent (10) + Pos.Percent (40),
+				Y = Pos.Percent (10) + Pos.Percent (40),
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (5, testView.Frame.X);
+			Assert.Equal (5, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = 1 + Pos.Percent (10) + Pos.Percent (40) - 1,
+				Y = 5 + Pos.Percent (10) + Pos.Percent (40) - 5,
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (5, testView.Frame.X);
+			Assert.Equal (5, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = Pos.Left(testView),
+				Y = Pos.Left (testView),
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (5, testView.Frame.X);
+			Assert.Equal (5, testView.Frame.Y);
+
+			testView = new View () {
+				AutoSize = false,
+				X = 1 + Pos.Left (testView),
+				Y = Pos.Top (testView) + 1,
+				Width = 1,
+				Height = 1
+			};
+			superView.Add (testView);
+			testView.SetRelativeLayout (superView.Frame);
+			Assert.Equal (6, testView.Frame.X);
+			Assert.Equal (6, testView.Frame.Y);
+		}
+	}
+}

文件差異過大導致無法顯示
+ 123 - 1146
UnitTests/Core/ViewTests.cs


+ 127 - 127
UnitTests/Drivers/ClipboardTests.cs

@@ -141,133 +141,133 @@ else 				Assert.NotEqual (clipText, Clipboard.Contents);
 		}
 
 
-		//[Fact, AutoInitShutdown (useFakeClipboard: false)]
-		//public void Contents_Copies_From_OS_Clipboard ()
-		//{
-		//	if (!Clipboard.IsSupported) {
-		//		output.WriteLine ($"The Clipboard not supported on this platform.");
-		//		return;
-		//	}
-
-		//	var clipText = "The Contents_Copies_From_OS_Clipboard unit test pasted this to the OS clipboard.";
-		//	var failed = false;
-		//	var getClipText = "";
-
-		//	Application.Iteration += () => {
-		//		int exitCode = 0;
-		//		string result = "";
-		//		output.WriteLine ($"Pasting to OS clipboard: {clipText}...");
-
-		//		if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
-		//			(exitCode, result) = ClipboardProcessRunner.Process ("pwsh", $"-command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
-		//			output.WriteLine ($"  Windows: pwsh Set-Clipboard: exitCode = {exitCode}, result = {result}");
-		//			getClipText = Clipboard.Contents.ToString ();
-
-		//		} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
-		//			(exitCode, result) = ClipboardProcessRunner.Process ("pbcopy", string.Empty, clipText);
-		//			output.WriteLine ($"  OSX: pbcopy: exitCode = {exitCode}, result = {result}");
-		//			getClipText = Clipboard.Contents.ToString ();
-
-		//		} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
-		//			if (Is_WSL_Platform ()) {
-		//				try {
-		//					// This runs the WINDOWS version of powershell.exe via WSL.
-		//					(exitCode, result) = ClipboardProcessRunner.Process ("powershell.exe", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
-		//					output.WriteLine ($"  WSL: powershell.exe Set-Clipboard: exitCode = {exitCode}, result = {result}");
-		//				} catch {
-		//					failed = true;
-		//				}
-
-		//				if (!failed) {
-		//					// If we set the OS clipboard via Powershell, then getting Contents should return the same text.
-		//					getClipText = Clipboard.Contents.ToString ();
-		//					output.WriteLine ($"  WSL: Clipboard.Contents: {getClipText}");
-		//				}
-		//				Application.RequestStop ();
-		//				return;
-		//			}
-
-		//			if (failed = xclipExists () == false) {
-		//				// if xclip doesn't exist then exit.
-		//				output.WriteLine ($"  WSL: no xclip found.");
-		//				Application.RequestStop ();
-		//				return;
-		//			}
-
-		//			// If we get here, powershell didn't work and xclip exists...
-		//			(exitCode, result) = ClipboardProcessRunner.Process ("bash", $"-c \"xclip -sel clip -i\"", clipText);
-		//			output.WriteLine ($"  Linux: bash xclip -sel clip -i: exitCode = {exitCode}, result = {result}");
-
-		//			if (!failed) {
-		//				getClipText = Clipboard.Contents.ToString ();
-		//				output.WriteLine ($"  Linux via xclip: Clipboard.Contents: {getClipText}");
-		//			}
-		//		}
-
-		//		Application.RequestStop ();
-		//	};
-
-		//	Application.Run ();
-
-		//	if (!failed) 				Assert.Equal (clipText, getClipText);
-		//}
-
-		//[Fact, AutoInitShutdown (useFakeClipboard: false)]
-		//public void Contents_Pastes_To_OS_Clipboard ()
-		//{
-		//	if (!Clipboard.IsSupported) {
-		//		output.WriteLine ($"The Clipboard not supported on this platform.");
-		//		return;
-		//	}
-
-		//	var clipText = "The Contents_Pastes_To_OS_Clipboard unit test pasted this via Clipboard.Contents.";
-		//	var clipReadText = "";
-		//	var failed = false;
-
-		//	Application.Iteration += () => {
-		//		Clipboard.Contents = clipText;
-
-		//		int exitCode = 0;
-		//		output.WriteLine ($"Getting OS clipboard...");
-
-		//		if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
-		//			(exitCode, clipReadText) = ClipboardProcessRunner.Process ("pwsh", "-noprofile -command \"Get-Clipboard\"");
-		//			output.WriteLine ($"  Windows: pwsh Get-Clipboard: exitCode = {exitCode}, result = {clipReadText}");
-
-		//		} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
-		//			(exitCode, clipReadText) = ClipboardProcessRunner.Process ("pbpaste", "");
-		//			output.WriteLine ($"  OSX: pbpaste: exitCode = {exitCode}, result = {clipReadText}");
-
-		//		} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
-		//			if (Is_WSL_Platform ()) {
-		//				(exitCode, clipReadText) = ClipboardProcessRunner.Process ("powershell.exe", "-noprofile -command \"Get-Clipboard\"");
-		//				output.WriteLine ($"  WSL: powershell.exe Get-Clipboard: exitCode = {exitCode}, result = {clipReadText}");
-		//				if (exitCode == 0) {
-		//					Application.RequestStop ();
-		//					return;
-		//				}
-		//				failed = true;
-		//			}
-
-		//			if (failed = xclipExists () == false) {
-		//				// xclip doesn't exist then exit.
-		//				Application.RequestStop ();
-		//				return;
-		//			}
-
-		//			(exitCode, clipReadText) = ClipboardProcessRunner.Process ("bash", $"-c \"xclip -sel clip -o\"");
-		//			output.WriteLine ($"  Linux: bash xclip -sel clip -o: exitCode = {exitCode}, result = {clipReadText}");
-		//			Assert.Equal (0, exitCode);
-		//		}
-
-		//		Application.RequestStop ();
-		//	};
-
-		//	Application.Run ();
-
-		//	if (!failed) 				Assert.Equal (clipText, clipReadText.TrimEnd ());
-
-		//}
+		[Fact, AutoInitShutdown (useFakeClipboard: false)]
+		public void Contents_Copies_From_OS_Clipboard ()
+		{
+			if (!Clipboard.IsSupported) {
+				output.WriteLine ($"The Clipboard not supported on this platform.");
+				return;
+			}
+
+			var clipText = "The Contents_Copies_From_OS_Clipboard unit test pasted this to the OS clipboard.";
+			var failed = false;
+			var getClipText = "";
+
+			Application.Iteration += () => {
+				int exitCode = 0;
+				string result = "";
+				output.WriteLine ($"Pasting to OS clipboard: {clipText}...");
+
+				if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
+					(exitCode, result) = ClipboardProcessRunner.Process ("powershell.exe", $"-command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
+					output.WriteLine ($"  Windows: powershell.exe Set-Clipboard: exitCode = {exitCode}, result = {result}");
+					getClipText = Clipboard.Contents.ToString ();
+
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
+					(exitCode, result) = ClipboardProcessRunner.Process ("pbcopy", string.Empty, clipText);
+					output.WriteLine ($"  OSX: pbcopy: exitCode = {exitCode}, result = {result}");
+					getClipText = Clipboard.Contents.ToString ();
+
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
+					if (Is_WSL_Platform ()) {
+						try {
+							// This runs the WINDOWS version of powershell.exe via WSL.
+							(exitCode, result) = ClipboardProcessRunner.Process ("powershell.exe", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
+							output.WriteLine ($"  WSL: powershell.exe Set-Clipboard: exitCode = {exitCode}, result = {result}");
+						} catch {
+							failed = true;
+						}
+
+						if (!failed) {
+							// If we set the OS clipboard via Powershell, then getting Contents should return the same text.
+							getClipText = Clipboard.Contents.ToString ();
+							output.WriteLine ($"  WSL: Clipboard.Contents: {getClipText}");
+						}
+						Application.RequestStop ();
+						return;
+					}
+
+					if (failed = xclipExists () == false) {
+						// if xclip doesn't exist then exit.
+						output.WriteLine ($"  WSL: no xclip found.");
+						Application.RequestStop ();
+						return;
+					}
+
+					// If we get here, powershell didn't work and xclip exists...
+					(exitCode, result) = ClipboardProcessRunner.Process ("bash", $"-c \"xclip -sel clip -i\"", clipText);
+					output.WriteLine ($"  Linux: bash xclip -sel clip -i: exitCode = {exitCode}, result = {result}");
+
+					if (!failed) {
+						getClipText = Clipboard.Contents.ToString ();
+						output.WriteLine ($"  Linux via xclip: Clipboard.Contents: {getClipText}");
+					}
+				}
+
+				Application.RequestStop ();
+			};
+
+			Application.Run ();
+
+			if (!failed) 				Assert.Equal (clipText, getClipText);
+		}
+
+		[Fact, AutoInitShutdown (useFakeClipboard: false)]
+		public void Contents_Pastes_To_OS_Clipboard ()
+		{
+			if (!Clipboard.IsSupported) {
+				output.WriteLine ($"The Clipboard not supported on this platform.");
+				return;
+			}
+
+			var clipText = "The Contents_Pastes_To_OS_Clipboard unit test pasted this via Clipboard.Contents.";
+			var clipReadText = "";
+			var failed = false;
+
+			Application.Iteration += () => {
+				Clipboard.Contents = clipText;
+
+				int exitCode = 0;
+				output.WriteLine ($"Getting OS clipboard...");
+
+				if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
+					(exitCode, clipReadText) = ClipboardProcessRunner.Process ("powershell.exe", "-noprofile -command \"Get-Clipboard\"");
+					output.WriteLine ($"  Windows: powershell.exe Get-Clipboard: exitCode = {exitCode}, result = {clipReadText}");
+
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
+					(exitCode, clipReadText) = ClipboardProcessRunner.Process ("pbpaste", "");
+					output.WriteLine ($"  OSX: pbpaste: exitCode = {exitCode}, result = {clipReadText}");
+
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
+					if (Is_WSL_Platform ()) {
+						(exitCode, clipReadText) = ClipboardProcessRunner.Process ("powershell.exe", "-noprofile -command \"Get-Clipboard\"");
+						output.WriteLine ($"  WSL: powershell.exe Get-Clipboard: exitCode = {exitCode}, result = {clipReadText}");
+						if (exitCode == 0) {
+							Application.RequestStop ();
+							return;
+						}
+						failed = true;
+					}
+
+					if (failed = xclipExists () == false) {
+						// xclip doesn't exist then exit.
+						Application.RequestStop ();
+						return;
+					}
+
+					(exitCode, clipReadText) = ClipboardProcessRunner.Process ("bash", $"-c \"xclip -sel clip -o\"");
+					output.WriteLine ($"  Linux: bash xclip -sel clip -o: exitCode = {exitCode}, result = {clipReadText}");
+					Assert.Equal (0, exitCode);
+				}
+
+				Application.RequestStop ();
+			};
+
+			Application.Run ();
+
+			if (!failed) 				Assert.Equal (clipText, clipReadText.TrimEnd ());
+
+		}
 
 		bool Is_WSL_Platform ()
 		{

+ 2 - 2
UnitTests/TopLevels/ToplevelTests.cs

@@ -19,8 +19,8 @@ namespace Terminal.Gui.TopLevelTests {
 			var top = new Toplevel ();
 
 			Assert.Equal (Colors.TopLevel, top.ColorScheme);
-			Assert.Equal ("Dim.Fill(margin=0)", top.Width.ToString ());
-			Assert.Equal ("Dim.Fill(margin=0)", top.Height.ToString ());
+			Assert.Equal ("Fill(0)", top.Width.ToString ());
+			Assert.Equal ("Fill(0)", top.Height.ToString ());
 			Assert.False (top.Running);
 			Assert.False (top.Modal);
 			Assert.Null (top.MenuBar);

+ 74 - 75
UnitTests/Types/DimTests.cs

@@ -37,15 +37,15 @@ namespace Terminal.Gui.TypeTests {
 		public void Sized_SetsValue ()
 		{
 			var dim = Dim.Sized (0);
-			Assert.Equal ("Dim.Absolute(0)", dim.ToString ());
+			Assert.Equal ("Absolute(0)", dim.ToString ());
 
 			int testVal = 5;
 			dim = Dim.Sized (testVal);
-			Assert.Equal ($"Dim.Absolute({testVal})", dim.ToString ());
+			Assert.Equal ($"Absolute({testVal})", dim.ToString ());
 
 			testVal = -1;
 			dim = Dim.Sized (testVal);
-			Assert.Equal ($"Dim.Absolute({testVal})", dim.ToString ());
+			Assert.Equal ($"Absolute({testVal})", dim.ToString ());
 		}
 
 		[Fact]
@@ -83,11 +83,11 @@ namespace Terminal.Gui.TypeTests {
 			var testVal = Rect.Empty;
 			testVal = Rect.Empty;
 			dim = Dim.Width (new View (testVal));
-			Assert.Equal ($"DimView(side=Width, target=View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
+			Assert.Equal ($"DimView(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
 
 			testVal = new Rect (1, 2, 3, 4);
 			dim = Dim.Width (new View (testVal));
-			Assert.Equal ($"DimView(side=Width, target=View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
+			Assert.Equal ($"DimView(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
 		}
 
 		[Fact]
@@ -141,11 +141,11 @@ namespace Terminal.Gui.TypeTests {
 			var testVal = Rect.Empty;
 			testVal = Rect.Empty;
 			dim = Dim.Height (new View (testVal));
-			Assert.Equal ($"DimView(side=Height, target=View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
+			Assert.Equal ($"DimView(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
 
 			testVal = new Rect (1, 2, 3, 4);
 			dim = Dim.Height (new View (testVal));
-			Assert.Equal ($"DimView(side=Height, target=View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
+			Assert.Equal ($"DimView(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ());
 		}
 
 		// TODO: Other Dim.Height tests (e.g. Equal?)
@@ -155,15 +155,15 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var testMargin = 0;
 			var dim = Dim.Fill ();
-			Assert.Equal ($"Dim.Fill(margin={testMargin})", dim.ToString ());
+			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
 
 			testMargin = 0;
 			dim = Dim.Fill (testMargin);
-			Assert.Equal ($"Dim.Fill(margin={testMargin})", dim.ToString ());
+			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
 
 			testMargin = 5;
 			dim = Dim.Fill (testMargin);
-			Assert.Equal ($"Dim.Fill(margin={testMargin})", dim.ToString ());
+			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
 		}
 
 
@@ -182,13 +182,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			float f = 0;
 			var dim = Dim.Percent (f);
-			Assert.Equal ($"Dim.Factor(factor={f / 100:0.###}, remaining={false})", dim.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
 			f = 0.5F;
 			dim = Dim.Percent (f);
-			Assert.Equal ($"Dim.Factor(factor={f / 100:0.###}, remaining={false})", dim.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
 			f = 100;
 			dim = Dim.Percent (f);
-			Assert.Equal ($"Dim.Factor(factor={f / 100:0.###}, remaining={false})", dim.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
 		}
 
 		[Fact]
@@ -420,112 +420,111 @@ namespace Terminal.Gui.TypeTests {
 			t.Add (w);
 
 			t.Ready += () => {
-				Assert.Equal ("Dim.Absolute(100)", w.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(100)", w.Height.ToString ());
+				Assert.Equal ("Absolute(100)", w.Width.ToString ());
+				Assert.Equal ("Absolute(100)", w.Height.ToString ());
 				Assert.Equal (100, w.Frame.Width);
 				Assert.Equal (100, w.Frame.Height);
 
-				Assert.Equal ("Dim.Factor(factor=0.5, remaining=False)", f1.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(5)", f1.Height.ToString ());
+				Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
+				Assert.Equal ("Absolute(5)", f1.Height.ToString ());
 				Assert.Equal (49, f1.Frame.Width); // 50-1=49
 				Assert.Equal (5, f1.Frame.Height);
 
-				Assert.Equal ("Dim.Fill(margin=0)", f2.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(5)", f2.Height.ToString ());
+				Assert.Equal ("Fill(0)", f2.Width.ToString ());
+				Assert.Equal ("Absolute(5)", f2.Height.ToString ());
 				Assert.Equal (49, f2.Frame.Width); // 50-1=49
 				Assert.Equal (5, f2.Frame.Height);
-
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=FrameView()({X=0,Y=0,Width=49,Height=5}))-Dim.Absolute(2))", v1.Width.ToString ());
-				Assert.Equal ("Dim.Combine(Dim.Fill(margin=0)-Dim.Absolute(2))", v1.Height.ToString ());
+	
+				Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.ToString ());
+				Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
 				Assert.Equal (47, v1.Frame.Width); // 49-2=47
 				Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89
 
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=FrameView()({X=49,Y=0,Width=49,Height=5}))-Dim.Absolute(2))", v2.Width.ToString ());
-				Assert.Equal ("Dim.Combine(Dim.Fill(margin=0)-Dim.Absolute(2))", v2.Height.ToString ());
+				Assert.Equal ("Combine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.ToString ());
+				Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
 				Assert.Equal (47, v2.Frame.Width); // 49-2=47
 				Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89
 
-				Assert.Equal ("Dim.Factor(factor=0.1, remaining=False)", v3.Width.ToString ());
-				Assert.Equal ("Dim.Factor(factor=0.1, remaining=False)", v3.Height.ToString ());
+				Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ());
+				Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
 				Assert.Equal (9, v3.Frame.Width); // 98*10%=9
 				Assert.Equal (9, v3.Frame.Height); // 98*10%=9
 
-				Assert.Equal ("Dim.Absolute(50)", v4.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(50)", v4.Height.ToString ());
+				Assert.Equal ("Absolute(50)", v4.Width.ToString ());
+				Assert.Equal ("Absolute(50)", v4.Height.ToString ());
 				Assert.Equal (50, v4.Frame.Width);
 				Assert.Equal (50, v4.Frame.Height);
 
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=Button()({X=2,Y=7,Width=47,Height=89}))-DimView(side=Width, target=Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ());
-				Assert.Equal ("Dim.Combine(DimView(side=Height, target=Button()({X=2,Y=7,Width=47,Height=89}))-DimView(side=Height, target=Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ());
+				Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ());
+				Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ());
 				Assert.Equal (38, v5.Frame.Width); // 47-9=38
 				Assert.Equal (80, v5.Frame.Height); // 89-9=80
 
-				Assert.Equal ("Dim.Factor(factor=0.2, remaining=True)", v6.Width.ToString ());
-				Assert.Equal ("Dim.Factor(factor=0.2, remaining=True)", v6.Height.ToString ());
+				Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ());
+				Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
 				Assert.Equal (9, v6.Frame.Width); // 47*20%=9
 				Assert.Equal (18, v6.Frame.Height); // 89*20%=18
 
-
 				w.Width = 200;
 				w.Height = 200;
 				t.LayoutSubviews ();
 
-				Assert.Equal ("Dim.Absolute(200)", w.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(200)", w.Height.ToString ());
+				Assert.Equal ("Absolute(200)", w.Width.ToString ());
+				Assert.Equal ("Absolute(200)", w.Height.ToString ());
 				Assert.Equal (200, w.Frame.Width);
 				Assert.Equal (200, w.Frame.Height);
 
 				f1.Text = "Frame1";
-				Assert.Equal ("Dim.Factor(factor=0.5, remaining=False)", f1.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(5)", f1.Height.ToString ());
+				Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
+				Assert.Equal ("Absolute(5)", f1.Height.ToString ());
 				Assert.Equal (99, f1.Frame.Width); // 100-1=99
 				Assert.Equal (5, f1.Frame.Height);
 
 				f2.Text = "Frame2";
-				Assert.Equal ("Dim.Fill(margin=0)", f2.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(5)", f2.Height.ToString ());
+				Assert.Equal ("Fill(0)", f2.Width.ToString ());
+				Assert.Equal ("Absolute(5)", f2.Height.ToString ());
 				Assert.Equal (99, f2.Frame.Width); // 100-1=99
 				Assert.Equal (5, f2.Frame.Height);
 
 				v1.Text = "Button1";
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=FrameView()({X=0,Y=0,Width=99,Height=5}))-Dim.Absolute(2))", v1.Width.ToString ());
-				Assert.Equal ("Dim.Combine(Dim.Fill(margin=0)-Dim.Absolute(2))", v1.Height.ToString ());
+				Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=99,Height=5}))-Absolute(2))", v1.Width.ToString ());
+				Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
 				Assert.Equal (97, v1.Frame.Width); // 99-2=97
 				Assert.Equal (189, v1.Frame.Height); // 198-2-7=189
 
 				v2.Text = "Button2";
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=FrameView()({X=99,Y=0,Width=99,Height=5}))-Dim.Absolute(2))", v2.Width.ToString ());
-				Assert.Equal ("Dim.Combine(Dim.Fill(margin=0)-Dim.Absolute(2))", v2.Height.ToString ());
+				Assert.Equal ("Combine(DimView(Width,FrameView()({X=99,Y=0,Width=99,Height=5}))-Absolute(2))", v2.Width.ToString ());
+				Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
 				Assert.Equal (97, v2.Frame.Width); // 99-2=97
 				Assert.Equal (189, v2.Frame.Height); // 198-2-7=189
 
 				v3.Text = "Button3";
-				Assert.Equal ("Dim.Factor(factor=0.1, remaining=False)", v3.Width.ToString ());
-				Assert.Equal ("Dim.Factor(factor=0.1, remaining=False)", v3.Height.ToString ());
+				Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ());
+				Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
 				Assert.Equal (19, v3.Frame.Width); // 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width
 				Assert.Equal (19, v3.Frame.Height); // 199*10%=19
 
 				v4.Text = "Button4";
 				v4.AutoSize = false;
-				Assert.Equal ("Dim.Absolute(50)", v4.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(50)", v4.Height.ToString ());
+				Assert.Equal ("Absolute(50)", v4.Width.ToString ());
+				Assert.Equal ("Absolute(50)", v4.Height.ToString ());
 				Assert.Equal (50, v4.Frame.Width);
 				Assert.Equal (50, v4.Frame.Height);
 				v4.AutoSize = true;
-				Assert.Equal ("Dim.Absolute(11)", v4.Width.ToString ());
-				Assert.Equal ("Dim.Absolute(1)", v4.Height.ToString ());
+				Assert.Equal ("Absolute(11)", v4.Width.ToString ());
+				Assert.Equal ("Absolute(1)", v4.Height.ToString ());
 				Assert.Equal (11, v4.Frame.Width); // 11 is the text length and because is Dim.DimAbsolute
 				Assert.Equal (1, v4.Frame.Height); // 1 because is Dim.DimAbsolute
 
 				v5.Text = "Button5";
-				Assert.Equal ("Dim.Combine(DimView(side=Width, target=Button()({X=2,Y=7,Width=97,Height=189}))-DimView(side=Width, target=Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ());
-				Assert.Equal ("Dim.Combine(DimView(side=Height, target=Button()({X=2,Y=7,Width=97,Height=189}))-DimView(side=Height, target=Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ());
+				Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ());
+				Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ());
 				Assert.Equal (78, v5.Frame.Width); // 97-19=78
 				Assert.Equal (170, v5.Frame.Height); // 189-19=170
 
 				v6.Text = "Button6";
-				Assert.Equal ("Dim.Factor(factor=0.2, remaining=True)", v6.Width.ToString ());
-				Assert.Equal ("Dim.Factor(factor=0.2, remaining=True)", v6.Height.ToString ());
+				Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ());
+				Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
 				Assert.Equal (19, v6.Frame.Width); // 99*20%=19
 				Assert.Equal (38, v6.Frame.Height); // 198-7*20=38
 			};
@@ -635,12 +634,12 @@ namespace Terminal.Gui.TypeTests {
 					var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 };
 					view.Add (label);
 					Assert.Equal ($"Label {count}", label.Text);
-					Assert.Equal ($"Pos.Absolute({count})", label.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", label.Y.ToString ());
 
-					Assert.Equal ($"Dim.Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
 					view.Height += 1;
 					count++;
-					Assert.Equal ($"Dim.Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
 				}
 			};
 
@@ -1007,18 +1006,18 @@ namespace Terminal.Gui.TypeTests {
 						var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 10 };
 						view.Add (label);
 						Assert.Equal ($"Label {count}", label.Text);
-						Assert.Equal ($"Pos.Absolute({count + 1})", label.Y.ToString ());
+						Assert.Equal ($"Absolute({count + 1})", label.Y.ToString ());
 						listLabels.Add (label);
 						if (count == 0) {
-							Assert.Equal ($"Dim.Absolute({count})", view.Height.ToString ());
+							Assert.Equal ($"Absolute({count})", view.Height.ToString ());
 							view.Height += 2;
 						} else {
-							Assert.Equal ($"Dim.Absolute({count + 1})", view.Height.ToString ());
+							Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
 							view.Height += 1;
 						}
 						count++;
 					}
-					Assert.Equal ($"Dim.Absolute({count + 1})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
 				}
 			};
 
@@ -1067,12 +1066,12 @@ namespace Terminal.Gui.TypeTests {
 				var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 };
 				view.Add (label);
 				Assert.Equal ($"Label {i}", label.Text);
-				Assert.Equal ($"Pos.Absolute({i})", label.Y.ToString ());
+				Assert.Equal ($"Absolute({i})", label.Y.ToString ());
 				listLabels.Add (label);
 
-				Assert.Equal ($"Dim.Absolute({i})", view.Height.ToString ());
+				Assert.Equal ($"Absolute({i})", view.Height.ToString ());
 				view.Height += 1;
-				Assert.Equal ($"Dim.Absolute({i + 1})", view.Height.ToString ());
+				Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
 			}
 
 			field.KeyDown += (k) => {
@@ -1080,10 +1079,10 @@ namespace Terminal.Gui.TypeTests {
 					Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
 					view.Remove (listLabels [count - 1]);
 
-					Assert.Equal ($"Dim.Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
 					view.Height -= 1;
 					count--;
-					Assert.Equal ($"Dim.Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
 				}
 			};
 
@@ -1126,17 +1125,17 @@ namespace Terminal.Gui.TypeTests {
 				var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 10 };
 				view.Add (label);
 				Assert.Equal ($"Label {i}", label.Text);
-				Assert.Equal ($"Pos.Absolute({i + 1})", label.Y.ToString ());
+				Assert.Equal ($"Absolute({i + 1})", label.Y.ToString ());
 				listLabels.Add (label);
 
 				if (i == 0) {
-					Assert.Equal ($"Dim.Absolute({i})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({i})", view.Height.ToString ());
 					view.Height += 2;
-					Assert.Equal ($"Dim.Absolute({i + 2})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
 				} else {
-					Assert.Equal ($"Dim.Absolute({i + 1})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
 					view.Height += 1;
-					Assert.Equal ($"Dim.Absolute({i + 2})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
 				}
 			}
 
@@ -1150,7 +1149,7 @@ namespace Terminal.Gui.TypeTests {
 						Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
 						view.Remove (listLabels [count - 1]);
 						listLabels.RemoveAt (count - 1);
-						Assert.Equal ($"Dim.Absolute({count + 1})", view.Height.ToString ());
+						Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
 						view.Height -= 1;
 						count--;
 						if (listLabels.Count > 0)
@@ -1158,7 +1157,7 @@ namespace Terminal.Gui.TypeTests {
 						else
 							field.Text = NStack.ustring.Empty;
 					}
-					Assert.Equal ($"Dim.Absolute({count + 1})", view.Height.ToString ());
+					Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
 				}
 			};
 
@@ -1218,13 +1217,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var text = "Test";
 			var dim = Dim.Function (() => text.Length);
-			Assert.Equal ("Dim.DimFunc(4)", dim.ToString ());
+			Assert.Equal ("DimFunc(4)", dim.ToString ());
 
 			text = "New Test";
-			Assert.Equal ("Dim.DimFunc(8)", dim.ToString ());
+			Assert.Equal ("DimFunc(8)", dim.ToString ());
 
 			text = "";
-			Assert.Equal ("Dim.DimFunc(0)", dim.ToString ());
+			Assert.Equal ("DimFunc(0)", dim.ToString ());
 		}
 
 		[Fact]

+ 55 - 50
UnitTests/Types/PosTests.cs

@@ -32,11 +32,11 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var n = 0;
 			var pos = Pos.AnchorEnd ();
-			Assert.Equal ($"Pos.AnchorEnd(margin={n})", pos.ToString ());
+			Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
 
 			n = 5;
 			pos = Pos.AnchorEnd (n);
-			Assert.Equal ($"Pos.AnchorEnd(margin={n})", pos.ToString ());
+			Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
 		}
 
 		[Fact]
@@ -351,13 +351,13 @@ namespace Terminal.Gui.TypeTests {
 		public void At_SetsValue ()
 		{
 			var pos = Pos.At (0);
-			Assert.Equal ("Pos.Absolute(0)", pos.ToString ());
+			Assert.Equal ("Absolute(0)", pos.ToString ());
 
 			pos = Pos.At (5);
-			Assert.Equal ("Pos.Absolute(5)", pos.ToString ());
+			Assert.Equal ("Absolute(5)", pos.ToString ());
 
 			pos = Pos.At (-1);
-			Assert.Equal ("Pos.Absolute(-1)", pos.ToString ());
+			Assert.Equal ("Absolute(-1)", pos.ToString ());
 		}
 
 		[Fact]
@@ -411,140 +411,140 @@ namespace Terminal.Gui.TypeTests {
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Left (new View ());
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Left (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Left (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Left(win) + 0
 			pos = Pos.Left (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Left(win) +1
 			pos = Pos.Left (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Left(win) -1
 			pos = Pos.Left (new View (testRect)) - testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.X
 			side = "x";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.X (new View ());
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			pos = Pos.X (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.X (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.X(win) + 0
 			pos = Pos.X (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.X(win) +1
 			pos = Pos.X (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.X(win) -1
 			pos = Pos.X (new View (testRect)) - testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Top
 			side = "y";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Top (new View ());
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Top (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Top (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Top(win) + 0
 			pos = Pos.Top (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Top(win) +1
 			pos = Pos.Top (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Top(win) -1
 			pos = Pos.Top (new View (testRect)) - testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Y
 			side = "y";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Y (new View ());
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Y (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Y (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Y(win) + 0
 			pos = Pos.Y (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Y(win) +1
 			pos = Pos.Y (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Y(win) -1
 			pos = Pos.Y (new View (testRect)) - testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Bottom
 			side = "bottom";
 			testRect = Rect.Empty;
 			testInt = 0;
 			pos = Pos.Bottom (new View ());
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Bottom (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Bottom (new View (testRect));
-			Assert.Equal ($"Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			// Pos.Bottom(win) + 0
 			pos = Pos.Bottom (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Bottom(win) +1
 			pos = Pos.Bottom (new View (testRect)) + testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Bottom(win) -1
 			pos = Pos.Bottom (new View (testRect)) - testInt;
-			Assert.Equal ($"Pos.Combine(Pos.Combine(Pos.View(side={side}, target=View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Pos.Absolute(0)){(testInt < 0 ? '-' : '+')}Pos.Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
 		}
 
 		// See: https://github.com/gui-cs/Terminal.Gui/issues/504
@@ -632,7 +632,7 @@ namespace Terminal.Gui.TypeTests {
 		public void Center_SetsValue ()
 		{
 			var pos = Pos.Center ();
-			Assert.Equal ("Pos.Center", pos.ToString ());
+			Assert.Equal ("Center", pos.ToString ());
 		}
 
 		[Fact]
@@ -640,13 +640,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			float f = 0;
 			var pos = Pos.Percent (f);
-			Assert.Equal ($"Pos.Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
 			f = 0.5F;
 			pos = Pos.Percent (f);
-			Assert.Equal ($"Pos.Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
 			f = 100;
 			pos = Pos.Percent (f);
-			Assert.Equal ($"Pos.Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
 		}
 
 		[Fact]
@@ -881,12 +881,12 @@ namespace Terminal.Gui.TypeTests {
 					var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 };
 					view.Add (label);
 					Assert.Equal ($"Label {count}", label.Text);
-					Assert.Equal ($"Pos.Absolute({count})", label.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", label.Y.ToString ());
 
-					Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
 					field.Y += 1;
 					count++;
-					Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
 				}
 			};
 
@@ -928,12 +928,12 @@ namespace Terminal.Gui.TypeTests {
 				var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 };
 				view.Add (label);
 				Assert.Equal ($"Label {i}", label.Text);
-				Assert.Equal ($"Pos.Absolute({i})", field.Y.ToString ());
+				Assert.Equal ($"Absolute({i})", field.Y.ToString ());
 				listLabels.Add (label);
 
-				Assert.Equal ($"Pos.Absolute({i})", field.Y.ToString ());
+				Assert.Equal ($"Absolute({i})", field.Y.ToString ());
 				field.Y += 1;
-				Assert.Equal ($"Pos.Absolute({i + 1})", field.Y.ToString ());
+				Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ());
 			}
 
 			field.KeyDown += (k) => {
@@ -941,10 +941,10 @@ namespace Terminal.Gui.TypeTests {
 					Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
 					view.Remove (listLabels [count - 1]);
 
-					Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
 					field.Y -= 1;
 					count--;
-					Assert.Equal ($"Pos.Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
 				}
 			};
 
@@ -988,6 +988,11 @@ namespace Terminal.Gui.TypeTests {
 			Assert.Equal (posCombine.right, posAbsolute);
 			Assert.Equal (20, posCombine.Anchor (100));
 
+			posCombine = new Pos.PosCombine (true, posAbsolute, posFactor);
+			Assert.Equal (posCombine.left, posAbsolute);
+			Assert.Equal (posCombine.right, posFactor);
+			Assert.Equal (20, posCombine.Anchor (100));
+
 			var view = new View (new Rect (20, 10, 20, 1));
 			var posViewX = new Pos.PosView (view, 0);
 			Assert.Equal (20, posViewX.Anchor (0));
@@ -1004,13 +1009,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var text = "Test";
 			var pos = Pos.Function (() => text.Length);
-			Assert.Equal ("Pos.PosFunc(4)", pos.ToString ());
+			Assert.Equal ("PosFunc(4)", pos.ToString ());
 
 			text = "New Test";
-			Assert.Equal ("Pos.PosFunc(8)", pos.ToString ());
+			Assert.Equal ("PosFunc(8)", pos.ToString ());
 
 			text = "";
-			Assert.Equal ("Pos.PosFunc(0)", pos.ToString ());
+			Assert.Equal ("PosFunc(0)", pos.ToString ());
 		}
 
 		[Fact]

+ 20 - 20
UnitTests/Views/ScrollBarViewTests.cs

@@ -362,85 +362,85 @@ namespace Terminal.Gui.ViewTests {
 			_hostView.Redraw (_hostView.Bounds);
 			Assert.True (_scrollBar.ShowScrollIndicator);
 			Assert.True (_scrollBar.Visible);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 
 			_hostView.Lines = 10;
 			_hostView.Redraw (_hostView.Bounds);
 			Assert.False (_scrollBar.ShowScrollIndicator);
 			Assert.False (_scrollBar.Visible);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 
 			_hostView.Cols = 60;
 			_hostView.Redraw (_hostView.Bounds);
 			Assert.False (_scrollBar.ShowScrollIndicator);
 			Assert.False (_scrollBar.Visible);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.False (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 
 			_hostView.Lines = 40;
 			_hostView.Redraw (_hostView.Bounds);
 			Assert.True (_scrollBar.ShowScrollIndicator);
 			Assert.True (_scrollBar.Visible);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (25, _scrollBar.Bounds.Height);
 			Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.False (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 
 			_hostView.Cols = 120;
 			_hostView.Redraw (_hostView.Bounds);
 			Assert.True (_scrollBar.ShowScrollIndicator);
 			Assert.True (_scrollBar.Visible);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 		}
 

+ 5 - 223
UnitTests/Views/ScrollViewTests.cs

@@ -1,4 +1,8 @@
-using NStack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using Xunit;
 using Xunit.Abstractions;
 
@@ -276,227 +280,5 @@ namespace Terminal.Gui.ViewTests {
 ◄░░░├─┤░► 
 ", output);
 		}
-
-		[Fact, AutoInitShutdown]
-		public void Frame_And_Labels_Does_Not_Overspill_ScrollView ()
-		{
-			var sv = new ScrollView {
-				X = 3,
-				Y = 3,
-				Width = 10,
-				Height = 10,
-				ContentSize = new Size (50, 50)
-			};
-			for (int i = 0; i < 8; i++) {
-				sv.Add (new CustomButton ("█", $"Button {i}", 20, 3) { Y = i * 3 });
-			}
-			Application.Top.Add (sv);
-			Application.Begin (Application.Top);
-
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-   █████████▲
-   ██████But┬
-   █████████┴
-   ┌────────░
-   │     But░
-   └────────░
-   ┌────────░
-   │     But░
-   └────────▼
-   ◄├┤░░░░░► ", output);
-
-			sv.ContentOffset = new Point (5, 5);
-			Application.Refresh ();
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-   ─────────▲
-   ─────────┬
-    Button 2│
-   ─────────┴
-   ─────────░
-    Button 3░
-   ─────────░
-   ─────────░
-    Button 4▼
-   ◄├─┤░░░░► ", output);
-		}
-
-		private class CustomButton : FrameView {
-			private Label labelFill;
-			private Label labelText;
-
-			public CustomButton (string fill, ustring text, int width, int height)
-			{
-				Width = width;
-				Height = height;
-				labelFill = new Label () { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill (), Visible = false };
-				var fillText = new System.Text.StringBuilder ();
-				for (int i = 0; i < Bounds.Height; i++) {
-					if (i > 0) {
-						fillText.AppendLine ("");
-					}
-					for (int j = 0; j < Bounds.Width; j++) {
-						fillText.Append (fill);
-					}
-				}
-				labelFill.Text = fillText.ToString ();
-				labelText = new Label (text) { X = Pos.Center (), Y = Pos.Center () };
-				Add (labelFill, labelText);
-				CanFocus = true;
-			}
-
-			public override bool OnEnter (View view)
-			{
-				Border.BorderStyle = BorderStyle.None;
-				Border.DrawMarginFrame = false;
-				labelFill.Visible = true;
-				view = this;
-				return base.OnEnter (view);
-			}
-
-			public override bool OnLeave (View view)
-			{
-				Border.BorderStyle = BorderStyle.Single;
-				Border.DrawMarginFrame = true;
-				labelFill.Visible = false;
-				if (view == null)
-					view = this;
-				return base.OnLeave (view);
-			}
-		}
-
-		[Fact, AutoInitShutdown]
-		public void Clear_Window_Inside_ScrollView ()
-		{
-			var topLabel = new Label ("At 15,0") { X = 15 };
-			var sv = new ScrollView {
-				X = 3,
-				Y = 3,
-				Width = 10,
-				Height = 10,
-				ContentSize = new Size (23, 23),
-				KeepContentAlwaysInViewport = false
-			};
-			var bottomLabel = new Label ("At 15,15") { X = 15, Y = 15 };
-			Application.Top.Add (topLabel, sv, bottomLabel);
-			Application.Begin (Application.Top);
-
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-               At 15,0 
-                       
-                       
-            ▲          
-            ┬          
-            ┴          
-            ░          
-            ░          
-            ░          
-            ░          
-            ░          
-            ▼          
-   ◄├┤░░░░░►           
-                       
-                       
-               At 15,15", output);
-
-			var attributes = new Attribute [] {
-				Colors.TopLevel.Normal,
-				Colors.TopLevel.Focus,
-				Colors.Base.Normal
-			};
-
-			TestHelpers.AssertDriverColorsAre (@"
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00011111111110000000000
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000", attributes);
-
-			sv.Add (new Window ("1") { X = 3, Y = 3, Width = 20, Height = 20 });
-			Application.Refresh ();
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-               At 15,0 
-                       
-                       
-            ▲          
-            ┬          
-            ┴          
-      ┌ 1 ──░          
-      │     ░          
-      │     ░          
-      │     ░          
-      │     ░          
-      │     ▼          
-   ◄├┤░░░░░►           
-                       
-                       
-               At 15,15", output);
-
-			TestHelpers.AssertDriverColorsAre (@"
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000022222210000000000
-00000022222210000000000
-00000022222210000000000
-00000022222210000000000
-00000022222210000000000
-00000022222210000000000
-00011111111110000000000
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000", attributes);
-
-			sv.ContentOffset = new Point (20, 20);
-			Application.Refresh ();
-			TestHelpers.AssertDriverContentsWithFrameAre (@"
-               At 15,0 
-                       
-                       
-     │      ▲          
-     │      ░          
-   ──┘      ░          
-            ░          
-            ░          
-            ┬          
-            │          
-            ┴          
-            ▼          
-   ◄░░░░├─┤►           
-                       
-                       
-               At 15,15", output);
-
-			TestHelpers.AssertDriverColorsAre (@"
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000
-00022200000010000000000
-00022200000010000000000
-00022200000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00000000000010000000000
-00011111111110000000000
-00000000000000000000000
-00000000000000000000000
-00000000000000000000000", attributes);
-		}
 	}
 }

+ 1 - 1
UnitTests/Views/StatusBarTests.cs

@@ -31,7 +31,7 @@ namespace Terminal.Gui.ViewTests {
 			Assert.False (sb.CanFocus);
 			Assert.Equal (Colors.Menu, sb.ColorScheme);
 			Assert.Equal (0, sb.X);
-			Assert.Equal ("Pos.AnchorEnd(margin=1)", sb.Y.ToString ());
+			Assert.Equal ("AnchorEnd(1)", sb.Y.ToString ());
 			Assert.Equal (Dim.Fill (), sb.Width);
 			Assert.Equal (1, sb.Height);
 

+ 6 - 6
UnitTests/Views/TextViewTests.cs

@@ -1524,8 +1524,8 @@ namespace Terminal.Gui.ViewTests {
 			Assert.True (_textView.AllowsReturn);
 			Assert.Equal (4, _textView.TabWidth);
 			Assert.True (_textView.AllowsTab);
-			Assert.Equal ("Dim.Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Dim.Absolute(10)", _textView.Height.ToString ());
+			Assert.Equal ("Absolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("Absolute(10)", _textView.Height.ToString ());
 			Assert.False (_textView.WordWrap);
 
 			_textView.WordWrap = true;
@@ -1535,8 +1535,8 @@ namespace Terminal.Gui.ViewTests {
 			Assert.False (_textView.AllowsReturn);
 			Assert.Equal (0, _textView.TabWidth);
 			Assert.False (_textView.AllowsTab);
-			Assert.Equal ("Dim.Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Dim.Absolute(1)", _textView.Height.ToString ());
+			Assert.Equal ("Absolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("Absolute(1)", _textView.Height.ToString ());
 			Assert.False (_textView.WordWrap);
 
 			_textView.WordWrap = true;
@@ -1546,8 +1546,8 @@ namespace Terminal.Gui.ViewTests {
 			Assert.True (_textView.AllowsReturn);
 			Assert.Equal (4, _textView.TabWidth);
 			Assert.True (_textView.AllowsTab);
-			Assert.Equal ("Dim.Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Dim.Absolute(10)", _textView.Height.ToString ());
+			Assert.Equal ("Absolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("Absolute(10)", _textView.Height.ToString ());
 			Assert.False (_textView.WordWrap);
 		}
 

部分文件因文件數量過多而無法顯示