Tigger Kindel 2 年之前
父节点
当前提交
4424974185
共有 33 个文件被更改,包括 1883 次插入1613 次删除
  1. 11 11
      Terminal.Gui/Configuration/ConfigurationManager.cs
  2. 0 5
      Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
  3. 0 5
      Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
  4. 0 6
      Terminal.Gui/ConsoleDrivers/NetDriver.cs
  5. 0 5
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  6. 4 13
      Terminal.Gui/Core/Application.cs
  7. 126 46
      Terminal.Gui/Core/Border.cs
  8. 0 6
      Terminal.Gui/Core/ConsoleDriver.cs
  9. 10 10
      Terminal.Gui/Core/PosDim.cs
  10. 8 0
      Terminal.Gui/Core/Toplevel.cs
  11. 46 42
      Terminal.Gui/Core/View.cs
  12. 2 0
      Terminal.Gui/Terminal.Gui.csproj
  13. 21 26
      Terminal.Gui/Views/FrameView.cs
  14. 1 0
      Terminal.Gui/Windows/Dialog.cs
  15. 0 10
      UICatalog/Properties/launchSettings.json
  16. 313 0
      UICatalog/Scenarios/ASCIICustomButton.cs
  17. 6 7
      UICatalog/Scenarios/Borders.cs
  18. 3 3
      UICatalog/Scenarios/BordersComparisons.cs
  19. 386 0
      UICatalog/Scenarios/BordersOnContainers.cs
  20. 12 376
      UICatalog/Scenarios/BordersOnFrameView.cs
  21. 12 376
      UICatalog/Scenarios/BordersOnToplevel.cs
  22. 12 375
      UICatalog/Scenarios/BordersOnWindow.cs
  23. 9 7
      UICatalog/UICatalog.cs
  24. 66 14
      UnitTests/Core/BorderTests.cs
  25. 321 121
      UnitTests/Core/LayoutTests.cs
  26. 99 0
      UnitTests/Core/ViewTests.cs
  27. 50 2
      UnitTests/TopLevels/ToplevelTests.cs
  28. 68 68
      UnitTests/Types/DimTests.cs
  29. 47 47
      UnitTests/Types/PosTests.cs
  30. 20 20
      UnitTests/Views/ScrollBarViewTests.cs
  31. 223 5
      UnitTests/Views/ScrollViewTests.cs
  32. 1 1
      UnitTests/Views/StatusBarTests.cs
  33. 6 6
      UnitTests/Views/TextViewTests.cs

+ 11 - 11
Terminal.Gui/Configuration/ConfigurationManager.cs

