Explorar o código

Merge branch 'develop' of tig:migueldeicaza/gui.cs into develop

Charlie Kindel %!s(int64=2) %!d(string=hai) anos
pai
achega
1dec5fae2a

+ 15 - 7
Terminal.Gui/Core/TextFormatter.cs

@@ -356,7 +356,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Gets or sets whether the <see cref="TextFormatter"/> needs to format the text when <see cref="Draw(Rect, Attribute, Attribute, Rect)"/> is called.
+		/// Gets or sets whether the <see cref="TextFormatter"/> needs to format the text when <see cref="Draw(Rect, Attribute, Attribute, Rect, bool)"/> is called.
 		/// If it is <c>false</c> when Draw is called, the Draw call will be faster.
 		/// </summary>
 		/// <remarks>
@@ -693,7 +693,7 @@ namespace Terminal.Gui {
 				textCount = words.Sum (arg => arg.RuneCount);
 			}
 			var spaces = words.Length > 1 ? (width - textCount) / (words.Length - 1) : 0;
-			var extras = words.Length > 1 ? (width - textCount) % words.Length : 0;
+			var extras = words.Length > 1 ? (width - textCount) % (words.Length - 1) : 0;
 
 			var s = new System.Text.StringBuilder ();
 			for (int w = 0; w < words.Length; w++) {
@@ -703,8 +703,14 @@ namespace Terminal.Gui {
 					for (int i = 0; i < spaces; i++)
 						s.Append (spaceChar);
 				if (extras > 0) {
+					for (int i = 0; i < 1; i++)
+						s.Append (spaceChar);
 					extras--;
 				}
+				if (w + 1 == words.Length - 1) {
+					for (int i = 0; i < extras; i++)
+						s.Append (spaceChar);
+				}
 			}
 			return ustring.Make (s.ToString ());
 		}
