mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 05:18:16 +08:00
Add grid support
This commit is contained in:

committed by
Patrik Svensson

parent
f9bd936254
commit
66994cd904
79
src/Spectre.Console/Composition/Grid.cs
Normal file
79
src/Spectre.Console/Composition/Grid.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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)))
|
||||
{
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user