mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-08-04 04:47:59 +08:00
Add support for table footers
This commit is contained in:

committed by
Patrik Svensson

parent
c9c0ad733f
commit
03334f693d
@ -209,7 +209,7 @@ namespace Spectre.Console
|
||||
if (ShowHeader)
|
||||
{
|
||||
var heading = new DateTime(Year, Month, Day).ToString("Y", culture).EscapeMarkup();
|
||||
table.Heading = new TableTitle(heading, HeaderStyle);
|
||||
table.Title = new TableTitle(heading, HeaderStyle);
|
||||
}
|
||||
|
||||
// Add columns
|
||||
|
@ -17,7 +17,7 @@ namespace Spectre.Console
|
||||
private readonly List<List<IRenderable>> _rows;
|
||||
|
||||
private static Style _defaultHeadingStyle = new Style(Color.Silver);
|
||||
private static Style _defaultFootnoteStyle = new Style(Color.Grey);
|
||||
private static Style _defaultCaptionStyle = new Style(Color.Grey);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of columns in the table.
|
||||
@ -43,6 +43,11 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
public bool ShowHeaders { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not table footers should be shown.
|
||||
/// </summary>
|
||||
public bool ShowFooters { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not the table should
|
||||
/// fit the available space. If <c>false</c>, the table width will be
|
||||
@ -58,12 +63,12 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Gets or sets the table title.
|
||||
/// </summary>
|
||||
public TableTitle? Heading { get; set; }
|
||||
public TableTitle? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the table footnote.
|
||||
/// </summary>
|
||||
public TableTitle? Footnote { get; set; }
|
||||
public TableTitle? Caption { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Justify? Alignment { get; set; }
|
||||
@ -174,6 +179,7 @@ namespace Spectre.Console
|
||||
var showBorder = Border.Visible;
|
||||
var hideBorder = !Border.Visible;
|
||||
var hasRows = _rows.Count > 0;
|
||||
var hasFooters = _columns.Any(c => c.Footer != null);
|
||||
|
||||
if (Width != null)
|
||||
{
|
||||
@ -196,14 +202,19 @@ namespace Spectre.Console
|
||||
if (ShowHeaders)
|
||||
{
|
||||
// Add columns to top of rows
|
||||
rows.Add(new List<IRenderable>(_columns.Select(c => c.Text)));
|
||||
rows.Add(new List<IRenderable>(_columns.Select(c => c.Header)));
|
||||
}
|
||||
|
||||
// Add rows.
|
||||
rows.AddRange(_rows);
|
||||
|
||||
if (hasFooters)
|
||||
{
|
||||
rows.Add(new List<IRenderable>(_columns.Select(c => c.Footer ?? Text.Empty)));
|
||||
}
|
||||
|
||||
var result = new List<Segment>();
|
||||
result.AddRange(RenderAnnotation(context, Heading, actualMaxWidth, tableWidth, _defaultHeadingStyle));
|
||||
result.AddRange(RenderAnnotation(context, Title, actualMaxWidth, tableWidth, _defaultHeadingStyle));
|
||||
|
||||
// Iterate all rows
|
||||
foreach (var (index, firstRow, lastRow, row) in rows.Enumerate())
|
||||
@ -230,6 +241,18 @@ namespace Spectre.Console
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
|
||||
// Show footer separator?
|
||||
if (ShowFooters && lastRow && showBorder && hasFooters)
|
||||
{
|
||||
var textBorder = border.GetColumnRow(TablePart.FooterSeparator, columnWidths, _columns);
|
||||
if (!string.IsNullOrEmpty(textBorder))
|
||||
{
|
||||
var separator = Aligner.Align(context, textBorder, Alignment, actualMaxWidth);
|
||||
result.Add(new Segment(separator, borderStyle));
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
}
|
||||
|
||||
// Make cells the same shape
|
||||
cells = Segment.MakeSameHeight(cellHeight, cells);
|
||||
|
||||
@ -310,7 +333,7 @@ namespace Spectre.Console
|
||||
// Show header separator?
|
||||
if (firstRow && showBorder && ShowHeaders && hasRows)
|
||||
{
|
||||
var separator = Aligner.Align(context, border.GetColumnRow(TablePart.Separator, columnWidths, _columns), Alignment, actualMaxWidth);
|
||||
var separator = Aligner.Align(context, border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, _columns), Alignment, actualMaxWidth);
|
||||
result.Add(new Segment(separator, borderStyle));
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
@ -324,7 +347,7 @@ namespace Spectre.Console
|
||||
}
|
||||
}
|
||||
|
||||
result.AddRange(RenderAnnotation(context, Footnote, actualMaxWidth, tableWidth, _defaultFootnoteStyle));
|
||||
result.AddRange(RenderAnnotation(context, Caption, actualMaxWidth, tableWidth, _defaultCaptionStyle));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -437,16 +460,17 @@ namespace Spectre.Console
|
||||
var minWidths = new List<int>();
|
||||
var maxWidths = new List<int>();
|
||||
|
||||
// Include columns in measurement
|
||||
var measure = column.Text.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
// Include columns (both header and footer) in measurement
|
||||
var headerMeasure = column.Header.Measure(options, maxWidth);
|
||||
var footerMeasure = column.Footer?.Measure(options, maxWidth) ?? headerMeasure;
|
||||
minWidths.Add(Math.Min(headerMeasure.Min, footerMeasure.Min));
|
||||
maxWidths.Add(Math.Max(headerMeasure.Max, footerMeasure.Max));
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
measure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
var rowMeasure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(rowMeasure.Min);
|
||||
maxWidths.Add(rowMeasure.Max);
|
||||
}
|
||||
|
||||
return (minWidths.Count > 0 ? minWidths.Max() : padding,
|
||||
|
@ -9,9 +9,14 @@ namespace Spectre.Console
|
||||
public sealed class TableColumn : IColumn
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the text associated with the column.
|
||||
/// Gets the column header.
|
||||
/// </summary>
|
||||
public IRenderable Text { get; }
|
||||
public IRenderable Header { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column footer.
|
||||
/// </summary>
|
||||
public IRenderable? Footer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the column.
|
||||
@ -39,19 +44,19 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableColumn"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The table column text.</param>
|
||||
public TableColumn(string text)
|
||||
: this(new Markup(text).Overflow(Overflow.Ellipsis))
|
||||
/// <param name="header">The table column header.</param>
|
||||
public TableColumn(string header)
|
||||
: this(new Markup(header).Overflow(Overflow.Ellipsis))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableColumn"/> class.
|
||||
/// </summary>
|
||||
/// <param name="renderable">The <see cref="IRenderable"/> instance to use as the table column.</param>
|
||||
public TableColumn(IRenderable renderable)
|
||||
/// <param name="header">The <see cref="IRenderable"/> instance to use as the table column header.</param>
|
||||
public TableColumn(IRenderable header)
|
||||
{
|
||||
Text = renderable ?? throw new ArgumentNullException(nameof(renderable));
|
||||
Header = header ?? throw new ArgumentNullException(nameof(header));
|
||||
Width = null;
|
||||
Padding = new Padding(1, 0, 1, 0);
|
||||
NoWrap = false;
|
||||
|
Reference in New Issue
Block a user