浏览代码

better handling of unicode in table view

tznind 4 年之前
父节点
当前提交
f610cc8416
共有 3 个文件被更改,包括 27 次插入10 次删除
  1. 5 5
      Terminal.Gui/Views/TableView.cs
  2. 8 4
      UICatalog/Scenarios/TableEditor.cs
  3. 14 1
      UnitTests/TableViewTests.cs

+ 5 - 5
Terminal.Gui/Views/TableView.cs

@@ -497,10 +497,10 @@ namespace Terminal.Gui {
 				return representation;
 				return representation;
 
 
 			// if value is not wide enough
 			// if value is not wide enough
-			if(representation.Length < availableHorizontalSpace) {
+			if(representation.Sum(c=>Rune.ColumnWidth(c)) < availableHorizontalSpace) {
 				
 				
 				// pad it out with spaces to the given alignment
 				// pad it out with spaces to the given alignment
-				int toPad = availableHorizontalSpace - (representation.Length+1 /*leave 1 space for cell boundary*/);
+				int toPad = availableHorizontalSpace - (representation.Sum(c=>Rune.ColumnWidth(c)) +1 /*leave 1 space for cell boundary*/);
 
 
 				switch(colStyle?.GetAlignment(originalCellValue) ?? TextAlignment.Left) {
 				switch(colStyle?.GetAlignment(originalCellValue) ?? TextAlignment.Left) {
 
 
@@ -520,7 +520,7 @@ namespace Terminal.Gui {
 			}
 			}
 
 
 			// value is too wide
 			// value is too wide
-			return representation.Substring (0, availableHorizontalSpace);
+			return new string(representation.TakeWhile(c=>(availableHorizontalSpace-= Rune.ColumnWidth(c))>0).ToArray());
 		}
 		}
 
 
 		/// <inheritdoc/>
 		/// <inheritdoc/>
@@ -787,7 +787,7 @@ namespace Terminal.Gui {
 		/// <returns></returns>
 		/// <returns></returns>
 		private int CalculateMaxCellWidth(DataColumn col, int rowsToRender,ColumnStyle colStyle)
 		private int CalculateMaxCellWidth(DataColumn col, int rowsToRender,ColumnStyle colStyle)
 		{
 		{
-			int spaceRequired = col.ColumnName.Length;
+			int spaceRequired = col.ColumnName.Sum(c=>Rune.ColumnWidth(c));
 
 
 			// if table has no rows
 			// if table has no rows
 			if(RowOffset < 0)
 			if(RowOffset < 0)
@@ -797,7 +797,7 @@ namespace Terminal.Gui {
 			for (int i = RowOffset; i < RowOffset + rowsToRender && i < Table.Rows.Count; i++) {
 			for (int i = RowOffset; i < RowOffset + rowsToRender && i < Table.Rows.Count; i++) {
 
 
 				//expand required space if cell is bigger than the last biggest cell or header
 				//expand required space if cell is bigger than the last biggest cell or header
-				spaceRequired = Math.Max (spaceRequired, GetRepresentation(Table.Rows [i][col],colStyle).Length);
+				spaceRequired = Math.Max (spaceRequired, GetRepresentation(Table.Rows [i][col],colStyle).Sum(c=>Rune.ColumnWidth(c)));
 			}
 			}
 
 
 			// Don't require more space than the style allows
 			// Don't require more space than the style allows

+ 8 - 4
UICatalog/Scenarios/TableEditor.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Data;
 using System.Data;
 using Terminal.Gui;
 using Terminal.Gui;
+using System.Globalization;
 
 
 namespace UICatalog.Scenarios {
 namespace UICatalog.Scenarios {
 
 
@@ -261,14 +262,16 @@ namespace UICatalog.Scenarios {
 		{
 		{
 			var dt = new DataTable();
 			var dt = new DataTable();
 
 
+			int explicitCols = 6;
 			dt.Columns.Add(new DataColumn("StrCol",typeof(string)));
 			dt.Columns.Add(new DataColumn("StrCol",typeof(string)));
 			dt.Columns.Add(new DataColumn("DateCol",typeof(DateTime)));
 			dt.Columns.Add(new DataColumn("DateCol",typeof(DateTime)));
 			dt.Columns.Add(new DataColumn("IntCol",typeof(int)));
 			dt.Columns.Add(new DataColumn("IntCol",typeof(int)));
 			dt.Columns.Add(new DataColumn("DoubleCol",typeof(double)));
 			dt.Columns.Add(new DataColumn("DoubleCol",typeof(double)));
 			dt.Columns.Add(new DataColumn("NullsCol",typeof(string)));
 			dt.Columns.Add(new DataColumn("NullsCol",typeof(string)));
+			dt.Columns.Add(new DataColumn("Unicode",typeof(string)));
 
 
-			for(int i=0;i< cols -5; i++) {
-				dt.Columns.Add("Column" + (i+5));
+			for(int i=0;i< cols -explicitCols; i++) {
+				dt.Columns.Add("Column" + (i+explicitCols));
 			}
 			}
 			
 			
 			var r = new Random(100);
 			var r = new Random(100);
@@ -280,10 +283,11 @@ namespace UICatalog.Scenarios {
 					new DateTime(2000+i,12,25),
 					new DateTime(2000+i,12,25),
 					r.Next(i),
 					r.Next(i),
 					(r.NextDouble()*i)-0.5 /*add some negatives to demo styles*/,
 					(r.NextDouble()*i)-0.5 /*add some negatives to demo styles*/,
-					DBNull.Value
+					DBNull.Value,
+					"Les Mise" + Char.ConvertFromUtf32(Int32.Parse("0301", NumberStyles.HexNumber)) + "rables"
 				};
 				};
 				
 				
-				for(int j=0;j< cols -5; j++) {
+				for(int j=0;j< cols -explicitCols; j++) {
 					row.Add("SomeValue" + r.Next(100));
 					row.Add("SomeValue" + r.Next(100));
 				}
 				}
 
 

+ 14 - 1
UnitTests/TableViewTests.cs

@@ -2,10 +2,10 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Data;
 using System.Data;
 using System.Linq;
 using System.Linq;
-using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Terminal.Gui;
 using Terminal.Gui;
 using Xunit;
 using Xunit;
+using System.Globalization;
 
 
 namespace UnitTests {
 namespace UnitTests {
 	public class TableViewTests 
 	public class TableViewTests 
@@ -127,6 +127,19 @@ namespace UnitTests {
             tableView.SelectedRow = 10;
             tableView.SelectedRow = 10;
             Assert.True(called);
             Assert.True(called);
         }
         }
+
+        [Fact]
+        public void Test_SumColumnWidth_UnicodeLength()
+        {
+            Assert.Equal(11,"hello there".Sum(c=>Rune.ColumnWidth(c)));
+
+            // Creates a string with the peculiar (french?) r symbol
+            String surrogate = "Les Mise" + Char.ConvertFromUtf32(Int32.Parse("0301", NumberStyles.HexNumber)) + "rables";
+
+            // The unicode width of this string is shorter than the string length! 
+            Assert.Equal(14,surrogate.Sum(c=>Rune.ColumnWidth(c)));
+            Assert.Equal(15,surrogate.Length);
+        }
         
         
         /// <summary>
         /// <summary>
 		/// Builds a simple table of string columns with the requested number of columns and rows
 		/// Builds a simple table of string columns with the requested number of columns and rows