Browse Source

Renamed API to simplify and make more clear. Fixed Text formatting vertical/right aligned text. Fixed crash in scenario

Tig 1 year ago
parent
commit
00ac1bbf7a

+ 60 - 61
Terminal.Gui/Text/TextFormatter.cs

@@ -287,13 +287,13 @@ public class TextFormatter
             Rune [] runes = linesFormatted [line].ToRunes ();
             Rune [] runes = linesFormatted [line].ToRunes ();
 
 
             runes = Direction switch
             runes = Direction switch
-                    {
-                        TextDirection.RightLeft_BottomTop => runes.Reverse ().ToArray (),
-                        TextDirection.RightLeft_TopBottom => runes.Reverse ().ToArray (),
-                        TextDirection.BottomTop_LeftRight => runes.Reverse ().ToArray (),
-                        TextDirection.BottomTop_RightLeft => runes.Reverse ().ToArray (),
-                        _ => runes
-                    };
+            {
+                TextDirection.RightLeft_BottomTop => runes.Reverse ().ToArray (),
+                TextDirection.RightLeft_TopBottom => runes.Reverse ().ToArray (),
+                TextDirection.BottomTop_LeftRight => runes.Reverse ().ToArray (),
+                TextDirection.BottomTop_RightLeft => runes.Reverse ().ToArray (),
+                _ => runes
+            };
 
 
             // When text is justified, we lost left or right, so we use the direction to align. 
             // When text is justified, we lost left or right, so we use the direction to align. 
 
 
@@ -304,7 +304,7 @@ public class TextFormatter
             {
             {
                 if (isVertical)
                 if (isVertical)
                 {
                 {
-                    int runesWidth = GetWidestLineLength (linesFormatted, line, TabWidth);
+                    int runesWidth = GetColumnsRequiredForVerticalText (linesFormatted, tabWidth: TabWidth);
                     x = screen.Right - runesWidth;
                     x = screen.Right - runesWidth;
                     CursorPosition = screen.Width - runesWidth + (_hotKeyPos > -1 ? _hotKeyPos : 0);
                     CursorPosition = screen.Width - runesWidth + (_hotKeyPos > -1 ? _hotKeyPos : 0);
                 }
                 }
@@ -320,7 +320,7 @@ public class TextFormatter
                 if (isVertical)
                 if (isVertical)
                 {
                 {
                     int runesWidth = line > 0
                     int runesWidth = line > 0
-                                         ? GetWidestLineLength (linesFormatted, 0, line, TabWidth)
+                                         ? GetColumnsRequiredForVerticalText (linesFormatted, TabWidth)
                                          : 0;
                                          : 0;
                     x = screen.Left + runesWidth;
                     x = screen.Left + runesWidth;
                 }
                 }
@@ -335,7 +335,7 @@ public class TextFormatter
             {
             {
                 if (isVertical)
                 if (isVertical)
                 {
                 {
-                    int runesWidth = GetWidestLineLength (linesFormatted, line, TabWidth);
+                    int runesWidth = GetColumnsRequiredForVerticalText (linesFormatted, TabWidth);
                     x = screen.Left + line + (screen.Width - runesWidth) / 2;
                     x = screen.Left + line + (screen.Width - runesWidth) / 2;
 
 
                     CursorPosition = (screen.Width - runesWidth) / 2 + (_hotKeyPos > -1 ? _hotKeyPos : 0);
                     CursorPosition = (screen.Width - runesWidth) / 2 + (_hotKeyPos > -1 ? _hotKeyPos : 0);
@@ -700,48 +700,48 @@ public class TextFormatter
     public static bool IsHorizontalDirection (TextDirection textDirection)
     public static bool IsHorizontalDirection (TextDirection textDirection)
     {
     {
         return textDirection switch
         return textDirection switch
-               {
-                   TextDirection.LeftRight_TopBottom => true,
-                   TextDirection.LeftRight_BottomTop => true,
-                   TextDirection.RightLeft_TopBottom => true,
-                   TextDirection.RightLeft_BottomTop => true,
-                   _ => false
-               };
+        {
+            TextDirection.LeftRight_TopBottom => true,
+            TextDirection.LeftRight_BottomTop => true,
+            TextDirection.RightLeft_TopBottom => true,
+            TextDirection.RightLeft_BottomTop => true,
+            _ => false
+        };
     }
     }
 
 
     /// <summary>Check if it is a vertical direction</summary>
     /// <summary>Check if it is a vertical direction</summary>
     public static bool IsVerticalDirection (TextDirection textDirection)
     public static bool IsVerticalDirection (TextDirection textDirection)
     {
     {
         return textDirection switch
         return textDirection switch
-               {
-                   TextDirection.TopBottom_LeftRight => true,
-                   TextDirection.TopBottom_RightLeft => true,
-                   TextDirection.BottomTop_LeftRight => true,
-                   TextDirection.BottomTop_RightLeft => true,
-                   _ => false
-               };
+        {
+            TextDirection.TopBottom_LeftRight => true,
+            TextDirection.TopBottom_RightLeft => true,
+            TextDirection.BottomTop_LeftRight => true,
+            TextDirection.BottomTop_RightLeft => true,
+            _ => false
+        };
     }
     }
 
 
     /// <summary>Check if it is Left to Right direction</summary>
     /// <summary>Check if it is Left to Right direction</summary>
     public static bool IsLeftToRight (TextDirection textDirection)
     public static bool IsLeftToRight (TextDirection textDirection)
     {
     {
         return textDirection switch
         return textDirection switch
-               {
-                   TextDirection.LeftRight_TopBottom => true,
-                   TextDirection.LeftRight_BottomTop => true,
-                   _ => false
-               };
+        {
+            TextDirection.LeftRight_TopBottom => true,
+            TextDirection.LeftRight_BottomTop => true,
+            _ => false
+        };
     }
     }
 
 
     /// <summary>Check if it is Top to Bottom direction</summary>
     /// <summary>Check if it is Top to Bottom direction</summary>
     public static bool IsTopToBottom (TextDirection textDirection)
     public static bool IsTopToBottom (TextDirection textDirection)
     {
     {
         return textDirection switch
         return textDirection switch
-               {
-                   TextDirection.TopBottom_LeftRight => true,
-                   TextDirection.TopBottom_RightLeft => true,
-                   _ => false
-               };
+        {
+            TextDirection.TopBottom_LeftRight => true,
+            TextDirection.TopBottom_RightLeft => true,
+            _ => false
+        };
     }
     }
 
 
     // TODO: Move to StringExtensions?
     // TODO: Move to StringExtensions?
@@ -1122,21 +1122,21 @@ public class TextFormatter
                     case ' ':
                     case ' ':
                         return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length);
                         return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length);
                     case '\t':
                     case '\t':
-                    {
-                        length += tabWidth + 1;
-
-                        if (length == tabWidth && tabWidth > cWidth)
                         {
                         {
-                            return to + 1;
-                        }
+                            length += tabWidth + 1;
 
 
-                        if (length > cWidth && tabWidth > cWidth)
-                        {
-                            return to;
-                        }
+                            if (length == tabWidth && tabWidth > cWidth)
+                            {
+                                return to + 1;
+                            }
 
 
-                        return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length);
-                    }
+                            if (length > cWidth && tabWidth > cWidth)
+                            {
+                                return to;
+                            }
+
+                            return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length);
+                        }
                     default:
                     default:
                         to++;
                         to++;
 
 
@@ -1145,11 +1145,11 @@ public class TextFormatter
             }
             }
 
 
             return cLength switch
             return cLength switch
