Browse Source

Merge pull request #620 from tig/computed_layout_allviews

Adds new Scenario for testing all Views - Adds parameterless constructors to all Views
Charlie Kindel 5 years ago
parent
commit
ec6f896258

+ 21 - 21
Example/demo.cs

@@ -422,26 +422,26 @@ static class Demo {
 		MessageBox.Query (60, 10, "Selected Animals", result == "" ? "No animals selected" : result, "Ok");
 	}
 
-	static void ComboBoxDemo ()
-	{
-		IList<string> items = new List<string> ();
-		foreach (var dir in new [] { "/etc", @"\windows\System32" }) {
-			if (Directory.Exists (dir)) {
-				items = Directory.GetFiles (dir)
-				.Select (Path.GetFileName)
-				.Where (x => char.IsLetterOrDigit (x [0]))
-				.Distinct ()
-				.OrderBy (x => x).ToList ();
-			}
-		}
-		var list = new ComboBox (0, 0, 36, 7, items);
-		list.Changed += (object sender, ustring text) => { Application.RequestStop (); };
-
-		var d = new Dialog ("Select source file", 40, 12) { list };
-		Application.Run (d);
-
-		MessageBox.Query (60, 10, "Selected file", list.Text.ToString() == "" ? "Nothing selected" : list.Text.ToString(), "Ok");
-	}
+	//static void ComboBoxDemo ()
+	//{
+	//	IList<string> items = new List<string> ();
+	//	foreach (var dir in new [] { "/etc", @"\windows\System32" }) {
+	//		if (Directory.Exists (dir)) {
+	//			items = Directory.GetFiles (dir)
+	//			.Select (Path.GetFileName)
+	//			.Where (x => char.IsLetterOrDigit (x [0]))
+	//			.Distinct ()
+	//			.OrderBy (x => x).ToList ();
+	//		}
+	//	}
+	//	var list = new ComboBox (0, 0, 36, 7, items);
+	//	list.Changed += (object sender, ustring text) => { Application.RequestStop (); };
+
+	//	var d = new Dialog ("Select source file", 40, 12) { list };
+	//	Application.Run (d);
+
+	//	MessageBox.Query (60, 10, "Selected file", list.Text.ToString() == "" ? "Nothing selected" : list.Text.ToString(), "Ok");
+	//}
 	#endregion
 
 
@@ -573,7 +573,7 @@ static class Demo {
 			new MenuBarItem ("_List Demos", new MenuItem [] {
 				new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true)),
 				new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false)),
