From a1775b281f3a264c11d4c5e50638f3d91d527150 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 26 Mar 2020 14:15:45 -0400 Subject: [PATCH] feat: TableBuilder supports multi-line content --- CHANGELOG.md | 1 + ICD.Common.Utils/TableBuilder.cs | 79 ++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33321e3..1c1335a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added ToCollection extension method for copying an enumerable to a new collection + - TableBuilder supports multi-line content ## [11.0.0] - 2020-03-20 ### Added diff --git a/ICD.Common.Utils/TableBuilder.cs b/ICD.Common.Utils/TableBuilder.cs index 3d86dee..93d375c 100644 --- a/ICD.Common.Utils/TableBuilder.cs +++ b/ICD.Common.Utils/TableBuilder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using ICD.Common.Properties; using ICD.Common.Utils.Extensions; @@ -38,11 +39,13 @@ namespace ICD.Common.Utils private readonly List m_Rows; private readonly string[] m_Columns; + #region Properties + /// /// Gets the columns. /// [PublicAPI] - public string[] Columns { get { return m_Columns; } } + public string[] Columns { get { return m_Columns.ToArray(); } } /// /// Gets the number of columns. @@ -50,6 +53,8 @@ namespace ICD.Common.Utils [PublicAPI] public int ColumnsCount { get { return m_Columns.Length; } } + #endregion + /// /// Constructor. /// @@ -91,10 +96,37 @@ namespace ICD.Common.Utils [PublicAPI] public TableBuilder AddRow(params string[] row) { - if (row != null && row.Length != m_Columns.Length) + // Special empty row case + if (row == null) + { + m_Rows.Add(null); + return this; + } + + if (row.Length != m_Columns.Length) throw new ArgumentException("Row must match columns length."); - m_Rows.Add(row); + // Split new-lines into multiple rows + List rows = new List(); + + for (int column = 0; column < row.Length; column++) + { + string cell = row[column]; + string[] lines = Regex.Split(cell, "\r\n|\r|\n"); + + for (int line = 0; line < lines.Length; line++) + { + // Add a new row for this line + if (line >= rows.Count) + rows.Add(new string[row.Length]); + + // Insert the line into the row + rows[line][column] = lines[line]; + } + } + + // Add all of the rows into the table + m_Rows.AddRange(rows); return this; } @@ -108,12 +140,21 @@ namespace ICD.Common.Utils return AddRow(new string[m_Columns.Length]); } + /// + /// Adds a horizontal line to the builder. + /// + /// [PublicAPI] public TableBuilder AddSeparator() { return AddRow(null); } + /// + /// Adds a new header to the builder. + /// + /// + /// [PublicAPI] public TableBuilder AddHeader(params string[] row) { @@ -133,24 +174,24 @@ namespace ICD.Common.Utils public override string ToString() { StringBuilder sb = new StringBuilder(); - - int[] columnWidths = GetColumnWidths(); - - AppendTopSeparator(sb, columnWidths); - - AppendRow(sb, m_Columns, columnWidths); - AppendSeparator(sb, columnWidths); - - foreach (string[] row in m_Rows) { - if (row == null) - AppendSeparator(sb, columnWidths); - else - AppendRow(sb, row, columnWidths); + int[] columnWidths = GetColumnWidths(); + + AppendTopSeparator(sb, columnWidths); + + AppendRow(sb, m_Columns, columnWidths); + AppendSeparator(sb, columnWidths); + + foreach (string[] row in m_Rows) + { + if (row == null) + AppendSeparator(sb, columnWidths); + else + AppendRow(sb, row, columnWidths); + } + + AppendBottomSeparator(sb, columnWidths); } - - AppendBottomSeparator(sb, columnWidths); - return sb.ToString(); }