-                   {
-                       > 0 when to < runes.Count && runes [to].Value != ' ' && runes [to].Value != '\t' => from,
-                       > 0 when to < runes.Count && (runes [to].Value == ' ' || runes [to].Value == '\t') => from,
-                       _ => to
-                   };
+            {
+                > 0 when to < runes.Count && runes [to].Value != ' ' && runes [to].Value != '\t' => from,
+                > 0 when to < runes.Count && (runes [to].Value == ' ' || runes [to].Value == '\t') => from,
+                _ => to
+            };
         }
         }
 
 
         if (start < text.GetRuneCount ())
         if (start < text.GetRuneCount ())
@@ -1580,29 +1580,28 @@ public class TextFormatter
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Returns the number of columns in the widest line in the list based on the <paramref name="startIndex"/> and
-    ///     the <paramref name="length"/>.
+    ///     Returns the number of columns required to render <paramref name="lines"/> oriented vertically.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     This API will return incorrect results if the text includes glyphs who's width is dependent on surrounding
     ///     This API will return incorrect results if the text includes glyphs who's width is dependent on surrounding
     ///     glyphs (e.g. Arabic).
     ///     glyphs (e.g. Arabic).
     /// </remarks>
     /// </remarks>
     /// <param name="lines">The lines.</param>
     /// <param name="lines">The lines.</param>
-    /// <param name="startIndex">The start index.</param>
-    /// <param name="length">The length.</param>
+    /// <param name="startLine">The line in the list to start with (any lines before will be ignored).</param>
+    /// <param name="linesCount">The number of lines to process (if less than <c>lines.Count</c>, any lines after will be ignored).</param>
     /// <param name="tabWidth">The number of columns used for a tab.</param>
     /// <param name="tabWidth">The number of columns used for a tab.</param>
