Add grid support

This commit is contained in:
Patrik Svensson
2020-08-05 00:40:45 +02:00
committed by Patrik Svensson
parent f9bd936254
commit 66994cd904
5 changed files with 209 additions and 12 deletions

View File

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Text;
using Spectre.Console.Composition;
namespace Spectre.Console
{
/// <summary>
/// Represents a grid.
/// </summary>
public sealed class Grid : IRenderable
{
private readonly Table _table;
/// <summary>
/// Initializes a new instance of the <see cref="Grid"/> class.
/// </summary>
public Grid()
{
_table = new Table(BorderKind.None, showHeaders: false);
}
/// <inheritdoc/>
public int Measure(Encoding encoding, int maxWidth)
{
return _table.Measure(encoding, maxWidth);
}
/// <inheritdoc/>
public IEnumerable<Segment> Render(Encoding encoding, int width)
{
return _table.Render(encoding, width);
}
/// <summary>
/// Adds a single column to the grid.
/// </summary>
public void AddColumn()
{
_table.AddColumn(string.Empty);
}
/// <summary>
/// Adds the specified number of columns to the grid.
/// </summary>
/// <param name="count">The number of columns.</param>
public void AddColumns(int count)
{
for (var i = 0; i < count; i++)
{
_table.AddColumn(string.Empty);
}
}
/// <summary>
/// Adds a new row to the grid.
/// </summary>
/// <param name="columns">The columns to add.</param>
public void AddRow(params string[] columns)
{
if (columns is null)
{
throw new ArgumentNullException(nameof(columns));
}
if (columns.Length < _table.ColumnCount)
{
throw new InvalidOperationException("The number of row columns are less than the number of grid columns.");
}
if (columns.Length > _table.ColumnCount)
{
throw new InvalidOperationException("The number of row columns are greater than the number of grid columns.");
}
_table.AddRow(columns);
}
}
}

View File

@ -16,17 +16,25 @@ namespace Spectre.Console
private readonly List<List<Text>> _rows;
private readonly Border _border;
private readonly BorderKind _borderKind;
private readonly bool _showHeaders;
/// <summary>
/// Gets the number of columns in the table.
/// </summary>
public int ColumnCount => _columns.Count;
/// <summary>
/// Initializes a new instance of the <see cref="Table"/> class.
/// </summary>
/// <param name="border">The border to use.</param>
public Table(BorderKind border = BorderKind.Square)
/// <param name="showHeaders">Whether or not to show table headers.</param>
public Table(BorderKind border = BorderKind.Square, bool showHeaders = true)
{
_columns = new List<Text>();
_rows = new List<List<Text>>();
_border = Border.GetBorder(border);
_borderKind = border;
_showHeaders = showHeaders;
}
/// <summary>
@ -84,7 +92,7 @@ namespace Spectre.Console
/// <inheritdoc/>
public int Measure(Encoding encoding, int maxWidth)
{
// Calculate the max width for each column.
// Calculate the max width for each column
var maxColumnWidth = (maxWidth - (2 + (_columns.Count * 2) + (_columns.Count - 1))) / _columns.Count;
var columnWidths = _columns.Select(c => c.Measure(encoding, maxColumnWidth)).ToArray();
for (var rowIndex = 0; rowIndex < _rows.Count; rowIndex++)
@ -99,7 +107,7 @@ namespace Spectre.Console
}
}
// We now know the max width of each column, so let's recalculate the width.
// We now know the max width of each column, so let's recalculate the width
return columnWidths.Sum() + 2 + (_columns.Count * 2) + (_columns.Count - 1);
}
@ -128,12 +136,17 @@ namespace Spectre.Console
}
}
// We now know the max width of each column, so let's recalculate the width.
// We now know the max width of each column, so let's recalculate the width
width = columnWidths.Sum() + leftRightBorderWidth + columnPadding + separatorCount;
// Create the rows.
var rows = new List<List<Text>>();
rows.Add(new List<Text>(_columns));
if (_showHeaders)
{
// Add columns to top of rows
rows.Add(new List<Text>(_columns));
}
// Add tows.
rows.AddRange(_rows);
// Iterate all rows.
@ -142,7 +155,7 @@ namespace Spectre.Console
{
var cellHeight = 1;
// Get the list of cells for the row and calculate the cell height.
// Get the list of cells for the row and calculate the cell height
var cells = new List<List<SegmentLine>>();
foreach (var (rowWidth, cell) in columnWidths.Zip(row, (f, s) => (f, s)))
{

View File

@ -140,11 +140,11 @@ namespace Spectre.Console
{
// Creates individual segments of line breaks.
var result = new List<Segment>();
var queue = new Queue<Segment>(segments);
var queue = new Stack<Segment>(segments.Reverse());
while (queue.Count > 0)
{
var segment = queue.Dequeue();
var segment = queue.Pop();
var index = segment.Text.IndexOf("\n", StringComparison.OrdinalIgnoreCase);
if (index == -1)
@ -160,7 +160,7 @@ namespace Spectre.Console
}
result.Add(Segment.LineBreak());
queue.Enqueue(new Segment(second.Text.Substring(1), second.Style));
queue.Push(new Segment(second.Text.Substring(1), second.Style));
}
}
@ -178,10 +178,8 @@ namespace Spectre.Console
// Create a span list.
var spans = new List<(int Offset, bool Leaving, int Style)>();
spans.Add((0, false, 0));
spans.AddRange(_spans.SelectIndex((span, index) => (span.Start, false, index + 1)));
spans.AddRange(_spans.SelectIndex((span, index) => (span.End, true, index + 1)));
spans.Add((_text.Length, true, 0));
spans = spans.OrderBy(x => x.Offset).ThenBy(x => !x.Leaving).ToList();
// Keep track of applied styles using a stack