diff --git a/ConTabs.Tests/ConTabs.Tests.csproj b/ConTabs.Tests/ConTabs.Tests.csproj index 1f31e73..f75ed44 100644 --- a/ConTabs.Tests/ConTabs.Tests.csproj +++ b/ConTabs.Tests/ConTabs.Tests.csproj @@ -53,6 +53,7 @@ + diff --git a/ConTabs.Tests/UsageTests.cs b/ConTabs.Tests/UsageTests.cs new file mode 100644 index 0000000..85feb3f --- /dev/null +++ b/ConTabs.Tests/UsageTests.cs @@ -0,0 +1,42 @@ +using ConTabs.TestData; +using NUnit.Framework; +using Shouldly; +using System; + +namespace ConTabs.Tests +{ + [TestFixture] + class UsageTests + { + [Test] + public void OnceFormatSet_FormatCanBeUpdated() + { + // Arrange + var tableObj = Table.Create(); + tableObj.TableStyle = Style.Default; + + // Act + tableObj.TableStyle = Style.Heavy; + var result = tableObj.ToString(); + + // Assert + result[0].ShouldBe('#'); + } + + [Test] + public void OnceFormatSet_CornerCanBeUpdated() + { + // Arrange + var tableObj = Table.Create(); + tableObj.TableStyle = Style.Default; + + // Act + tableObj.TableStyle.Corners.CornerTopLeft = '$'; + var result = tableObj.ToString(); + + // Assert + result[0].ShouldBe('$'); + } + + } +} diff --git a/ConTabs/Corners.cs b/ConTabs/Corners.cs new file mode 100644 index 0000000..aa385f4 --- /dev/null +++ b/ConTabs/Corners.cs @@ -0,0 +1,50 @@ +namespace ConTabs +{ + public class Corners + { + private readonly char[,] cornerChars = new char[3, 3]; + + /* + * ╔═══╤═════╤═════╤═════╗ + * ║ │ 0 │ 1 │ 2 ║ + * ╠═══╪═════╪═════╪═════╣ + * ║ 0 │ TL │ TNU │ TR ║ + * ╟───┼─────┼─────┼─────╢ + * ║ 1 │ TNL │ I │ TNR ║ + * ╟───┼─────┼─────┼─────╢ + * ║ 2 │ BL │ TND │ BR ║ + * ╚═══╧═════╧═════╧═════╝ + * + */ + + public char CornerTopLeft { get { return cornerChars[0, 0]; } set { cornerChars[0, 0] = value; } } + public char CornerTopRight { get { return cornerChars[2, 0]; } set { cornerChars[2, 0] = value; } } + public char CornerBottomLeft { get { return cornerChars[0, 2]; } set { cornerChars[0, 2] = value; } } + public char CornerBottomRight { get { return cornerChars[2, 2]; } set { cornerChars[2, 2] = value; } } + + public char Intersection { get { return cornerChars[1, 1]; } set { cornerChars[1, 1] = value; } } + public char TeeNoUp { get { return cornerChars[1, 0]; } set { cornerChars[1, 0] = value; } } + public char TeeNoRight { get { return cornerChars[2, 1]; } set { cornerChars[2, 1] = value; } } + public char TeeNoDown { get { return cornerChars[1, 2]; } set { cornerChars[1, 2] = value; } } + public char TeeNoLeft { get { return cornerChars[0, 1]; } set { cornerChars[0, 1] = value; } } + + public char this[int i, int j] + { + get + { + return cornerChars[i, j]; + } + } + + public void SetAllCorners(char corner) + { + for(int i=0;i where T:class + public partial class Table { - private StringBuilder sb; - private Table table; - private Style style; - - public static string BuildOutput(Table t, Style s) + private sealed class OutputBuilder where T2 : class { - var instance = new OutputBuilder(t, s); - return instance.sb.ToString(); - } + private readonly StringBuilder sb; + private readonly Table table; + private readonly Style style; - private OutputBuilder(Table t, Style s) - { - table = t; - style = s; - sb = new StringBuilder(); - HLine(TopMidBot.Top); NewLine(); - Headers(); NewLine(); - HLine(TopMidBot.Mid); NewLine(); - if (table.Data == null || table.Data.Count() == 0) + internal static string BuildOutput(Table t, Style s) { - NoDataLine(); NewLine(); + var instance = new OutputBuilder(t, s); + return instance.sb.ToString(); } - else + + private OutputBuilder(Table t, Style s) { - for (int i = 0; i < table.Data.Count(); i++) + table = t; + style = s; + sb = new StringBuilder(); + HLine(TopMidBot.Top); NewLine(); + Headers(); NewLine(); + HLine(TopMidBot.Mid); NewLine(); + if (table.Data == null || table.Data.Count() == 0) + { + NoDataLine(); NewLine(); + } + else { - DataLine(i); NewLine(); + for (int i = 0; i < table.Data.Count(); i++) + { + DataLine(i); NewLine(); + } } + HLine(TopMidBot.Bot); } - HLine(TopMidBot.Bot); - } - private void NewLine() - { - sb.Append(Environment.NewLine); - } + private void NewLine() + { + sb.Append(Environment.NewLine); + } - private void HLine(TopMidBot v) - { - sb.Append(GetCorner(v, LeftCentreRight.Left)); - for (int i = 0; i < table._colsShown.Count; i++) + private void HLine(TopMidBot v) { - sb.Append(new string(style.Floor, table._colsShown[i].MaxWidth + 2)); - if (i < table._colsShown.Count - 1) sb.Append(GetCorner(v, LeftCentreRight.Centre)); + sb.Append(GetCorner(v, LeftCentreRight.Left)); + for (int i = 0; i < table._colsShown.Count; i++) + { + sb.Append(new string(style.Floor, table._colsShown[i].MaxWidth + 2)); + if (i < table._colsShown.Count - 1) sb.Append(GetCorner(v, LeftCentreRight.Centre)); + } + sb.Append(GetCorner(v, LeftCentreRight.Right)); } - sb.Append(GetCorner(v, LeftCentreRight.Right)); - } - private void NoDataLine() - { - var noDataText = "no data"; - int colWidths = table._colsShown.Sum(c => c.MaxWidth); - int innerWidth = colWidths + (3 * table._colsShown.Count) - 1; - int leftPad = (innerWidth - noDataText.Length) / 2; - int rightPad = innerWidth - (leftPad + noDataText.Length); - sb.Append(style.Wall + new String(' ', leftPad) + noDataText + new string(' ', rightPad) + style.Wall); - } + private void NoDataLine() + { + var noDataText = "no data"; + int colWidths = table._colsShown.Sum(c => c.MaxWidth); + int innerWidth = colWidths + (3 * table._colsShown.Count) - 1; + int leftPad = (innerWidth - noDataText.Length) / 2; + int rightPad = innerWidth - (leftPad + noDataText.Length); + sb.Append(style.Wall + new String(' ', leftPad) + noDataText + new string(' ', rightPad) + style.Wall); + } - private void Headers() - { - sb.Append(style.Wall); - foreach (var col in table._colsShown) + private void Headers() { - sb.Append(" " + col.ColumnName + new string(' ', col.MaxWidth - col.ColumnName.Length) + " " + style.Wall); + sb.Append(style.Wall); + foreach (var col in table._colsShown) + { + sb.Append(" " + col.ColumnName + new string(' ', col.MaxWidth - col.ColumnName.Length) + " " + style.Wall); + } } - } - private void DataLine(int i) - { - sb.Append(style.Wall); - foreach (var col in table._colsShown) + private void DataLine(int i) { - var value = col.StringValForCol(col.Values[i]); - sb.Append(" " + value + new string(' ', col.MaxWidth - value.Length) + " " + style.Wall); + sb.Append(style.Wall); + foreach (var col in table._colsShown) + { + var value = col.StringValForCol(col.Values[i]); + sb.Append(" " + value + new string(' ', col.MaxWidth - value.Length) + " " + style.Wall); + } } - } - private enum TopMidBot - { - Top, - Mid, - Bot - } + private enum TopMidBot + { + Top, + Mid, + Bot + } - private enum LeftCentreRight - { - Left, - Centre, - Right - } + private enum LeftCentreRight + { + Left, + Centre, + Right + } - private char GetCorner(TopMidBot v, LeftCentreRight h) - { - return style.Corners[(int)h, (int)v]; + private char GetCorner(TopMidBot v, LeftCentreRight h) + { + return style.Corners[(int)h, (int)v]; + } } } } diff --git a/ConTabs/Styles.cs b/ConTabs/Styles.cs index 8caea4a..32ae2eb 100644 --- a/ConTabs/Styles.cs +++ b/ConTabs/Styles.cs @@ -1,4 +1,6 @@ -namespace ConTabs +using System; + +namespace ConTabs { public class Style { @@ -6,72 +8,78 @@ public class Style public char Wall { get; set; } public char Floor { get; set; } - public char[,] Corners = new char[3, 3]; - - /* - * ╔═══╤═════╤═════╤═════╗ - * ║ │ 0 │ 1 │ 2 ║ - * ╠═══╪═════╪═════╪═════╣ - * ║ 0 │ TL │ TNU │ TR ║ - * ╟───┼─────┼─────┼─────╢ - * ║ 1 │ TNR │ I │ TNL ║ - * ╟───┼─────┼─────┼─────╢ - * ║ 2 │ BL │ TND │ BR ║ - * ╚═══╧═════╧═════╧═════╝ - * - */ - - public char CornerTopLeft { get { return Corners[0, 0]; } set { Corners[0, 0] = value; } } - public char CornerTopRight { get { return Corners[2, 0]; } set { Corners[2, 0] = value; } } - public char CornerBottomLeft { get { return Corners[0, 2]; } set { Corners[0, 2] = value; } } - public char CornerBottomRight { get { return Corners[2, 2]; } set { Corners[2, 2] = value; } } - - public char Intersection { get { return Corners[1, 1]; } set { Corners[1, 1] = value; } } - public char TeeNoUp { get { return Corners[1, 0]; } set { Corners[1, 0] = value; } } - public char TeeNoRight { get { return Corners[0, 1]; } set { Corners[0, 1] = value; } } - public char TeeNoDown { get { return Corners[1, 2]; } set { Corners[1, 2] = value; } } - public char TeeNoLeft { get { return Corners[2, 1]; } set { Corners[2, 1] = value; } } + public Corners Corners { get; set; } public Style(char wall, char floor, char corners) { Wall = wall; Floor = floor; - - CornerTopLeft = corners; - CornerTopRight = corners; - CornerBottomLeft = corners; - CornerBottomRight = corners; - Intersection = corners; - TeeNoUp = corners; - TeeNoRight = corners; - TeeNoDown = corners; - TeeNoLeft = corners; + Corners = new Corners(); + Corners.SetAllCorners(corners); } - public Style(char wall, char floor, char tl, char tr, char bl, char br, char i, char tnu, char tnr, char tnd, char tnl) + public Style(char wall, char floor, Corners corners) { Wall = wall; Floor = floor; - - CornerTopLeft = tl; - CornerTopRight = tr; - CornerBottomLeft = bl; - CornerBottomRight = br; - - Intersection = i; - TeeNoUp = tnu; - TeeNoRight = tnr; - TeeNoDown = tnd; - TeeNoLeft = tnl; + Corners = corners; } + // Built-in styles public static Style Default => new Style('|', '-', '+'); public static Style Heavy => new Style('#', '=', '#'); - public static Style UnicodePipes => new Style('║', '═', '╔', '╗', '╚', '╝', '╬', '╦', '╠', '╩', '╣'); + public static Style UnicodePipes => new Style('║', '═', new Corners { + CornerTopLeft = '╔', + CornerTopRight = '╗', + CornerBottomLeft = '╚', + CornerBottomRight = '╝', + Intersection = '╬', + TeeNoUp = '╦', + TeeNoLeft = '╠', + TeeNoDown = '╩', + TeeNoRight = '╣' + }); + // Deprecated setters/getters + [Obsolete("Use Corners.CornerTopLeft")] + public char CornerTopLeft { get { return Corners[0, 0]; } set { Corners.CornerTopLeft = value; } } + [Obsolete("Use Corners.CornerTopRight")] + public char CornerTopRight { get { return Corners[2, 0]; } set { Corners.CornerTopRight = value; } } + [Obsolete("Use Corners.CornerBottomLeft")] + public char CornerBottomLeft { get { return Corners[0, 2]; } set { Corners.CornerBottomLeft = value; } } + [Obsolete("Use Corners.CornerBottomRight")] + public char CornerBottomRight { get { return Corners[2, 2]; } set { Corners.CornerBottomRight = value; } } + [Obsolete("Use Corners.Intersection")] + public char Intersection { get { return Corners[1, 1]; } set { Corners.Intersection = value; } } + [Obsolete("Use Corners.TeeNoUp")] + public char TeeNoUp { get { return Corners[1, 0]; } set { Corners.TeeNoUp = value; } } + [Obsolete("Use Corners.TeeNoRight")] + public char TeeNoRight { get { return Corners[2, 1]; } set { Corners.TeeNoRight = value; } } + [Obsolete("Use Corners.TeeNoDown")] + public char TeeNoDown { get { return Corners[1, 2]; } set { Corners.TeeNoDown = value; } } + [Obsolete("Use Corners.TeeNoLeft")] + public char TeeNoLeft { get { return Corners[0, 1]; } set { Corners.TeeNoLeft = value; } } + + // Old constructor with too many params + [Obsolete] + public Style(char wall, char floor, char tl, char tr, char bl, char br, char i, char tnu, char tnr, char tnd, char tnl) + { + Wall = wall; + Floor = floor; + + Corners.CornerTopLeft = tl; + Corners.CornerTopRight = tr; + Corners.CornerBottomLeft = bl; + Corners.CornerBottomRight = br; + Corners.Intersection = i; + Corners.TeeNoUp = tnu; + Corners.TeeNoRight = tnr; + Corners.TeeNoDown = tnd; + Corners.TeeNoLeft = tnl; + } } } diff --git a/ConTabs/Table.cs b/ConTabs/Table.cs index ff664bf..c213fa0 100644 --- a/ConTabs/Table.cs +++ b/ConTabs/Table.cs @@ -5,7 +5,7 @@ namespace ConTabs { - public class Table where T:class + public partial class Table where T:class { public List Columns { get; set; } internal List _colsShown => Columns.Where(c => !c.Hide).ToList(); diff --git a/appveyor.yml b/appveyor.yml index 43bff63..6ad1bc6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ build: after_test: # Tell OpenCover to generate coverage.xml - - cmd: packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -filter:"+[ConTabs]*" -target:"packages\NUnit.ConsoleRunner.3.7.0\tools\nunit3-console.exe" -targetargs:"/domain:single ConTabs.Tests/bin/debug/ConTabs.Tests.dll" -output:coverage.xml + - cmd: packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -filter:"+[ConTabs]*" -target:"packages\NUnit.ConsoleRunner.3.7.0\tools\nunit3-console.exe" -targetargs:"/domain:single ConTabs.Tests/bin/debug/ConTabs.Tests.dll" -output:coverage.xml -excludebyattribute:"System.ObsoleteAttribute" # Send coverage.xml to Coveralls - cmd: packages\coveralls.io.1.4.2\tools\coveralls.net.exe --opencover coverage.xml -r %COVERALLS_REPO_TOKEN% \ No newline at end of file