diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index 32df7ed5e6..06b0323d5a 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -356,7 +356,7 @@ public List Lines { } /// - /// Gets or sets whether the needs to format the text when is called. + /// Gets or sets whether the needs to format the text when is called. /// If it is false when Draw is called, the Draw call will be faster. /// /// @@ -1159,7 +1159,8 @@ public static ustring RemoveHotKeySpecifier (ustring text, int hotPos, Rune hotK /// The color to use for all text except the hotkey /// The color to use to draw the hotkey /// Specifies the screen-relative location and maximum container size. - public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect containerBounds = default) + /// Determines if the bounds width will be used (default) or only the text width will be used. + 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)) { @@ -1262,7 +1263,7 @@ public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect c 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), @@ -1272,10 +1273,10 @@ public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect c } 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)' '; @@ -1307,7 +1308,8 @@ public void Draw (Rect bounds, Attribute normalColor, Attribute hotColor, Rect c } 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; } } diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs index 0d4c7cf00c..0199df733e 100644 --- a/UnitTests/TextFormatterTests.cs +++ b/UnitTests/TextFormatterTests.cs @@ -3365,6 +3365,48 @@ public void Draw_Vertical_Wide_TextAlignments () 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 () {