-				new MenuItem ("Search Single Item", "", ComboBoxDemo)
+//				new MenuItem ("Search Single Item", "", ComboBoxDemo)
 			}),
 			new MenuBarItem ("A_ssorted", new MenuItem [] {
 				new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),

+ 46 - 25
Terminal.Gui/Core/ConsoleDriver.cs

@@ -5,14 +5,11 @@
 //   Miguel de Icaza ([email protected])
 //
 // Define this to enable diagnostics drawing for Window Frames
-//#define DRAW_WINDOW_FRAME_DIAGNOSTICS
 using NStack;
 using System;
 using System.Runtime.CompilerServices;
 
-
 namespace Terminal.Gui {
-
 	/// <summary>
 	/// Basic colors that can be used to set the foreground and background colors in console applications.
 	/// </summary>
@@ -524,9 +521,6 @@ namespace Terminal.Gui {
 			TerminalResized = terminalResized;
 		}
 
-		// Useful for debugging (e.g. change to `*`
-		const char clearChar = ' ';
-
 		/// <summary>
 		/// Draws the title for a Window-style view incorporating padding. 
 		/// </summary>
@@ -550,17 +544,32 @@ namespace Terminal.Gui {
 			}
 		}
 
-#if DRAW_WINDOW_FRAME_DIAGNOSTICS
-		const char leftChar = 'L';
-		const char rightChar = 'R';
-		const char topChar = 'T';
-		const char bottomChar = 'B';
-#else
-		const char leftChar = clearChar;
-		const char rightChar = clearChar;
-		const char topChar = clearChar;
-		const char bottomChar = clearChar;
-#endif
+		/// <summary>
+		/// Enables diagnostic funcions
+		/// </summary>
+		[Flags]
+		public enum DiagnosticFlags : uint { 
+			/// <summary>
+			/// All diagnostics off
+			/// </summary>
+			Off		= 0b_0000_0000,
+			/// <summary>
+			/// When enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will draw a 
+			/// ruler in the frame for any side with a padding value greater than 0.
+			/// </summary>
+			FrameRuler	= 0b_0000_0001,
+			/// <summary>
+			/// When Enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will use
+			/// 'L', 'R', 'T', and 'B' for padding instead of ' '.
+			/// </summary>
+			FramePadding = 0b_0000_0010,
+		}
+
+		/// <summary>
+		/// Set flags to enable/disable <see cref="ConsoleDriver"/> diagnostics.
+		/// </summary>
+		public static DiagnosticFlags Diagnostics { get; set; }
+
 		/// <summary>
 		/// Draws a frame for a window with padding and an optional visible border inside the padding. 
 		/// </summary>
@@ -573,6 +582,20 @@ namespace Terminal.Gui {
 		/// <param name="fill">If set to <c>true</c> it will clear the content area (the area inside the padding) with the current color, otherwise the content area will be left untouched.</param>
 		public virtual void DrawWindowFrame (Rect region, int paddingLeft = 0, int paddingTop = 0, int paddingRight = 0, int paddingBottom = 0, bool border = true, bool fill = false)
 		{
+			char clearChar = ' ';
+			char leftChar = clearChar;
+			char rightChar = clearChar;
+			char topChar = clearChar;
+			char bottomChar = clearChar;
+
+			if ((Diagnostics & DiagnosticFlags.FramePadding) == DiagnosticFlags.FramePadding) {
+				leftChar = 'L';
+				rightChar = 'R';
+				topChar = 'T';
+				bottomChar = 'B';
+				clearChar = 'C';
+			}
+
 			void AddRuneAt (int col, int row, Rune ch)
 			{
 				Move (col, row);
@@ -656,11 +679,10 @@ namespace Terminal.Gui {
 
 					// Frame right
 					if (fright > fleft) {
-#if DRAW_WINDOW_FRAME_DIAGNOSTICS
-						var v = (char)(((int)'0') + ((r - ftop) % 10)); // vLine;
-#else
 						var v = vLine;
-#endif
+						if ((Diagnostics & DiagnosticFlags.FrameRuler) == DiagnosticFlags.FrameRuler) {
+							v = (char)(((int)'0') + ((r - ftop) % 10)); // vLine;
+						}
 						AddRuneAt (fright, r, paddingRight > 0 ? v : rightChar);
 					}
 
@@ -681,11 +703,10 @@ namespace Terminal.Gui {
 				if (fright > fleft) {
 					// Frame bottom
 					for (int c = fleft + 1; c < fright; c++) {
-#if DRAW_WINDOW_FRAME_DIAGNOSTICS
-						var h = (char)(((int)'0') + ((c - fleft) % 10)); // hLine;
-#else
 						var h = hLine;
-#endif	
+						if ((Diagnostics & DiagnosticFlags.FrameRuler) == DiagnosticFlags.FrameRuler) {
+							h = (char)(((int)'0') + ((c - fleft) % 10)); // hLine;
+						}
 						AddRuneAt (c, fbottom, paddingBottom > 0 ? h : bottomChar);
 					}
 

+ 1 - 1
Terminal.Gui/Core/Toplevel.cs

@@ -213,7 +213,7 @@ namespace Terminal.Gui {
 			}
 		}
 
-		///<inheritdoc cref="Add"/>
+		///<inheritdoc/>
 		public override void Add (View view)
 		{
 			if (this == Application.Top) {

+ 4 - 1
Terminal.Gui/Core/View.cs

@@ -285,7 +285,8 @@ namespace Terminal.Gui {
 			}
 		}
 
-		Pos x, y;
+		Pos x = Pos.At (0);
+		Pos y = Pos.At (0);
 		/// <summary>
 		/// Gets or sets the X position for the view (the column). Only used whe <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/>.
 		/// </summary>
@@ -382,6 +383,8 @@ namespace Terminal.Gui {
 		{
 			CanFocus = false;
 			LayoutStyle = LayoutStyle.Computed;
+			Height = 0;
+			Width = 0;
 		}
 
 		/// <summary>

+ 8 - 3
Terminal.Gui/Core/Window.cs

@@ -69,7 +69,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Window"/> class with an optional title.
+		/// Initializes a new instance of the <see cref="Window"/> class with an optional title using <see cref="LayoutStyle.Computed"/> positioning.
 		/// </summary>
 		/// <param name="title">Title.</param>
 		/// <remarks>
@@ -80,9 +80,14 @@ namespace Terminal.Gui {
 		{
 		}
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Window"/> class using <see cref="LayoutStyle.Computed"/> positioning.
+		/// </summary>
+		public Window () : this (title: null) { }
+
 		int padding;
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Window"/> with the specified frame for its location, with the specified border,
+		/// Initializes a new instance of the <see cref="Window"/> using <see cref="LayoutStyle.Absolute"/> positioning with the specified frame for its location, with the specified frame padding,
 		/// and an optional title.
 		/// </summary>
 		/// <param name="frame">Superview-relatie rectangle specifying the location and size</param>
@@ -103,7 +108,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Window"/> with the specified frame for its location, with the specified border,
+		/// Initializes a new instance of the <see cref="Window"/> using <see cref="LayoutStyle.Absolute"/> positioning with the specified frame for its location, with the specified frame padding,
 		/// and an optional title.
 		/// </summary>
 		/// <param name="padding">Number of characters to use for padding of the drawn frame.</param>

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

@@ -172,6 +172,7 @@
     <PackageReference Include="NStack.Core" Version="0.14.0" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Remove="Views\ComboBox.cs" />
   </ItemGroup>
   <!--<ItemGroup>
     <Reference Include="NStack">

+ 9 - 0
Terminal.Gui/Views/Button.cs

@@ -54,6 +54,15 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public Action Clicked;
 
+		/// <summary>
+		///   Initializes a new instance of <see cref="Button"/> using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		/// <remarks>
+		///   The width of the <see cref="Button"/> is computed based on the
+		///   text length. The height will always be 1.
+		/// </remarks>
+		public Button () : this (string.Empty) { }
+
 		/// <summary>
 		///   Initializes a new instance of <see cref="Button"/> using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>

+ 10 - 4
Terminal.Gui/Views/Checkbox.cs

@@ -30,12 +30,18 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Called when the <see cref="Checked"/> property changes. Invokes the <see cref="Toggled"/> event.
 		/// </summary>
-		public virtual void OnToggled (bool previousChecked) {
+		public virtual void OnToggled (bool previousChecked)
+		{
 			Toggled?.Invoke (this, previousChecked);
 		}
 
 		/// <summary>
-		/// Initializes a new instance of <see cref="CheckBox"/> based on the given text, uses Computed layout and sets the height and width.
+		/// Initializes a new instance of <see cref="CheckBox"/> based on the given text, using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		public CheckBox () : this (string.Empty) { }
+
+		/// <summary>
+		/// Initializes a new instance of <see cref="CheckBox"/> based on the given text, using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="s">S.</param>
 		/// <param name="is_checked">If set to <c>true</c> is checked.</param>
@@ -49,7 +55,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of <see cref="CheckBox"/> based on the given text at the given position and a state.
+		/// Initializes a new instance of <see cref="CheckBox"/> using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
 		/// <remarks>
 		///   The size of <see cref="CheckBox"/> is computed based on the
@@ -60,7 +66,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of <see cref="CheckBox"/> based on the given text at the given position and a state.
+		/// Initializes a new instance of <see cref="CheckBox"/> using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
 		/// <remarks>
 		///   The size of <see cref="CheckBox"/> is computed based on the

+ 13 - 8
Terminal.Gui/Views/DateField.cs

@@ -29,20 +29,25 @@ namespace Terminal.Gui {
 		string Format { get { return isShort ? shortFormat : longFormat; } }
 
 		/// <summary>
-		///    Initializes a new instance of <see cref="DateField"/> at an absolute position and fixed size.
+		///    Initializes a new instance of <see cref="DateField"/> using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
 		/// <param name="x">The x coordinate.</param>
 		/// <param name="y">The y coordinate.</param>
 		/// <param name="date">Initial date contents.</param>
 		/// <param name="isShort">If true, shows only two digits for the year.</param>
-		public DateField (int x, int y, DateTime date, bool isShort = false) : base(x, y, isShort ? 10 : 12, "")
+		public DateField (int x, int y, DateTime date, bool isShort = false) : base (x, y, isShort ? 10 : 12, "")
 		{
 			this.isShort = isShort;
 			Initialize (date);
 		}
 
 		/// <summary>
-		///  Initializes a new instance of <see cref="DateField"/> 
+		///  Initializes a new instance of <see cref="DateField"/> using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		public DateField () : this (DateTime.MinValue) { }
+
+		/// <summary>
+		///  Initializes a new instance of <see cref="DateField"/> using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="date"></param>
 		public DateField (DateTime date) : base ("")
@@ -65,7 +70,7 @@ namespace Terminal.Gui {
 
 		void DateField_Changed (object sender, ustring e)
 		{
-			if (!DateTime.TryParseExact (GetDate (Text).ToString(), GetInvarianteFormat (), CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result))
+			if (!DateTime.TryParseExact (GetDate (Text).ToString (), GetInvarianteFormat (), CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result))
 				Text = e;
 		}
 
@@ -259,8 +264,8 @@ namespace Terminal.Gui {
 				CursorPosition++;
 		}
 
-		///<inheritdoc/>
-		public override bool ProcessKey(KeyEvent kb)
+		/// <inheritdoc/>
+		public override bool ProcessKey (KeyEvent kb)
 		{
 			switch (kb.Key) {
 			case Key.DeleteChar:
@@ -306,8 +311,8 @@ namespace Terminal.Gui {
 			return true;
 		}
 
-		///<inheritdoc/>
-		public override bool MouseEvent(MouseEvent ev)
+		/// <inheritdoc/>
+		public override bool MouseEvent (MouseEvent ev)
 		{
 			if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked))
 				return false;

+ 16 - 14
Terminal.Gui/Views/FrameView.cs

@@ -4,10 +4,10 @@
 // Authors:
 //   Miguel de Icaza ([email protected])
 //
-	using System;
-	using System.Collections;
-	using System.Collections.Generic;
-	using NStack;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using NStack;
 
 namespace Terminal.Gui {
 	/// <summary>
@@ -36,27 +36,25 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class with
-		/// an absolute position and a title.
+		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
 		/// <param name="frame">Frame.</param>
 		/// <param name="title">Title.</param>
 		public FrameView (Rect frame, ustring title) : base (frame)
 		{
-			var cFrame = new Rect (1, 1 , frame.Width - 2, frame.Height - 2);
+			var cFrame = new Rect (1, 1, frame.Width - 2, frame.Height - 2);
 			this.title = title;
 			contentView = new ContentView (cFrame);
 			Initialize ();
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class with
-		/// an absolute position, a title and <see cref="View"/>s.
+		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="frame">Frame.</param>
 		/// <param name="title">Title.</param>
 		/// /// <param name="views">Views.</param>
-		public FrameView (Rect frame, ustring title, View[] views) : this (frame, title)
+		public FrameView (Rect frame, ustring title, View [] views) : this (frame, title)
 		{
 			foreach (var view in views) {
 				contentView.Add (view);
@@ -65,8 +63,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class with
-		/// a title and the result is suitable to have its X, Y, Width and Height properties computed.
+		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="title">Title.</param>
 		public FrameView (ustring title)
@@ -81,6 +78,11 @@ namespace Terminal.Gui {
 			Initialize ();
 		}
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Gui.FrameView"/> class using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		public FrameView () : this (title: string.Empty) { }
+
 		void Initialize ()
 		{
 			base.Add (contentView);
@@ -126,9 +128,9 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <remarks>
 		/// </remarks>
-		public override void RemoveAll()
+		public override void RemoveAll ()
 		{
-			contentView.RemoveAll();
+			contentView.RemoveAll ();
 		}
 
 		///<inheritdoc/>

+ 12 - 7
Terminal.Gui/Views/HexView.cs

@@ -41,10 +41,10 @@ namespace Terminal.Gui {
 		bool firstNibble, leftSide;
 
 		/// <summary>
-		/// Initialzies a <see cref="HexView"/>
+		/// Initialzies a <see cref="HexView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="source">The <see cref="Stream"/> to view and edit as hex, this <see cref="Stream"/> must support seeking, or an exception will be thrown.</param>
-		public HexView (Stream source) : base()
+		public HexView (Stream source) : base ()
 		{
 			Source = source;
 			this.source = source;
@@ -53,6 +53,11 @@ namespace Terminal.Gui {
 			firstNibble = true;
 		}
 
+		/// <summary>
+		/// Initialzies a <see cref="HexView"/> class using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		public HexView () : this (source: new MemoryStream ()) { }
+
 		/// <summary>
 		/// Sets or gets the <see cref="Stream"/> the <see cref="HexView"/> is operating on; the stream must support seeking (<see cref="Stream.CanSeek"/> == true).
 		/// </summary>
@@ -151,7 +156,7 @@ namespace Terminal.Gui {
 				var lineRect = new Rect (0, line, frame.Width, 1);
 				if (!bounds.Contains (lineRect))
 					continue;
-				
+
 				Move (0, line);
 				Driver.SetAttribute (ColorScheme.HotNormal);
 				Driver.AddStr (string.Format ("{0:x8} ", displayStart + line * nblocks * 4));
@@ -197,7 +202,7 @@ namespace Terminal.Gui {
 						SetAttribute (leftSide ? trackingColor : activeColor);
 					else
 						SetAttribute (ColorScheme.Normal);
-					
+
 					Driver.AddRune (c);
 				}
 			}
@@ -229,7 +234,7 @@ namespace Terminal.Gui {
 
 		void RedisplayLine (long pos)
 		{
-			var delta = (int) (pos - DisplayStart);
+			var delta = (int)(pos - DisplayStart);
 			var line = delta / bytesPerLine;
 
 			SetNeedsDisplay (new Rect (0, line, Frame.Width, 1));
@@ -277,7 +282,7 @@ namespace Terminal.Gui {
 				SetDisplayStart (DisplayStart + bytes);
 				SetNeedsDisplay ();
 			} else
-				RedisplayLine (position);			
+				RedisplayLine (position);
 		}
 
 		/// <inheritdoc/>
@@ -376,7 +381,7 @@ namespace Terminal.Gui {
 		/// Each Key indicates an offset where an edit was made and the Value is the changed byte.
 		/// </summary>
 		/// <value>The edits.</value>
-		public IReadOnlyDictionary<long,byte> Edits => edits;
+		public IReadOnlyDictionary<long, byte> Edits => edits;
 
 		/// <summary>
 		/// This method applies andy edits made to the <see cref="Stream"/> and resets the 

+ 54 - 9
Terminal.Gui/Views/Label.cs

@@ -64,29 +64,59 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		///   Initializes a new instance of <see cref="Label"/> at the given
-		///   coordinate with the given string, computes the bounding box
-		///   based on the size of the string, assumes that the string contains
-		///   newlines for multiple lines, no special breaking rules are used.
+		///   Initializes a new instance of <see cref="Label"/> using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
+		/// <remarks>
+		/// <para>
+		///   The <see cref="Label"/> will be created at the given
+		///   coordinates with the given string. The size (<see cref="View.Frame"/> will be 
+		///   adjusted to fit the contents of <see cref="Text"/>, including newlines ('\n') for multiple lines. 
+		/// </para>
+		/// <para>
+		///   No line wraping is provided.
+		/// </para>
+		/// </remarks>
+		/// <param name="x">column to locate the Label.</param>
+		/// <param name="y">row to locate the Label.</param>
+		/// <param name="text">text to initialize the <see cref="Text"/> property with.</param>
 		public Label (int x, int y, ustring text) : this (CalcRect (x, y, text), text)
 		{
 		}
 
 		/// <summary>
-		///   Initializes a new instance of <see cref="Label"/> at the given
-		///   coordinate with the given string and uses the specified
-		///   frame for the string.
+		///   Initializes a new instance of <see cref="Label"/> using <see cref="LayoutStyle.Absolute"/> layout.
 		/// </summary>
+		/// <remarks>
+		/// <para>
+		///   The <see cref="Label"/> will be created at the given
+		///   coordinates with the given string. The initial size (<see cref="View.Frame"/> will be 
+		///   adjusted to fit the contents of <see cref="Text"/>, including newlines ('\n') for multiple lines. 
+		/// </para>
+		/// <para>
+		///   No line wraping is provided.
+		/// </para>
+		/// </remarks>
+		/// <param name="rect">Location.</param>
+		/// <param name="text">text to initialize the <see cref="Text"/> property with.</param>
 		public Label (Rect rect, ustring text) : base (rect)
 		{
 			this.text = text;
 		}
 
 		/// <summary>
-		/// Initializes a new instance of <see cref="Label"/> and configures the default Width and Height based on the text, the result is suitable for Computed layout.
+		///   Initializes a new instance of <see cref="Label"/> using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
-		/// <param name="text">Text.</param>
+		/// <remarks>
+		/// <para>
+		///   The <see cref="Label"/> will be created using <see cref="LayoutStyle.Computed"/>
+		///   coordinates with the given string. The initial size (<see cref="View.Frame"/> will be 
+		///   adjusted to fit the contents of <see cref="Text"/>, including newlines ('\n') for multiple lines. 
+		/// </para>
+		/// <para>
+		///   No line wraping is provided.
+		/// </para>
+		/// </remarks>
+		/// <param name="text">text to initialize the <see cref="Text"/> property with.</param>
 		public Label (ustring text) : base ()
 		{
 			this.text = text;
@@ -95,6 +125,21 @@ namespace Terminal.Gui {
 			Height = r.Height;
 		}
 
+		/// <summary>
+		///   Initializes a new instance of <see cref="Label"/> using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		/// <remarks>
+		/// <para>
+		///   The <see cref="Label"/> will be created using <see cref="LayoutStyle.Computed"/>
+		///   coordinates. The initial size (<see cref="View.Frame"/> will be 
+		///   adjusted to fit the contents of <see cref="Text"/>, including newlines ('\n') for multiple lines. 
+		/// </para>
+		/// <para>
+		///   No line wraping is provided.
+		/// </para>
+		/// </remarks>
+		public Label () : this (text: string.Empty) { }
+
 		static char [] whitespace = new char [] { ' ', '\t' };
 
 		static ustring ClipAndJustify (ustring str, int width, TextAlignment talign)

+ 11 - 3
Terminal.Gui/Views/Menu.cs

@@ -173,9 +173,12 @@ namespace Terminal.Gui {
 		/// Initializes a new <see cref="MenuBarItem"/>.
 		/// </summary>
 		/// <param name="children">The items in the current menu.</param>
-		public MenuBarItem (MenuItem [] children) : this (new string (' ', GetMaxTitleLength (children)), children)
-		{
-		}
+		public MenuBarItem (MenuItem [] children) : this (new string (' ', GetMaxTitleLength (children)), children) { }
+
+		/// <summary>
+		/// Initializes a new <see cref="MenuBarItem"/>.
+		/// </summary>
+		public MenuBarItem () : this (children: new MenuItem [] { }) { }
 
 		static int GetMaxTitleLength (MenuItem [] children)
 		{
@@ -550,6 +553,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		public bool UseKeysUpDownAsKeysLeftRight { get; set; } = true;
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="MenuBar"/>.
+		/// </summary>
+		public MenuBar () : this (new MenuBarItem [] { }) { }
+
 		/// <summary>
 		/// Initializes a new instance of the <see cref="MenuBar"/> class with the specified set of toplevel menu items.
 		/// </summary>

+ 9 - 10
Terminal.Gui/Views/RadioGroup.cs

@@ -7,9 +7,7 @@ namespace Terminal.Gui {
 		int selected, cursor;
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="RadioGroup"/> class
-		/// setting up the initial set of radio labels and the item that should be selected and uses
-		/// an absolute layout for the result.
+		/// Initializes a new instance of the <see cref="RadioGroup"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="rect">Boundaries for the radio group.</param>
 		/// <param name="radioLabels">The radio labels; an array of strings that can contain hotkeys using an underscore before the letter.</param>
@@ -35,8 +33,12 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="RadioGroup"/> class
-		/// setting up the initial set of radio labels and the item that should be selected.
+		/// Initializes a new instance of the <see cref="RadioGroup"/> class using <see cref="LayoutStyle.Computed"/> layout.
+		/// </summary>
+		public RadioGroup () : this (radioLabels: new string [] { }) { }
+
+		/// <summary>
+		/// Initializes a new instance of the <see cref="RadioGroup"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// <param name="radioLabels">The radio labels; an array of strings that can contain hotkeys using an underscore before the letter.</param>
 		/// <param name="selected">The index of the item to be selected, the value is clamped to the number of items.</param>
@@ -66,17 +68,14 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="RadioGroup"/> class
-		/// setting up the initial set of radio labels and the item that should be selected.
+		/// Initializes a new instance of the <see cref="RadioGroup"/> class using <see cref="LayoutStyle.Absolute"/> layout.
 		/// The <see cref="View"/> frame is computed from the provided radio labels.
 		/// </summary>
 		/// <param name="x">The x coordinate.</param>
 		/// <param name="y">The y coordinate.</param>
 		/// <param name="radioLabels">The radio labels; an array of strings that can contain hotkeys using an underscore before the letter.</param>
 		/// <param name="selected">The item to be selected, the value is clamped to the number of items.</param>		
-		public RadioGroup (int x, int y, string [] radioLabels, int selected = 0) : this (MakeRect (x, y, radioLabels), radioLabels, selected)
-		{
-		}
+		public RadioGroup (int x, int y, string [] radioLabels, int selected = 0) : this (MakeRect (x, y, radioLabels), radioLabels, selected) { }
 
 		string [] radioLabels;
 

+ 1 - 1
Terminal.Gui/Views/ScrollView.cs

@@ -125,7 +125,7 @@ namespace Terminal.Gui {
 		///<inheritdoc/>
 		public override void Redraw (Rect region)
 		{
-			if (ColorScheme == null)
+			if (ColorScheme == null || Size == 0)
 				return;
 
 			Driver.SetAttribute (ColorScheme.Normal);

+ 11 - 6
Terminal.Gui/Views/StatusBar.cs

@@ -47,7 +47,7 @@ namespace Terminal.Gui {
 		/// A <see cref="StatusItem.Title"/> set to `~F1~ Help` will render as *F1* using <see cref="ColorScheme.HotNormal"/> and
 		/// *Help* as <see cref="ColorScheme.HotNormal"/>.
 		/// </remarks>
-		public ustring Title { get; set;}
+		public ustring Title { get; set; }
 
 		/// <summary>
 		/// Gets or sets the action to be invoked when the statusbar item is triggered
@@ -103,6 +103,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		public StatusItem [] Items { get; set; }
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="StatusBar"/> class.
+		/// </summary>
+		public StatusBar () : this (items: new StatusItem [] { }) { }
+
 		/// <summary>
 		/// Initializes a new instance of the <see cref="StatusBar"/> class with the specified set of <see cref="StatusItem"/>s.
 		/// The <see cref="StatusBar"/> will be drawn on the lowest line of the terminal or <see cref="StatusBar.Parent"/> (if not null).
@@ -131,11 +136,11 @@ namespace Terminal.Gui {
 					break;
 				case StatusBarStyle.SnapToBottom:
 #endif
-					if (Parent == null) {
-						Y = Driver.Rows - 1; 
-					} else {
-						Y = Pos.Bottom (Parent);
-					}
+				if (Parent == null) {
+					Y = Driver.Rows - 1;
+				} else {
+					Y = Pos.Bottom (Parent);
+				}
 #if SNAP_TO_TOP
 					break;
 				}

+ 8 - 3
Terminal.Gui/Views/TextField.cs

@@ -44,7 +44,7 @@ namespace Terminal.Gui {
 		public event EventHandler<ustring> Changed;
 
 		/// <summary>
-		///    Public constructor that creates a text field, with layout controlled with X, Y, Width and Height.
+		/// Initializes a new instance of the <see cref="TextField"/> class using <see cref="LayoutStyle.Computed"/> positioning.
 		/// </summary>
 		/// <param name="text">Initial text contents.</param>
 		public TextField (string text) : this (ustring.Make (text))
@@ -53,7 +53,12 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		///    Public constructor that creates a text field, with layout controlled with X, Y, Width and Height.
+		/// Initializes a new instance of the <see cref="TextField"/> class using <see cref="LayoutStyle.Computed"/> positioning.
+		/// </summary>
+		public TextField () : this (string.Empty) { }
+
+		/// <summary>
+		/// Initializes a new instance of the <see cref="TextField"/> class using <see cref="LayoutStyle.Computed"/> positioning.
 		/// </summary>
 		/// <param name="text">Initial text contents.</param>
 		public TextField (ustring text)
@@ -62,7 +67,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		///    Public constructor that creates a text field at an absolute position and size.
+		/// Initializes a new instance of the <see cref="TextField"/> class using <see cref="LayoutStyle.Absolute"/> positioning.
 		/// </summary>
 		/// <param name="x">The x coordinate.</param>
 		/// <param name="y">The y coordinate.</param>

+ 12 - 7
Terminal.Gui/Views/TimeField.cs

@@ -30,12 +30,12 @@ namespace Terminal.Gui {
 
 
 		/// <summary>
-		///    Initializes a new instance of <see cref="TimeField"/> at an absolute position and fixed size.
+		///    Initializes a new instance of <see cref="TimeField"/> using <see cref="LayoutStyle.Absolute"/> positioning.
 		/// </summary>
 		/// <param name="x">The x coordinate.</param>
 		/// <param name="y">The y coordinate.</param>
-		/// <param name="time">Initial time contents.</param>
-		/// <param name="isShort">If true, the seconds are hidden.</param>
+		/// <param name="time">Initial time.</param>
+		/// <param name="isShort">If true, the seconds are hidden. Sets the <see cref="IsShortFormat"/> property.</param>
 		public TimeField (int x, int y, DateTime time, bool isShort = false) : base (x, y, isShort ? 7 : 10, "")
 		{
 			this.isShort = isShort;
@@ -43,16 +43,21 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Initializes a new instance of <see cref="TimeField"/> 
+		///    Initializes a new instance of <see cref="TimeField"/> using <see cref="LayoutStyle.Computed"/> positioning.
 		/// </summary>
-		/// <param name="time"></param>
-		public TimeField (DateTime time) : base ("")
+		/// <param name="time">Initial time</param>
+		public TimeField (DateTime time) : base (string.Empty)
 		{
 			this.isShort = true;
 			Width = FieldLen + 2;
 			Initialize (time);
 		}
 
+		/// <summary>
+		///    Initializes a new instance of <see cref="TimeField"/> using <see cref="LayoutStyle.Computed"/> positioning.
+		/// </summary>
+		public TimeField () : this (time: DateTime.MinValue) { }
+
 		void Initialize (DateTime time)
 		{
 			CultureInfo cultureInfo = CultureInfo.CurrentCulture;
@@ -86,7 +91,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Get or set the data format for the widget.
+		/// Get or sets whether <see cref="TimeField"/> uses the short or long time format.
 		/// </summary>
 		public bool IsShortFormat {
 			get => isShort;

+ 17 - 7
Terminal.Gui/Windows/Dialog.cs

@@ -24,7 +24,7 @@ namespace Terminal.Gui {
 		const int padding = 0;
 
 		/// <summary>
-		/// Initializes a new instance of the <see cref="Dialog"/> class using <see cref="LayoutStyle.Absolute"/> positioning 
+		/// Initializes a new instance of the <see cref="Dialog"/> class using <see cref="LayoutStyle.Computed"/> positioning 
 		/// and an optional set of <see cref="Button"/>s to display
 		/// </summary>
 		/// <param name="title">Title for the dialog.</param>
@@ -61,10 +61,22 @@ namespace Terminal.Gui {
 					Add (b);
 				}
 			}
-
-			//LayoutComplete += (sender, a) => AdjustButtonLayout ();
 		}
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Dialog"/> class using <see cref="LayoutStyle.Computed"/>.
+		/// </summary>
+		/// <remarks>
+		/// <para>
+		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
+		/// After initialzation use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
+		/// </para>
+		/// <para>
+		/// Use <see cref="AddButton(Button)"/> to add buttons to the dialog.
+		/// </para>
+		/// </remarks>
+		public Dialog () : this (title: string.Empty, width: 0, height: 0, buttons: null) { }
+
 		/// <summary>
 		/// Initializes a new instance of the <see cref="Dialog"/> class using <see cref="LayoutStyle.Computed"/> positioning 
 		/// and with an optional set of <see cref="Button"/>s to display
@@ -72,12 +84,10 @@ namespace Terminal.Gui {
 		/// <param name="title">Title for the dialog.</param>
 		/// <param name="buttons">Optional buttons to lay out at the bottom of the dialog.</param>
 		/// <remarks>
-		/// if <c>width</c> and <c>height</c> are both 0, the Dialog will be vertically and horizontally centered in the
-		/// container and the size will be 85% of the container. 
+		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
 		/// After initialzation use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
 		/// </remarks>
-		public Dialog (ustring title, params Button [] buttons) : this (title: title, width: 0, height: 0, buttons: buttons) { 
-		}
+		public Dialog (ustring title, params Button [] buttons) : this (title: title, width: 0, height: 0, buttons: buttons) { }
 
 		/// <summary>
 		/// Adds a <see cref="Button"/> to the <see cref="Dialog"/>, its layout will be controled by the <see cref="Dialog"/>

+ 28 - 15
Terminal.Gui/Windows/FileDialog.cs

@@ -19,7 +19,7 @@ namespace Terminal.Gui {
 	internal class DirListView : View {
 		int top, selected;
 		DirectoryInfo dirInfo;
-		List<(string,bool,bool)> infos;
+		List<(string, bool, bool)> infos;
 		internal bool canChooseFiles = true;
 		internal bool canChooseDirectories = false;
 		internal bool allowsMultipleSelection = false;
@@ -27,7 +27,7 @@ namespace Terminal.Gui {
 
 		public DirListView (FileDialog host)
 		{
-			infos = new List<(string,bool,bool)> ();
+			infos = new List<(string, bool, bool)> ();
 			CanFocus = true;
 			this.host = host;
 		}
@@ -35,7 +35,7 @@ namespace Terminal.Gui {
 		bool IsAllowed (FileSystemInfo fsi)
 		{
 			if (fsi.Attributes.HasFlag (FileAttributes.Directory))
-			    return true;
+				return true;
 			if (allowedFileTypes == null)
 				return true;
 			foreach (var ft in allowedFileTypes)
@@ -48,9 +48,9 @@ namespace Terminal.Gui {
 		{
 			dirInfo = new DirectoryInfo (directory.ToString ());
 			infos = (from x in dirInfo.GetFileSystemInfos ()
-			         where IsAllowed (x)
-			         orderby (!x.Attributes.HasFlag (FileAttributes.Directory)) + x.Name
-			         select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory), false)).ToList ();
+				 where IsAllowed (x)
+				 orderby (!x.Attributes.HasFlag (FileAttributes.Directory)) + x.Name
+				 select (x.Name, x.Attributes.HasFlag (FileAttributes.Directory), false)).ToList ();
 			infos.Insert (0, ("..", true, false));
 			top = 0;
 			selected = 0;
@@ -407,7 +407,7 @@ namespace Terminal.Gui {
 							return new List<string> () { MakePath (infos [selected].Item1) };
 						return Array.Empty<string> ();
 					} else {
-						if (canChooseFiles) 
+						if (canChooseFiles)
 							return new List<string> () { MakePath (infos [selected].Item1) };
 						return Array.Empty<string> ();
 					}
@@ -425,6 +425,11 @@ namespace Terminal.Gui {
 		TextField dirEntry, nameEntry;
 		internal DirListView dirListView;
 
+		/// <summary>
+		/// Initializes a new <see cref="FileDialog"/>.
+		/// </summary>
+		public FileDialog () : this (title: string.Empty, prompt: string.Empty, nameFieldLabel: string.Empty, message: string.Empty) { }
+
 		/// <summary>
 		/// Initializes a new instance of <see cref="FileDialog"/>
 		/// </summary>
@@ -582,9 +587,9 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <value>The absolute file path for the file path entered.</value>
 		public ustring FilePath {
-			get => dirListView.MakePath(nameEntry.Text.ToString());
+			get => dirListView.MakePath (nameEntry.Text.ToString ());
 			set {
-				nameEntry.Text = Path.GetFileName(value.ToString());
+				nameEntry.Text = Path.GetFileName (value.ToString ());
 			}
 		}
 
@@ -608,13 +613,16 @@ namespace Terminal.Gui {
 	/// </remarks>
 	public class SaveDialog : FileDialog {
 		/// <summary>
-		/// Initializes a new <see cref="SaveDialog"/>
+		/// Initializes a new <see cref="SaveDialog"/>.
+		/// </summary>
+		public SaveDialog () : this (title: string.Empty, message: string.Empty) { }
+
+		/// <summary>
+		/// Initializes a new <see cref="SaveDialog"/>.
 		/// </summary>
 		/// <param name="title">The title.</param>
 		/// <param name="message">The message.</param>
-		public SaveDialog (ustring title, ustring message) : base (title, prompt: "Save", nameFieldLabel: "Save as:", message: message)
-		{
-		}
+		public SaveDialog (ustring title, ustring message) : base (title, prompt: "Save", nameFieldLabel: "Save as:", message: message) { }
 
 		/// <summary>
 		/// Gets the name of the file the user selected for saving, or null
@@ -625,7 +633,7 @@ namespace Terminal.Gui {
 			get {
 				if (canceled)
 					return null;
-				return Path.GetFileName(FilePath.ToString());
+				return Path.GetFileName (FilePath.ToString ());
 			}
 		}
 	}
@@ -650,7 +658,12 @@ namespace Terminal.Gui {
 	/// </remarks>
 	public class OpenDialog : FileDialog {
 		/// <summary>
-		/// Initializes a new <see cref="OpenDialog"/>
+		/// Initializes a new <see cref="OpenDialog"/>.
+		/// </summary>
+		public OpenDialog () : this (title: string.Empty, message: string.Empty) { }
+
+		/// <summary>
+		/// Initializes a new <see cref="OpenDialog"/>.
 		/// </summary>
 		/// <param name="title"></param>
 		/// <param name="message"></param>

+ 395 - 0
UICatalog/Scenarios/AllViewsTester.cs

@@ -0,0 +1,395 @@
+using NStack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Terminal.Gui;
+
+namespace UICatalog {
+	[ScenarioMetadata (Name: "All Views Tester", Description: "Provides a test UI for all classes derived from View")]
+	[ScenarioCategory ("Layout")]
+	class AllViewsTester : Scenario {
+		Window _leftPane;
+		ListView _classListView;
+		FrameView _hostPane;
+
+		Dictionary<string, Type> _viewClasses;
+		View _curView = null;
+
+		// Settings
+		FrameView _settingsPane;
+		CheckBox _computedCheckBox;
+		FrameView _locationFrame;
+		RadioGroup _xRadioGroup;
+		TextField _xText;
+		int _xVal = 0;
+		RadioGroup _yRadioGroup;
+		TextField _yText;
+		int _yVal = 0;
+
+		FrameView _sizeFrame;
+		RadioGroup _wRadioGroup;
+		TextField _wText;
+		int _wVal = 0;
+		RadioGroup _hRadioGroup;
+		TextField _hText;
+		int _hVal = 0;
+
+		public override void Init (Toplevel top)
+		{
+			Application.Init ();
+
+			Top = top;
+			if (Top == null) {
+				Top = Application.Top;
+			}
+
+			//Win = new Window ($"CTRL-Q to Close - Scenario: {GetName ()}") {
+			//	X = 0,
+			//	Y = 0,
+			//	Width = Dim.Fill (),
+			//	Height = Dim.Fill ()
+			//};
+			//Top.Add (Win);
+		}
+
+		public override void Setup ()
+		{
+			var statusBar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.ControlQ, "~^Q~ Quit", () => Quit()),
+				new StatusItem(Key.F2, "~F2~ Toggle Frame Ruler", () => {
+					ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler;
+					Top.SetNeedsDisplay ();
+				}),
+				new StatusItem(Key.F3, "~F3~ Toggle Frame Padding", () => {
+					ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FramePadding;
+					Top.SetNeedsDisplay ();
+				}),
+			});
+			Top.Add (statusBar);
+
+			_viewClasses = GetAllViewClassesCollection ()
+				.OrderBy (t => t.Name)
+				.Select (t => new KeyValuePair<string, Type> (t.Name, t))
+				.ToDictionary (t => t.Key, t => t.Value);
+
+			_leftPane = new Window ("Classes") {
+				X = 0,
+				Y = 0, // for menu
+				Width = 15,
+				Height = Dim.Fill (),
+				CanFocus = false,
+				ColorScheme = Colors.TopLevel,
+			};
+
+			_classListView = new ListView (_viewClasses.Keys.ToList ()) {
+				X = 0,
+				Y = 0,
+				Width = Dim.Fill (0),
+				Height = Dim.Fill (), // for status bar
+				AllowsMarking = false,
+				ColorScheme = Colors.TopLevel,
+			};
+			_classListView.OpenSelectedItem += (o, a) => {
+				Top.SetFocus (_settingsPane);
+			};
+			_classListView.SelectedChanged += (sender, args) => {
+				ClearClass (_curView);
+				_curView = CreateClass (_viewClasses.Values.ToArray () [_classListView.SelectedItem]);
+			};
+			_leftPane.Add (_classListView);
+
+			_settingsPane = new FrameView ("Settings") {
+				X = Pos.Right (_leftPane),
+				Y = 0, // for menu
+				Width = Dim.Fill (),
+				Height = 10,
+				CanFocus = false,
+				ColorScheme = Colors.TopLevel,
+			};
+			_computedCheckBox = new CheckBox ("Computed Layout", true) { X = 0, Y = 0 };
+			_computedCheckBox.Toggled += (sender, previousState) => {
+				if (_curView != null) {
+					_curView.LayoutStyle = previousState ? LayoutStyle.Absolute : LayoutStyle.Computed;
+					_hostPane.LayoutSubviews ();
+				}
+			};
+			_settingsPane.Add (_computedCheckBox);
+
+			var radioItems = new [] { "Percent(x)", "AnchorEnd(x)", "Center", "At(x)" };
+			_locationFrame = new FrameView ("Location (Pos)") {
+				X = Pos.Left (_computedCheckBox),
+				Y = Pos.Bottom (_computedCheckBox),
+				Height = 3 + radioItems.Length,
+				Width = 36,
+			};
+			_settingsPane.Add (_locationFrame);
+
+			var label = new Label ("x:") { X = 0, Y = 0 };
+			_locationFrame.Add (label);
+			_xRadioGroup = new RadioGroup (radioItems) {
+				X = 0,
+				Y = Pos.Bottom (label),
+				SelectionChanged = (selected) => DimPosChanged (_curView),
+			};
+			_xText = new TextField ($"{_xVal}") { X = Pos.Right (label) + 1, Y = 0, Width = 4 };
+			_xText.Changed += (sender, args) => {
+				try {
+					_xVal = int.Parse (_xText.Text.ToString ());
+					DimPosChanged (_curView);
+				} catch {
+
+				}
+			};
+			_locationFrame.Add (_xText);
+
+			_locationFrame.Add (_xRadioGroup);
+
+			radioItems = new [] { "Percent(y)", "AnchorEnd(y)", "Center", "At(y)" };
+			label = new Label ("y:") { X = Pos.Right (_xRadioGroup) + 1, Y = 0 };
+			_locationFrame.Add (label);
+			_yText = new TextField ($"{_yVal}") { X = Pos.Right (label) + 1, Y = 0, Width = 4 };
+			_yText.Changed += (sender, args) => {
+				try {
+					_yVal = int.Parse (_yText.Text.ToString ());
+					DimPosChanged (_curView);
+				} catch {
+
+				}
+			};
+			_locationFrame.Add (_yText);
+			_yRadioGroup = new RadioGroup (radioItems) {
+				X = Pos.X (label),
+				Y = Pos.Bottom (label),
+				SelectionChanged = (selected) => DimPosChanged (_curView),
+			};
+			_locationFrame.Add (_yRadioGroup);
+
+			_sizeFrame = new FrameView ("Size (Dim)") {
+				X = Pos.Right (_locationFrame),
+				Y = Pos.Y (_locationFrame),
+				Height = 3 + radioItems.Length,
+				Width = 40,
+			};
+
+			radioItems = new [] { "Percent(width)", "Fill(width)", "Sized(width)" };
+			label = new Label ("width:") { X = 0, Y = 0 };
+			_sizeFrame.Add (label);
+			_wRadioGroup = new RadioGroup (radioItems) {
+				X = 0,
+				Y = Pos.Bottom (label),
+				SelectionChanged = (selected) => DimPosChanged (_curView)
+			};
+			_wText = new TextField ($"{_wVal}") { X = Pos.Right (label) + 1, Y = 0, Width = 4 };
+			_wText.Changed += (sender, args) => {
+				try {
+					_wVal = int.Parse (_wText.Text.ToString ());
+					DimPosChanged (_curView);
+				} catch {
+
+				}
+			};
+			_sizeFrame.Add (_wText);
+			_sizeFrame.Add (_wRadioGroup);
+
+			radioItems = new [] { "Percent(height)", "Fill(height)", "Sized(height)" };
+			label = new Label ("height:") { X = Pos.Right (_wRadioGroup) + 1, Y = 0 };
+			_sizeFrame.Add (label);
+			_hText = new TextField ($"{_hVal}") { X = Pos.Right (label) + 1, Y = 0, Width = 4 };
+			_hText.Changed += (sender, args) => {
+				try {
+					_hVal = int.Parse (_hText.Text.ToString ());
+					DimPosChanged (_curView);
+				} catch {
+
+				}
+			};
+			_sizeFrame.Add (_hText);
+
+			_hRadioGroup = new RadioGroup (radioItems) {
+				X = Pos.X (label),
+				Y = Pos.Bottom (label),
+				SelectionChanged = (selected) => DimPosChanged (_curView),
+			};
+			_sizeFrame.Add (_hRadioGroup);
+
+			_settingsPane.Add (_sizeFrame);
+
+			_hostPane = new FrameView ("") {
+				X = Pos.Right (_leftPane),
+				Y = Pos.Bottom (_settingsPane),
+				Width = Dim.Fill (),
+				Height = Dim.Fill (1), // + 1 for status bar
+				ColorScheme = Colors.Dialog,
+			};
+
+			Top.Add (_leftPane, _settingsPane, _hostPane);
+
+			_curView = CreateClass (_viewClasses.First ().Value);
+		}
+
+		void DimPosChanged (View view)
+		{
+			if (view == null) {
+				return;
+			}
+			try {
+				switch (_xRadioGroup.Selected) {
+				case 0:
+					view.X = Pos.Percent (_xVal);
+					break;
+				case 1:
+					view.X = Pos.AnchorEnd (_xVal);
+					break;
+				case 2:
+					view.X = Pos.Center ();
+					break;
+				case 3:
+					view.X = Pos.At (_xVal);
+					break;
+				}
+
+				switch (_yRadioGroup.Selected) {
+				case 0:
+					view.Y = Pos.Percent (_yVal);
+					break;
+				case 1:
+					view.Y = Pos.AnchorEnd (_yVal);
+					break;
+				case 2:
+					view.Y = Pos.Center ();
+					break;
+				case 3:
+					view.Y = Pos.At (_yVal);
+					break;
+				}
+
+				switch (_wRadioGroup.Selected) {
+				case 0:
+					view.Width = Dim.Percent (_wVal);
+					break;
+				case 1:
+					view.Width = Dim.Fill (_wVal);
+					break;
+				case 2:
+					view.Width = Dim.Sized (_wVal);
+					break;
+				}
+
+				switch (_hRadioGroup.Selected) {
+				case 0:
+					view.Height = Dim.Percent (_hVal);
+					break;
+				case 1:
+					view.Height = Dim.Fill (_hVal);
+					break;
+				case 2:
+					view.Height = Dim.Sized (_hVal);
+					break;
+				}
+			} catch (Exception e) {
+				MessageBox.ErrorQuery ("Exception", e.Message, "Ok");
+			}
+			UpdateTitle (view);
+		}
+
+		List<string> posNames = new List<String> { "Factor", "AnchorEnd", "Center", "Absolute" };
+		List<string> dimNames = new List<String> { "Factor", "Fill", "Absolute" };
+
+		void UpdateSettings (View view)
+		{
+			var x = view.X.ToString ();
+			var y = view.Y.ToString ();
+			_xRadioGroup.Selected = posNames.IndexOf (posNames.Where (s => x.Contains (s)).First ());
+			_yRadioGroup.Selected = posNames.IndexOf (posNames.Where (s => y.Contains (s)).First ());
+			_xText.Text = $"{view.Frame.X}";
+			_yText.Text = $"{view.Frame.Y}";
+
+			var w = view.Width.ToString ();
+			var h = view.Height.ToString ();
+			_wRadioGroup.Selected = dimNames.IndexOf (dimNames.Where (s => w.Contains (s)).First ());
+			_hRadioGroup.Selected = dimNames.IndexOf (dimNames.Where (s => h.Contains (s)).First ());
+			_wText.Text = $"{view.Frame.Width}";
+			_hText.Text = $"{view.Frame.Height}";
+		}
+
+		void UpdateTitle (View view)
+		{
+			_hostPane.Title = $"{view.GetType().Name} - {view.X.ToString ()}, {view.Y.ToString ()}, {view.Width.ToString ()}, {view.Height.ToString ()}";
+		}
+
+		List<Type> GetAllViewClassesCollection ()
+		{
+			List<Type> types = new List<Type> ();
+			foreach (Type type in typeof (View).Assembly.GetTypes ()
+			 .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsPublic && myType.IsSubclassOf (typeof (View)))) {
+				types.Add (type);
+			}
+			return types;
+		}
+
+		void ClearClass (View view)
+		{
+			// Remove existing class, if any
+			if (view != null) {
+				_hostPane.Remove (view);
+				_hostPane.Clear ();
+			}
+		}
+
+		View CreateClass (Type type)
+		{
+			// Instantiate view
+			var view = (View)Activator.CreateInstance (type);
+
+			//_curView.X = Pos.Center ();
+			//_curView.Y = Pos.Center ();
+			//_curView.Width = Dim.Fill (5);
+			//_curView.Height = Dim.Fill (5);
+
+			// Set the colorscheme to make it stand out
+			view.ColorScheme = Colors.Base;
+
+			// If the view supports a Text property, set it so we have something to look at
+			if (view.GetType ().GetProperty ("Text") != null) {
+				try {
+					view.GetType ().GetProperty ("Text")?.GetSetMethod ()?.Invoke (view, new [] { ustring.Make ("Test Text") });
+				} catch (TargetInvocationException e) {
+					MessageBox.ErrorQuery ("Exception", e.InnerException.Message, "Ok");
+					view = null;
+				}
+			}
+
+			if (view == null) return null;
+
+			// If the view supports a Title property, set it so we have something to look at
+			if (view.GetType ().GetProperty ("Title") != null) {
+				view?.GetType ().GetProperty ("Title")?.GetSetMethod ()?.Invoke (view, new [] { ustring.Make ("Test Title") });
+			}
+
+			// Set Settings
+			_computedCheckBox.Checked = view.LayoutStyle == LayoutStyle.Computed;
+
+			// Add
+			_hostPane.Add (view);
+			//DimPosChanged ();
+			_hostPane.LayoutSubviews ();
+			_hostPane.Clear ();
+			_hostPane.SetNeedsDisplay ();
+			UpdateSettings (view);
+			UpdateTitle (view);
+			return view;
+		}
+
+		public override void Run ()
+		{
+			base.Run ();
+		}
+
+		private void Quit ()
+		{
+			Application.RequestStop ();
+		}
+	}
+}

+ 26 - 6
UICatalog/Scenarios/ComputedLayout.cs

@@ -1,6 +1,8 @@
-using System;
+using NStack;
+using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 using Terminal.Gui;
 
@@ -17,13 +19,26 @@ namespace UICatalog {
 
 		public override void Setup ()
 		{
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("_Settings", new MenuItem [] {
+					null,
+					new MenuItem ("_Quit", "", () => Quit()),
+				}),
+			});
+			Top.Add (menu);
+
+			var statusBar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.ControlQ, "~^Q~ Quit", () => Quit()),
+			});
+			Top.Add (statusBar);
+
 			//Top.LayoutStyle = LayoutStyle.Computed;
 			// Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width
 			// BUGBUG: Dim.Fill returns too big a value sometimes.
 			const string rule = "|123456789";
 			var horizontalRuler = new Label ("") {
 				X = 0,
-				Y = 0,		
+				Y = 0,
 				Width = Dim.Fill (1),  // BUGBUG: I don't think this should be needed; DimFill() should respect container's frame. X does.
 				ColorScheme = Colors.Error
 			};
@@ -44,7 +59,7 @@ namespace UICatalog {
 
 			Win.LayoutComplete += (sender, a) => {
 				horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)];
-				verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height*2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height*2)];
+				verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height * 2)];
 			};
 
 			Win.Add (verticalRuler);
@@ -59,7 +74,7 @@ namespace UICatalog {
 			// Demonstrate using Dim to create a window that fills the parent with a margin
 			int margin = 10;
 			var subWin = new Window ($"Centered Sub Window with {margin} character margin") {
-				X = Pos.Center(),
+				X = Pos.Center (),
 				Y = 2,
 				Width = Dim.Fill (margin),
 				Height = 7
@@ -79,7 +94,7 @@ namespace UICatalog {
 			// #522 repro?
 			var frameView = new FrameView ($"Centered FrameView with {margin} character margin") {
 				X = Pos.Center (),
-				Y = Pos.Bottom(subWin),
+				Y = Pos.Bottom (subWin),
 				Width = Dim.Fill (margin),
 				Height = 7
 			};
@@ -176,7 +191,7 @@ namespace UICatalog {
 
 			// Center three buttons with 5 spaces between them
 			// TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
-			leftButton.X = Pos.Left (centerButton) - (Pos.Right(leftButton) - Pos.Left (leftButton)) - 5;
+			leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
 			rightButton.X = Pos.Right (centerButton) + 5;
 
 			Win.Add (leftButton);
@@ -188,6 +203,11 @@ namespace UICatalog {
 		{
 			base.Run ();
 		}
+
+		private void Quit ()
+		{
+			Application.RequestStop ();
+		}
 	}
 
 	internal static class StringExtensions {

+ 1 - 1
UICatalog/Scenarios/Progress.cs

@@ -63,7 +63,7 @@ namespace UICatalog {
 				var pulseButton = new Button ("Pulse") {
 					X = Pos.Right (startButton) + 2,
 					Y = Pos.Y (startButton),
-					Clicked = () => PulseBtnClick.Invoke ()
+					Clicked = () => Pulse()
 				};
 				var stopbutton = new Button ("Stop Timer") {
 					X = Pos.Right (pulseButton) + 2,

+ 10 - 10
UICatalog/Scenarios/Unicode.cs

@@ -35,16 +35,16 @@ namespace UICatalog {
 			var checkBox = new CheckBox (" ~  s  gui.cs   master ↑10") { X = 15, Y = Pos.Y (label), Width = Dim.Percent (50) };
 			Win.Add (checkBox);
 
-			label = new Label ("ComboBox:") { X = Pos.X (label), Y = Pos.Bottom (label) + 1 };
-			Win.Add (label);
-			var comboBox = new ComboBox (1, 1, 30, 5, new List<string> () { "item #1", " ~  s  gui.cs   master ↑10", "Со_хранить" }) {
-				X = 15,
-				Y = Pos.Y (label),
-				Width = 30,
-				ColorScheme = Colors.Error
-			};
-			Win.Add (comboBox);
-			comboBox.Text = " ~  s  gui.cs   master ↑10";
+			//label = new Label ("ComboBox:") { X = Pos.X (label), Y = Pos.Bottom (label) + 1 };
+			//Win.Add (label);
+			//var comboBox = new ComboBox (1, 1, 30, 5, new List<string> () { "item #1", " ~  s  gui.cs   master ↑10", "Со_хранить" }) {
+			//	X = 15,
+			//	Y = Pos.Y (label),
+			//	Width = 30,
+			//	ColorScheme = Colors.Error
+			//};
+			//Win.Add (comboBox);
+			//comboBox.Text = " ~  s  gui.cs   master ↑10";
 
 			label = new Label ("HexView:") { X = Pos.X (label), Y = Pos.Bottom (label) + 2 };
 			Win.Add (label);

+ 32 - 8
UICatalog/UICatalog.cs

@@ -59,7 +59,6 @@ namespace UICatalog {
 
 		private static Scenario _runningScenario = null;
 		private static bool _useSystemConsole = false;
-		private static MenuItem _sysConsoleMenu;
 
 		static void Main (string [] args)
 		{
@@ -124,6 +123,17 @@ namespace UICatalog {
 			return _runningScenario;
 		}
 
+		static MenuItem CheckedMenuMenuItem(ustring menuItem, Action action, Func<bool> checkFunction)
+		{
+			var mi = new MenuItem ();
+			mi.Title = $"[{(checkFunction () ? 'x' : ' ')}] {menuItem}"; 
+			mi.Action = () => {
+				action?.Invoke ();
+				mi.Title = $"[{(checkFunction () ? 'x' : ' ')}] {menuItem}";
+			};
+			return mi;
+		}
+
 
 		/// <summary>
 		/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
@@ -137,18 +147,32 @@ namespace UICatalog {
 			aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}");
 			aboutMessage.AppendLine ("");
 
-			void HandleSysConsoleMenuChange ()
-			{
-				_useSystemConsole = !_useSystemConsole;
-				_sysConsoleMenu.Title = $"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console";
-			}
-			_sysConsoleMenu = new MenuItem ($"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console", "", () => HandleSysConsoleMenuChange ());
 
+			var framePaddingMenuText = "Diagnostics: _Frame Padding";
 			_menu = new MenuBar (new MenuBarItem [] {
 				new MenuBarItem ("_File", new MenuItem [] {
 					new MenuItem ("_Quit", "", () => Application.RequestStop() )
 				}),
-				new MenuBarItem ("_Settings", new MenuItem [] { _sysConsoleMenu }),
+				new MenuBarItem ("_Settings", new MenuItem [] { 
+					CheckedMenuMenuItem ("Use _System Console", 
+						() => {
+							_useSystemConsole = !_useSystemConsole;
+						},
+						() => _useSystemConsole),
+					CheckedMenuMenuItem ("Diagnostics: _Frame Padding",
+						() => {
+							ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FramePadding;
+							_top.SetNeedsDisplay ();
+						},
+						() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding),
+					CheckedMenuMenuItem ("Diagnostics: Frame _Ruler",
+						() => {
+							ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler;
+							_top.SetNeedsDisplay ();
+						},
+						() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler),
+
+				}),
 				new MenuBarItem ("_About...", "About this app", () =>  MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "Ok")),
 			});
 

+ 4 - 0
UICatalog/UICatalog.csproj

@@ -7,6 +7,10 @@
     <AssemblyVersion>1.0.0.1</AssemblyVersion>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Remove="Scenarios\ListsAndCombos.cs" />
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
   </ItemGroup>