-    /// <returns>The maximum characters width.</returns>
-    public static int GetWidestLineLength (
+    /// <returns>The width required.</returns>
+    public static int GetColumnsRequiredForVerticalText (
         List<string> lines,
         List<string> lines,
-        int startIndex = -1,
-        int length = -1,
+        int startLine = -1,
+        int linesCount = -1,
         int tabWidth = 0
         int tabWidth = 0
     )
     )
     {
     {
         var max = 0;
         var max = 0;
 
 
-        for (int i = startIndex == -1 ? 0 : startIndex;
-             i < (length == -1 ? lines.Count : startIndex + length);
+        for (int i = startLine == -1 ? 0 : startLine;
+             i < (linesCount == -1 ? lines.Count : startLine + linesCount);
              i++)
              i++)
         {
         {
             string runes = lines [i];
             string runes = lines [i];

+ 1 - 1
Terminal.Gui/View/ViewText.cs

@@ -334,7 +334,7 @@ public partial class View
             switch (TextFormatter.IsVerticalDirection (TextDirection))
             switch (TextFormatter.IsVerticalDirection (TextDirection))
             {
             {
                 case true:
                 case true:
-                    int colWidth = TextFormatter.GetWidestLineLength (new List<string> { TextFormatter.Text }, 0, 1);
+                    int colWidth = TextFormatter.GetColumnsRequiredForVerticalText (new List<string> { TextFormatter.Text }, 0, 1);
 
 
                     // TODO: v2 - This uses frame.Width; it should only use Viewport
                     // TODO: v2 - This uses frame.Width; it should only use Viewport
                     if (_frame.Width < colWidth
                     if (_frame.Width < colWidth

+ 22 - 8
UnitTests/Text/TextFormatterTests.cs

@@ -1,5 +1,6 @@
 using System.Text;
 using System.Text;
 using Xunit.Abstractions;
 using Xunit.Abstractions;
+using static Terminal.Gui.SpinnerStyle;
 
 
 // Alias Console to MockConsole so we don't accidentally use Console
 // Alias Console to MockConsole so we don't accidentally use Console
 
 
@@ -961,30 +962,43 @@ ssb
         Assert.Equal (1, TextFormatter.GetMaxColsForWidth (text, 1));
         Assert.Equal (1, TextFormatter.GetMaxColsForWidth (text, 1));
     }
     }
 
 
+
+    [Theory]
+    [InlineData (new [] { "0123456789" }, 1)]
+    [InlineData (new [] { "Hello World" }, 1)]
+    [InlineData (new [] { "Hello", "World" }, 2)]
+    [InlineData (new [] { "こんにちは", "世界" }, 4)]
+    public void GetColumnsRequiredForVerticalText_List_GetsWidth (IEnumerable<string> text, int expectedWidth)
+    {
+        Assert.Equal (expectedWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList ()));
+
+    }
+
     [Theory]
     [Theory]
+    [InlineData (new [] { "Hello World" }, 1, 0, 1, 1)]
     [InlineData (new [] { "Hello", "World" }, 2, 1, 1, 1)]
     [InlineData (new [] { "Hello", "World" }, 2, 1, 1, 1)]
     [InlineData (new [] { "こんにちは", "世界" }, 4, 1, 1, 2)]
     [InlineData (new [] { "こんにちは", "世界" }, 4, 1, 1, 2)]
-    public void GetWidestLineLength_List_Simple_And_Wide_Runes (
+    public void GetColumnsRequiredForVerticalText_List_Simple_And_Wide_Runes (
         IEnumerable<string> text,
         IEnumerable<string> text,
-        int width,
+        int expectedWidth,
         int index,
         int index,
         int length,
         int length,
-        int indexWidth
+        int expectedIndexWidth
     )
     )
     {
     {
-        Assert.Equal (width, TextFormatter.GetWidestLineLength (text.ToList ()));
-        Assert.Equal (indexWidth, TextFormatter.GetWidestLineLength (text.ToList (), index, length));
+        Assert.Equal (expectedWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList ()));
+        Assert.Equal (expectedIndexWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList (), index, length));
     }
     }
 
 
     [Fact]
     [Fact]
-    public void GetWidestLineLength_List_With_Combining_Runes ()
+    public void GetColumnsRequiredForVerticalText_List_With_Combining_Runes ()
     {
     {
         List<string> text = new () { "Les Mis", "e\u0328\u0301", "rables" };
         List<string> text = new () { "Les Mis", "e\u0328\u0301", "rables" };
-        Assert.Equal (1, TextFormatter.GetWidestLineLength (text, 1, 1));
+        Assert.Equal (1, TextFormatter.GetColumnsRequiredForVerticalText (text, 1, 1));
     }
     }
 
 
     [Fact]
     [Fact]
-    public void GetWidestLineLength_With_Combining_Runes ()
+    public void GetColumnsRequiredForVerticalText_With_Combining_Runes ()
     {
     {
         var text = "Les Mise\u0328\u0301rables";
         var text = "Les Mise\u0328\u0301rables";
         Assert.Equal (1, TextFormatter.GetWidestLineLength (text, 1, 1));
         Assert.Equal (1, TextFormatter.GetWidestLineLength (text, 1, 1));