@@ -1153,7 +1159,8 @@ namespace Terminal.Gui {
 		/// <param name="normalColor">The color to use for all text except the hotkey</param>
 		/// <param name="hotColor">The color to use to draw the hotkey</param>
 		/// <param name="containerBounds">Specifies the screen-relative location and maximum container size.</param>
-		public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect containerBounds = default)
+		/// <param name="fillRemaining">Determines if the bounds width will be used (default) or only the text width will be used.</param>
+		public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect containerBounds = default, bool fillRemaining = true)
 		{
 			// With this check, we protect against subclasses with overrides of Text (like Button)
 			if (ustring.IsNullOrEmpty (text)) {
@@ -1256,7 +1263,7 @@ namespace Terminal.Gui {
 				var size = isVertical ? bounds.Height : bounds.Width;
 				var current = start;
 				var savedClip = Application.Driver?.Clip;
-				if (Application.Driver != null && containerBounds != default) {
+				if (Application.Driver != null) {
 					Application.Driver.Clip = containerBounds == default
 						? bounds
 						: new Rect (Math.Max (containerBounds.X, bounds.X),
@@ -1266,10 +1273,10 @@ namespace Terminal.Gui {
 				}
 
 				for (var idx = (isVertical ? start - y : start - x); current < start + size; idx++) {
-					if (idx < 0) {
+					if (!fillRemaining && idx < 0) {
 						current++;
 						continue;
-					} else if (idx > runes.Length - 1) {
+					} else if (!fillRemaining && idx > runes.Length - 1) {
 						break;
 					}
 					var rune = (Rune)' ';
@@ -1301,7 +1308,8 @@ namespace Terminal.Gui {
 					} else {
 						current += runeWidth;
 					}
-					if (!isVertical && idx + 1 < runes.Length && current + Rune.ColumnWidth (runes [idx + 1]) > start + size) {
+					var nextRuneWidth = idx + 1 > -1 && idx + 1 < runes.Length ? Rune.ColumnWidth (runes [idx + 1]) : 0;
+					if (!isVertical && idx + 1 < runes.Length && current + nextRuneWidth > start + size) {
 						break;
 					}
 				}

+ 3 - 2
Terminal.Gui/Core/View.cs

@@ -2997,8 +2997,9 @@ namespace Terminal.Gui {
 		/// Determines the current <see cref="ColorScheme"/> based on the <see cref="Enabled"/> value.
 		/// </summary>
 		/// <returns><see cref="ColorScheme.Normal"/> if <see cref="Enabled"/> is <see langword="true"/>
-		/// or <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/></returns>
-		public Attribute GetNormalColor ()
+		/// or <see cref="ColorScheme.Disabled"/> if <see cref="Enabled"/> is <see langword="false"/>.
+		/// If it's overridden can return other values.</returns>
+		public virtual Attribute GetNormalColor ()
 		{
 			return Enabled ? ColorScheme.Normal : ColorScheme.Disabled;
 		}

+ 7 - 1
Terminal.Gui/Views/TextField.cs

@@ -414,7 +414,7 @@ namespace Terminal.Gui {
 			var selColor = new Attribute (ColorScheme.Focus.Background, ColorScheme.Focus.Foreground);
 			SetSelectedStartSelectedLength ();
 
-			Driver.SetAttribute (ColorScheme.Focus);
+			Driver.SetAttribute (GetNormalColor ());
 			Move (0, 0);
 
 			int p = first;
@@ -466,6 +466,12 @@ namespace Terminal.Gui {
 			Autocomplete.RenderOverlay (renderAt);
 		}
 
+		/// <inheritdoc/>
+		public override Attribute GetNormalColor ()
+		{
+			return Enabled ? ColorScheme.Focus : ColorScheme.Disabled;
+		}
+
 		Attribute GetReadOnlyColor ()
 		{
 			if (ColorScheme.Disabled.Foreground == ColorScheme.Focus.Background) {

+ 37 - 11
Terminal.Gui/Views/TextView.cs

@@ -1938,7 +1938,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Sets the driver to the default color for the control where no text is being rendered.  Defaults to <see cref="ColorScheme.Normal"/>.
 		/// </summary>
-		protected virtual void ColorNormal ()
+		protected virtual void SetNormalColor ()
 		{
 			Driver.SetAttribute (GetNormalColor ());
 		}
@@ -1950,7 +1950,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="line"></param>
 		/// <param name="idx"></param>
-		protected virtual void ColorNormal (List<Rune> line, int idx)
+		protected virtual void SetNormalColor (List<Rune> line, int idx)
 		{
 			Driver.SetAttribute (GetNormalColor ());
 		}
@@ -1962,9 +1962,27 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="line"></param>
 		/// <param name="idx"></param>
-		protected virtual void ColorSelection (List<Rune> line, int idx)
+		protected virtual void SetSelectionColor (List<Rune> line, int idx)
 		{
-			Driver.SetAttribute (ColorScheme.Focus);
+			Driver.SetAttribute (new Attribute (ColorScheme.Focus.Background, ColorScheme.Focus.Foreground));
+		}
+
+		/// <summary>
+		/// Sets the <see cref="View.Driver"/> to an appropriate color for rendering the given <paramref name="idx"/> of the
+		/// current <paramref name="line"/>.  Override to provide custom coloring by calling <see cref="ConsoleDriver.SetAttribute(Attribute)"/>
+		/// Defaults to <see cref="ColorScheme.Focus"/>.
+		/// </summary>
+		/// <param name="line"></param>
+		/// <param name="idx"></param>
+		protected virtual void SetReadOnlyColor (List<Rune> line, int idx)
+		{
+			Attribute attribute;
+			if (ColorScheme.Disabled.Foreground == ColorScheme.Focus.Background) {
+				attribute = new Attribute (ColorScheme.Focus.Foreground, ColorScheme.Focus.Background);
+			} else {
+				attribute = new Attribute (ColorScheme.Disabled.Foreground, ColorScheme.Focus.Background);
+			}
+			Driver.SetAttribute (attribute);
 		}
 
 		/// <summary>
@@ -1974,7 +1992,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="line"></param>
 		/// <param name="idx"></param>
-		protected virtual void ColorUsed (List<Rune> line, int idx)
+		protected virtual void SetUsedColor (List<Rune> line, int idx)
 		{
 			Driver.SetAttribute (ColorScheme.HotFocus);
 		}
@@ -2366,7 +2384,7 @@ namespace Terminal.Gui {
 		///<inheritdoc/>
 		public override void Redraw (Rect bounds)
 		{
-			ColorNormal ();
+			SetNormalColor ();
 
 			var offB = OffSetBackground ();
 			int right = Frame.Width + offB.width + RightOffset;
@@ -2382,12 +2400,14 @@ namespace Terminal.Gui {
 					var rune = idxCol >= lineRuneCount ? ' ' : line [idxCol];
 					var cols = Rune.ColumnWidth (rune);
 					if (idxCol < line.Count && selecting && PointInSelection (idxCol, idxRow)) {
-						ColorSelection (line, idxCol);
+						SetSelectionColor (line, idxCol);
 					} else if (idxCol == currentColumn && idxRow == currentRow && !selecting && !Used
 						&& HasFocus && idxCol < lineRuneCount) {
-						ColorUsed (line, idxCol);
+						SetSelectionColor (line, idxCol);
+					} else if (ReadOnly) {
+						SetReadOnlyColor (line, idxCol);
 					} else {
-						ColorNormal (line, idxCol);
+						SetNormalColor (line, idxCol);
 					}
 
 					if (rune == '\t') {
@@ -2411,13 +2431,13 @@ namespace Terminal.Gui {
 					}
 				}
 				if (col < right) {
-					ColorNormal ();
+					SetNormalColor ();
 					ClearRegion (col, row, right, row + 1);
 				}
 				row++;
 			}
 			if (row < bottom) {
-				ColorNormal ();
+				SetNormalColor ();
 				ClearRegion (bounds.Left, row, right, bottom);
 			}
 
@@ -2438,6 +2458,12 @@ namespace Terminal.Gui {
 			Autocomplete.RenderOverlay (renderAt);
 		}
 
+		/// <inheritdoc/>
+		public override Attribute GetNormalColor ()
+		{
+			return Enabled ? ColorScheme.Focus : ColorScheme.Disabled;
+		}
+
 		///<inheritdoc/>
 		public override bool CanFocus {
 			get => base.CanFocus;

+ 0 - 5
Terminal.Gui/Windows/Wizard.cs

@@ -203,11 +203,6 @@ namespace Terminal.Gui {
 
 				base.Add (contentView);
 
-				helpTextView.ColorScheme = new ColorScheme () {  
-					Normal = new Attribute(Color.Gray, Color.DarkGray),
-					Focus = new Attribute(Color.DarkGray, Color.Gray),
-					HotFocus = new Attribute(Color.White, Color.DarkGray)
-				};
 				helpTextView.ReadOnly = true;
 				helpTextView.WordWrap = true;
 				base.Add (helpTextView);

+ 0 - 1
UICatalog/Scenarios/AutoSizeAndDirectionText.cs

@@ -33,7 +33,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.Center (),
 				Width = 20,
 				Height = 5,
-				ColorScheme = color,
 				Text = text
 			};
 

+ 0 - 3
UICatalog/Scenarios/BordersComparisons.cs

@@ -46,7 +46,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			var tf2 = new TextField ("1234567890") {
@@ -86,7 +85,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			var tf4 = new TextField ("1234567890") {
@@ -123,7 +121,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			var tf6 = new TextField ("1234567890") {

+ 0 - 1
UICatalog/Scenarios/BordersOnFrameView.cs

@@ -56,7 +56,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			smartView.Add (tf1, button, label, tf2, tv);

+ 0 - 1
UICatalog/Scenarios/BordersOnToplevel.cs

@@ -56,7 +56,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			smartView.Add (tf1, button, label, tf2, tv);

+ 0 - 1
UICatalog/Scenarios/BordersOnWindow.cs

@@ -56,7 +56,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (2),
 				Width = 10,
 				Height = Dim.Fill (),
-				ColorScheme = Colors.Dialog,
 				Text = "1234567890"
 			};
 			smartView.Add (tf1, button, label, tf2, tv);

+ 0 - 1
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -681,7 +681,6 @@ namespace UICatalog.Scenarios {
 				Add (_lblAction);
 
 				_txtAction = new TextView () {
-					ColorScheme = Colors.Dialog,
 					X = Pos.Left (_txtTitle),
 					Y = Pos.Top (_lblAction),
 					Width = Dim.Fill (),

+ 0 - 1
UICatalog/Scenarios/DynamicStatusBar.cs

@@ -383,7 +383,6 @@ namespace UICatalog.Scenarios {
 				Add (_lblAction);
 
 				_txtAction = new TextView () {
-					ColorScheme = Colors.Dialog,
 					X = Pos.Left (_txtTitle),
 					Y = Pos.Top (_lblAction),
 					Width = Dim.Fill (),

+ 0 - 1
UICatalog/Scenarios/MessageBoxes.cs

@@ -90,7 +90,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.Top (label),
 				Width = Dim.Fill (),
 				Height = 5,
-				ColorScheme = Colors.Dialog,
 			};
 			frame.Add (messageEdit);
 

+ 59 - 63
UICatalog/Scenarios/SyntaxHighlighting.cs

@@ -38,7 +38,7 @@ namespace UICatalog.Scenarios {
 				Height = Dim.Fill (1),
 			};
 
-			textView.Init();
+			textView.Init ();
 
 			textView.Text = "SELECT TOP 100 * \nfrom\n MyDb.dbo.Biochemistry;";
 
@@ -63,49 +63,49 @@ namespace UICatalog.Scenarios {
 			Application.RequestStop ();
 		}
 
-		private class SqlTextView : TextView{
+		private class SqlTextView : TextView {
 
-			private HashSet<string> keywords = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
+			private HashSet<string> keywords = new HashSet<string> (StringComparer.CurrentCultureIgnoreCase);
 			private Attribute blue;
 			private Attribute white;
 			private Attribute magenta;
 
 
-		public void Init()
+			public void Init ()
 			{
-				keywords.Add("select");
-				keywords.Add("distinct");
-				keywords.Add("top");
-				keywords.Add("from");
-				keywords.Add("create");
-				keywords.Add("CIPHER");
-				keywords.Add("CLASS_ORIGIN");
-				keywords.Add("CLIENT");
-				keywords.Add("CLOSE");
-				keywords.Add("COALESCE");
-				keywords.Add("CODE");
-				keywords.Add("COLUMNS");
-				keywords.Add("COLUMN_FORMAT");
-				keywords.Add("COLUMN_NAME");
-				keywords.Add("COMMENT");
-				keywords.Add("COMMIT");
-				keywords.Add("COMPACT");
-				keywords.Add("COMPLETION");
-				keywords.Add("COMPRESSED");
-				keywords.Add("COMPRESSION");
-				keywords.Add("CONCURRENT");
-				keywords.Add("CONNECT");
-				keywords.Add("CONNECTION");
-				keywords.Add("CONSISTENT");
-				keywords.Add("CONSTRAINT_CATALOG");
-				keywords.Add("CONSTRAINT_SCHEMA");
-				keywords.Add("CONSTRAINT_NAME");
-				keywords.Add("CONTAINS");
-				keywords.Add("CONTEXT");
-				keywords.Add("CONTRIBUTORS");
-				keywords.Add("COPY");
-				keywords.Add("CPU");
-				keywords.Add("CURSOR_NAME");
+				keywords.Add ("select");
+				keywords.Add ("distinct");
+				keywords.Add ("top");
+				keywords.Add ("from");
+				keywords.Add ("create");
+				keywords.Add ("CIPHER");
+				keywords.Add ("CLASS_ORIGIN");
+				keywords.Add ("CLIENT");
+				keywords.Add ("CLOSE");
+				keywords.Add ("COALESCE");
+				keywords.Add ("CODE");
+				keywords.Add ("COLUMNS");
+				keywords.Add ("COLUMN_FORMAT");
+				keywords.Add ("COLUMN_NAME");
+				keywords.Add ("COMMENT");
+				keywords.Add ("COMMIT");
+				keywords.Add ("COMPACT");
+				keywords.Add ("COMPLETION");
+				keywords.Add ("COMPRESSED");
+				keywords.Add ("COMPRESSION");
+				keywords.Add ("CONCURRENT");
+				keywords.Add ("CONNECT");
+				keywords.Add ("CONNECTION");
+				keywords.Add ("CONSISTENT");
+				keywords.Add ("CONSTRAINT_CATALOG");
+				keywords.Add ("CONSTRAINT_SCHEMA");
+				keywords.Add ("CONSTRAINT_NAME");
+				keywords.Add ("CONTAINS");
+				keywords.Add ("CONTEXT");
+				keywords.Add ("CONTRIBUTORS");
+				keywords.Add ("COPY");
+				keywords.Add ("CPU");
+				keywords.Add ("CURSOR_NAME");
 				keywords.Add ("primary");
 				keywords.Add ("key");
 				keywords.Add ("insert");
@@ -138,29 +138,26 @@ namespace UICatalog.Scenarios {
 				keywords.Add ("union");
 				keywords.Add ("exists");
 
-				Autocomplete.AllSuggestions = keywords.ToList();
+				Autocomplete.AllSuggestions = keywords.ToList ();
 
 				magenta = Driver.MakeAttribute (Color.Magenta, Color.Black);
 				blue = Driver.MakeAttribute (Color.Cyan, Color.Black);
 				white = Driver.MakeAttribute (Color.White, Color.Black);
 			}
 
-			protected override void ColorNormal ()
+			protected override void SetNormalColor ()
 			{
 				Driver.SetAttribute (white);
 			}
 
-			protected override void ColorNormal (List<System.Rune> line, int idx)
+			protected override void SetNormalColor (List<System.Rune> line, int idx)
 			{
-				if(IsInStringLiteral(line,idx)) {
+				if (IsInStringLiteral (line, idx)) {
 					Driver.SetAttribute (magenta);
-				}
-				else
-				if(IsKeyword(line,idx))
-				{
+				} else
+				if (IsKeyword (line, idx)) {
 					Driver.SetAttribute (blue);
-				}
-				else{
+				} else {
 					Driver.SetAttribute (white);
 				}
 			}
@@ -168,9 +165,9 @@ namespace UICatalog.Scenarios {
 			private bool IsInStringLiteral (List<System.Rune> line, int idx)
 			{
 				string strLine = new string (line.Select (r => (char)r).ToArray ());
-				
-				foreach(Match m in Regex.Matches(strLine, "'[^']*'")) {
-					if(idx >= m.Index && idx < m.Index+m.Length) {
+
+				foreach (Match m in Regex.Matches (strLine, "'[^']*'")) {
+					if (idx >= m.Index && idx < m.Index + m.Length) {
 						return true;
 					}
 				}
@@ -178,37 +175,36 @@ namespace UICatalog.Scenarios {
 				return false;
 			}
 
-			private bool IsKeyword(List<System.Rune> line, int idx)
+			private bool IsKeyword (List<System.Rune> line, int idx)
 			{
-				var word = IdxToWord(line,idx);
-				
-				if(string.IsNullOrWhiteSpace(word)){
+				var word = IdxToWord (line, idx);
+
+				if (string.IsNullOrWhiteSpace (word)) {
 					return false;
 				}
 
-				return keywords.Contains(word,StringComparer.CurrentCultureIgnoreCase);
+				return keywords.Contains (word, StringComparer.CurrentCultureIgnoreCase);
 			}
 
-			private string IdxToWord(List<System.Rune> line, int idx)
+			private string IdxToWord (List<System.Rune> line, int idx)
 			{
-				var words = Regex.Split(
-					new string(line.Select(r=>(char)r).ToArray()),
+				var words = Regex.Split (
+					new string (line.Select (r => (char)r).ToArray ()),
 					"\\b");
 
 
 				int count = 0;
 				string current = null;
 
-				foreach(var word in words)
-				{
+				foreach (var word in words) {
 					current = word;
-					count+= word.Length;
-					if(count > idx){
+					count += word.Length;
+					if (count > idx) {
 						break;
 					}
 				}
 
-				return current?.Trim();
+				return current?.Trim ();
 			}
 		}
 	}

+ 0 - 1
UICatalog/Scenarios/Text.cs

@@ -49,7 +49,6 @@ namespace UICatalog.Scenarios {
 				Y = 3,
 				Width = Dim.Percent (50),
 				Height = Dim.Percent (30),
-				ColorScheme = Colors.Dialog
 			};
 			textView.Text = s;
 			textView.DrawContent += TextView_DrawContent;

+ 1 - 1
UICatalog/Scenarios/TextAlignmentsAndDirection.cs

@@ -105,7 +105,7 @@ namespace UICatalog.Scenarios {
 				Y = Pos.Bottom (container) + 1,
 				Width = Dim.Fill (10),
 				Height = Dim.Fill (1),
-				ColorScheme = color2,
+				ColorScheme = Colors.TopLevel,
 				Text = txt
 			};
 

+ 0 - 6
UICatalog/Scenarios/TextViewAutocompletePopup.cs

@@ -24,7 +24,6 @@ namespace UICatalog.Scenarios {
 		{
 			Win.Title = GetName ();
 			var width = 20;
-			var colorScheme = Colors.Dialog;
 			var text = " jamp jemp jimp jomp jump";
 
 			var menu = new MenuBar (new MenuBarItem [] {
@@ -39,7 +38,6 @@ namespace UICatalog.Scenarios {
 			textViewTopLeft = new TextView () {
 				Width = width,
 				Height = height,
-				ColorScheme = colorScheme,
 				Text = text
 			};
 			textViewTopLeft.DrawContent += TextViewTopLeft_DrawContent;
@@ -49,7 +47,6 @@ namespace UICatalog.Scenarios {
 				X = Pos.AnchorEnd (width),
 				Width = width,
 				Height = height,
-				ColorScheme = colorScheme,
 				Text = text
 			};
 			textViewTopRight.DrawContent += TextViewTopRight_DrawContent;
@@ -59,7 +56,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (height),
 				Width = width,
 				Height = height,
-				ColorScheme = colorScheme,
 				Text = text
 			};
 			textViewBottomLeft.DrawContent += TextViewBottomLeft_DrawContent;
@@ -70,7 +66,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.AnchorEnd (height),
 				Width = width,
 				Height = height,
-				ColorScheme = colorScheme,
 				Text = text
 			};
 			textViewBottomRight.DrawContent += TextViewBottomRight_DrawContent;
@@ -81,7 +76,6 @@ namespace UICatalog.Scenarios {
 				Y = Pos.Center (),
 				Width = width,
 				Height = height,
-				ColorScheme = colorScheme,
 				Text = text
 			};
 			textViewCentered.DrawContent += TextViewCentered_DrawContent;

+ 1 - 0
UICatalog/Scenarios/Wizards.cs

@@ -217,6 +217,7 @@ namespace UICatalog.Scenarios {
 						Height = Dim.Fill (1),
 						WordWrap = true,
 						AllowsTab = false,
+						ColorScheme = Colors.Base
 					};
 					var help = "This is helpful.";
 					fourthStep.Add (someText);

+ 38 - 18
UnitTests/CheckboxTests.cs

@@ -314,10 +314,18 @@ namespace Terminal.Gui.Views {
 		[Fact, AutoInitShutdown]
 		public void TextAlignment_Justified ()
 		{
-			var checkBox = new CheckBox () {
+			var checkBox1 = new CheckBox () {
 				X = 1,
 				Y = Pos.Center (),
-				Text = "Check this out 你",
+				Text = "Check first out 你",
+				TextAlignment = TextAlignment.Justified,
+				AutoSize = false,
+				Width = 25
+			};
+			var checkBox2 = new CheckBox () {
+				X = 1,
+				Y = Pos.Bottom (checkBox1),
+				Text = "Check second out 你",
 				TextAlignment = TextAlignment.Justified,
 				AutoSize = false,
 				Width = 25
@@ -327,44 +335,56 @@ namespace Terminal.Gui.Views {
 				Height = Dim.Fill (),
 				Title = "Test Demo 你"
 			};
-			win.Add (checkBox);
+			win.Add (checkBox1, checkBox2);
 			Application.Top.Add (win);
 
 			Application.Begin (Application.Top);
-			((FakeDriver)Application.Driver).SetBufferSize (30, 5);
+			((FakeDriver)Application.Driver).SetBufferSize (30, 6);
+
+			Assert.Equal (TextAlignment.Justified, checkBox1.TextAlignment);
+			Assert.Equal (new Rect (1, 1, 25, 1), checkBox1.Frame);
+			Assert.Equal (new Size (25, 1), checkBox1.TextFormatter.Size);
+			Assert.Equal ("Check first out 你", checkBox1.Text);
+			Assert.Equal ("╴ Check first out 你", checkBox1.TextFormatter.Text);
+			Assert.False (checkBox1.AutoSize);
+			Assert.Equal (TextAlignment.Justified, checkBox2.TextAlignment);
+			Assert.Equal (new Rect (1, 2, 25, 1), checkBox2.Frame);
+			Assert.Equal (new Size (25, 1), checkBox2.TextFormatter.Size);
+			Assert.Equal ("Check second out 你", checkBox2.Text);
+			Assert.Equal ("╴ Check second out 你", checkBox2.TextFormatter.Text);
+			Assert.False (checkBox2.AutoSize);
 
-			Assert.Equal (TextAlignment.Justified, checkBox.TextAlignment);
-			Assert.Equal (new Rect (1, 1, 25, 1), checkBox.Frame);
-			Assert.Equal (new Size (25, 1), checkBox.TextFormatter.Size);
-			Assert.Equal ("Check this out 你", checkBox.Text);
-			Assert.Equal ("╴ Check this out 你", checkBox.TextFormatter.Text);
-			Assert.False (checkBox.AutoSize);
 
 			var expected = @"
 ┌ Test Demo 你 ──────────────┐
 │                            │
-│ ╴  Check  this  out  你    │
+│ ╴   Check  first  out  你  │
+│ ╴  Check  second  out  你  │
 │                            │
 └────────────────────────────┘
 ";
 
 			var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
-			Assert.Equal (new Rect (0, 0, 30, 5), pos);
-
-			checkBox.Checked = true;
-			Assert.Equal (new Rect (1, 1, 25, 1), checkBox.Frame);
-			Assert.Equal (new Size (25, 1), checkBox.TextFormatter.Size);
+			Assert.Equal (new Rect (0, 0, 30, 6), pos);
+
+			checkBox1.Checked = true;
+			Assert.Equal (new Rect (1, 1, 25, 1), checkBox1.Frame);
+			Assert.Equal (new Size (25, 1), checkBox1.TextFormatter.Size);
+			checkBox2.Checked = true;
+			Assert.Equal (new Rect (1, 2, 25, 1), checkBox2.Frame);
+			Assert.Equal (new Size (25, 1), checkBox2.TextFormatter.Size);
 			Application.Refresh ();
 			expected = @"
 ┌ Test Demo 你 ──────────────┐
 │                            │
-│ √  Check  this  out  你    │
+│ √   Check  first  out  你  │
+│ √  Check  second  out  你  │
 │                            │
 └────────────────────────────┘
 ";
 
 			pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
-			Assert.Equal (new Rect (0, 0, 30, 5), pos);
+			Assert.Equal (new Rect (0, 0, 30, 6), pos);
 		}
 
 		[Fact, AutoInitShutdown]

+ 97 - 24
UnitTests/TextFormatterTests.cs

@@ -1093,11 +1093,11 @@ namespace Terminal.Gui.Core {
 			text = "A sentence has words.";
 			// should fit
 			maxWidth = text.RuneCount + 1;
-			expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+			expectedClippedWidth = Math.Max (text.RuneCount, maxWidth);
 			justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
-			//Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
+			Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
 			Assert.True (expectedClippedWidth <= maxWidth);
-			Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
+			Assert.Throws<ArgumentOutOfRangeException> (() => ustring.Make (text.ToRunes () [0..expectedClippedWidth]));
 
 			// Should fit.
 			maxWidth = text.RuneCount + 0;
@@ -1205,7 +1205,6 @@ namespace Terminal.Gui.Core {
 			Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
 
 			// see Justify_ tests below
-
 		}
 
 		[Fact]
@@ -1310,7 +1309,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "012++456+89";
 			forceToWidth = text.RuneCount + 1;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1322,7 +1321,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "012+++456++89";
 			forceToWidth = text.RuneCount + 3;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1334,7 +1333,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+++");
+			justifiedText = "012++++456+++89";
 			forceToWidth = text.RuneCount + 5;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1352,7 +1351,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++++++++++++");
+			justifiedText = "012+++++++++++++456++++++++++++89";
 			forceToWidth = text.RuneCount + 23;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1368,13 +1367,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "012++456+89+end";
 			forceToWidth = text.RuneCount + 1;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "012++456++89+end";
 			forceToWidth = text.RuneCount + 2;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1386,13 +1385,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "012+++456++89++end";
 			forceToWidth = text.RuneCount + 4;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "012+++456+++89++end";
 			forceToWidth = text.RuneCount + 5;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1404,13 +1403,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+++++++");
+			justifiedText = "012++++++++456++++++++89+++++++end";
 			forceToWidth = text.RuneCount + 20;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++++++++");
+			justifiedText = "012+++++++++456+++++++++89++++++++end";
 			forceToWidth = text.RuneCount + 23;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1427,7 +1426,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "пÑÐ++вÐ+Ñ";
 			forceToWidth = text.RuneCount + 1;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1439,7 +1438,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "пÑÐ+++вÐ++Ñ";
 			forceToWidth = text.RuneCount + 3;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1451,7 +1450,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+++");
+			justifiedText = "пÑÐ++++вÐ+++Ñ";
 			forceToWidth = text.RuneCount + 5;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1469,7 +1468,7 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++++++++++++");
+			justifiedText = "пÑÐ+++++++++++++вÐ++++++++++++Ñ";
 			forceToWidth = text.RuneCount + 23;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1486,13 +1485,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "Ð++ÑÐ+вÐ+Ñ";
 			forceToWidth = text.RuneCount + 1;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+");
+			justifiedText = "Ð++ÑÐ++вÐ+Ñ";
 			forceToWidth = text.RuneCount + 2;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1504,13 +1503,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "Ð+++ÑÐ++вÐ++Ñ";
 			forceToWidth = text.RuneCount + 4;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++");
+			justifiedText = "Ð+++ÑÐ+++вÐ++Ñ";
 			forceToWidth = text.RuneCount + 5;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -1522,13 +1521,13 @@ namespace Terminal.Gui.Core {
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "+++++++");
+			justifiedText = "Ð++++++++ÑÐ++++++++вÐ+++++++Ñ";
 			forceToWidth = text.RuneCount + 20;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
 			Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
 
-			justifiedText = text.Replace (" ", "++++++++");
+			justifiedText = "Ð+++++++++ÑÐ+++++++++вÐ++++++++Ñ";
 			forceToWidth = text.RuneCount + 23;
 			Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
 			Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
@@ -2934,6 +2933,38 @@ namespace Terminal.Gui.Core {
 			Assert.Null (exception);
 		}
 
+
+
+		[Fact, AutoInitShutdown]
+		public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Horizontal ()
+		{
+			ustring text = "Hello world, how are you today? Pretty neat!";
+
+			Assert.Equal (44, text.RuneCount);
+
+			for (int i = 44; i < 80; i++) {
+				var fmtText = TextFormatter.Format (text, i, TextAlignment.Justified, false, true) [0];
+				Assert.Equal (i, fmtText.RuneCount);
+				var c = (char)fmtText [^1];
+				Assert.Equal ('!', c);
+			}
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Vertical ()
+		{
+			ustring text = "Hello world, how are you today? Pretty neat!";
+
+			Assert.Equal (44, text.RuneCount);
+
+			for (int i = 44; i < 80; i++) {
+				var fmtText = TextFormatter.Format (text, i, TextAlignment.Justified, false, true, 0, TextDirection.TopBottom_LeftRight) [0];
+				Assert.Equal (i, fmtText.RuneCount);
+				var c = (char)fmtText [^1];
+				Assert.Equal ('!', c);
+			}
+		}
+
 		[Fact]
 		public void Draw_Horizontal_Throws_IndexOutOfRangeException_With_Negative_Bounds ()
 		{
@@ -3334,6 +3365,48 @@ e
 			Assert.Equal (new Rect (0, 0, 13, height + 2), pos);
 		}
 
+		[Fact, AutoInitShutdown]
+		public void Draw_Fill_Remaining ()
+		{
+			var view = new View ("This view needs to be cleared before rewritten.");
+
+			var tf1 = new TextFormatter ();
+			tf1.Text = "This TextFormatter (tf1) without fill will not be cleared on rewritten.";
+			var tf1Size = tf1.Size;
+
+			var tf2 = new TextFormatter ();
+			tf2.Text = "This TextFormatter (tf2) with fill will be cleared on rewritten.";
+			var tf2Size = tf2.Size;
+
+			Application.Top.Add (view);
+			Application.Begin (Application.Top);
+
+			tf1.Draw (new Rect (new Point (0, 1), tf1Size), view.GetNormalColor (), view.ColorScheme.HotNormal, default, false);
+
+			tf2.Draw (new Rect (new Point (0, 2), tf2Size), view.GetNormalColor (), view.ColorScheme.HotNormal);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+This view needs to be cleared before rewritten.                        
+This TextFormatter (tf1) without fill will not be cleared on rewritten.
+This TextFormatter (tf2) with fill will be cleared on rewritten.       
+", output);
+
+			view.Text = "This view is rewritten.";
+			view.Redraw (view.Bounds);
+
+			tf1.Text = "This TextFormatter (tf1) is rewritten.";
+			tf1.Draw (new Rect (new Point (0, 1), tf1Size), view.GetNormalColor (), view.ColorScheme.HotNormal, default, false);
+
+			tf2.Text = "This TextFormatter (tf2) is rewritten.";
+			tf2.Draw (new Rect (new Point (0, 2), tf2Size), view.GetNormalColor (), view.ColorScheme.HotNormal);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+This view is rewritten.                                                
+This TextFormatter (tf1) is rewritten.will not be cleared on rewritten.
+This TextFormatter (tf2) is rewritten.                                 
+", output);
+		}
+
 		[Fact]
 		public void GetTextWidth_Simple_And_Wide_Runes ()
 		{