فهرست منبع

Merge branch 'v2_develop' into events

Thomas Nind 2 سال پیش
والد
کامیت
057cea44d2

+ 6 - 9
Terminal.Gui/Core/Application.cs

@@ -983,13 +983,10 @@ namespace Terminal.Gui {
 
 			var rs = new RunState (toplevel);
 
-			if (toplevel is ISupportInitializeNotification initializableNotification &&
-			    !initializableNotification.IsInitialized) {
-				initializableNotification.BeginInit ();
-				initializableNotification.EndInit ();
-			} else if (toplevel is ISupportInitialize initializable) {
-				initializable.BeginInit ();
-				initializable.EndInit ();
+			// View implements ISupportInitializeNotification which is derived from ISupportInitialize
+			if (!toplevel.IsInitialized) {
+				toplevel.BeginInit ();
+				toplevel.EndInit ();
 			}
 
 			lock (toplevels) {
@@ -1251,7 +1248,7 @@ namespace Terminal.Gui {
 					MdiTop?.OnDeactivate (state.Toplevel);
 					state.Toplevel = Current;
 					MdiTop?.OnActivate (state.Toplevel);
-					Top.SetChildNeedsDisplay ();
+					Top.SetSubViewNeedsDisplay ();
 					Refresh ();
 				}
 				if (Driver.EnsureCursorVisibility ()) {
@@ -1315,7 +1312,7 @@ namespace Terminal.Gui {
 
 			foreach (var top in toplevels) {
 				if (top != Current && top.Visible && (!top.NeedDisplay.IsEmpty || top.ChildNeedsDisplay || top.LayoutNeeded)) {
-					MdiTop.SetChildNeedsDisplay ();
+					MdiTop.SetSubViewNeedsDisplay ();
 					return true;
 				}
 			}

+ 11 - 18
Terminal.Gui/Core/Toplevel.cs

@@ -20,19 +20,6 @@ namespace Terminal.Gui {
 	///     and run (e.g. <see cref="Dialog"/>s. To run a Toplevel, create the <see cref="Toplevel"/> and 
 	///     call <see cref="Application.Run(Toplevel, Func{Exception, bool})"/>.
 	///   </para>
-	///   <para>
-	///     Toplevels can also opt-in to more sophisticated initialization
-	///     by implementing <see cref="ISupportInitialize"/>. When they do
-	///     so, the <see cref="ISupportInitialize.BeginInit"/> and
-	///     <see cref="ISupportInitialize.EndInit"/> methods will be called
-	///     before running the view.
-	///     If first-run-only initialization is preferred, the <see cref="ISupportInitializeNotification"/>
-	///     can be implemented too, in which case the <see cref="ISupportInitialize"/>
-	///     methods will only be called if <see cref="ISupportInitializeNotification.IsInitialized"/>
-	///     is <see langword="false"/>. This allows proper <see cref="View"/> inheritance hierarchies
-	///     to override base class layout code optimally by doing so only on first run,
-	///     instead of on every run.
-	///   </para>
 	/// </remarks>
 	public class Toplevel : View {
 		/// <summary>
@@ -147,7 +134,7 @@ namespace Terminal.Gui {
 		internal virtual void OnChildClosed (Toplevel top)
 		{
 			if (IsMdiContainer) {
-				SetChildNeedsDisplay ();
+				SetSubViewNeedsDisplay ();
 			}
 			ChildClosed?.Invoke (this, new ToplevelEventArgs (top));
 		}
@@ -223,6 +210,10 @@ namespace Terminal.Gui {
 
 			Application.GrabbingMouse += Application_GrabbingMouse;
 			Application.UnGrabbingMouse += Application_UnGrabbingMouse;
+      
+			// TODO: v2 - ALL Views (Responders??!?!) should support the commands related to 
+			//    - Focus
+			//  Move the appropriate AddCommand calls to `Responder`
 
 			// Things this view knows how to do
 			AddCommand (Command.QuitToplevel, () => { QuitToplevel (); return true; });
@@ -387,7 +378,7 @@ 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"/>
+		/// <see langword="false"/>, otherwise. This is used to avoid the <see cref="View._needsDisplay"/>
 		/// having wrong values while this was not yet loaded.
 		/// </summary>
 		public bool IsLoaded { get; private set; }
@@ -625,7 +616,7 @@ namespace Terminal.Gui {
 		}
 
 		internal View EnsureVisibleBounds (Toplevel top, int x, int y,
-			out int nx, out int ny, out View mb, out View sb)
+			out int nx, out int ny, out MenuBar mb, out StatusBar sb)
 		{
 			int l;
 			View superView;
@@ -698,13 +689,14 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
+		/// Adjusts the location and size of <paramref name="top"/> within this Toplevel.
 		/// Virtual method enabling implementation of specific positions for inherited <see cref="Toplevel"/> views.
 		/// </summary>
-		/// <param name="top">The toplevel.</param>
+		/// <param name="top">The Toplevel to adjust.</param>
 		public virtual void PositionToplevel (Toplevel top)
 		{
 			var superView = EnsureVisibleBounds (top, top.Frame.X, top.Frame.Y,
-				out int nx, out int ny, out _, out View sb);
+				out int nx, out int ny, out _, out StatusBar sb);
 			bool layoutSubviews = false;
 			if ((top?.SuperView != null || (top != Application.Top && top.Modal)
 				|| (top?.SuperView == null && top.IsMdiChild))
@@ -720,6 +712,7 @@ namespace Terminal.Gui {
 				}
 			}
 
+			// TODO: v2 - This is a hack to get the StatusBar to be positioned correctly.
 			if (sb != null && ny + top.Frame.Height != superView.Frame.Height - (sb.Visible ? 1 : 0)
 				&& top.Height is Dim.DimFill && -top.Height.Anchor (0) < 1) {
 

+ 178 - 117
Terminal.Gui/Core/View.cs

@@ -100,6 +100,20 @@ namespace Terminal.Gui {
 	///    for views that use the <see cref="LayoutStyle.Absolute"/>, and will recompute the
 	///    frames for the vies that use <see cref="LayoutStyle.Computed"/>.
 	/// </para>
+	/// <para>
+	///     Views can also opt-in to more sophisticated initialization
+	///     by implementing overrides to <see cref="ISupportInitialize.BeginInit"/> and
+	///     <see cref="ISupportInitialize.EndInit"/> which will be called
+	///     when the view is added to a <see cref="SuperView"/>. 
+	/// </para>
+	/// <para>
+	///     If first-run-only initialization is preferred, overrides to <see cref="ISupportInitializeNotification"/>
+	///     can be implemented, in which case the <see cref="ISupportInitialize"/>
+	///     methods will only be called if <see cref="ISupportInitializeNotification.IsInitialized"/>
+	///     is <see langword="false"/>. This allows proper <see cref="View"/> inheritance hierarchies
+	///     to override base class layout code optimally by doing so only on first run,
+	///     instead of on every run.
+	///   </para>
 	/// </remarks>
 	public partial class View : Responder, ISupportInitializeNotification {
 
@@ -448,7 +462,7 @@ namespace Terminal.Gui {
 			get => frame;
 			set {
 				frame = new Rect (value.X, value.Y, Math.Max (value.Width, 0), Math.Max (value.Height, 0));
-				TextFormatter.Size = GetBoundsTextFormatterSize ();
+				TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 				SetNeedsLayout ();
 				SetNeedsDisplay ();
 			}
@@ -521,7 +535,7 @@ namespace Terminal.Gui {
 
 				x = value;
 
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 
@@ -541,7 +555,7 @@ namespace Terminal.Gui {
 
 				y = value;
 
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 		Dim width, height;
@@ -569,7 +583,7 @@ namespace Terminal.Gui {
 						throw new InvalidOperationException ("Must set AutoSize to false before set the Width.");
 					}
 				}
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 
@@ -594,7 +608,7 @@ namespace Terminal.Gui {
 						throw new InvalidOperationException ("Must set AutoSize to false before set the Height.");
 					}
 				}
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 
@@ -618,11 +632,16 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Verifies if the minimum width or height can be sets in the view.
+		/// Gets the minimum dimensions required to fit the View's <see cref="Text"/>, factoring in <see cref="TextDirection"/>.
 		/// </summary>
-		/// <param name="size">The size.</param>
-		/// <returns><see langword="true"/> if the size can be set, <see langword="false"/> otherwise.</returns>
-		public bool GetMinWidthHeight (out Size size)
+		/// <param name="size">The minimum dimensions required.</param>
+		/// <returns><see langword="true"/> if the dimensions fit within the View's <see cref="Bounds"/>, <see langword="false"/> otherwise.</returns>
+		/// <remarks>
+		/// Always returns <see langword="false"/> if <see cref="AutoSize"/> is <see langword="true"/> or
+		/// if <see cref="Height"/> (Horizontal) or <see cref="Width"/> (Vertical) are not not set or zero.
+		/// Does not take into account word wrapping.
+		/// </remarks>
+		public bool GetMinimumBounds (out Size size)
 		{
 			size = Size.Empty;
 
@@ -630,14 +649,22 @@ namespace Terminal.Gui {
 				switch (TextFormatter.IsVerticalDirection (TextDirection)) {
 				case true:
 					var colWidth = TextFormatter.GetSumMaxCharWidth (new List<ustring> { TextFormatter.Text }, 0, 1);
-					if (frame.Width < colWidth && (Width == null || (Bounds.Width >= 0 && Width is Dim.DimAbsolute
-						&& Width.Anchor (0) >= 0 && Width.Anchor (0) < colWidth))) {
+					// TODO: v2 - This uses frame.Width; it should only use Bounds
+					if (frame.Width < colWidth &&
+						(Width == null ||
+							(Bounds.Width >= 0 &&
+								Width is Dim.DimAbsolute &&
+								Width.Anchor (0) >= 0 &&
+								Width.Anchor (0) < colWidth))) {
 						size = new Size (colWidth, Bounds.Height);
 						return true;
 					}
 					break;
 				default:
-					if (frame.Height < 1 && (Height == null || (Height is Dim.DimAbsolute && Height.Anchor (0) == 0))) {
+					if (frame.Height < 1 &&
+						(Height == null ||
+							(Height is Dim.DimAbsolute &&
+								Height.Anchor (0) == 0))) {
 						size = new Size (Bounds.Width, 1);
 						return true;
 					}
@@ -648,14 +675,14 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Sets the minimum width or height if the view can be resized.
+		/// Sets the size of the View to the minimum width or height required to fit <see cref="Text"/> (see <see cref="GetMinimumBounds(out Size)"/>.
 		/// </summary>
-		/// <returns><see langword="true"/> if the size can be set, <see langword="false"/> otherwise.</returns>
+		/// <returns><see langword="true"/> if the size was changed, <see langword="false"/> if <see cref="Text"/>
+		/// will not fit.</returns>
 		public bool SetMinWidthHeight ()
 		{
-			if (GetMinWidthHeight (out Size size)) {
+			if (GetMinimumBounds (out Size size)) {
 				Bounds = new Rect (Bounds.Location, size);
-				TextFormatter.Size = GetBoundsTextFormatterSize ();
 				return true;
 			}
 			return false;
@@ -683,7 +710,7 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public View (Rect frame)
 		{
-			Initialize (ustring.Empty, frame, LayoutStyle.Absolute, TextDirection.LeftRight_TopBottom);
+			SetInitialProperties (ustring.Empty, frame, LayoutStyle.Absolute, TextDirection.LeftRight_TopBottom);
 		}
 
 		/// <summary>
@@ -742,7 +769,7 @@ namespace Terminal.Gui {
 		/// <param name="border">The <see cref="Border"/>.</param>
 		public View (Rect rect, ustring text, Border border = null)
 		{
-			Initialize (text, rect, LayoutStyle.Absolute, TextDirection.LeftRight_TopBottom, border);
+			SetInitialProperties (text, rect, LayoutStyle.Absolute, TextDirection.LeftRight_TopBottom, border);
 		}
 
 		/// <summary>
@@ -763,19 +790,25 @@ namespace Terminal.Gui {
 		/// <param name="border">The <see cref="Border"/>.</param>
 		public View (ustring text, TextDirection direction = TextDirection.LeftRight_TopBottom, Border border = null)
 		{
-			Initialize (text, Rect.Empty, LayoutStyle.Computed, direction, border);
+			SetInitialProperties (text, Rect.Empty, LayoutStyle.Computed, direction, border);
 		}
 
-		void Initialize (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed,
+		// TODO: v2 - Remove constructors with parameters
+		/// <summary>
+		/// Private helper to set the initial properties of the View that were provided via constructors.
+		/// </summary>
+		/// <param name="text"></param>
+		/// <param name="rect"></param>
+		/// <param name="layoutStyle"></param>
+		/// <param name="direction"></param>
+		/// <param name="border"></param>
+		void SetInitialProperties (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed,
 		    TextDirection direction = TextDirection.LeftRight_TopBottom, Border border = null)
 		{
+
 			TextFormatter = new TextFormatter ();
 			TextFormatter.HotKeyChanged += TextFormatter_HotKeyChanged;
 			TextDirection = direction;
-			Border = border;
-			if (Border != null) {
-				Border.Child = this;
-			}
 			shortcutHelper = new ShortcutHelper ();
 			CanFocus = false;
 			TabIndex = -1;
@@ -783,12 +816,18 @@ namespace Terminal.Gui {
 			LayoutStyle = layoutStyle;
 			// BUGBUG: CalcRect doesn't account for line wrapping
 
+			// TODO: Remove this once v2's new Frames is ready
+			Border = border;
+			if (Border != null) {
+				Border.Child = this;
+			}
+
 			var r = rect.IsEmpty ? TextFormatter.CalcRect (0, 0, text, direction) : rect;
 			Frame = r;
 
 			Text = text;
-			UpdateTextFormatterText ();
-			ProcessResizeView ();
+
+			OnResizeNeeded ();
 		}
 
 		/// <summary>
@@ -801,10 +840,11 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
+		/// Called whenever the view needs to be resized. 
 		/// Can be overridden if the view resize behavior is
 		///  different than the default.
 		/// </summary>
-		protected virtual void ProcessResizeView ()
+		protected virtual void OnResizeNeeded ()
 		{
 			var actX = x is Pos.PosAbsolute ? x.Anchor (0) : frame.X;
 			var actY = y is Pos.PosAbsolute ? y.Anchor (0) : frame.Y;
@@ -820,7 +860,8 @@ namespace Terminal.Gui {
 				frame = new Rect (new Point (actX, actY), new Size (w, h));
 				SetMinWidthHeight ();
 			}
-			TextFormatter.Size = GetBoundsTextFormatterSize ();
+			// BUGBUG: I think these calls are redundant or should be moved into just the AutoSize case
+			TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 			SetNeedsLayout ();
 			SetNeedsDisplay ();
 		}
@@ -877,7 +918,7 @@ namespace Terminal.Gui {
 				var h = Math.Max (NeedDisplay.Height, region.Height);
 				NeedDisplay = new Rect (x, y, w, h);
 			}
-			container?.SetChildNeedsDisplay ();
+			container?.SetSubViewNeedsDisplay ();
 
 			if (subviews == null)
 				return;
@@ -896,11 +937,11 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Indicates that any child views (in the <see cref="Subviews"/> list) need to be repainted.
 		/// </summary>
-		public void SetChildNeedsDisplay ()
+		public void SetSubViewNeedsDisplay ()
 		{
 			ChildNeedsDisplay = true;
 			if (container != null)
-				container.SetChildNeedsDisplay ();
+				container.SetSubViewNeedsDisplay ();
 		}
 
 		internal bool addingView;
@@ -942,8 +983,9 @@ namespace Terminal.Gui {
 			}
 			SetNeedsLayout ();
 			SetNeedsDisplay ();
+      
 			OnAdded (new SuperViewChangedEventArgs (this, view));
-			if (IsInitialized) {
+			if (IsInitialized && !view.IsInitialized) {
 				view.BeginInit ();
 				view.EndInit ();
 			}
@@ -1488,14 +1530,14 @@ namespace Terminal.Gui {
 				(!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) {
 
 				Clear ();
-				SetChildNeedsDisplay ();
+				SetSubViewNeedsDisplay ();
 			}
 
 			if (!ustring.IsNullOrEmpty (TextFormatter.Text)) {
 				Rect containerBounds = GetContainerBounds ();
 				if (!containerBounds.IsEmpty) {
 					Clear (GetNeedDisplay (containerBounds));
-					SetChildNeedsDisplay ();
+					SetSubViewNeedsDisplay ();
 					// Draw any Text
 					if (TextFormatter != null) {
 						TextFormatter.NeedsFormat = true;
@@ -2233,8 +2275,9 @@ namespace Terminal.Gui {
 			var r = new Rect (newX, newY, newW, newH);
 			if (Frame != r) {
 				Frame = r;
+				// BUGBUG: Why is this AFTER setting Frame? Seems duplicative.
 				if (!SetMinWidthHeight ()) {
-					TextFormatter.Size = GetBoundsTextFormatterSize ();
+					TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 				}
 			}
 		}
@@ -2368,9 +2411,13 @@ namespace Terminal.Gui {
 				(var from, var to) = edges.First ();
 				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}?");
+						if (ReferenceEquals (from.SuperView, to)) {
+							throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{to}\" references a SubView (\"{from}\").");
+						} else {
+							throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{from}\" linked with \"{to}\" was not found. Did you forget to add it to {superView}?");
+						}
 					} else {
-						throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + superView);
+						throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": A recursive cycle was found in the relative Pos/Dim of the SubViews.");
 					}
 				}
 			}
@@ -2395,7 +2442,7 @@ namespace Terminal.Gui {
 			var oldBounds = Bounds;
 			OnLayoutStarted (new LayoutEventArgs () { OldBounds = oldBounds });
 
-			TextFormatter.Size = GetBoundsTextFormatterSize ();
+			TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 
 			// Sort out the dependencies of the X, Y, Width, Height properties
 			var nodes = new HashSet<View> ();
@@ -2456,17 +2503,22 @@ namespace Terminal.Gui {
 				text = value;
 				SetHotKey ();
 				UpdateTextFormatterText ();
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 
 		/// <summary>
-		/// Gets or sets a flag that determines whether the View will be automatically resized to fit the <see cref="Text"/>.
-		/// The default is <see langword="false"/>. Set to <see langword="true"/> to turn on AutoSize. If <see cref="AutoSize"/> is <see langword="true"/> the <see cref="Width"/>
-		/// and <see cref="Height"/> will always be used if the text size is lower. If the text size is higher the bounds will
-		/// be resized to fit it.
+		/// Gets or sets a flag that determines whether the View will be automatically resized to fit the <see cref="Text"/> 
+		/// within <see cref="Bounds"/>
+		/// <para>
+		/// The default is <see langword="false"/>. Set to <see langword="true"/> to turn on AutoSize. If <see langword="true"/> then
+		/// <see cref="Width"/> and <see cref="Height"/> will be used if <see cref="Text"/> can fit; 
+		/// if <see cref="Text"/> won't fit the view will be resized as needed.
+		/// </para>
+		/// <para>
 		/// In addition, if <see cref="ForceValidatePosDim"/> is <see langword="true"/> the new values of <see cref="Width"/> and
 		/// <see cref="Height"/> must be of the same types of the existing one to avoid breaking the <see cref="Dim"/> settings.
+		/// </para>
 		/// </summary>
 		public virtual bool AutoSize {
 			get => autoSize;
@@ -2477,7 +2529,7 @@ namespace Terminal.Gui {
 					autoSize = v;
 					TextFormatter.NeedsFormat = true;
 					UpdateTextFormatterText ();
-					ProcessResizeView ();
+					OnResizeNeeded ();
 				}
 			}
 		}
@@ -2508,7 +2560,7 @@ namespace Terminal.Gui {
 			set {
 				TextFormatter.Alignment = value;
 				UpdateTextFormatterText ();
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 
@@ -2541,23 +2593,31 @@ namespace Terminal.Gui {
 
 					if ((!ForceValidatePosDim && directionChanged && AutoSize)
 					    || (ForceValidatePosDim && directionChanged && AutoSize && isValidOldAutSize)) {
-						ProcessResizeView ();
+						OnResizeNeeded ();
 					} else if (directionChanged && IsAdded) {
 						SetWidthHeight (Bounds.Size);
 						SetMinWidthHeight ();
 					} else {
 						SetMinWidthHeight ();
 					}
-					TextFormatter.Size = GetBoundsTextFormatterSize ();
+					TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 					SetNeedsDisplay ();
 				}
 			}
 		}
 
 		/// <summary>
-		/// Get or sets if  the <see cref="View"/> was already initialized.
-		/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being initialized.
+		/// Get or sets if  the <see cref="View"/> has been initialized (via <see cref="ISupportInitialize.BeginInit"/> 
+		/// and <see cref="ISupportInitialize.EndInit"/>).
 		/// </summary>
+		/// <para>
+		///     If first-run-only initialization is preferred, overrides to <see cref="ISupportInitializeNotification.IsInitialized"/>
+		///     can be implemented, in which case the <see cref="ISupportInitialize"/>
+		///     methods will only be called if <see cref="ISupportInitializeNotification.IsInitialized"/>
+		///     is <see langword="false"/>. This allows proper <see cref="View"/> inheritance hierarchies
+		///     to override base class layout code optimally by doing so only on first run,
+		///     instead of on every run.
+		///   </para>
 		public virtual bool IsInitialized { get; set; }
 
 		/// <summary>
@@ -2679,15 +2739,21 @@ namespace Terminal.Gui {
 					Bounds = new Rect (Bounds.X, Bounds.Y, nBoundsSize.Width, nBoundsSize.Height);
 				}
 			}
-			TextFormatter.Size = GetBoundsTextFormatterSize ();
+			// BUGBUG: This call may be redundant
+			TextFormatter.Size = GetSizeNeededForTextAndHotKey ();
 			return aSize;
 		}
 
+		/// <summary>
+		/// Resizes the View to fit the specified <see cref="Bounds"/> size.
+		/// </summary>
+		/// <param name="nBounds"></param>
+		/// <returns></returns>
 		bool SetWidthHeight (Size nBounds)
 		{
 			var aSize = false;
-			var canSizeW = SetWidth (nBounds.Width - GetHotKeySpecifierLength (), out var rW);
-			var canSizeH = SetHeight (nBounds.Height - GetHotKeySpecifierLength (false), out var rH);
+			var canSizeW = TrySetWidth (nBounds.Width - GetHotKeySpecifierLength (), out var rW);
+			var canSizeH = TrySetHeight (nBounds.Height - GetHotKeySpecifierLength (false), out var rH);
 			if (canSizeW) {
 				aSize = true;
 				width = rW;
@@ -2698,7 +2764,6 @@ namespace Terminal.Gui {
 			}
 			if (aSize) {
 				Bounds = new Rect (Bounds.X, Bounds.Y, canSizeW ? rW : Bounds.Width, canSizeH ? rH : Bounds.Height);
-				TextFormatter.Size = GetBoundsTextFormatterSize ();
 			}
 
 			return aSize;
@@ -2744,8 +2809,12 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Gets the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> characters in the <see cref="Text"/> property.
+		/// Gets the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> characters 
+		/// in the <see cref="Text"/> property.
 		/// </summary>
+		/// <remarks>
+		/// Only the first hotkey specifier found in <see cref="Text"/> is supported.
+		/// </remarks>
 		/// <param name="isWidth">If <see langword="true"/> (the default) the width required for the hotkey specifier is returned. Otherwise the height is returned.</param>
 		/// <returns>The number of characters required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>. If the text direction specified
 		/// by <see cref="TextDirection"/> does not match the <paramref name="isWidth"/> parameter, <c>0</c> is returned.</returns>
@@ -2763,24 +2832,27 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Gets the <see cref="TextFormatter.Size"/> minus the size required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.
-		/// </summary>
-		/// <returns>The bounds size minus the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> length.</returns>
-		public Size GetTextFormatterBoundsSize ()
+		/// Gets the dimensions required for <see cref="Text"/> ignoring a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.
+		/// /// <summary/>
+		/// <returns></returns>
+		public Size GetSizeNeededForTextWithoutHotKey ()
 		{
 			return new Size (TextFormatter.Size.Width - GetHotKeySpecifierLength (),
 			    TextFormatter.Size.Height - GetHotKeySpecifierLength (false));
 		}
 
 		/// <summary>
-		/// Gets the text formatter size from a <see cref="Bounds"/> size.
-		/// </summary>
-		/// <returns>The text formatter size more the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> length.</returns>
-		public Size GetBoundsTextFormatterSize ()
+		/// Gets the dimensions required for <see cref="Text"/> accounting for a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> .
+		/// <summary/>
+		/// <returns></returns>
+		public Size GetSizeNeededForTextAndHotKey ()
 		{
-			if (ustring.IsNullOrEmpty (TextFormatter.Text))
+			if (ustring.IsNullOrEmpty (TextFormatter.Text)) {
 				return Bounds.Size;
+			}
 
+			// BUGBUG: This IGNORES what Text is set to, using on only the current View size. This doesn't seem to make sense.
+			// BUGBUG: This uses Frame; in v2 it should be Bounds
 			return new Size (frame.Size.Width + GetHotKeySpecifierLength (),
 			    frame.Size.Height + GetHotKeySpecifierLength (false));
 		}
@@ -2885,14 +2957,39 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are beginning initialized.
+		///  Signals the View that initialization is starting. See <see cref="ISupportInitialize"/>.
 		/// </summary>
-		public void BeginInit ()
+		/// <remarks>
+		/// <para>
+		///     Views can opt-in to more sophisticated initialization
+		///     by implementing overrides to <see cref="ISupportInitialize.BeginInit"/> and
+		///     <see cref="ISupportInitialize.EndInit"/> which will be called
+		///     when the view is added to a <see cref="SuperView"/>. 
+		/// </para>
+		/// <para>
+		///     If first-run-only initialization is preferred, overrides to <see cref="ISupportInitializeNotification"/>
+		///     can be implemented too, in which case the <see cref="ISupportInitialize"/>
+		///     methods will only be called if <see cref="ISupportInitializeNotification.IsInitialized"/>
+		///     is <see langword="false"/>. This allows proper <see cref="View"/> inheritance hierarchies
+		///     to override base class layout code optimally by doing so only on first run,
+		///     instead of on every run.
+		///   </para>
+		/// </remarks>
+		public virtual void BeginInit ()
 		{
 			if (!IsInitialized) {
 				oldCanFocus = CanFocus;
 				oldTabIndex = tabIndex;
+
+				//UpdateTextFormatterText ();
+				// TODO: Figure out why ScrollView and other tests fail if this call is put here 
+				// instead of the constructor.
+				// OnSizeChanged ();
+
+			} else {
+				//throw new InvalidOperationException ("The view is already initialized.");
 			}
+
 			if (subviews?.Count > 0) {
 				foreach (var view in subviews) {
 					if (!view.IsInitialized) {
@@ -2903,12 +3000,12 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are ending initialized.
+		///  Signals the View that initialization is ending. See <see cref="ISupportInitialize"/>.
 		/// </summary>
 		public void EndInit ()
 		{
 			IsInitialized = true;
-			if (subviews?.Count > 0) {
+			if (subviews != null) {
 				foreach (var view in subviews) {
 					if (!view.IsInitialized) {
 						view.EndInit ();
@@ -2932,7 +3029,13 @@ namespace Terminal.Gui {
 			return true;
 		}
 
-		bool CanSetWidth (int desiredWidth, out int resultWidth)
+		/// <summary>
+		/// Determines if the View's <see cref="Width"/> can be set to a new value.
+		/// </summary>
+		/// <param name="desiredWidth"></param>
+		/// <param name="resultWidth">Contains the width that would result if <see cref="Width"/> were set to <paramref name="desiredWidth"/>"/> </param>
+		/// <returns><see langword="true"/> if the View's <see cref="Width"/> can be changed to the specified value. False otherwise.</returns>
+		internal bool TrySetWidth (int desiredWidth, out int resultWidth)
 		{
 			var w = desiredWidth;
 			bool canSetWidth;
@@ -2956,7 +3059,13 @@ namespace Terminal.Gui {
 			return canSetWidth;
 		}
 
-		bool CanSetHeight (int desiredHeight, out int resultHeight)
+		/// <summary>
+		/// Determines if the View's <see cref="Height"/> can be set to a new value.
+		/// </summary>
+		/// <param name="desiredHeight"></param>
+		/// <param name="resultHeight">Contains the width that would result if <see cref="Height"/> were set to <paramref name="desiredHeight"/>"/> </param>
+		/// <returns><see langword="true"/> if the View's <see cref="Height"/> can be changed to the specified value. False otherwise.</returns>
+		internal bool TrySetHeight (int desiredHeight, out int resultHeight)
 		{
 			var h = desiredHeight;
 			bool canSetHeight;
@@ -2986,54 +3095,6 @@ namespace Terminal.Gui {
 			return canSetHeight;
 		}
 
-		/// <summary>
-		/// Calculate the width based on the <see cref="Width"/> settings.
-		/// </summary>
-		/// <param name="desiredWidth">The desired width.</param>
-		/// <param name="resultWidth">The real result width.</param>
-		/// <returns><see langword="true"/> if the width can be directly assigned, <see langword="false"/> otherwise.</returns>
-		public bool SetWidth (int desiredWidth, out int resultWidth)
-		{
-			return CanSetWidth (desiredWidth, out resultWidth);
-		}
-
-		/// <summary>
-		/// Calculate the height based on the <see cref="Height"/> settings.
-		/// </summary>
-		/// <param name="desiredHeight">The desired height.</param>
-		/// <param name="resultHeight">The real result height.</param>
-		/// <returns><see langword="true"/> if the height can be directly assigned, <see langword="false"/> otherwise.</returns>
-		public bool SetHeight (int desiredHeight, out int resultHeight)
-		{
-			return CanSetHeight (desiredHeight, out resultHeight);
-		}
-
-		/// <summary>
-		/// Gets the current width based on the <see cref="Width"/> settings.
-		/// </summary>
-		/// <param name="currentWidth">The real current width.</param>
-		/// <returns><see langword="true"/> if the width can be directly assigned, <see langword="false"/> otherwise.</returns>
-		public bool GetCurrentWidth (out int currentWidth)
-		{
-			SetRelativeLayout (SuperView?.frame ?? frame);
-			currentWidth = frame.Width;
-
-			return CanSetWidth (0, out _);
-		}
-
-		/// <summary>
-		/// Calculate the height based on the <see cref="Height"/> settings.
-		/// </summary>
-		/// <param name="currentHeight">The real current height.</param>
-		/// <returns><see langword="true"/> if the height can be directly assigned, <see langword="false"/> otherwise.</returns>
-		public bool GetCurrentHeight (out int currentHeight)
-		{
-			SetRelativeLayout (SuperView?.frame ?? frame);
-			currentHeight = frame.Height;
-
-			return CanSetHeight (0, out _);
-		}
-
 		/// <summary>
 		/// Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.
 		/// </summary>

+ 1 - 1
Terminal.Gui/Types/Rect.cs

@@ -130,7 +130,7 @@ namespace Terminal.Gui
 		///
 		/// <remarks>
 		///	Produces a new Rectangle by intersecting 2 existing 
-		///	Rectangles. Returns null if there is no	intersection.
+		///	Rectangles. Returns Empty if there is no intersection.
 		/// </remarks>
 
 		public static Rect Intersect (Rect a, Rect b)

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

@@ -60,7 +60,7 @@ namespace Terminal.Gui {
 		/// </param>
 		public Button (ustring text, bool is_default = false) : base (text)
 		{
-			Initialize (text, is_default);
+			SetInitialProperties (text, is_default);
 		}
 
 		/// <summary>
@@ -92,10 +92,15 @@ namespace Terminal.Gui {
 		public Button (int x, int y, ustring text, bool is_default)
 		    : base (new Rect (x, y, text.RuneCount + 4 + (is_default ? 2 : 0), 1), text)
 		{
-			Initialize (text, is_default);
+			SetInitialProperties (text, is_default);
 		}
-
-		void Initialize (ustring text, bool is_default)
+		// TODO: v2 - Remove constructors with parameters
+		/// <summary>
+		/// Private helper to set the initial properties of the View that were provided via constructors.
+		/// </summary>
+		/// <param name="text"></param>
+		/// <param name="is_default"></param>
+		void SetInitialProperties (ustring text, bool is_default)
 		{
 			TextAlignment = TextAlignment.Centered;
 			VerticalTextAlignment = VerticalTextAlignment.Middle;
@@ -111,8 +116,8 @@ namespace Terminal.Gui {
 			AutoSize = true;
 			this.is_default = is_default;
 			Text = text ?? string.Empty;
-			UpdateTextFormatterText ();
-			ProcessResizeView ();
+
+			OnResizeNeeded ();
 
 			// Things this view knows how to do
 			AddCommand (Command.Accept, () => AcceptKey ());
@@ -134,7 +139,7 @@ namespace Terminal.Gui {
 			set {
 				is_default = value;
 				UpdateTextFormatterText ();
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 

+ 12 - 6
Terminal.Gui/Views/CheckBox.cs

@@ -49,7 +49,7 @@ namespace Terminal.Gui {
 		/// <param name="is_checked">If set to <c>true</c> is checked.</param>
 		public CheckBox (ustring s, bool is_checked = false) : base ()
 		{
-			Initialize (s, is_checked);
+			SetInitialProperties (s, is_checked);
 		}
 
 		/// <summary>
@@ -72,10 +72,16 @@ namespace Terminal.Gui {
 		/// </remarks>
 		public CheckBox (int x, int y, ustring s, bool is_checked) : base (new Rect (x, y, s.Length, 1))
 		{
-			Initialize (s, is_checked);
+			SetInitialProperties (s, is_checked);
 		}
 
-		void Initialize (ustring s, bool is_checked)
+		// TODO: v2 - Remove constructors with parameters
+		/// <summary>
+		/// Private helper to set the initial properties of the View that were provided via constructors.
+		/// </summary>
+		/// <param name="s"></param>
+		/// <param name="is_checked"></param>
+		void SetInitialProperties (ustring s, bool is_checked)
 		{
 			charNullChecked = new Rune (Driver != null ? Driver.NullChecked : '?');
 			charChecked = new Rune (Driver != null ? Driver.Checked : '√');
@@ -85,8 +91,8 @@ namespace Terminal.Gui {
 			CanFocus = true;
 			AutoSize = true;
 			Text = s;
-			UpdateTextFormatterText ();
-			ProcessResizeView ();
+			
+			OnResizeNeeded ();
 
 			// Things this view knows how to do
 			AddCommand (Command.ToggleChecked, () => ToggleChecked ());
@@ -139,7 +145,7 @@ namespace Terminal.Gui {
 				}
 				@checked = value;
 				UpdateTextFormatterText ();
-				ProcessResizeView ();
+				OnResizeNeeded ();
 			}
 		}
 

+ 1 - 15
Terminal.Gui/Views/FrameView.cs

@@ -1,16 +1,4 @@
-//
-// Authors:
-//   Miguel de Icaza ([email protected])
-//
-// NOTE: FrameView is functionally identical to Window with the following exceptions. 
-//  - Is not a Toplevel
-//  - Does not support mouse dragging
-//  - Does not support padding (but should)
-//  - Does not support IEnumerable
-// Any udpates done here should probably be done in Window as well; TODO: Merge these classes
-
-using System;
-using System.Linq;
+using System.Linq;
 using System.Text.Json.Serialization;
 using NStack;
 using Terminal.Gui.Graphs;
@@ -127,8 +115,6 @@ namespace Terminal.Gui {
 		/// <param name="border">The <see cref="Border"/>.</param>
 		public FrameView (Rect frame, ustring title = null, View [] views = null, Border border = null) : base (frame)
 		{
-			//var cFrame = new Rect (1, 1, Math.Max (frame.Width - 2, 0), Math.Max (frame.Height - 2, 0));
-
 			Initialize (frame, title, views, border);
 		}
 

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

@@ -45,7 +45,7 @@ namespace Terminal.Gui {
 		/// <param name="frame"></param>
 		public ScrollView (Rect frame) : base (frame)
 		{
-			Initialize (frame);
+			SetInitialProperties (frame);
 		}
 
 
@@ -54,10 +54,10 @@ namespace Terminal.Gui {
 		/// </summary>
 		public ScrollView () : base ()
 		{
-			Initialize (Rect.Empty);
+			SetInitialProperties (Rect.Empty);
 		}
 
-		void Initialize (Rect frame)
+		void SetInitialProperties (Rect frame)
 		{
 			contentView = new ContentView (frame);
 			vertical = new ScrollBarView (1, 0, isVertical: true) {

+ 12 - 2
UICatalog/Scenarios/MessageBoxes.cs

@@ -159,10 +159,20 @@ namespace UICatalog.Scenarios {
 			};
 			frame.Add (ckbWrapMessage);
 
+      frame.ForceValidatePosDim = true;
 			void Top_Loaded (object sender, EventArgs args)
 			{
-				frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit)
-				+ Dim.Height (numButtonsEdit) + Dim.Height (defaultButtonEdit) + Dim.Height (styleRadioGroup) + 2 + Dim.Height (ckbEffect3D) + Dim.Height (ckbWrapMessage);
+				frame.Height =
+					widthEdit.Frame.Height +
+					heightEdit.Frame.Height +
+					titleEdit.Frame.Height +
+					messageEdit.Frame.Height +
+					numButtonsEdit.Frame.Height +
+					defaultButtonEdit.Frame.Height +
+					styleRadioGroup.Frame.Height +
+					2 +
+					ckbEffect3D.Frame.Height +
+					ckbWrapMessage.Frame.Height;
 				Application.Top.Loaded -= Top_Loaded;
 			}
 			Application.Top.Loaded += Top_Loaded;

+ 2 - 2
UICatalog/UICatalog.cs

@@ -304,7 +304,7 @@ namespace UICatalog {
 						StatusBar.Visible = !StatusBar.Visible;
 						ContentPane.Height = Dim.Fill(StatusBar.Visible ? 1 : 0);
 						LayoutSubviews();
-						SetChildNeedsDisplay();
+						SetSubViewNeedsDisplay();
 					}),
 					DriverName,
 					OS
@@ -393,7 +393,7 @@ namespace UICatalog {
 					var height = (StatusBar.Visible ? 1 : 0);// + (MenuBar.Visible ? 1 : 0);
 					ContentPane.Height = Dim.Fill (height);
 					LayoutSubviews ();
-					SetChildNeedsDisplay ();
+					SetSubViewNeedsDisplay ();
 				};
 
 				Loaded -= LoadedHandler;

+ 82 - 24
UnitTests/Core/LayoutTests.cs

@@ -47,8 +47,58 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
 		}
 
+		[Fact]
+		public void LayoutSubviews_No_SuperView ()
+		{
+			var root = new View ();
+			var first = new View () { Id = "first", X = 1, Y = 2, Height = 3, Width = 4 };
+			root.Add (first);
+
+			var second = new View () { Id = "second" };
+			root.Add (second);
+
+			second.X = Pos.Right (first) + 1;
+
+			root.LayoutSubviews ();
+			
+			Assert.Equal (6, second.Frame.X);
+		}
+
+		[Fact]
+		public void LayoutSubviews_RootHas_SuperView ()
+		{
+			var top = new View ();
+			var root = new View ();
+			top.Add (root);
+
+			var first = new View () { Id = "first", X = 1, Y = 2, Height = 3, Width = 4 };
+			root.Add (first);
+
+			var second = new View () { Id = "second" };
+			root.Add (second);
+
+			second.X = Pos.Right (first) + 1;
+
+			root.LayoutSubviews ();
+
+			Assert.Equal (6, second.Frame.X);
+		}
+
+
+		[Fact]
+		public void LayoutSubviews_ViewThatRefsSuperView_Throws ()
+		{
+			var root = new View ();
+			var super = new View ();
+			root.Add (super);
+			var sub = new View ();
+			super.Add (sub);
+			super.Width = Dim.Width (sub);
+			Assert.Throws<InvalidOperationException> (() => root.LayoutSubviews ());
+		}
+
 		[Fact, AutoInitShutdown]
-		public void SetWidth_CanSetWidth_ForceValidatePosDim ()
+		public void TrySetWidth_ForceValidatePosDim ()
 		{
 			var top = new View () {
 				X = 0,
@@ -62,15 +112,15 @@ namespace Terminal.Gui.CoreTests {
 			};
 			top.Add (v);
 
-			Assert.False (v.SetWidth (70, out int rWidth));
+			Assert.False (v.TrySetWidth (70, out int rWidth));
 			Assert.Equal (70, rWidth);
 
 			v.Width = Dim.Fill (1);
-			Assert.False (v.SetWidth (70, out rWidth));
+			Assert.False (v.TrySetWidth (70, out rWidth));
 			Assert.Equal (69, rWidth);
 
 			v.Width = null;
-			Assert.True (v.SetWidth (70, out rWidth));
+			Assert.True (v.TrySetWidth (70, out rWidth));
 			Assert.Equal (70, rWidth);
 			Assert.False (v.IsInitialized);
 
@@ -82,12 +132,12 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Throws<ArgumentException> (() => v.Width = 75);
 			v.LayoutStyle = LayoutStyle.Absolute;
 			v.Width = 75;
-			Assert.True (v.SetWidth (60, out rWidth));
+			Assert.True (v.TrySetWidth (60, out rWidth));
 			Assert.Equal (60, rWidth);
 		}
 
 		[Fact, AutoInitShutdown]
-		public void SetHeight_CanSetHeight_ForceValidatePosDim ()
+		public void TrySetHeight_ForceValidatePosDim ()
 		{
 			var top = new View () {
 				X = 0,
@@ -101,15 +151,15 @@ namespace Terminal.Gui.CoreTests {
 			};
 			top.Add (v);
 
-			Assert.False (v.SetHeight (10, out int rHeight));
+			Assert.False (v.TrySetHeight (10, out int rHeight));
 			Assert.Equal (10, rHeight);
 
 			v.Height = Dim.Fill (1);
-			Assert.False (v.SetHeight (10, out rHeight));
+			Assert.False (v.TrySetHeight (10, out rHeight));
 			Assert.Equal (9, rHeight);
 
 			v.Height = null;
-			Assert.True (v.SetHeight (10, out rHeight));
+			Assert.True (v.TrySetHeight (10, out rHeight));
 			Assert.Equal (10, rHeight);
 			Assert.False (v.IsInitialized);
 
@@ -122,12 +172,12 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Throws<ArgumentException> (() => v.Height = 15);
 			v.LayoutStyle = LayoutStyle.Absolute;
 			v.Height = 15;
-			Assert.True (v.SetHeight (5, out rHeight));
+			Assert.True (v.TrySetHeight (5, out rHeight));
 			Assert.Equal (5, rHeight);
 		}
 
 		[Fact]
-		public void GetCurrentWidth_CanSetWidth ()
+		public void GetCurrentWidth_TrySetWidth ()
 		{
 			var top = new View () {
 				X = 0,
@@ -139,23 +189,27 @@ namespace Terminal.Gui.CoreTests {
 				Width = Dim.Fill ()
 			};
 			top.Add (v);
+			top.LayoutSubviews ();
 
 			Assert.False (v.AutoSize);
-			Assert.True (v.GetCurrentWidth (out int cWidth));
-			Assert.Equal (80, cWidth);
+			Assert.True (v.TrySetWidth (0, out _));
+			Assert.Equal (80, v.Frame.Width);
 
 			v.Width = Dim.Fill (1);
-			Assert.True (v.GetCurrentWidth (out cWidth));
-			Assert.Equal (79, cWidth);
+			top.LayoutSubviews ();
+
+			Assert.True (v.TrySetWidth (0, out _));
+			Assert.Equal (79, v.Frame.Width);
 
 			v.AutoSize = true;
+			top.LayoutSubviews ();
 
-			Assert.True (v.GetCurrentWidth (out cWidth));
-			Assert.Equal (79, cWidth);
+			Assert.True (v.TrySetWidth (0, out _));
+			Assert.Equal (79, v.Frame.Width);
 		}
 
 		[Fact]
-		public void GetCurrentHeight_CanSetHeight ()
+		public void GetCurrentHeight_TrySetHeight ()
 		{
 			var top = new View () {
 				X = 0,
@@ -167,19 +221,23 @@ namespace Terminal.Gui.CoreTests {
 				Height = Dim.Fill ()
 			};
 			top.Add (v);
+			top.LayoutSubviews ();
 
 			Assert.False (v.AutoSize);
-			Assert.True (v.GetCurrentHeight (out int cHeight));
-			Assert.Equal (20, cHeight);
+			Assert.True (v.TrySetHeight (0, out _));
+			Assert.Equal (20, v.Frame.Height);
 
 			v.Height = Dim.Fill (1);
-			Assert.True (v.GetCurrentHeight (out cHeight));
-			Assert.Equal (19, cHeight);
+			top.LayoutSubviews ();
+
+			Assert.True (v.TrySetHeight (0, out _));
+			Assert.Equal (19, v.Frame.Height);
 
 			v.AutoSize = true;
+			top.LayoutSubviews ();
 
-			Assert.True (v.GetCurrentHeight (out cHeight));
-			Assert.Equal (19, cHeight);
+			Assert.True (v.TrySetHeight (0, out _));
+			Assert.Equal (19, v.Frame.Height);
 		}
 
 		[Fact]

+ 17 - 17
UnitTests/Core/ViewTests.cs

@@ -2115,7 +2115,7 @@ namespace Terminal.Gui.CoreTests {
 		}
 
 		[Fact]
-		public void GetTextFormatterBoundsSize_GetBoundsTextFormatterSize_HotKeySpecifier ()
+		public void GetTextFormatterBoundsSize_GetSizeNeededForText_HotKeySpecifier ()
 		{
 			var text = "Say Hello 你";
 			var horizontalView = new View () { Text = text, AutoSize = true, HotKeySpecifier = '_' };
@@ -2128,17 +2128,17 @@ namespace Terminal.Gui.CoreTests {
 
 			Assert.True (horizontalView.AutoSize);
 			Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
-			Assert.Equal (new Size (12, 1), horizontalView.GetTextFormatterBoundsSize ());
-			Assert.Equal (new Size (12, 1), horizontalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetTextFormatterBoundsSize ());
+			Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
+			Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
 
 			Assert.True (verticalView.AutoSize);
 			Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
-			Assert.Equal (new Size (2, 11), verticalView.GetTextFormatterBoundsSize ());
-			Assert.Equal (new Size (2, 11), verticalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (verticalView.Frame.Size, verticalView.GetTextFormatterBoundsSize ());
+			Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
+			Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
 
 			text = "Say He_llo 你";
 			horizontalView.Text = text;
@@ -2146,17 +2146,17 @@ namespace Terminal.Gui.CoreTests {
 
 			Assert.True (horizontalView.AutoSize);
 			Assert.Equal (new Rect (0, 0, 12, 1), horizontalView.Frame);
-			Assert.Equal (new Size (12, 1), horizontalView.GetTextFormatterBoundsSize ());
-			Assert.Equal (new Size (13, 1), horizontalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetTextFormatterBoundsSize ());
+			Assert.Equal (new Size (12, 1), horizontalView.GetSizeNeededForTextWithoutHotKey ());
+			Assert.Equal (new Size (13, 1), horizontalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (horizontalView.TextFormatter.Size, horizontalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (horizontalView.Frame.Size, horizontalView.GetSizeNeededForTextWithoutHotKey ());
 
 			Assert.True (verticalView.AutoSize);
 			Assert.Equal (new Rect (0, 0, 2, 11), verticalView.Frame);
-			Assert.Equal (new Size (2, 11), verticalView.GetTextFormatterBoundsSize ());
-			Assert.Equal (new Size (2, 12), verticalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetBoundsTextFormatterSize ());
-			Assert.Equal (verticalView.Frame.Size, verticalView.GetTextFormatterBoundsSize ());
+			Assert.Equal (new Size (2, 11), verticalView.GetSizeNeededForTextWithoutHotKey ());
+			Assert.Equal (new Size (2, 12), verticalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (verticalView.TextFormatter.Size, verticalView.GetSizeNeededForTextAndHotKey ());
+			Assert.Equal (verticalView.Frame.Size, verticalView.GetSizeNeededForTextWithoutHotKey ());
 		}
 
 		[Fact]

+ 1 - 1
UnitTests/TopLevels/ToplevelTests.cs

@@ -201,7 +201,7 @@ namespace Terminal.Gui.TopLevelTests {
 			Assert.Equal (top, Application.Top);
 
 			// top is Application.Top without menu and status bar.
-			var supView = top.EnsureVisibleBounds (top, 2, 2, out int nx, out int ny, out View mb, out View sb);
+			var supView = top.EnsureVisibleBounds (top, 2, 2, out int nx, out int ny, out MenuBar mb, out StatusBar sb);
 			Assert.Equal (Application.Top, supView);
 			Assert.Equal (0, nx);
 			Assert.Equal (0, ny);

+ 2 - 2
UnitTests/Views/ButtonTests.cs

@@ -30,8 +30,8 @@ namespace Terminal.Gui.ViewTests {
 [  ]
 ";
 			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
-
 			Application.End (rs);
+			
 			btn = new Button ("ARGS", true) { Text = "Test" };
 			Assert.Equal ("Test", btn.Text);
 			Application.Top.Add (btn);
@@ -48,8 +48,8 @@ namespace Terminal.Gui.ViewTests {
 [◦ Test ◦]
 ";
 			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
-
 			Application.End (rs);
+			
 			btn = new Button (3, 4, "Test", true);
 			Assert.Equal ("Test", btn.Text);
 			Application.Top.Add (btn);

+ 2 - 2
UnitTests/Views/CheckBoxTests.cs

@@ -452,7 +452,7 @@ namespace Terminal.Gui.ViewTests {
 				Y = Pos.Center (),
 				Text = "Check this out 你"
 			};
-			checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetTextFormatterBoundsSize ().Width);
+			checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
 
 			var win = new Window () {
 				Width = Dim.Fill (),
@@ -498,7 +498,7 @@ namespace Terminal.Gui.ViewTests {
 				Y = Pos.Center (),
 				Text = "C_heck this out 你"
 			};
-			checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetTextFormatterBoundsSize ().Width);
+			checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
 
 			var win = new Window () {
 				Width = Dim.Fill (),

+ 2 - 2
UnitTests/Views/ScrollViewTests.cs

@@ -324,8 +324,8 @@ namespace Terminal.Gui.ViewTests {
 			private Label labelFill;
 			private Label labelText;
 
-			public CustomButton (string fill, ustring text, int width, int height)
-			{
+			public CustomButton (string fill, ustring text, int width, int height) : base()
+			{				
 				Width = width;
 				Height = height;
 				labelFill = new Label () { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill (), Visible = false };

+ 0 - 2
UnitTests/Views/TableViewTests.cs

@@ -1655,8 +1655,6 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Single(tableView.GetAllSelectedCells());
 		}
 
-
-
 		[Fact, AutoInitShutdown]
 		public void TestToggleCells_MultiSelectOn_Two_SquareSelects_BothToggled ()
 		{