mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 21:38:16 +08:00

committed by
Patrik Svensson

parent
57731c0d55
commit
e169df6303
@ -11,7 +11,6 @@ namespace Spectre.Console
|
||||
public sealed class Table : Renderable, IHasTableBorder, IExpandable, IAlignable
|
||||
{
|
||||
private readonly List<TableColumn> _columns;
|
||||
private readonly List<TableRow> _rows;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the table columns.
|
||||
@ -21,7 +20,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Gets the table rows.
|
||||
/// </summary>
|
||||
public IReadOnlyList<TableRow> Rows => _rows;
|
||||
public TableRowCollection Rows { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TableBorder Border { get; set; } = TableBorder.Square;
|
||||
@ -81,7 +80,7 @@ namespace Spectre.Console
|
||||
public Table()
|
||||
{
|
||||
_columns = new List<TableColumn>();
|
||||
_rows = new List<TableRow>();
|
||||
Rows = new TableRowCollection(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -96,7 +95,7 @@ namespace Spectre.Console
|
||||
throw new ArgumentNullException(nameof(column));
|
||||
}
|
||||
|
||||
if (_rows.Count > 0)
|
||||
if (Rows.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot add new columns to table with existing rows.");
|
||||
}
|
||||
@ -105,36 +104,6 @@ namespace Spectre.Console
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a row to the table.
|
||||
/// </summary>
|
||||
/// <param name="columns">The row columns to add.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public Table AddRow(IEnumerable<IRenderable> columns)
|
||||
{
|
||||
if (columns is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(columns));
|
||||
}
|
||||
|
||||
var rowColumnCount = columns.GetCount();
|
||||
if (rowColumnCount > _columns.Count)
|
||||
{
|
||||
throw new InvalidOperationException("The number of row columns are greater than the number of table columns.");
|
||||
}
|
||||
|
||||
_rows.Add(new TableRow(columns));
|
||||
|
||||
// Need to add missing columns?
|
||||
if (rowColumnCount < _columns.Count)
|
||||
{
|
||||
var diff = _columns.Count - rowColumnCount;
|
||||
Enumerable.Range(0, diff).ForEach(_ => _rows.Last().Add(Text.Empty));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Measurement Measure(RenderContext context, int maxWidth)
|
||||
{
|
||||
@ -190,7 +159,7 @@ namespace Spectre.Console
|
||||
}
|
||||
|
||||
// Add rows
|
||||
rows.AddRange(_rows);
|
||||
rows.AddRange(Rows);
|
||||
|
||||
// Show footers?
|
||||
if (ShowFooters && _columns.Any(c => c.Footer != null))
|
||||
|
@ -12,6 +12,11 @@ namespace Spectre.Console
|
||||
{
|
||||
private readonly List<IRenderable> _items;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of columns in the row.
|
||||
/// </summary>
|
||||
public int Count => _items.Count;
|
||||
|
||||
internal bool IsHeader { get; }
|
||||
internal bool IsFooter { get; }
|
||||
|
||||
|
160
src/Spectre.Console/Widgets/Table/TableRowCollection.cs
Normal file
160
src/Spectre.Console/Widgets/Table/TableRowCollection.cs
Normal file
@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection holding table rows.
|
||||
/// </summary>
|
||||
public sealed class TableRowCollection : IReadOnlyList<TableRow>
|
||||
{
|
||||
private readonly Table _table;
|
||||
private readonly IList<TableRow> _list;
|
||||
private readonly object _lock;
|
||||
|
||||
/// <inheritdoc/>
|
||||
TableRow IReadOnlyList<TableRow>.this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _list[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of rows in the collection.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _list.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal TableRowCollection(Table table)
|
||||
{
|
||||
_table = table ?? throw new ArgumentNullException(nameof(table));
|
||||
_list = new List<TableRow>();
|
||||
_lock = new object();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new row.
|
||||
/// </summary>
|
||||
/// <param name="columns">The columns that are part of the row to add.</param>
|
||||
/// <returns>The index of the added item.</returns>
|
||||
public int Add(IEnumerable<IRenderable> columns)
|
||||
{
|
||||
if (columns is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(columns));
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
var row = CreateRow(columns);
|
||||
_list.Add(row);
|
||||
return _list.IndexOf(row);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new row at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to insert the row at.</param>
|
||||
/// <param name="columns">The columns that are part of the row to insert.</param>
|
||||
/// <returns>The index of the inserted item.</returns>
|
||||
public int Insert(int index, IEnumerable<IRenderable> columns)
|
||||
{
|
||||
if (columns is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(columns));
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
var row = CreateRow(columns);
|
||||
_list.Insert(index, row);
|
||||
return _list.IndexOf(row);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a row at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to remove a row at.</param>
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Table row index cannot be negative.");
|
||||
}
|
||||
else if (index >= _list.Count)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Table row index cannot exceed the number of rows in the table.");
|
||||
}
|
||||
|
||||
_list.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all rows.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<TableRow> GetEnumerator()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var items = new TableRow[_list.Count];
|
||||
_list.CopyTo(items, 0);
|
||||
return new TableRowEnumerator(items);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
private TableRow CreateRow(IEnumerable<IRenderable> columns)
|
||||
{
|
||||
var row = new TableRow(columns);
|
||||
|
||||
if (row.Count > _table.Columns.Count)
|
||||
{
|
||||
throw new InvalidOperationException("The number of row columns are greater than the number of table columns.");
|
||||
}
|
||||
|
||||
// Need to add missing columns
|
||||
if (row.Count < _table.Columns.Count)
|
||||
{
|
||||
var diff = _table.Columns.Count - row.Count;
|
||||
Enumerable.Range(0, diff).ForEach(_ => row.Add(Text.Empty));
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
}
|
36
src/Spectre.Console/Widgets/Table/TableRowEnumerator.cs
Normal file
36
src/Spectre.Console/Widgets/Table/TableRowEnumerator.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
internal sealed class TableRowEnumerator : IEnumerator<TableRow>
|
||||
{
|
||||
private readonly TableRow[] _items;
|
||||
private int _index;
|
||||
|
||||
public TableRow Current => _items[_index];
|
||||
object? IEnumerator.Current => _items[_index];
|
||||
|
||||
public TableRowEnumerator(TableRow[] items)
|
||||
{
|
||||
_items = items ?? throw new ArgumentNullException(nameof(items));
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
_index++;
|
||||
return _index < _items.Length;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_index = -1;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user