@@ -44,7 +44,7 @@ namespace Terminal.Gui.Configuration {
 	///	3. Application configuration found in the applications's resources (<c>Resources/config.json</c>). 
 	/// </para>
 	/// <para>
-	///	4. Global configuration found in the the user's home directory (<c>~/.tui/config.json</c>).
+	///	4. Global configuration found in the user's home directory (<c>~/.tui/config.json</c>).
 	/// </para>
 	/// <para>
 	///	5. Global configuration found in the directory the app was launched from (<c>./.tui/config.json</c>).
@@ -63,7 +63,7 @@ namespace Terminal.Gui.Configuration {
 			DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
 			WriteIndented = true,
 			Converters = {
-				// No need to set converterss - the ConfigRootConverter uses property attributes apply the correct
+				// No need to set converters - the ConfigRootConverter uses property attributes apply the correct
 				// Converter.
 			},
 		};
@@ -196,7 +196,7 @@ namespace Terminal.Gui.Configuration {
 		/// </summary>
 		/// <remarks>
 		/// Is <see langword="null"/> until <see cref="Reset"/> is called. Gets set to a new instance by
-		/// deserializtion (see <see cref="Load"/>).
+		/// deserialization (see <see cref="Load"/>).
 		/// </remarks>
 		private static SettingsScope? _settings;
 
@@ -230,7 +230,7 @@ namespace Terminal.Gui.Configuration {
 
 		/// <summary>
 		/// Initializes the internal state of ConfiguraitonManager. Nominally called once as part of application
-		/// startup to initilaize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
+		/// startup to initialize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
 		/// </summary>
 		internal static void Initialize ()
 		{
@@ -260,7 +260,7 @@ namespace Terminal.Gui.Configuration {
 					  select p) {
 				if (p.GetCustomAttribute (typeof (SerializableConfigurationProperty)) is SerializableConfigurationProperty scp) {
 					if (p.GetGetMethod (true)!.IsStatic) {
-						// If the class name is ommited, JsonPropertyName is allowed. 
+						// If the class name is omitted, JsonPropertyName is allowed. 
 						_allConfigProperties!.Add (scp.OmitClassName ? ConfigProperty.GetJsonPropertyName (p) : $"{p.DeclaringType?.Name}.{p.Name}", new ConfigProperty {
 							PropertyInfo = p,
 							PropertyValue = null
@@ -357,7 +357,7 @@ namespace Terminal.Gui.Configuration {
 		}
 
 		/// <summary>
-		/// Event fired when the configuration has been upddated from a configuration source.  
+		/// Event fired when the configuration has been updated from a configuration source.  
 		/// application.
 		/// </summary>
 		public static event Action<ConfigurationManagerEventArgs>? Updated;
@@ -378,7 +378,7 @@ namespace Terminal.Gui.Configuration {
 			}
 
 			ClearJsonErrors ();
-			
+
 			Settings = new SettingsScope ();
 			ThemeManager.Reset ();
 			AppSettings = new AppScope ();
@@ -402,7 +402,7 @@ namespace Terminal.Gui.Configuration {
 		/// to generate the JSON doc that is embedded into Terminal.Gui (during development). 
 		/// </para>
 		/// <para>
-		/// WARNING: The <c>Terminal.Gui.Resources.config.json</c> resource has setting defintions (Themes)
+		/// WARNING: The <c>Terminal.Gui.Resources.config.json</c> resource has setting definitions (Themes)
 		/// that are NOT generated by this function. If you use this function to regenerate <c>Terminal.Gui.Resources.config.json</c>,
 		/// make sure you copy the Theme definitions from the existing <c>Terminal.Gui.Resources.config.json</c> file.
 		/// </para>		
@@ -455,7 +455,7 @@ namespace Terminal.Gui.Configuration {
 		public static string AppName { get; set; } = Assembly.GetEntryAssembly ()?.FullName?.Split (',') [0]?.Trim ()!;
 
 		/// <summary>
-		/// Describes the location of the configuration files. The constancts can be
+		/// Describes the location of the configuration files. The constants can be
 		/// combined (bitwise) to specify multiple locations.
 		/// </summary>
 		[Flags]
@@ -488,7 +488,7 @@ namespace Terminal.Gui.Configuration {
 		public static ConfigLocations Locations { get; set; } = ConfigLocations.All;
 
 		/// <summary>
-		/// Loads all settings found in the various configuraiton storage locations to 
+		/// Loads all settings found in the various configuration storage locations to 
 		/// the <see cref="ConfigurationManager"/>. Optionally,
 		/// resets all settings attributed with <see cref="SerializableConfigurationProperty"/> to the defaults.
 		/// </summary>
@@ -507,7 +507,7 @@ namespace Terminal.Gui.Configuration {
 			if (Locations == ConfigLocations.All) {
 				var embeddedStylesResourceName = Assembly.GetEntryAssembly ()?
 					.GetManifestResourceNames ().FirstOrDefault (x => x.EndsWith (_configFilename));
-				if (string.IsNullOrEmpty(embeddedStylesResourceName)) {
+				if (string.IsNullOrEmpty (embeddedStylesResourceName)) {
 					embeddedStylesResourceName = _configFilename;
 				}
 

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

@@ -21,11 +21,6 @@ namespace Terminal.Gui {
 		public override int Left => 0;
 		public override int Top => 0;
 		public override bool EnableConsoleScrolling { get; set; }
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public override bool HeightAsBuffer {
-			get => EnableConsoleScrolling;
-			set => EnableConsoleScrolling = value;
-		}
 		public override IClipboard Clipboard { get => clipboard; }
 
 		CursorVisibility? initialCursorVisibility = null;

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

@@ -46,11 +46,6 @@ namespace Terminal.Gui {
 		public override int Left => 0;
 		public override int Top => 0;
 		public override bool EnableConsoleScrolling { get; set; }
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public override bool HeightAsBuffer {
-			get => EnableConsoleScrolling;
-			set => EnableConsoleScrolling = value;
-		}
 		private IClipboard clipboard = null;
 		public override IClipboard Clipboard => clipboard;
 

+ 0 - 6
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -621,12 +621,6 @@ namespace Terminal.Gui {
 		public override int Left => left;
 		public override int Top => top;
 		public override bool EnableConsoleScrolling { get; set; }
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public override bool HeightAsBuffer {
-			get => EnableConsoleScrolling;
-			set => EnableConsoleScrolling = value;
-		}
-
 		public NetWinVTConsole NetWinConsole { get; }
 		public bool IsWinPlatform { get; }
 		public override IClipboard Clipboard { get; }

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

@@ -716,11 +716,6 @@ namespace Terminal.Gui {
 		public override int Left => left;
 		public override int Top => top;
 		public override bool EnableConsoleScrolling { get; set; }
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public override bool HeightAsBuffer {
-			get => EnableConsoleScrolling;
-			set => EnableConsoleScrolling = value;
-		}
 		public override IClipboard Clipboard => clipboard;
 		public override int [,,] Contents => contents;
 

+ 4 - 13
Terminal.Gui/Core/Application.cs

@@ -133,7 +133,7 @@ namespace Terminal.Gui {
 		/// </para>
 		/// This API was previously named 'HeightAsBuffer` but was renamed to make its purpose more clear.
 		/// </remarks>
-		[SerializableConfigurationProperty (Scope = typeof(SettingsScope))]
+		[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
 		public static bool EnableConsoleScrolling {
 			get {
 				if (Driver == null) {
@@ -150,21 +150,12 @@ namespace Terminal.Gui {
 			}
 		}
 
-		/// <summary>
-		/// This API is deprecated; use <see cref="EnableConsoleScrolling"/> instead.
-		/// </summary>
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public static bool HeightAsBuffer {
-			get => EnableConsoleScrolling;
-			set => EnableConsoleScrolling = value;
-		}
-
 		static Key alternateForwardKey = Key.PageDown | Key.CtrlMask;
 
 		/// <summary>
 		/// Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.
 		/// </summary>
-		[SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter(typeof(KeyJsonConverter))]
+		[SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
 		public static Key AlternateForwardKey {
 			get => alternateForwardKey;
 			set {
@@ -188,7 +179,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.
 		/// </summary>
-		[SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
+		[SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
 		public static Key AlternateBackwardKey {
 			get => alternateBackwardKey;
 			set {
@@ -212,7 +203,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Gets or sets the key to quit the application.
 		/// </summary>
-		[SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
+		[SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
 		public static Key QuitKey {
 			get => quitKey;
 			set {

+ 126 - 46
Terminal.Gui/Core/Border.cs

@@ -331,7 +331,8 @@ namespace Terminal.Gui {
 		private Point effect3DOffset = new Point (1, 1);
 		private Attribute? effect3DBrush;
 		private ustring title = ustring.Empty;
-
+		private View child;
+		
 		/// <summary>
 		/// Specifies the <see cref="Gui.BorderStyle"/> for a view.
 		/// </summary>
@@ -447,8 +448,47 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Gets or sets the single child element of a <see cref="View"/>.
 		/// </summary>
-		[JsonIgnore]
-		public View Child { get; set; }
+		public View Child {
+			get => child;
+			set {
+				child = value;
+				if (child != null && Parent != null) {
+					Parent.Initialized += Parent_Initialized;
+					Parent.Removed += Parent_Removed;
+				}
+			}
+		}
+
+		private void Parent_Removed (View obj)
+		{
+			BorderBrush = default;
+			Background = default;
+			child.Removed -= Parent_Removed;
+		}
+
+		private void Parent_Initialized (object s, EventArgs e)
+		{
+			SetMarginFrameTitleBrush ();
+			child.Initialized -= Parent_Initialized;
+		}
+
+		private void SetMarginFrameTitleBrush ()
+		{
+			if (child != null) {
+				var view = Parent?.Border != null ? Parent : child;
+				if (view.ColorScheme != null) {
+					if (borderBrush == default) {
+						BorderBrush = view.GetNormalColor ().Foreground;
+					}
+					if (background == default) {
+						Background = view.GetNormalColor ().Background;
+					}
+					return;
+				}
+			}
+			BorderBrush = default;
+			Background = default;
+		}
 
 		/// <summary>
 		/// Gets the parent <see cref="Child"/> parent if any.
@@ -651,9 +691,13 @@ namespace Terminal.Gui {
 
 			// Draw the upper BorderThickness
 			for (int r = frame.Y - drawMarginFrame - sumThickness.Top;
-				r > 0 && r < frame.Y - drawMarginFrame - padding.Top; r++) {
+				r < frame.Y - drawMarginFrame - padding.Top; r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -661,9 +705,13 @@ namespace Terminal.Gui {
 
 			// Draw the left BorderThickness
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c > 0 && c < frame.X - drawMarginFrame - padding.Left; c++) {
+					c < frame.X - drawMarginFrame - padding.Left; c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -671,9 +719,13 @@ namespace Terminal.Gui {
 
 			// Draw the right BorderThickness
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.Right + drawMarginFrame + padding.Right;
-					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -681,9 +733,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower BorderThickness
 			for (int r = frame.Bottom + drawMarginFrame + padding.Bottom;
-				r > 0 && r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - sumThickness.Left;
-					c > 0 && c > 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -693,9 +745,13 @@ namespace Terminal.Gui {
 
 			// Draw the upper Padding
 			for (int r = frame.Y - drawMarginFrame - padding.Top;
-				r > 0 && r < frame.Y - drawMarginFrame; r++) {
+				r < frame.Y - drawMarginFrame; r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -703,9 +759,9 @@ namespace Terminal.Gui {
 
 			// Draw the left Padding
 			for (int r = frame.Y - drawMarginFrame;
-				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c > 0 && c < frame.X - drawMarginFrame; c++) {
+					c < frame.X - drawMarginFrame; c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -713,9 +769,9 @@ namespace Terminal.Gui {
 
 			// Draw the right Padding
 			for (int r = frame.Y - drawMarginFrame;
-				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
 				for (int c = frame.Right + drawMarginFrame;
-					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -723,9 +779,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower Padding
 			for (int r = frame.Bottom + drawMarginFrame;
-				r > 0 && r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
 				for (int c = frame.X - drawMarginFrame - padding.Left;
-					c > 0 && c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -825,9 +881,12 @@ namespace Terminal.Gui {
 
 			// Draw the upper BorderThickness
 			for (int r = frame.Y;
-				r > 0 && r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
+				r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X;
-					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -835,9 +894,13 @@ namespace Terminal.Gui {
 
 			// Draw the left BorderThickness
 			for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
-				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X;
-					c > 0 && c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
+					c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -845,9 +908,13 @@ namespace Terminal.Gui {
 
 			// Draw the right BorderThickness
 			for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
-				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = Math.Max (frame.Right - borderThickness.Right, frame.X);
-					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -855,9 +922,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower BorderThickness
 			for (int r = Math.Max (frame.Bottom - borderThickness.Bottom, frame.Y);
-				r > 0 && r < Math.Min (frame.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom, driver.Rows); r++) {
 				for (int c = frame.X;
-					c > 0 && c < Math.Min (frame.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -867,9 +934,13 @@ namespace Terminal.Gui {
 
 			// Draw the upper Padding
 			for (int r = frame.Y + borderThickness.Top;
-				r > 0 && r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
+				r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X + borderThickness.Left;
-					c > 0 && c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -877,9 +948,13 @@ namespace Terminal.Gui {
 
 			// Draw the left Padding
 			for (int r = frame.Y + sumThickness.Top;
-				r > 0 && r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = frame.X + borderThickness.Left;
-					c > 0 && c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
+					c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -887,9 +962,13 @@ namespace Terminal.Gui {
 
 			// Draw the right Padding
 			for (int r = frame.Y + sumThickness.Top;
-				r > 0 && r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
+
+				if (r < 0) {
+					continue;
+				}
 				for (int c = Math.Max (frame.Right - sumThickness.Right, frame.X + sumThickness.Left);
-					c > 0 && c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
+					c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -897,9 +976,9 @@ namespace Terminal.Gui {
 
 			// Draw the lower Padding
 			for (int r = Math.Max (frame.Bottom - sumThickness.Bottom, frame.Y + borderThickness.Top);
-				r > 0 && r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
+				r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
 				for (int c = frame.X + borderThickness.Left;
-					c > 0 && c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
+					c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
 
 					AddRuneAt (driver, c, r, ' ');
 				}
@@ -926,9 +1005,9 @@ namespace Terminal.Gui {
 
 				// Draw the upper Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r > 0 && r < frame.Y; r++) {
+					r < frame.Y; r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -936,9 +1015,9 @@ namespace Terminal.Gui {
 
 				// Draw the left Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c > 0 && c < frame.X; c++) {
+						c < frame.X; c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -946,9 +1025,9 @@ namespace Terminal.Gui {
 
 				// Draw the right Effect3D
 				for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
-					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = frame.Right;
-						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -956,9 +1035,9 @@ namespace Terminal.Gui {
 
 				// Draw the lower Effect3D
 				for (int r = frame.Bottom;
-					r > 0 && r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
+					r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
 					for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
-						c > 0 && c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
+						c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
 
 						AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
 					}
@@ -987,9 +1066,10 @@ namespace Terminal.Gui {
 		{
 			var driver = Application.Driver;
 			if (DrawMarginFrame) {
-				driver.SetAttribute (Child.GetNormalColor ());
-				if (Child.HasFocus)
-					driver.SetAttribute (Child.ColorScheme.HotNormal);
+				driver.SetAttribute (new Attribute (BorderBrush, Background));
+				if (view.HasFocus) {
+					driver.SetAttribute (new Attribute (Child.ColorScheme.HotNormal.Foreground, Background));
+				}
 				var padding = view.Border.GetSumThickness ();
 				Rect scrRect;
 				if (view == Child) {

+ 0 - 6
Terminal.Gui/Core/ConsoleDriver.cs

@@ -713,12 +713,6 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public abstract bool EnableConsoleScrolling { get; set; }
 
-		/// <summary>
-		/// This API is deprecated; use <see cref="EnableConsoleScrolling"/> instead.
-		/// </summary>
-		[Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)]
-		public abstract bool HeightAsBuffer { get; set; }
-
 		/// <summary>
 		/// The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag
 		/// </summary>

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

@@ -85,7 +85,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Factor({factor})";
+				return $"PosFactor({factor})";
 			}
 
 			public override int GetHashCode () => factor.GetHashCode ();
@@ -135,7 +135,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"AnchorEnd({n})";
+				return $"PosAnchorEnd({n})";
 			}
 		}
 
@@ -174,7 +174,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return "Center";
+				return "PosCenter";
 			}
 		}
 
@@ -209,7 +209,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Absolute({n})";
+				return $"PosAbsolute({n})";
 			}
 
 			internal override int Anchor (int width)
@@ -264,7 +264,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Combine({left}{(add ? '+' : '-')}{right})";
+				return $"PosCombine({left}{(add ? '+' : '-')}{right})";
 			}
 
 		}
@@ -345,7 +345,7 @@ namespace Terminal.Gui {
 				case 3: tside = "bottom"; break;
 				default: tside = "unknown"; break;
 				}
-				return $"View({tside},{Target.ToString()})";
+				return $"PosView({tside},{Target.ToString ()})";
 			}
 
 			public override int GetHashCode () => Target.GetHashCode ();
@@ -482,7 +482,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Factor({factor},{remaining})";
+				return $"DimFactor({factor},{remaining})";
 			}
 
 			public override int GetHashCode () => factor.GetHashCode ();
@@ -522,7 +522,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Absolute({n})";
+				return $"DimAbsolute({n})";
 			}
 
 			internal override int Anchor (int width)
@@ -541,7 +541,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Fill({margin})";
+				return $"DimFill({margin})";
 			}
 
 			internal override int Anchor (int width)
@@ -613,7 +613,7 @@ namespace Terminal.Gui {
 
 			public override string ToString ()
 			{
-				return $"Combine({left}{(add ? '+' : '-')}{right})";
+				return $"DimCombine({left}{(add ? '+' : '-')}{right})";
 			}
 
 		}

+ 8 - 0
Terminal.Gui/Core/Toplevel.cs

@@ -167,6 +167,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		virtual public void OnLoaded ()
 		{
+			IsLoaded = true;
 			foreach (Toplevel tl in Subviews.Where (v => v is Toplevel)) {
 				tl.OnLoaded ();
 			}
@@ -367,6 +368,13 @@ namespace Terminal.Gui {
 			}
 		}
 
+		/// <summary>
+		/// <see langword="true"/> if was already loaded by the <see cref="Application.Begin(Toplevel)"/>
+		/// <see langword="false"/>, otherwise. This is used to avoid the <see cref="View.NeedDisplay"/>
+		/// having wrong values while this was not yet loaded.
+		/// </summary>
+		public bool IsLoaded { get; private set; }
+
 		///<inheritdoc/>
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		{

+ 46 - 42
Terminal.Gui/Core/View.cs

@@ -829,6 +829,11 @@ namespace Terminal.Gui {
 
 		Rect GetMaxNeedDisplay (Rect oldFrame, Rect newFrame)
 		{
+			var topSuperView = GetTopSuperView ();
+			if (topSuperView == null || topSuperView is not Toplevel || ((Toplevel)topSuperView)?.IsLoaded == false) {
+				return newFrame;
+			}
+
 			var rect = new Rect () {
 				X = Math.Min (oldFrame.X, newFrame.X),
 				Y = Math.Min (oldFrame.Y, newFrame.Y),
@@ -1110,15 +1115,8 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public void Clear ()
 		{
-			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;
+			var h = Frame.Height;
+			var w = Frame.Width;
 			for (var line = 0; line < h; line++) {
 				Move (0, line);
 				for (var col = 0; col < w; col++)
@@ -1524,8 +1522,6 @@ namespace Terminal.Gui {
 			var boundsAdjustedForBorder = Bounds;
 			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)) {
@@ -1536,14 +1532,14 @@ namespace Terminal.Gui {
 
 			if (!ustring.IsNullOrEmpty (TextFormatter.Text)) {
 				Rect containerBounds = GetContainerBounds ();
-				Clear (ViewToScreen (GetNeedDisplay (containerBounds)));
+				Clear (GetNeedDisplay (containerBounds));
 				SetChildNeedsDisplay ();
 				// Draw any Text
 				if (TextFormatter != null) {
 					TextFormatter.NeedsFormat = true;
 				}
-				TextFormatter?.Draw (ViewToScreen (boundsAdjustedForBorder), HasFocus ? ColorScheme.Focus : GetNormalColor (),
-				    HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
+				TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (),
+				    HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (),
 				    containerBounds);
 			}
 
@@ -1553,7 +1549,7 @@ namespace Terminal.Gui {
 			if (subviews != null) {
 				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.Frame.IntersectsWith (clipRect) && (view.Frame.IntersectsWith (bounds) || bounds.X < 0 || bounds.Y < 0)) {
 							if (view.LayoutNeeded) {
 								view.LayoutSubviews ();
 							}
@@ -1582,7 +1578,7 @@ namespace Terminal.Gui {
 
 		Rect GetNeedDisplay (Rect containerBounds)
 		{
-			Rect rect = NeedDisplay;
+			Rect rect = ViewToScreen (NeedDisplay);
 			if (!containerBounds.IsEmpty) {
 				rect.Width = Math.Min (NeedDisplay.Width, containerBounds.Width);
 				rect.Height = Math.Min (NeedDisplay.Height, containerBounds.Height);
@@ -2223,8 +2219,7 @@ namespace Terminal.Gui {
 					newLocation = pos.Anchor (superviewDimension - newDimension);
 					break;
 
-				case Pos.PosCombine:
-					var combine = pos as Pos.PosCombine;
+				case Pos.PosCombine combine:
 					int left, right;
 					(left, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.left, dim, autosizeDimension);
 					(right, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.right, dim, autosizeDimension);
@@ -2251,7 +2246,7 @@ namespace Terminal.Gui {
 
 			// 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)
+			//   the current dimension (width or height)
 			int CalculateNewDimension (Dim d, int location, int dimension, int autosize)
 			{
 				int newDimension;
@@ -2269,12 +2264,12 @@ namespace Terminal.Gui {
 					}
 					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);
@@ -2286,11 +2281,11 @@ namespace Terminal.Gui {
 			}
 
 
-			// horiztonal
-			(newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, Width, autosize.Width);
+			// horizontal
+			(newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, width, autosize.Width);
 
 			// vertical
-			(newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, Height, autosize.Height);
+			(newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, height, autosize.Height);
 
 			var r = new Rect (newX, newY, newW, newH);
 			if (Frame != r) {
@@ -2438,7 +2433,7 @@ namespace Terminal.Gui {
 
 			if (edges.Any ()) {
 				(var from, var to) = edges.First ();
-				if (from != Application.Top) {
+				if (from != superView?.GetTopSuperView (to, from)) {
 					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 {
@@ -2449,8 +2444,8 @@ namespace Terminal.Gui {
 			// 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.
@@ -2475,20 +2470,16 @@ namespace Terminal.Gui {
 			CollectAll (this, ref nodes, ref edges);
 			var ordered = View.TopologicalSort (SuperView, nodes, edges);
 			foreach (var v in ordered) {
-				if (v.LayoutStyle == LayoutStyle.Computed) {
-					v.SetRelativeLayout (Frame);
-				}
-
-				v.LayoutSubviews ();
-				v.LayoutNeeded = false;
+				LayoutSubview (v, Frame);
 			}
 
-			// 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) {
-				Debug.Assert (Application.Top.Frame.Location == Point.Empty);
-				SetRelativeLayout (Application.Top.Frame);
+			// If the 'to' is rooted to 'from' and the layoutstyle is Computed it's a special-case.
+			// Use LayoutSubview with the Frame of the 'from' 
+			if (SuperView != null && GetTopSuperView () != null && LayoutNeeded
+			    && ordered.Count == 0 && edges.Count > 0 && LayoutStyle == LayoutStyle.Computed) {
+
+				(var from, var to) = edges.First ();
+				LayoutSubview (to, from.Frame);
 			}
 
 			LayoutNeeded = false;
@@ -2496,6 +2487,16 @@ namespace Terminal.Gui {
 			OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
 		}
 
+		private void LayoutSubview (View v, Rect hostFrame)
+		{
+			if (v.LayoutStyle == LayoutStyle.Computed) {
+				v.SetRelativeLayout (hostFrame);
+			}
+
+			v.LayoutSubviews ();
+			v.LayoutNeeded = false;
+		}
+
 		ustring text;
 
 		/// <summary>
@@ -3165,11 +3166,14 @@ namespace Terminal.Gui {
 		/// Get the top superview of a given <see cref="View"/>.
 		/// </summary>
 		/// <returns>The superview view.</returns>
-		public View GetTopSuperView ()
+		public View GetTopSuperView (View view = null, View superview = null)
 		{
-			View top = Application.Top;
-			for (var v = this?.SuperView; v != null; v = v.SuperView) {
+			View top = superview ?? Application.Top;
+			for (var v = view?.SuperView ?? (this?.SuperView); v != null; v = v.SuperView) {
 				top = v;
+				if (top == superview) {
+					break;
+				}
 			}
 
 			return top;

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

@@ -30,6 +30,7 @@
     <PackageReference Include="System.Text.Json" Version="7.0.1" />
     <PackageReference Include="System.Management" Version="7.0.0" />
     <InternalsVisibleTo Include="UnitTests" />
+ 
   </ItemGroup>
   <!-- Uncomment the RestoreSources element to have dotnet restore pull NStack from a local dir for testing -->
   <PropertyGroup>
@@ -60,6 +61,7 @@
       <LastGenOutput>Strings.Designer.cs</LastGenOutput>
     </EmbeddedResource>
   </ItemGroup>
+
   <PropertyGroup>
     <TargetFrameworks>net472;netstandard2.0;net6.0</TargetFrameworks>
     <LangVersion>9</LangVersion>

+ 21 - 26
Terminal.Gui/Views/FrameView.cs

@@ -162,7 +162,8 @@ namespace Terminal.Gui {
 			this.Title = title;
 			if (border == null) {
 				Border = new Border () {
-					BorderStyle = DefaultBorderStyle
+					BorderStyle = DefaultBorderStyle,
+					Title = title
 				};
 			} else {
 				Border = border;
@@ -284,13 +285,7 @@ namespace Terminal.Gui {
 
 			if (!IgnoreBorderPropertyOnRedraw) {
 				Driver.SetAttribute (GetNormalColor ());
-				//Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: false);
 				Border.DrawContent (this, false);
-				if (HasFocus)
-					Driver.SetAttribute (ColorScheme.HotNormal);
-				if (Border.DrawMarginFrame)
-					Driver.DrawWindowTitle (scrRect, Title, padding.Left, padding.Top, padding.Right, padding.Bottom);
-				Driver.SetAttribute (GetNormalColor ());
 			} else {
 				var lc = new LineCanvas ();
 
@@ -312,28 +307,28 @@ namespace Terminal.Gui {
 
 				//}
 
-				Driver.SetAttribute (ColorScheme.Normal);
-				foreach (var p in lc.GenerateImage (bounds)) {
-					this.AddRune (p.Key.X, p.Key.Y, p.Value);
-				}
+				//Driver.SetAttribute (ColorScheme.Normal);
+				//foreach (var p in lc.GenerateImage (bounds)) {
+				//	this.AddRune (p.Key.X, p.Key.Y, p.Value);
+				//}
 
-				// Redraw the lines so that focus/drag symbol renders
-				foreach (var subview in contentView.Subviews) {
-					//	line.DrawSplitterSymbol ();
-				}
+				//// Redraw the lines so that focus/drag symbol renders
+				//foreach (var subview in contentView.Subviews) {
+				//	//	line.DrawSplitterSymbol ();
+				//}
 
 
-				// Draw Titles over Border
-				foreach (var subview in contentView.Subviews) {
-					// TODO: Use reflection to see if subview has a Title property
-					if (subview is FrameView viewWithTite) {
-						var rect = viewWithTite.Frame;
-						rect.X = rect.X + 1;
-						rect.Y = rect.Y + 2;
-						// TODO: Do focus color correctly
-						Driver.DrawWindowTitle (rect, viewWithTite.Title, padding.Left, padding.Top, padding.Right, padding.Bottom);
-					}
-				}
+				//// Draw Titles over Border
+				//foreach (var subview in contentView.Subviews) {
+				//	// TODO: Use reflection to see if subview has a Title property
+				//	if (subview is FrameView viewWithTite) {
+				//		var rect = viewWithTite.Frame;
+				//		rect.X = rect.X + 1;
+				//		rect.Y = rect.Y + 2;
+				//		// TODO: Do focus color correctly
+				//		Driver.DrawWindowTitle (rect, viewWithTite.Title, padding.Left, padding.Top, padding.Right, padding.Bottom);
+				//	}
+				//}
 			}
 		}
 

+ 1 - 0
Terminal.Gui/Windows/Dialog.cs

@@ -79,6 +79,7 @@ namespace Terminal.Gui {
 			Modal = true;
 			ButtonAlignment = DefaultButtonAlignment;
 			Border = DefaultBorder;
+			Border.Title = title;
 
 			if (buttons != null) {
 				foreach (var b in buttons) {

+ 0 - 10
UICatalog/Properties/launchSettings.json

@@ -50,16 +50,6 @@
     "Windows & FrameViews": {
       "commandName": "Project",
       "commandLineArgs": "\"Windows & FrameViews\""
-    },
-    "WSL : UICatalog": {
-      "commandName": "Executable",
-      "executablePath": "wsl",
-      "commandLineArgs": "dotnet UICatalog.dll",
-      "distributionName": ""
-    },
-    "Tile View Experiments": {
-      "commandName": "Project",
-      "commandLineArgs": "\"Tile View Experiments\""
     }
   }
 }

+ 313 - 0
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -0,0 +1,313 @@
+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));
+				}
+			}
+		}
+	}
+}

+ 6 - 7
UICatalog/Scenarios/Borders.cs

@@ -19,6 +19,8 @@ namespace UICatalog.Scenarios {
 			var effect3D = true;
 
 			var smartPanel = new PanelView () {
+				X = Pos.Center () - 20,
+				Y = Pos.Center () + 2,
 				Width = 24,
 				Height = 13,
 				Border = new Border () {
@@ -70,6 +72,8 @@ namespace UICatalog.Scenarios {
 			//};
 
 			var smartLabel = new Label () {
+				X = Pos.Center () + 16,
+				Y = Pos.Center () + 2,
 				Border = new Border () {
 					BorderStyle = borderStyle,
 					DrawMarginFrame = drawMarginFrame,
@@ -184,7 +188,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (paddingBottomEdit);
 
 			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Left(paddingLeftEdit),
+				X = Pos.Left (paddingLeftEdit),
 				Y = 5
 			};
 			replacePadding.Clicked += () => {
@@ -303,7 +307,7 @@ namespace UICatalog.Scenarios {
 			Win.Add (borderBottomEdit);
 
 			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Left(borderLeftEdit),
+				X = Pos.Left (borderLeftEdit),
 				Y = 5
 			};
 			replaceBorder.Clicked += () => {
@@ -457,14 +461,9 @@ namespace UICatalog.Scenarios {
 			};
 			Win.Add (rbBorderBrush);
 
-			smartPanel.X = Pos.Left (paddingLeftEdit);
-			smartPanel.Y = Pos.Top (smartLabel);
 			Win.Add (smartPanel);
-			smartLabel.X = Pos.Left (borderLeftEdit);
-			smartLabel.Y = Pos.Bottom (cbUseUsePanelFrame) + 5;
 			Win.Add (smartLabel);
 			Win.BringSubviewToFront (smartPanel);
-
 		}
 	}
 }

+ 3 - 3
UICatalog/Scenarios/BordersComparisons.cs

@@ -38,7 +38,7 @@ namespace UICatalog.Scenarios {
 			button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Window?", "Yes", "No");
 			var label = new Label ("I'm a Window") {
 				X = Pos.Center (),
-				Y = Pos.Center () - 3,
+				Y = Pos.Center () - 1,
 			};
 			var tv = new TextView () {
 				Y = Pos.AnchorEnd (2),
@@ -77,7 +77,7 @@ namespace UICatalog.Scenarios {
 			button2.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Toplevel?", "Yes", "No");
 			var label2 = new Label ("I'm a Toplevel") {
 				X = Pos.Center (),
-				Y = Pos.Center () - 3,
+				Y = Pos.Center () - 1,
 			};
 			var tv2 = new TextView () {
 				Y = Pos.AnchorEnd (2),
@@ -113,7 +113,7 @@ namespace UICatalog.Scenarios {
 			button3.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a FrameView?", "Yes", "No");
 			var label3 = new Label ("I'm a FrameView") {
 				X = Pos.Center (),
-				Y = Pos.Center () - 3,
+				Y = Pos.Center () - 1,
 			};
 			var tv3 = new TextView () {
 				Y = Pos.AnchorEnd (2),

+ 386 - 0
UICatalog/Scenarios/BordersOnContainers.cs

@@ -0,0 +1,386 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+	public class BordersOnContainers : Window {
+		public BordersOnContainers (NStack.ustring title, string typeName, View smartView)
+		{
+			var borderStyle = BorderStyle.Double;
+			var drawMarginFrame = false;
+			var borderThickness = new Thickness (1, 2, 3, 4);
+			var borderBrush = Colors.Base.HotFocus.Foreground;
+			var padding = new Thickness (1, 2, 3, 4);
+			var background = Colors.Base.HotNormal.Foreground;
+			var effect3D = true;
+
+			smartView.X = Pos.Center ();
+			smartView.Y = 0;
+			smartView.Width = 40;
+			smartView.Height = 20;
+			smartView.Border = new Border () {
+				BorderStyle = borderStyle,
+				DrawMarginFrame = drawMarginFrame,
+				BorderThickness = borderThickness,
+				BorderBrush = borderBrush,
+				Padding = padding,
+				Background = background,
+				Effect3D = effect3D,
+				Title = typeName
+			};
+			smartView.ColorScheme = Colors.TopLevel;
+
+			var tf1 = new TextField ("1234567890") { Width = 10 };
+
+			var button = new Button ("Press me!") {
+				X = Pos.Center (),
+				Y = Pos.Center (),
+			};
+			button.Clicked += () => MessageBox.Query (20, 7, "Hi", $"I'm a {typeName}?", "Yes", "No");
+			var label = new Label ($"I'm a {typeName}") {
+				X = Pos.Center (),
+				Y = Pos.Center () - 1,
+			};
+			var tf2 = new TextField ("1234567890") {
+				X = Pos.AnchorEnd (10),
+				Y = Pos.AnchorEnd (1),
+				Width = 10
+			};
+			var tv = new TextView () {
+				Y = Pos.AnchorEnd (2),
+				Width = 10,
+				Height = Dim.Fill (),
+				Text = "1234567890"
+			};
+			smartView.Add (tf1, button, label, tf2, tv);
+
+			Add (new Label ("Padding:") {
+				X = Pos.Center () - 23,
+			});
+
+			var paddingTopEdit = new TextField ("") {
+				X = Pos.Center () - 22,
+				Y = 1,
+				Width = 5
+			};
+			paddingTopEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
+						int.Parse (e.NewText.ToString ()), smartView.Border.Padding.Right,
+						smartView.Border.Padding.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			paddingTopEdit.Text = $"{smartView.Border.Padding.Top}";
+
+			Add (paddingTopEdit);
+
+			var paddingLeftEdit = new TextField ("") {
+				X = Pos.Center () - 30,
+				Y = 2,
+				Width = 5
+			};
+			paddingLeftEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
+						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
+						smartView.Border.Padding.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			paddingLeftEdit.Text = $"{smartView.Border.Padding.Left}";
+			Add (paddingLeftEdit);
+
+			var paddingRightEdit = new TextField ("") {
+				X = Pos.Center () - 15,
+				Y = 2,
+				Width = 5
+			};
+			paddingRightEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
+						smartView.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
+						smartView.Border.Padding.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			paddingRightEdit.Text = $"{smartView.Border.Padding.Right}";
+			Add (paddingRightEdit);
+
+			var paddingBottomEdit = new TextField ("") {
+				X = Pos.Center () - 22,
+				Y = 3,
+				Width = 5
+			};
+			paddingBottomEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
+						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
+						int.Parse (e.NewText.ToString ()));
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			paddingBottomEdit.Text = $"{smartView.Border.Padding.Bottom}";
+			Add (paddingBottomEdit);
+
+			var replacePadding = new Button ("Replace all based on top") {
+				X = Pos.Left (paddingLeftEdit),
+				Y = 5
+			};
+			replacePadding.Clicked += () => {
+				smartView.Border.Padding = new Thickness (smartView.Border.Padding.Top);
+				if (paddingTopEdit.Text.IsEmpty) {
+					paddingTopEdit.Text = "0";
+				}
+				paddingBottomEdit.Text = paddingLeftEdit.Text = paddingRightEdit.Text = paddingTopEdit.Text;
+			};
+			Add (replacePadding);
+
+			Add (new Label ("Border:") {
+				X = Pos.Center () + 11,
+			});
+
+			var borderTopEdit = new TextField ("") {
+				X = Pos.Center () + 12,
+				Y = 1,
+				Width = 5
+			};
+			borderTopEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
+						int.Parse (e.NewText.ToString ()), smartView.Border.BorderThickness.Right,
+						smartView.Border.BorderThickness.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			borderTopEdit.Text = $"{smartView.Border.BorderThickness.Top}";
+
+			Add (borderTopEdit);
+
+			var borderLeftEdit = new TextField ("") {
+				X = Pos.Center () + 5,
+				Y = 2,
+				Width = 5
+			};
+			borderLeftEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
+						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
+						smartView.Border.BorderThickness.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			borderLeftEdit.Text = $"{smartView.Border.BorderThickness.Left}";
+			Add (borderLeftEdit);
+
+			var borderRightEdit = new TextField ("") {
+				X = Pos.Center () + 19,
+				Y = 2,
+				Width = 5
+			};
+			borderRightEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
+						smartView.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
+						smartView.Border.BorderThickness.Bottom);
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			borderRightEdit.Text = $"{smartView.Border.BorderThickness.Right}";
+			Add (borderRightEdit);
+
+			var borderBottomEdit = new TextField ("") {
+				X = Pos.Center () + 12,
+				Y = 3,
+				Width = 5
+			};
+			borderBottomEdit.TextChanging += (e) => {
+				try {
+					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
+						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
+						int.Parse (e.NewText.ToString ()));
+				} catch {
+					if (!e.NewText.IsEmpty) {
+						e.Cancel = true;
+					}
+				}
+			};
+			borderBottomEdit.Text = $"{smartView.Border.BorderThickness.Bottom}";
+			Add (borderBottomEdit);
+
+			var replaceBorder = new Button ("Replace all based on top") {
+				X = Pos.Left (borderLeftEdit),
+				Y = 5
+			};
+			replaceBorder.Clicked += () => {
+				smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Top);
+				if (borderTopEdit.Text.IsEmpty) {
+					borderTopEdit.Text = "0";
+				}
+				borderBottomEdit.Text = borderLeftEdit.Text = borderRightEdit.Text = borderTopEdit.Text;
+			};
+			Add (replaceBorder);
+
+			smartView.Y = Pos.Center () + 4;
+
+			Add (new Label ("BorderStyle:"));
+
+			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();
+			var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
+				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
+
+				X = 2,
+				Y = 1,
+				SelectedItem = (int)smartView.Border.BorderStyle
+			};
+			Add (rbBorderStyle);
+
+			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartView.Border.DrawMarginFrame) {
+				X = Pos.AnchorEnd (20),
+				Y = 0,
+				Width = 5
+			};
+			cbDrawMarginFrame.Toggled += (e) => {
+				try {
+					smartView.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
+					if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
+						cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
+					}
+				} catch { }
+			};
+			Add (cbDrawMarginFrame);
+
+			rbBorderStyle.SelectedItemChanged += (e) => {
+				smartView.Border.BorderStyle = (BorderStyle)e.SelectedItem;
+				smartView.SetNeedsDisplay ();
+				if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
+					cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
+				}
+			};
+
+			var cbEffect3D = new CheckBox ("Draw 3D effects", smartView.Border.Effect3D) {
+				X = Pos.AnchorEnd (20),
+				Y = 1,
+				Width = 5
+			};
+			Add (cbEffect3D);
+
+			Add (new Label ("Effect3D Offset:") {
+				X = Pos.AnchorEnd (20),
+				Y = 2
+			});
+			Add (new Label ("X:") {
+				X = Pos.AnchorEnd (19),
+				Y = 3
+			});
+
+			var effect3DOffsetX = new TextField ("") {
+				X = Pos.AnchorEnd (16),
+				Y = 3,
+				Width = 5
+			};
+			effect3DOffsetX.TextChanging += (e) => {
+				try {
+					smartView.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
+						smartView.Border.Effect3DOffset.Y);
+				} catch {
+					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
+						e.Cancel = true;
+					}
+				}
+			};
+			effect3DOffsetX.Text = $"{smartView.Border.Effect3DOffset.X}";
+			Add (effect3DOffsetX);
+
+			Add (new Label ("Y:") {
+				X = Pos.AnchorEnd (10),
+				Y = 3
+			});
+
+			var effect3DOffsetY = new TextField ("") {
+				X = Pos.AnchorEnd (7),
+				Y = 3,
+				Width = 5
+			};
+			effect3DOffsetY.TextChanging += (e) => {
+				try {
+					smartView.Border.Effect3DOffset = new Point (smartView.Border.Effect3DOffset.X,
+						int.Parse (e.NewText.ToString ()));
+				} catch {
+					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
+						e.Cancel = true;
+					}
+				}
+			};
+			effect3DOffsetY.Text = $"{smartView.Border.Effect3DOffset.Y}";
+			Add (effect3DOffsetY);
+
+			cbEffect3D.Toggled += (e) => {
+				try {
+					smartView.Border.Effect3D = effect3DOffsetX.Enabled =
+						effect3DOffsetY.Enabled = (bool)cbEffect3D.Checked;
+				} catch { }
+			};
+
+			Add (new Label ("Background:") {
+				Y = 5
+			});
+
+			var colorEnum = Enum.GetValues (typeof (Color)).Cast<Color> ().ToList ();
+			var rbBackground = new RadioGroup (colorEnum.Select (
+				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
+
+				X = 2,
+				Y = 6,
+				SelectedItem = (int)smartView.Border.Background
+			};
+			rbBackground.SelectedItemChanged += (e) => {
+				smartView.Border.Background = (Color)e.SelectedItem;
+			};
+			Add (rbBackground);
+
+			Add (new Label ("BorderBrush:") {
+				X = Pos.AnchorEnd (20),
+				Y = 5
+			});
+
+			var rbBorderBrush = new RadioGroup (colorEnum.Select (
+				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
+
+				X = Pos.AnchorEnd (18),
+				Y = 6,
+				SelectedItem = (int)smartView.Border.BorderBrush
+			};
+			rbBorderBrush.SelectedItemChanged += (e) => {
+				smartView.Border.BorderBrush = (Color)e.SelectedItem;
+			};
+			Add (rbBorderBrush);
+
+			Add (smartView);
+
+			Title = title;
+		}
+	}
+}

+ 12 - 376
UICatalog/Scenarios/BordersOnFrameView.cs

@@ -1,389 +1,25 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using Terminal.Gui;
+using Terminal.Gui;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "Borders on FrameView", Description: "Demonstrate FrameView borders manipulation.")]
 	[ScenarioCategory ("Layout")]
 	[ScenarioCategory ("Borders")]
 	public class BordersOnFrameView : Scenario {
-		public override void Setup ()
+		public override void Init (ColorScheme colorScheme)
 		{
-			var borderStyle = BorderStyle.Double;
-			var drawMarginFrame = false;
-			var borderThickness = new Thickness (1, 2, 3, 4);
-			var borderBrush = Colors.Base.HotFocus.Foreground;
-			var padding = new Thickness (1, 2, 3, 4);
-			var background = Colors.Base.HotNormal.Foreground;
-			var effect3D = true;
+			Application.Init ();
 
-			var smartView = new FrameView () {
-				X = Pos.Center (),
-				Y = 0, // Y is set below 
-				Width = 40,
-				Height = 20,
-				Border = new Border () {
-					BorderStyle = borderStyle,
-					DrawMarginFrame = drawMarginFrame,
-					BorderThickness = borderThickness,
-					BorderBrush = borderBrush,
-					Padding = padding,
-					Background = background,
-					Effect3D = effect3D,
-					Title = "Frame"
-				},
-				ColorScheme = Colors.TopLevel
-			};
+			var boc = new BordersOnContainers (
+				$"CTRL-Q to Close - Scenario: {GetName ()}",
+				"FrameView",
+				new FrameView ());
 
-			var tf1 = new TextField ("1234567890") { Width = 10 };
-
-			var button = new Button ("Press me!") {
-				X = Pos.Center (),
-				Y = Pos.Center (),
-			};
-			button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a FrameView?", "Yes", "No");
-			var label = new Label ("I'm a FrameView") {
-				X = Pos.Center (),
-				Y = Pos.Center () - 3,
-			};
-			var tf2 = new TextField ("1234567890") {
-				X = Pos.AnchorEnd (10),
-				Y = Pos.AnchorEnd (1),
-				Width = 10
-			};
-			var tv = new TextView () {
-				Y = Pos.AnchorEnd (2),
-				Width = 10,
-				Height = Dim.Fill (),
-				Text = "1234567890"
-			};
-			smartView.Add (tf1, button, label, tf2, tv);
-
-			Win.Add (new Label ("Padding:") {
-				X = Pos.Center () - 23,
-			});
-
-			var paddingTopEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 1,
-				Width = 5
-			};
-			paddingTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingTopEdit.Text = $"{smartView.Border.Padding.Top}";
-
-			Win.Add (paddingTopEdit);
-
-			var paddingLeftEdit = new TextField ("") {
-				X = Pos.Center () - 30,
-				Y = 2,
-				Width = 5
-			};
-			paddingLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingLeftEdit.Text = $"{smartView.Border.Padding.Left}";
-			Win.Add (paddingLeftEdit);
-
-			var paddingRightEdit = new TextField ("") {
-				X = Pos.Center () - 15,
-				Y = 2,
-				Width = 5
-			};
-			paddingRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingRightEdit.Text = $"{smartView.Border.Padding.Right}";
-			Win.Add (paddingRightEdit);
-
-			var paddingBottomEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 3,
-				Width = 5
-			};
-			paddingBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingBottomEdit.Text = $"{smartView.Border.Padding.Bottom}";
-			Win.Add (paddingBottomEdit);
-
-			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Left (paddingLeftEdit),
-				Y = 5
-			};
-			replacePadding.Clicked += () => {
-				smartView.Border.Padding = new Thickness (smartView.Border.Padding.Top);
-				if (paddingTopEdit.Text.IsEmpty) {
-					paddingTopEdit.Text = "0";
-				}
-				paddingBottomEdit.Text = paddingLeftEdit.Text = paddingRightEdit.Text = paddingTopEdit.Text;
-			};
-			Win.Add (replacePadding);
-
-			Win.Add (new Label ("Border:") {
-				X = Pos.Center () + 11,
-			});
-
-			var borderTopEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 1,
-				Width = 5
-			};
-			borderTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderTopEdit.Text = $"{smartView.Border.BorderThickness.Top}";
-
-			Win.Add (borderTopEdit);
-
-			var borderLeftEdit = new TextField ("") {
-				X = Pos.Center () + 5,
-				Y = 2,
-				Width = 5
-			};
-			borderLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderLeftEdit.Text = $"{smartView.Border.BorderThickness.Left}";
-			Win.Add (borderLeftEdit);
-
-			var borderRightEdit = new TextField ("") {
-				X = Pos.Center () + 19,
-				Y = 2,
-				Width = 5
-			};
-			borderRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderRightEdit.Text = $"{smartView.Border.BorderThickness.Right}";
-			Win.Add (borderRightEdit);
-
-			var borderBottomEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 3,
-				Width = 5
-			};
-			borderBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderBottomEdit.Text = $"{smartView.Border.BorderThickness.Bottom}";
-			Win.Add (borderBottomEdit);
-
-			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Left (borderLeftEdit),
-				Y = 5
-			};
-			replaceBorder.Clicked += () => {
-				smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Top);
-				if (borderTopEdit.Text.IsEmpty) {
-					borderTopEdit.Text = "0";
-				}
-				borderBottomEdit.Text = borderLeftEdit.Text = borderRightEdit.Text = borderTopEdit.Text;
-			};
-			Win.Add (replaceBorder);
-
-			smartView.Y = Pos.Bottom (replaceBorder) + 1;
-
-			Win.Add (new Label ("BorderStyle:"));
-
-			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();
-			var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = 2,
-				Y = 1,
-				SelectedItem = (int)smartView.Border.BorderStyle
-			};
-			Win.Add (rbBorderStyle);
-
-			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartView.Border.DrawMarginFrame) {
-				X = Pos.AnchorEnd (20),
-				Y = 0,
-				Width = 5
-			};
-			cbDrawMarginFrame.Toggled += (e) => {
-				try {
-					smartView.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
-					if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-						cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-					}
-				} catch { }
-			};
-			Win.Add (cbDrawMarginFrame);
-
-			rbBorderStyle.SelectedItemChanged += (e) => {
-				smartView.Border.BorderStyle = (BorderStyle)e.SelectedItem;
-				smartView.SetNeedsDisplay ();
-				if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-					cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-				}
-			};
-
-			var cbEffect3D = new CheckBox ("Draw 3D effects", smartView.Border.Effect3D) {
-				X = Pos.AnchorEnd (20),
-				Y = 1,
-				Width = 5
-			};
-			Win.Add (cbEffect3D);
-
-			Win.Add (new Label ("Effect3D Offset:") {
-				X = Pos.AnchorEnd (20),
-				Y = 2
-			});
-			Win.Add (new Label ("X:") {
-				X = Pos.AnchorEnd (19),
-				Y = 3
-			});
-
-			var effect3DOffsetX = new TextField ("") {
-				X = Pos.AnchorEnd (16),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetX.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Effect3DOffset.Y);
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetX.Text = $"{smartView.Border.Effect3DOffset.X}";
-			Win.Add (effect3DOffsetX);
-
-			Win.Add (new Label ("Y:") {
-				X = Pos.AnchorEnd (10),
-				Y = 3
-			});
-
-			var effect3DOffsetY = new TextField ("") {
-				X = Pos.AnchorEnd (7),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetY.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (smartView.Border.Effect3DOffset.X,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetY.Text = $"{smartView.Border.Effect3DOffset.Y}";
-			Win.Add (effect3DOffsetY);
-
-			cbEffect3D.Toggled += (e) => {
-				try {
-					smartView.Border.Effect3D = effect3DOffsetX.Enabled =
-						effect3DOffsetY.Enabled = (bool)cbEffect3D.Checked;
-				} catch { }
-			};
-
-			Win.Add (new Label ("Background:") {
-				Y = 5
-			});
-
-			var colorEnum = Enum.GetValues (typeof (Color)).Cast<Color> ().ToList ();
-			var rbBackground = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = 2,
-				Y = 6,
-				SelectedItem = (int)smartView.Border.Background
-			};
-			rbBackground.SelectedItemChanged += (e) => {
-				smartView.Border.Background = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBackground);
-
-			Win.Add (new Label ("BorderBrush:") {
-				X = Pos.AnchorEnd (20),
-				Y = 5
-			});
-
-			var rbBorderBrush = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = Pos.AnchorEnd (18),
-				Y = 6,
-				SelectedItem = (int)smartView.Border.BorderBrush
-			};
-			rbBorderBrush.SelectedItemChanged += (e) => {
-				smartView.Border.BorderBrush = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBorderBrush);
+			Application.Run (boc);
+			Application.Shutdown ();
+		}
 
-			Win.Add (smartView);
+		public override void Run ()
+		{
 		}
 	}
 }

+ 12 - 376
UICatalog/Scenarios/BordersOnToplevel.cs

@@ -1,389 +1,25 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using Terminal.Gui;
+using Terminal.Gui;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "Borders on Toplevel", Description: "Demonstrates Toplevel borders manipulation.")]
 	[ScenarioCategory ("Layout")]
 	[ScenarioCategory ("Borders")]
 	public class BordersOnToplevel : Scenario {
-		public override void Setup ()
+		public override void Init (ColorScheme colorScheme)
 		{
-			var borderStyle = BorderStyle.Double;
-			var drawMarginFrame = false;
-			var borderThickness = new Thickness (1, 2, 3, 4);
-			var borderBrush = Colors.Base.HotFocus.Foreground;
-			var padding = new Thickness (1, 2, 3, 4);
-			var background = Colors.Base.HotNormal.Foreground;
-			var effect3D = true;
+			Application.Init ();
 
-			var smartView = new Border.ToplevelContainer () {
-				X = Pos.Center (),
-				Y = 0, // Y is set below 
-				Width = 40,
-				Height = 20,
-				Border = new Border () {
-					BorderStyle = borderStyle,
-					DrawMarginFrame = drawMarginFrame,
-					BorderThickness = borderThickness,
-					BorderBrush = borderBrush,
-					Padding = padding,
-					Background = background,
-					Effect3D = effect3D,
-					Title = "Toplevel"
-				},
-				ColorScheme = Colors.TopLevel
-			};
+			var boc = new BordersOnContainers (
+				$"CTRL-Q to Close - Scenario: {GetName ()}",
+				"Toplevel",
+				new Border.ToplevelContainer ());
 
-			var tf1 = new TextField ("1234567890") { Width = 10 };
-
-			var button = new Button ("Press me!") {
-				X = Pos.Center (),
-				Y = Pos.Center (),
-			};
-			button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Toplevel?", "Yes", "No");
-			var label = new Label ("I'm a Toplevel") {
-				X = Pos.Center (),
-				Y = Pos.Center () - 3,
-			};
-			var tf2 = new TextField ("1234567890") {
-				X = Pos.AnchorEnd (10),
-				Y = Pos.AnchorEnd (1),
-				Width = 10
-			};
-			var tv = new TextView () {
-				Y = Pos.AnchorEnd (2),
-				Width = 10,
-				Height = Dim.Fill (),
-				Text = "1234567890"
-			};
-			smartView.Add (tf1, button, label, tf2, tv);
-
-			Win.Add (new Label ("Padding:") {
-				X = Pos.Center () - 23,
-			});
-
-			var paddingTopEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 1,
-				Width = 5
-			};
-			paddingTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingTopEdit.Text = $"{smartView.Border.Padding.Top}";
-
-			Win.Add (paddingTopEdit);
-
-			var paddingLeftEdit = new TextField ("") {
-				X = Pos.Center () - 30,
-				Y = 2,
-				Width = 5
-			};
-			paddingLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingLeftEdit.Text = $"{smartView.Border.Padding.Left}";
-			Win.Add (paddingLeftEdit);
-
-			var paddingRightEdit = new TextField ("") {
-				X = Pos.Center () - 15,
-				Y = 2,
-				Width = 5
-			};
-			paddingRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingRightEdit.Text = $"{smartView.Border.Padding.Right}";
-			Win.Add (paddingRightEdit);
-
-			var paddingBottomEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 3,
-				Width = 5
-			};
-			paddingBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingBottomEdit.Text = $"{smartView.Border.Padding.Bottom}";
-			Win.Add (paddingBottomEdit);
-
-			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Left(paddingLeftEdit),
-				Y = 5
-			};
-			replacePadding.Clicked += () => {
-				smartView.Border.Padding = new Thickness (smartView.Border.Padding.Top);
-				if (paddingTopEdit.Text.IsEmpty) {
-					paddingTopEdit.Text = "0";
-				}
-				paddingBottomEdit.Text = paddingLeftEdit.Text = paddingRightEdit.Text = paddingTopEdit.Text;
-			};
-			Win.Add (replacePadding);
-
-			Win.Add (new Label ("Border:") {
-				X = Pos.Center () + 11,
-			});
-
-			var borderTopEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 1,
-				Width = 5
-			};
-			borderTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderTopEdit.Text = $"{smartView.Border.BorderThickness.Top}";
-
-			Win.Add (borderTopEdit);
-
-			var borderLeftEdit = new TextField ("") {
-				X = Pos.Center () + 5,
-				Y = 2,
-				Width = 5
-			};
-			borderLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderLeftEdit.Text = $"{smartView.Border.BorderThickness.Left}";
-			Win.Add (borderLeftEdit);
-
-			var borderRightEdit = new TextField ("") {
-				X = Pos.Center () + 19,
-				Y = 2,
-				Width = 5
-			};
-			borderRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderRightEdit.Text = $"{smartView.Border.BorderThickness.Right}";
-			Win.Add (borderRightEdit);
-
-			var borderBottomEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 3,
-				Width = 5
-			};
-			borderBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderBottomEdit.Text = $"{smartView.Border.BorderThickness.Bottom}";
-			Win.Add (borderBottomEdit);
-
-			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Left(borderLeftEdit),
-				Y = 5
-			};
-			replaceBorder.Clicked += () => {
-				smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Top);
-				if (borderTopEdit.Text.IsEmpty) {
-					borderTopEdit.Text = "0";
-				}
-				borderBottomEdit.Text = borderLeftEdit.Text = borderRightEdit.Text = borderTopEdit.Text;
-			};
-			Win.Add (replaceBorder);
-
-			smartView.Y = Pos.Bottom (replaceBorder) + 1;
-
-			Win.Add (new Label ("BorderStyle:"));
-
-			var borderStyleEnum = Enum.GetValues (typeof (BorderStyle)).Cast<BorderStyle> ().ToList ();
-			var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = 2,
-				Y = 1,
-				SelectedItem = (int)smartView.Border.BorderStyle
-			};
-			Win.Add (rbBorderStyle);
-
-			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartView.Border.DrawMarginFrame) {
-				X = Pos.AnchorEnd (20),
-				Y = 0,
-				Width = 5
-			};
-			cbDrawMarginFrame.Toggled += (e) => {
-				try {
-					smartView.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
-					if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-						cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-					}
-				} catch { }
-			};
-			Win.Add (cbDrawMarginFrame);
-
-			rbBorderStyle.SelectedItemChanged += (e) => {
-				smartView.Border.BorderStyle = (BorderStyle)e.SelectedItem;
-				smartView.SetNeedsDisplay ();
-				if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-					cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-				}
-			};
-
-			var cbEffect3D = new CheckBox ("Draw 3D effects", smartView.Border.Effect3D) {
-				X = Pos.AnchorEnd (20),
-				Y = 1,
-				Width = 5
-			};
-			Win.Add (cbEffect3D);
-
-			Win.Add (new Label ("Effect3D Offset:") {
-				X = Pos.AnchorEnd (20),
-				Y = 2
-			});
-			Win.Add (new Label ("X:") {
-				X = Pos.AnchorEnd (19),
-				Y = 3
-			});
-
-			var effect3DOffsetX = new TextField ("") {
-				X = Pos.AnchorEnd (16),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetX.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Effect3DOffset.Y);
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetX.Text = $"{smartView.Border.Effect3DOffset.X}";
-			Win.Add (effect3DOffsetX);
-
-			Win.Add (new Label ("Y:") {
-				X = Pos.AnchorEnd (10),
-				Y = 3
-			});
-
-			var effect3DOffsetY = new TextField ("") {
-				X = Pos.AnchorEnd (7),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetY.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (smartView.Border.Effect3DOffset.X,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetY.Text = $"{smartView.Border.Effect3DOffset.Y}";
-			Win.Add (effect3DOffsetY);
-
-			cbEffect3D.Toggled += (e) => {
-				try {
-					smartView.Border.Effect3D = effect3DOffsetX.Enabled =
-						effect3DOffsetY.Enabled = (bool)cbEffect3D.Checked;
-				} catch { }
-			};
-
-			Win.Add (new Label ("Background:") {
-				Y = 5
-			});
-
-			var colorEnum = Enum.GetValues (typeof (Color)).Cast<Color> ().ToList ();
-			var rbBackground = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = 2,
-				Y = 6,
-				SelectedItem = (int)smartView.Border.Background
-			};
-			rbBackground.SelectedItemChanged += (e) => {
-				smartView.Border.Background = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBackground);
-
-			Win.Add (new Label ("BorderBrush:") {
-				X = Pos.AnchorEnd (20),
-				Y = 5
-			});
-
-			var rbBorderBrush = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = Pos.AnchorEnd (18),
-				Y = 6,
-				SelectedItem = (int)smartView.Border.BorderBrush
-			};
-			rbBorderBrush.SelectedItemChanged += (e) => {
-				smartView.Border.BorderBrush = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBorderBrush);
+			Application.Run (boc);
+			Application.Shutdown ();
+		}
 
-			Win.Add (smartView);
+		public override void Run ()
+		{
 		}
 	}
 }

+ 12 - 375
UICatalog/Scenarios/BordersOnWindow.cs

@@ -1,388 +1,25 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using Terminal.Gui;
+using Terminal.Gui;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "Borders on Window", Description: "Demonstrates Window borders manipulation.")]
 	[ScenarioCategory ("Layout")]
 	[ScenarioCategory ("Borders")]
 	public class BordersOnWindow : Scenario {
-		public override void Setup ()
+		public override void Init (ColorScheme colorScheme)
 		{
-			var borderStyle = BorderStyle.Double;
-			var drawMarginFrame = false;
-			var borderThickness = new Thickness (1, 2, 3, 4);
-			var borderBrush = Colors.Base.HotFocus.Foreground;
-			var padding = new Thickness (1, 2, 3, 4);
-			var background = Colors.Base.HotNormal.Foreground;
-			var effect3D = true;
+			Application.Init ();
 
-			var smartView = new Window () {
-				X = Pos.Center (),
-				Width = 40,
-				Height = 20,
-				Border = new Border () {
-					BorderStyle = borderStyle,
-					DrawMarginFrame = drawMarginFrame,
-					BorderThickness = borderThickness,
-					BorderBrush = borderBrush,
-					Padding = padding,
-					Background = background,
-					Effect3D = effect3D,
-					Title = "Window"
-				},
-				ColorScheme = Colors.TopLevel
-			};
+			var boc = new BordersOnContainers (
+				$"CTRL-Q to Close - Scenario: {GetName ()}",
+				"Window",
+				new Window ());
 
-			var tf1 = new TextField ("1234567890") { Width = 10 };
-
-			var button = new Button ("Press me!") {
-				X = Pos.Center (),
-				Y = Pos.Center (),
-			};
-			button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Window?", "Yes", "No");
-			var label = new Label ("I'm a Window") {
-				X = Pos.Center (),
-				Y = Pos.Center () - 3,
-			};
-			var tf2 = new TextField ("1234567890") {
-				X = Pos.AnchorEnd (10),
-				Y = Pos.AnchorEnd (1),
-				Width = 10
-			};
-			var tv = new TextView () {
-				Y = Pos.AnchorEnd (2),
-				Width = 10,
-				Height = Dim.Fill (),
-				Text = "1234567890"
-			};
-			smartView.Add (tf1, button, label, tf2, tv);
-
-			Win.Add (new Label ("Padding:") {
-				X = Pos.Center () - 23,
-			});
-
-			var paddingTopEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 1,
-				Width = 5
-			};
-			paddingTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingTopEdit.Text = $"{smartView.Border.Padding.Top}";
-
-			Win.Add (paddingTopEdit);
-
-			var paddingLeftEdit = new TextField ("") {
-				X = Pos.Center () - 30,
-				Y = 2,
-				Width = 5
-			};
-			paddingLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingLeftEdit.Text = $"{smartView.Border.Padding.Left}";
-			Win.Add (paddingLeftEdit);
-
-			var paddingRightEdit = new TextField ("") {
-				X = Pos.Center () - 15,
-				Y = 2,
-				Width = 5
-			};
-			paddingRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.Padding.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingRightEdit.Text = $"{smartView.Border.Padding.Right}";
-			Win.Add (paddingRightEdit);
-
-			var paddingBottomEdit = new TextField ("") {
-				X = Pos.Center () - 22,
-				Y = 3,
-				Width = 5
-			};
-			paddingBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.Padding = new Thickness (smartView.Border.Padding.Left,
-						smartView.Border.Padding.Top, smartView.Border.Padding.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			paddingBottomEdit.Text = $"{smartView.Border.Padding.Bottom}";
-			Win.Add (paddingBottomEdit);
-
-			var replacePadding = new Button ("Replace all based on top") {
-				X = Pos.Left (paddingLeftEdit),
-				Y = 5
-			};
-			replacePadding.Clicked += () => {
-				smartView.Border.Padding = new Thickness (smartView.Border.Padding.Top);
-				if (paddingTopEdit.Text.IsEmpty) {
-					paddingTopEdit.Text = "0";
-				}
-				paddingBottomEdit.Text = paddingLeftEdit.Text = paddingRightEdit.Text = paddingTopEdit.Text;
-			};
-			Win.Add (replacePadding);
-
-			Win.Add (new Label ("Border:") {
-				X = Pos.Center () + 11,
-			});
-
-			var borderTopEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 1,
-				Width = 5
-			};
-			borderTopEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						int.Parse (e.NewText.ToString ()), smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderTopEdit.Text = $"{smartView.Border.BorderThickness.Top}";
-
-			Win.Add (borderTopEdit);
-
-			var borderLeftEdit = new TextField ("") {
-				X = Pos.Center () + 5,
-				Y = 2,
-				Width = 5
-			};
-			borderLeftEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderLeftEdit.Text = $"{smartView.Border.BorderThickness.Left}";
-			Win.Add (borderLeftEdit);
-
-			var borderRightEdit = new TextField ("") {
-				X = Pos.Center () + 19,
-				Y = 2,
-				Width = 5
-			};
-			borderRightEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, int.Parse (e.NewText.ToString ()),
-						smartView.Border.BorderThickness.Bottom);
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderRightEdit.Text = $"{smartView.Border.BorderThickness.Right}";
-			Win.Add (borderRightEdit);
-
-			var borderBottomEdit = new TextField ("") {
-				X = Pos.Center () + 12,
-				Y = 3,
-				Width = 5
-			};
-			borderBottomEdit.TextChanging += (e) => {
-				try {
-					smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Left,
-						smartView.Border.BorderThickness.Top, smartView.Border.BorderThickness.Right,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty) {
-						e.Cancel = true;
-					}
-				}
-			};
-			borderBottomEdit.Text = $"{smartView.Border.BorderThickness.Bottom}";
-			Win.Add (borderBottomEdit);
-
-			var replaceBorder = new Button ("Replace all based on top") {
-				X = Pos.Left (borderLeftEdit),
-				Y = 5
-			};
-			replaceBorder.Clicked += () => {
-				smartView.Border.BorderThickness = new Thickness (smartView.Border.BorderThickness.Top);
-				if (borderTopEdit.Text.IsEmpty) {
-					borderTopEdit.Text = "0";
-				}
-				borderBottomEdit.Text = borderLeftEdit.Text = borderRightEdit.Text = borderTopEdit.Text;
-			};
-			Win.Add (replaceBorder);
-
-			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 ()) {
-
-				X = 2,
-				Y = 1,
-				SelectedItem = (int)smartView.Border.BorderStyle
-			};
-			Win.Add (rbBorderStyle);
-
-			var cbDrawMarginFrame = new CheckBox ("Draw Margin Frame", smartView.Border.DrawMarginFrame) {
-				X = Pos.AnchorEnd (20),
-				Y = 0,
-				Width = 5
-			};
-			cbDrawMarginFrame.Toggled += (e) => {
-				try {
-					smartView.Border.DrawMarginFrame = (bool)cbDrawMarginFrame.Checked;
-					if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-						cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-					}
-				} catch { }
-			};
-			Win.Add (cbDrawMarginFrame);
-
-			rbBorderStyle.SelectedItemChanged += (e) => {
-				smartView.Border.BorderStyle = (BorderStyle)e.SelectedItem;
-				smartView.SetNeedsDisplay ();
-				if (cbDrawMarginFrame.Checked != smartView.Border.DrawMarginFrame) {
-					cbDrawMarginFrame.Checked = smartView.Border.DrawMarginFrame;
-				}
-			};
-
-			var cbEffect3D = new CheckBox ("Draw 3D effects", smartView.Border.Effect3D) {
-				X = Pos.AnchorEnd (20),
-				Y = 1,
-				Width = 5
-			};
-			Win.Add (cbEffect3D);
-
-			Win.Add (new Label ("Effect3D Offset:") {
-				X = Pos.AnchorEnd (20),
-				Y = 2
-			});
-			Win.Add (new Label ("X:") {
-				X = Pos.AnchorEnd (19),
-				Y = 3
-			});
-
-			var effect3DOffsetX = new TextField ("") {
-				X = Pos.AnchorEnd (16),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetX.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (int.Parse (e.NewText.ToString ()),
-						smartView.Border.Effect3DOffset.Y);
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetX.Text = $"{smartView.Border.Effect3DOffset.X}";
-			Win.Add (effect3DOffsetX);
-
-			Win.Add (new Label ("Y:") {
-				X = Pos.AnchorEnd (10),
-				Y = 3
-			});
-
-			var effect3DOffsetY = new TextField ("") {
-				X = Pos.AnchorEnd (7),
-				Y = 3,
-				Width = 5
-			};
-			effect3DOffsetY.TextChanging += (e) => {
-				try {
-					smartView.Border.Effect3DOffset = new Point (smartView.Border.Effect3DOffset.X,
-						int.Parse (e.NewText.ToString ()));
-				} catch {
-					if (!e.NewText.IsEmpty && e.NewText != CultureInfo.CurrentCulture.NumberFormat.NegativeSign) {
-						e.Cancel = true;
-					}
-				}
-			};
-			effect3DOffsetY.Text = $"{smartView.Border.Effect3DOffset.Y}";
-			Win.Add (effect3DOffsetY);
-
-			cbEffect3D.Toggled += (e) => {
-				try {
-					smartView.Border.Effect3D = effect3DOffsetX.Enabled =
-						effect3DOffsetY.Enabled = (bool)cbEffect3D.Checked;
-				} catch { }
-			};
-
-			Win.Add (new Label ("Background:") {
-				Y = 5
-			});
-
-			var colorEnum = Enum.GetValues (typeof (Color)).Cast<Color> ().ToList ();
-			var rbBackground = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = 2,
-				Y = 6,
-				SelectedItem = (int)smartView.Border.Background
-			};
-			rbBackground.SelectedItemChanged += (e) => {
-				smartView.Border.Background = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBackground);
-
-			Win.Add (new Label ("BorderBrush:") {
-				X = Pos.AnchorEnd (20),
-				Y = 5
-			});
-
-			var rbBorderBrush = new RadioGroup (colorEnum.Select (
-				e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
-
-				X = Pos.AnchorEnd (18),
-				Y = 6,
-				SelectedItem = (int)smartView.Border.BorderBrush
-			};
-			rbBorderBrush.SelectedItemChanged += (e) => {
-				smartView.Border.BorderBrush = (Color)e.SelectedItem;
-			};
-			Win.Add (rbBorderBrush);
+			Application.Run (boc);
+			Application.Shutdown ();
+		}
 
-			Win.Add (smartView);
+		public override void Run ()
+		{
 		}
 	}
 }

+ 9 - 7
UICatalog/UICatalog.cs

@@ -219,6 +219,7 @@ namespace UICatalog {
 
 		static bool _useSystemConsole = false;
 		static ConsoleDriver.DiagnosticFlags _diagnosticFlags;
+//		static bool _enableConsoleScrolling = false;
 		static bool _isFirstRunning = true;
 		static string _topLevelColorScheme;
 
@@ -355,6 +356,8 @@ namespace UICatalog {
 			{
 				ConfigChanged ();
 
+				miIsMouseDisabled.Checked = Application.IsMouseDisabled;
+				miEnableConsoleScrolling.Checked = Application.EnableConsoleScrolling;
 				DriverName.Title = $"Driver: {Driver.GetType ().Name}";
 				OS.Title = $"OS: {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem} {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion}";
 
@@ -409,13 +412,12 @@ namespace UICatalog {
 
 			List<MenuItem []> CreateDiagnosticMenuItems ()
 			{
-				List<MenuItem []> menuItems = new List<MenuItem []> {
-					CreateDiagnosticFlagsMenuItems (),
-					new MenuItem [] { null },
-					CreateEnableConsoleScrollingMenuItems (),
-					CreateDisabledEnabledMouseItems (),
-					CreateKeybindingsMenuItems ()
-				};
+				List<MenuItem []> menuItems = new List<MenuItem []> ();
+				menuItems.Add (CreateDiagnosticFlagsMenuItems ());
+				menuItems.Add (new MenuItem [] { null });
+				menuItems.Add (CreateEnableConsoleScrollingMenuItems ());
+				menuItems.Add (CreateDisabledEnabledMouseItems ());
+				menuItems.Add (CreateKeybindingsMenuItems ());
 				return menuItems;
 			}
 

+ 66 - 14
UnitTests/Core/BorderTests.cs

@@ -1,15 +1,19 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Reflection.Emit;
 using Xunit;
+using Xunit.Abstractions;
 using Rune = System.Rune;
 
 namespace Terminal.Gui.CoreTests {
 	public class BorderTests {
-		[Fact]
-		[AutoInitShutdown]
+		readonly ITestOutputHelper output;
+
+		public BorderTests (ITestOutputHelper output)
+		{
+			this.output = output;
+		}
+
+		[Fact, AutoInitShutdown]
 		public void Constructor_Defaults ()
 		{
 			var b = new Border ();
@@ -45,8 +49,7 @@ 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 ());
@@ -81,8 +84,7 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Equal (new Thickness (5, 5, 5, 5), b.GetSumThickness ());
 		}
 
-		[Fact]
-		[AutoInitShutdown]
+		[Fact, AutoInitShutdown]
 		public void DrawContent_With_Child_Border ()
 		{
 			var top = Application.Top;
@@ -308,8 +310,7 @@ namespace Terminal.Gui.CoreTests {
 			}
 		}
 
-		[Fact]
-		[AutoInitShutdown]
+		[Fact, AutoInitShutdown]
 		public void DrawContent_With_Parent_Border ()
 		{
 			var top = Application.Top;
@@ -550,8 +551,7 @@ namespace Terminal.Gui.CoreTests {
 			}
 		}
 
-		[Fact]
-		[AutoInitShutdown]
+		[Fact, AutoInitShutdown]
 		public void BorderOnControlWithNoChildren ()
 		{
 			var label = new TextField ("Loading...") {
@@ -567,5 +567,57 @@ 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);
+		}
 	}
 }

+ 321 - 121
UnitTests/Core/LayoutTests.cs

@@ -35,6 +35,53 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
 		}
 
+		[Fact]
+		public void TopologicalSort_Does_Never_Throws_If_Root_Is_Not_Null ()
+		{
+			var root = new View () { Id = "root", Width = 20, Height = 20 };
+			var sub1 = new View () {
+				Id = "sub1",
+				X = Pos.Left (root) + 1,
+				Y = Pos.Top (root) + 1,
+				Width = Dim.Width (root) - 2,
+				Height = Dim.Height (root) - 2
+			};
+			var sub2 = new View () {
+				Id = "sub2",
+				X = Pos.Left (root) + 1,
+				Y = Pos.Top (root) + 1,
+				Width = Dim.Width (root) - 2,
+				Height = Dim.Height (root) - 2
+			};
+			var sub3 = new View () {
+				Id = "sub3",
+				X = Pos.Left (root) + 1,
+				Y = Pos.Top (root) + 1,
+				Width = Dim.Width (root) - 2,
+				Height = Dim.Height (root) - 2
+			};
+			sub2.Add (sub3);
+			sub1.Add (sub2);
+			root.Add (sub1);
+
+			var exception = Record.Exception (root.LayoutSubviews);
+			Assert.Null (exception);
+			Assert.Equal (new Rect (0, 0, 20, 20), root.Frame);
+			Assert.Equal (new Rect (1, 1, 18, 18), sub1.Frame);
+			Assert.Equal (new Rect (1, 1, 18, 18), sub2.Frame);
+			Assert.Equal (new Rect (1, 1, 18, 18), sub3.Frame);
+
+			sub2.Width = Dim.Width (root);
+			exception = Record.Exception (root.LayoutSubviews);
+			Assert.Null (exception);
+			Assert.Equal (new Rect (1, 1, 20, 18), sub2.Frame);
+
+			sub3.Width = Dim.Width (root);
+			exception = Record.Exception (root.LayoutSubviews);
+			Assert.Null (exception);
+			Assert.Equal (new Rect (1, 1, 20, 18), sub3.Frame);
+		}
+
 		[Fact]
 		public void TopologicalSort_Recursive_Ref ()
 		{
@@ -598,10 +645,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view.Height.ToString ());
 			var expected = @"
 ┌────────────────────┐
 │                    │
@@ -635,10 +682,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │Hello World         │
@@ -672,10 +719,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │Hello Worlds        │
@@ -708,10 +755,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │H                   │
@@ -745,10 +792,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │HelloWorlds         │
@@ -781,10 +828,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │Hello World         │
@@ -821,10 +868,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(1)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │H                   │
@@ -857,10 +904,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view.Y.ToString ());
+			Assert.Equal ("DimAbsolute(1)", view.Width.ToString ());
+			Assert.Equal ("DimAbsolute(11)", view.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │H                   │
@@ -921,15 +968,15 @@ Y
 			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 ("PosAbsolute(0)", horizontalView.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", horizontalView.Y.ToString ());
+			Assert.Equal ("DimAbsolute(9)", horizontalView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ());
+			Assert.Equal ("PosAbsolute(0)", verticalView.X.ToString ());
+			Assert.Equal ("PosAbsolute(3)", verticalView.Y.ToString ());
+			Assert.Equal ("DimAbsolute(2)", verticalView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(8)", verticalView.Height.ToString ());
 			var expected = @"
 ┌────────────────────┐
 │Finish 終           │
@@ -964,10 +1011,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", verticalView.X.ToString ());
+			Assert.Equal ("PosAbsolute(3)", verticalView.Y.ToString ());
+			Assert.Equal ("DimAbsolute(2)", verticalView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(8)", verticalView.Height.ToString ());
 			expected = @"
 ┌────────────────────┐
 │Finish 終           │
@@ -1079,28 +1126,28 @@ Y
 			Assert.False (view5.IsInitialized);
 			Assert.False (view1.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame);
-			Assert.Equal ("Absolute(10)", view1.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view1.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ());
 			Assert.False (view2.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame);
-			Assert.Equal ("Absolute(10)", view2.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view2.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ());
 			Assert.False (view3.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame);
-			Assert.Equal ("Absolute(10)", view3.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view3.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ());
 			Assert.False (view4.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame);
-			Assert.Equal ("Absolute(10)", view4.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view4.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ());
 			Assert.False (view5.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame);
-			Assert.Equal ("Absolute(10)", view5.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view5.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ());
 			Assert.False (view6.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame);
-			Assert.Equal ("Absolute(10)", view6.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view6.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ());
 
 			Application.Begin (Application.Top);
 
@@ -1111,28 +1158,28 @@ Y
 			Assert.True (view5.IsInitialized);
 			Assert.False (view1.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame);
-			Assert.Equal ("Absolute(10)", view1.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view1.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ());
 			Assert.False (view2.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame);
-			Assert.Equal ("Absolute(10)", view2.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view2.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ());
 			Assert.False (view3.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame);
-			Assert.Equal ("Absolute(10)", view3.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view3.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ());
 			Assert.False (view4.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame);
-			Assert.Equal ("Absolute(10)", view4.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view4.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ());
 			Assert.False (view5.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame);
-			Assert.Equal ("Absolute(10)", view5.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view5.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ());
 			Assert.False (view6.AutoSize);
 			Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame);
-			Assert.Equal ("Absolute(10)", view6.Width.ToString ());
-			Assert.Equal ("Absolute(5)", view6.Height.ToString ());
+			Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ());
 		}
 
 		[Fact, AutoInitShutdown]
@@ -1171,28 +1218,28 @@ Y
 			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.Equal ("DimAbsolute(10)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view3.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view4.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view5.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ());
+			Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ());
 
 			Application.Begin (Application.Top);
 
@@ -1203,28 +1250,28 @@ Y
 			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.Equal ("DimAbsolute(10)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view3.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view4.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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.Equal ("DimAbsolute(10)", view5.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ());
+			Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ());
+			Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ());
 		}
 
 		[Fact, AutoInitShutdown]
@@ -1243,17 +1290,17 @@ Y
 			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.Equal ("PosAbsolute(0)", view1.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ());
+			Assert.Equal ("DimAbsolute(18)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ());
+			Assert.Equal ("PosAbsolute(0)", view2.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view2.Y.ToString ());
+			Assert.Equal ("DimAbsolute(2)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(17)", view2.Height.ToString ());
 
 			view1.Frame = new Rect (0, 0, 25, 4);
 			bool firstIteration = false;
@@ -1262,10 +1309,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view1.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ());
+			Assert.Equal ("DimAbsolute(18)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", view1.Height.ToString ());
 
 			view2.Frame = new Rect (0, 0, 1, 25);
 			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
@@ -1273,10 +1320,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view2.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view2.Y.ToString ());
+			Assert.Equal ("DimAbsolute(2)", view2.Width.ToString ());
+			Assert.Equal ("DimAbsolute(17)", view2.Height.ToString ());
 		}
 
 		[Fact, AutoInitShutdown]
@@ -1291,10 +1338,10 @@ Y
 			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 ());
+			Assert.Equal ("PosAbsolute(0)", view1.X.ToString ());
+			Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view1.Width.ToString ());
+			Assert.Equal ("DimAbsolute(0)", view1.Height.ToString ());
 
 			var view2 = new View () {
 				X = Pos.Center (),
@@ -1303,16 +1350,16 @@ Y
 				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 ());
+			Assert.Equal ("PosCenter", view2.X.ToString ());
+			Assert.Equal ("PosCenter", view2.Y.ToString ());
+			Assert.Equal ("DimFill(0)", view2.Width.ToString ());
+			Assert.Equal ("DimFill(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 ());
+			Assert.Equal ("PosCenter", view2.X.ToString ());
+			Assert.Equal ("PosCenter", view2.Y.ToString ());
+			Assert.Equal ("DimFill(0)", view2.Width.ToString ());
+			Assert.Equal ("DimFill(0)", view2.Height.ToString ());
 		}
 
 		[Fact]
@@ -1398,7 +1445,7 @@ Y
 
 			testView = new View () {
 				AutoSize = false,
-				X = Pos.Left(testView),
+				X = Pos.Left (testView),
 				Y = Pos.Left (testView),
 				Width = 1,
 				Height = 1
@@ -1420,5 +1467,158 @@ Y
 			Assert.Equal (6, testView.Frame.X);
 			Assert.Equal (6, testView.Frame.Y);
 		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void Y_Center_Minus_Absolute_Inside_Window_Height_Ten ()
+		{
+			var win = new Window ();
+
+			var label = new Label ("This should be the first line.") {
+				TextAlignment = Terminal.Gui.TextAlignment.Centered,
+				ColorScheme = Colors.Menu,
+				Width = Dim.Fill (),
+				X = Pos.Center (),
+				Y = Pos.Center () - 3  // center minus 3 minus two lines top and bottom borders equal to zero (5-3-2=0)
+			};
+
+			var button = new Button ("Press me!") {
+				X = Pos.Center (),
+				Y = Pos.Center ()
+			};
+
+			win.Add (label, button);
+
+			var top = Application.Top;
+			top.Add (win);
+			Application.Begin (top);
+			((FakeDriver)Application.Driver).SetBufferSize (40, 10);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
+			Assert.Equal (new Rect (0, 0, 40, 10), win.Frame);
+			Assert.Equal (new Rect (1, 1, 38, 8), win.Subviews [0].Frame);
+			Assert.Equal ("ContentView()({X=1,Y=1,Width=38,Height=8})", win.Subviews [0].ToString ());
+			Assert.Equal (new Rect (0, 0, 40, 10), new Rect (
+				win.Frame.Left, win.Frame.Top,
+				win.Frame.Right, win.Frame.Bottom));
+			Assert.Equal (new Rect (0, 0, 38, 1), label.Frame);
+			Assert.Equal (new Rect (12, 3, 13, 1), button.Frame);
+			var expected = @"
+┌──────────────────────────────────────┐
+│    This should be the first line.    │
+│                                      │
+│                                      │
+│            [ Press me! ]             │
+│                                      │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void Y_Center_Minus_Absolute_Inside_Window_Height_Nine ()
+		{
+			var win = new Window ();
+
+			var label = new Label ("This should be the first line.") {
+				TextAlignment = Terminal.Gui.TextAlignment.Centered,
+				ColorScheme = Colors.Menu,
+				Width = Dim.Fill (),
+				X = Pos.Center (),
+				Y = Pos.Center () - 3  // center minus 2 minus two lines top and bottom borders equal to zero (5-3-2=0)
+			};
+
+			var button = new Button ("Press me!") {
+				X = Pos.Center (),
+				Y = Pos.Center ()
+			};
+
+			win.Add (label, button);
+
+			var top = Application.Top;
+			top.Add (win);
+			Application.Begin (top);
+			((FakeDriver)Application.Driver).SetBufferSize (40, 9);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 40, 9), top.Frame);
+			Assert.Equal (new Rect (0, 0, 40, 9), win.Frame);
+			Assert.Equal (new Rect (1, 1, 38, 7), win.Subviews [0].Frame);
+			Assert.Equal ("ContentView()({X=1,Y=1,Width=38,Height=7})", win.Subviews [0].ToString ());
+			Assert.Equal (new Rect (0, 0, 40, 9), new Rect (
+				win.Frame.Left, win.Frame.Top,
+				win.Frame.Right, win.Frame.Bottom));
+			Assert.Equal (new Rect (0, 0, 38, 1), label.Frame);
+			Assert.Equal (new Rect (12, 3, 13, 1), button.Frame);
+			var expected = @"
+┌──────────────────────────────────────┐
+│    This should be the first line.    │
+│                                      │
+│                                      │
+│            [ Press me! ]             │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void Y_Center_Minus_Absolute_Inside_Window_Height_Eight ()
+		{
+			var win = new Window ();
+
+			var label = new Label ("This should be the first line.") {
+				TextAlignment = Terminal.Gui.TextAlignment.Centered,
+				ColorScheme = Colors.Menu,
+				Width = Dim.Fill (),
+				X = Pos.Center (),
+				Y = Pos.Center () - 2  // center minus 2 minus two lines top and bottom borders equal to zero (4-2-2=0)
+			};
+
+			var button = new Button ("Press me!") {
+				X = Pos.Center (),
+				Y = Pos.Center ()
+			};
+
+			win.Add (label, button);
+
+			var top = Application.Top;
+			top.Add (win);
+			Application.Begin (top);
+			((FakeDriver)Application.Driver).SetBufferSize (40, 8);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 40, 8), top.Frame);
+			Assert.Equal (new Rect (0, 0, 40, 8), win.Frame);
+			Assert.Equal (new Rect (1, 1, 38, 6), win.Subviews [0].Frame);
+			Assert.Equal ("ContentView()({X=1,Y=1,Width=38,Height=6})", win.Subviews [0].ToString ());
+			Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+				win.Frame.Left, win.Frame.Top,
+				win.Frame.Right, win.Frame.Bottom));
+			Assert.Equal (new Rect (0, 0, 38, 1), label.Frame);
+			Assert.Equal (new Rect (12, 2, 13, 1), button.Frame);
+			var expected = @"
+┌──────────────────────────────────────┐
+│    This should be the first line.    │
+│                                      │
+│            [ Press me! ]             │
+│                                      │
+│                                      │
+│                                      │
+└──────────────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+		}
 	}
 }

+ 99 - 0
UnitTests/Core/ViewTests.cs

@@ -2857,5 +2857,104 @@ At 0,0
 222";
 			TestHelpers.AssertDriverContentsAre (looksLike, output);
 		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void Frame_Set_After_Initialze_Update_NeededDisplay ()
+		{
+			var frame = new FrameView ();
+
+			var label = new Label ("This should be the first line.") {
+				TextAlignment = Terminal.Gui.TextAlignment.Centered,
+				ColorScheme = Colors.Menu,
+				Width = Dim.Fill (),
+				X = Pos.Center (),
+				Y = Pos.Center () - 2  // center minus 2 minus two lines top and bottom borders equal to zero (4-2-2=0)
+			};
+
+			var button = new Button ("Press me!") {
+				X = Pos.Center (),
+				Y = Pos.Center ()
+			};
+
+			frame.Add (label, button);
+
+			frame.X = Pos.Center ();
+			frame.Y = Pos.Center ();
+			frame.Width = 40;
+			frame.Height = 8;
+
+			var top = Application.Top;
+
+			top.Add (frame);
+
+			Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
+			Assert.Equal (new Rect (0, 0, 40, 8), frame.Frame);
+			Assert.Equal (new Rect (1, 1, 0, 0), frame.Subviews [0].Frame);
+			Assert.Equal ("ContentView()({X=1,Y=1,Width=0,Height=0})", frame.Subviews [0].ToString ());
+			Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+				frame.Frame.Left, frame.Frame.Top,
+				frame.Frame.Right, frame.Frame.Bottom));
+			Assert.Equal (new Rect (0, 0, 30, 1), label.Frame);
+			Assert.Equal (new Rect (0, 0, 13, 1), button.Frame);
+
+			Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+			Assert.Equal (Rect.Empty, frame.Subviews [0].NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+				frame.NeedDisplay.Left, frame.NeedDisplay.Top,
+				frame.NeedDisplay.Right, frame.NeedDisplay.Bottom));
+			Assert.Equal (new Rect (0, 0, 30, 1), label.NeedDisplay);
+			Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+
+			top.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+			};
+
+			frame.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+			};
+
+			frame.Subviews [0].LayoutComplete += e => {
+				if (top.IsLoaded) {
+					Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay);
+				} else {
+					Assert.Equal (new Rect (1, 1, 38, 6), frame.Subviews [0].NeedDisplay);
+				}
+			};
+
+			label.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 38, 1), label.NeedDisplay);
+			};
+
+			button.LayoutComplete += e => {
+				Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+			};
+
+			Application.Begin (top);
+
+			Assert.True (label.AutoSize);
+			Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
+			Assert.Equal (new Rect (20, 8, 40, 8), frame.Frame);
+			Assert.Equal (new Rect (1, 1, 38, 6), frame.Subviews [0].Frame);
+			Assert.Equal ("ContentView()({X=1,Y=1,Width=38,Height=6})", frame.Subviews [0].ToString ());
+			Assert.Equal (new Rect (20, 8, 60, 16), new Rect (
+				frame.Frame.Left, frame.Frame.Top,
+				frame.Frame.Right, frame.Frame.Bottom));
+			Assert.Equal (new Rect (0, 0, 38, 1), label.Frame);
+			Assert.Equal (new Rect (12, 2, 13, 1), button.Frame);
+			var expected = @"
+                    ┌──────────────────────────────────────┐
+                    │    This should be the first line.    │
+                    │                                      │
+                    │            [ Press me! ]             │
+                    │                                      │
+                    │                                      │
+                    │                                      │
+                    └──────────────────────────────────────┘
+";
+
+			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+		}
 	}
 }

+ 50 - 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 ("Fill(0)", top.Width.ToString ());
-			Assert.Equal ("Fill(0)", top.Height.ToString ());
+			Assert.Equal ("DimFill(0)", top.Width.ToString ());
+			Assert.Equal ("DimFill(0)", top.Height.ToString ());
 			Assert.False (top.Running);
 			Assert.False (top.Modal);
 			Assert.Null (top.MenuBar);
@@ -1033,5 +1033,53 @@ namespace Terminal.Gui.TopLevelTests {
 			Application.Driver.GetCursorVisibility (out cursor);
 			Assert.Equal (CursorVisibility.Invisible, cursor);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void IsLoaded_Application_Begin ()
+		{
+			var top = Application.Top;
+			Assert.False (top.IsLoaded);
+
+			Application.Begin (top);
+			Assert.True (top.IsLoaded);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void IsLoaded_With_Sub_Toplevel_Application_Begin_NeedDisplay ()
+		{
+			var top = Application.Top;
+			var subTop = new Toplevel ();
+			var view = new View (new Rect (0, 0, 20, 10));
+			subTop.Add (view);
+			top.Add (subTop);
+
+			Assert.False (top.IsLoaded);
+			Assert.False (subTop.IsLoaded);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+
+			view.LayoutStarted += view_LayoutStarted;
+
+			void view_LayoutStarted (View.LayoutEventArgs e)
+			{
+				Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+				view.LayoutStarted -= view_LayoutStarted;
+			}
+
+			Application.Begin (top);
+
+			Assert.True (top.IsLoaded);
+			Assert.True (subTop.IsLoaded);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+
+			view.Frame = new Rect (1, 3, 10, 5);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.Frame);
+			Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+
+			view.Redraw (view.Bounds);
+			view.Frame = new Rect (1, 3, 10, 5);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.Frame);
+			Assert.Equal (new Rect (1, 3, 10, 5), view.NeedDisplay);
+		}
 	}
 }

+ 68 - 68
UnitTests/Types/DimTests.cs

@@ -37,15 +37,15 @@ namespace Terminal.Gui.TypeTests {
 		public void Sized_SetsValue ()
 		{
 			var dim = Dim.Sized (0);
-			Assert.Equal ("Absolute(0)", dim.ToString ());
+			Assert.Equal ("DimAbsolute(0)", dim.ToString ());
 
 			int testVal = 5;
 			dim = Dim.Sized (testVal);
-			Assert.Equal ($"Absolute({testVal})", dim.ToString ());
+			Assert.Equal ($"DimAbsolute({testVal})", dim.ToString ());
 
 			testVal = -1;
 			dim = Dim.Sized (testVal);
-			Assert.Equal ($"Absolute({testVal})", dim.ToString ());
+			Assert.Equal ($"DimAbsolute({testVal})", dim.ToString ());
 		}
 
 		[Fact]
@@ -155,15 +155,15 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var testMargin = 0;
 			var dim = Dim.Fill ();
-			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
+			Assert.Equal ($"DimFill({testMargin})", dim.ToString ());
 
 			testMargin = 0;
 			dim = Dim.Fill (testMargin);
-			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
+			Assert.Equal ($"DimFill({testMargin})", dim.ToString ());
 
 			testMargin = 5;
 			dim = Dim.Fill (testMargin);
-			Assert.Equal ($"Fill({testMargin})", dim.ToString ());
+			Assert.Equal ($"DimFill({testMargin})", dim.ToString ());
 		}
 
 
@@ -182,13 +182,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			float f = 0;
 			var dim = Dim.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
+			Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ());
 			f = 0.5F;
 			dim = Dim.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
+			Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ());
 			f = 100;
 			dim = Dim.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
+			Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ());
 		}
 
 		[Fact]
@@ -420,48 +420,48 @@ namespace Terminal.Gui.TypeTests {
 			t.Add (w);
 
 			t.Ready += () => {
-				Assert.Equal ("Absolute(100)", w.Width.ToString ());
-				Assert.Equal ("Absolute(100)", w.Height.ToString ());
+				Assert.Equal ("DimAbsolute(100)", w.Width.ToString ());
+				Assert.Equal ("DimAbsolute(100)", w.Height.ToString ());
 				Assert.Equal (100, w.Frame.Width);
 				Assert.Equal (100, w.Frame.Height);
 
-				Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
-				Assert.Equal ("Absolute(5)", f1.Height.ToString ());
+				Assert.Equal ("DimFactor(0.5,False)", f1.Width.ToString ());
+				Assert.Equal ("DimAbsolute(5)", f1.Height.ToString ());
 				Assert.Equal (49, f1.Frame.Width); // 50-1=49
 				Assert.Equal (5, f1.Frame.Height);
 
-				Assert.Equal ("Fill(0)", f2.Width.ToString ());
-				Assert.Equal ("Absolute(5)", f2.Height.ToString ());
+				Assert.Equal ("DimFill(0)", f2.Width.ToString ());
+				Assert.Equal ("DimAbsolute(5)", f2.Height.ToString ());
 				Assert.Equal (49, f2.Frame.Width); // 50-1=49
 				Assert.Equal (5, f2.Frame.Height);
 	
-				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 ("DimCombine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-DimAbsolute(2))", v1.Width.ToString ());
+				Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(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 ("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 ("DimCombine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-DimAbsolute(2))", v2.Width.ToString ());
+				Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(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 ("Factor(0.1,False)", v3.Width.ToString ());
-				Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
+				Assert.Equal ("DimFactor(0.1,False)", v3.Width.ToString ());
+				Assert.Equal ("DimFactor(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 ("Absolute(50)", v4.Width.ToString ());
-				Assert.Equal ("Absolute(50)", v4.Height.ToString ());
+				Assert.Equal ("DimAbsolute(50)", v4.Width.ToString ());
+				Assert.Equal ("DimAbsolute(50)", v4.Height.ToString ());
 				Assert.Equal (50, v4.Frame.Width);
 				Assert.Equal (50, v4.Frame.Height);
 
-				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 ("DimCombine(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 ("DimCombine(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 ("Factor(0.2,True)", v6.Width.ToString ());
-				Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
+				Assert.Equal ("DimFactor(0.2,True)", v6.Width.ToString ());
+				Assert.Equal ("DimFactor(0.2,True)", v6.Height.ToString ());
 				Assert.Equal (9, v6.Frame.Width); // 47*20%=9
 				Assert.Equal (18, v6.Frame.Height); // 89*20%=18
 
@@ -469,64 +469,64 @@ namespace Terminal.Gui.TypeTests {
 				w.Height = 200;
 				t.LayoutSubviews ();
 
-				Assert.Equal ("Absolute(200)", w.Width.ToString ());
-				Assert.Equal ("Absolute(200)", w.Height.ToString ());
+				Assert.Equal ("DimAbsolute(200)", w.Width.ToString ());
+				Assert.Equal ("DimAbsolute(200)", w.Height.ToString ());
 				Assert.Equal (200, w.Frame.Width);
 				Assert.Equal (200, w.Frame.Height);
 
 				f1.Text = "Frame1";
 				Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
 				Assert.Equal ("Absolute(5)", f1.Height.ToString ());
-				Assert.Equal (49, f1.Frame.Width); // 100*0.5=49
+				Assert.Equal (99, f1.Frame.Width); // 100-1=99
 				Assert.Equal (5, f1.Frame.Height);
 
 				f2.Text = "Frame2";
 				Assert.Equal ("Fill(0)", f2.Width.ToString ());
 				Assert.Equal ("Absolute(5)", f2.Height.ToString ());
-				Assert.Equal (49, f2.Frame.Width); // f2.X = Pos.Right(f1), thus 50-1=49
+				Assert.Equal (99, f2.Frame.Width); // 100-1=99
 				Assert.Equal (5, f2.Frame.Height);
 
 				v1.Text = "Button1";
-				Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.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 (47, v1.Frame.Width); // 49-2=47
-				Assert.Equal (89, v1.Frame.Height); // 98-2-7=89
+				Assert.Equal (97, v1.Frame.Width); // 99-2=97
+				Assert.Equal (189, v1.Frame.Height); // 198-2-7=189
 
 				v2.Text = "Button2";
-				Assert.Equal ("Combine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.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 (47, v2.Frame.Width); // 49-2=47
-				Assert.Equal (89, v2.Frame.Height); // 98-2-7=89
+				Assert.Equal (97, v2.Frame.Width); // 99-2=97
+				Assert.Equal (189, v2.Frame.Height); // 198-2-7=189
 
 				v3.Text = "Button3";
 				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 * Percent is related to the super-view if it isn't null otherwise the view width
-				Assert.Equal (9, v3.Frame.Height); // 99*10%=9
+				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 ("Absolute(50)", v4.Width.ToString ());
-				Assert.Equal ("Absolute(50)", v4.Height.ToString ());
+				Assert.Equal ("DimAbsolute(50)", v4.Width.ToString ());
+				Assert.Equal ("DimAbsolute(50)", v4.Height.ToString ());
 				Assert.Equal (50, v4.Frame.Width);
 				Assert.Equal (50, v4.Frame.Height);
 				v4.AutoSize = true;
-				Assert.Equal ("Absolute(11)", v4.Width.ToString ());
-				Assert.Equal ("Absolute(1)", v4.Height.ToString ());
+				Assert.Equal ("DimAbsolute(11)", v4.Width.ToString ());
+				Assert.Equal ("DimAbsolute(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 ("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 ("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 ("Factor(0.2,True)", v6.Width.ToString ());
 				Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
-				Assert.Equal (9, v6.Frame.Width); // 49*20%=9
-				Assert.Equal (18, v6.Frame.Height); // 98-7*20=18
+				Assert.Equal (19, v6.Frame.Width); // 99*20%=19
+				Assert.Equal (38, v6.Frame.Height); // 198-7*20=38
 			};
 
 			Application.Iteration += () => Application.RequestStop ();
@@ -634,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 ($"Absolute({count})", label.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({count})", label.Y.ToString ());
 
-					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ());
 					view.Height += 1;
 					count++;
-					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ());
 				}
 			};
 
@@ -1006,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 ($"Absolute({count + 1})", label.Y.ToString ());
+						Assert.Equal ($"PosAbsolute({count + 1})", label.Y.ToString ());
 						listLabels.Add (label);
 						if (count == 0) {
-							Assert.Equal ($"Absolute({count})", view.Height.ToString ());
+							Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ());
 							view.Height += 2;
 						} else {
-							Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
+							Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ());
 							view.Height += 1;
 						}
 						count++;
 					}
-					Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ());
 				}
 			};
 
@@ -1066,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 ($"Absolute({i})", label.Y.ToString ());
+				Assert.Equal ($"PosAbsolute({i})", label.Y.ToString ());
 				listLabels.Add (label);
 
-				Assert.Equal ($"Absolute({i})", view.Height.ToString ());
+				Assert.Equal ($"DimAbsolute({i})", view.Height.ToString ());
 				view.Height += 1;
-				Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
+				Assert.Equal ($"DimAbsolute({i + 1})", view.Height.ToString ());
 			}
 
 			field.KeyDown += (k) => {
@@ -1079,10 +1079,10 @@ namespace Terminal.Gui.TypeTests {
 					Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
 					view.Remove (listLabels [count - 1]);
 
-					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ());
 					view.Height -= 1;
 					count--;
-					Assert.Equal ($"Absolute({count})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ());
 				}
 			};
 
@@ -1125,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 ($"Absolute({i + 1})", label.Y.ToString ());
+				Assert.Equal ($"PosAbsolute({i + 1})", label.Y.ToString ());
 				listLabels.Add (label);
 
 				if (i == 0) {
-					Assert.Equal ($"Absolute({i})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({i})", view.Height.ToString ());
 					view.Height += 2;
-					Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({i + 2})", view.Height.ToString ());
 				} else {
-					Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({i + 1})", view.Height.ToString ());
 					view.Height += 1;
-					Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({i + 2})", view.Height.ToString ());
 				}
 			}
 
@@ -1149,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 ($"Absolute({count + 1})", view.Height.ToString ());
+						Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ());
 						view.Height -= 1;
 						count--;
 						if (listLabels.Count > 0)
@@ -1157,7 +1157,7 @@ namespace Terminal.Gui.TypeTests {
 						else
 							field.Text = NStack.ustring.Empty;
 					}
-					Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
+					Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ());
 				}
 			};
 

+ 47 - 47
UnitTests/Types/PosTests.cs

@@ -32,11 +32,11 @@ namespace Terminal.Gui.TypeTests {
 		{
 			var n = 0;
 			var pos = Pos.AnchorEnd ();
-			Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
+			Assert.Equal ($"PosAnchorEnd({n})", pos.ToString ());
 
 			n = 5;
 			pos = Pos.AnchorEnd (n);
-			Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
+			Assert.Equal ($"PosAnchorEnd({n})", pos.ToString ());
 		}
 
 		[Fact]
@@ -351,13 +351,13 @@ namespace Terminal.Gui.TypeTests {
 		public void At_SetsValue ()
 		{
 			var pos = Pos.At (0);
-			Assert.Equal ("Absolute(0)", pos.ToString ());
+			Assert.Equal ("PosAbsolute(0)", pos.ToString ());
 
 			pos = Pos.At (5);
-			Assert.Equal ("Absolute(5)", pos.ToString ());
+			Assert.Equal ("PosAbsolute(5)", pos.ToString ());
 
 			pos = Pos.At (-1);
-			Assert.Equal ("Absolute(-1)", pos.ToString ());
+			Assert.Equal ("PosAbsolute(-1)", pos.ToString ());
 		}
 
 		[Fact]
@@ -411,140 +411,140 @@ namespace Terminal.Gui.TypeTests {
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Left (new View ());
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Left (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Left (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Left(win) + 0
 			pos = Pos.Left (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Left(win) +1
 			pos = Pos.Left (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Left(win) -1
 			pos = Pos.Left (new View (testRect)) - testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.X
 			side = "x";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.X (new View ());
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			pos = Pos.X (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.X (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.X(win) + 0
 			pos = Pos.X (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.X(win) +1
 			pos = Pos.X (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.X(win) -1
 			pos = Pos.X (new View (testRect)) - testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Top
 			side = "y";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Top (new View ());
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Top (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Top (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Top(win) + 0
 			pos = Pos.Top (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Top(win) +1
 			pos = Pos.Top (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Top(win) -1
 			pos = Pos.Top (new View (testRect)) - testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Y
 			side = "y";
 			testInt = 0;
 			testRect = Rect.Empty;
 			pos = Pos.Y (new View ());
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Y (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Y (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Y(win) + 0
 			pos = Pos.Y (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Y(win) +1
 			pos = Pos.Y (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Y(win) -1
 			pos = Pos.Y (new View (testRect)) - testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Bottom
 			side = "bottom";
 			testRect = Rect.Empty;
 			testInt = 0;
 			pos = Pos.Bottom (new View ());
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			pos = Pos.Bottom (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testRect = new Rect (1, 2, 3, 4);
 			pos = Pos.Bottom (new View (testRect));
-			Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ());
+			Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			// Pos.Bottom(win) + 0
 			pos = Pos.Bottom (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = 1;
 			// Pos.Bottom(win) +1
 			pos = Pos.Bottom (new View (testRect)) + testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ());
 
 			testInt = -1;
 			// Pos.Bottom(win) -1
 			pos = Pos.Bottom (new View (testRect)) - testInt;
-			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 ());
+			Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({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 ("Center", pos.ToString ());
+			Assert.Equal ("PosCenter", pos.ToString ());
 		}
 
 		[Fact]
@@ -640,13 +640,13 @@ namespace Terminal.Gui.TypeTests {
 		{
 			float f = 0;
 			var pos = Pos.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"PosFactor({f / 100:0.###})", pos.ToString ());
 			f = 0.5F;
 			pos = Pos.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"PosFactor({f / 100:0.###})", pos.ToString ());
 			f = 100;
 			pos = Pos.Percent (f);
-			Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ());
+			Assert.Equal ($"PosFactor({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 ($"Absolute({count})", label.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({count})", label.Y.ToString ());
 
-					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ());
 					field.Y += 1;
 					count++;
-					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({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 ($"Absolute({i})", field.Y.ToString ());
+				Assert.Equal ($"PosAbsolute({i})", field.Y.ToString ());
 				listLabels.Add (label);
 
-				Assert.Equal ($"Absolute({i})", field.Y.ToString ());
+				Assert.Equal ($"PosAbsolute({i})", field.Y.ToString ());
 				field.Y += 1;
-				Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ());
+				Assert.Equal ($"PosAbsolute({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 ($"Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ());
 					field.Y -= 1;
 					count--;
-					Assert.Equal ($"Absolute({count})", field.Y.ToString ());
+					Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ());
 				}
 			};
 

+ 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 ("Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
+			Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.False (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
+			Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
+			Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (25, _scrollBar.Bounds.Height);
 			Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.False (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))",
+			Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(1)", _scrollBar.Width.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ());
 			Assert.Equal (1, _scrollBar.Bounds.Width);
-			Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.Height.ToString ());
 			Assert.Equal (24, _scrollBar.Bounds.Height);
 			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 			Assert.True (_scrollBar.OtherScrollBarView.Visible);
-			Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))",
+			Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))",
 				_scrollBar.OtherScrollBarView.Width.ToString ());
 			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
-			Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ());
 			Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height);
 		}
 

+ 223 - 5
UnitTests/Views/ScrollViewTests.cs

@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using NStack;
 using Xunit;
 using Xunit.Abstractions;
 
@@ -280,5 +276,227 @@ 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 ("AnchorEnd(1)", sb.Y.ToString ());
+			Assert.Equal ("PosAnchorEnd(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 ("Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Absolute(10)", _textView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Absolute(1)", _textView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(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 ("Absolute(30)", _textView.Width.ToString ());
-			Assert.Equal ("Absolute(10)", _textView.Height.ToString ());
+			Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ());
+			Assert.Equal ("DimAbsolute(10)", _textView.Height.ToString ());
 			Assert.False (_textView.WordWrap);
 		}