Make styles composable

Also adds some new extension methods and make some APIs a bit more consistent.

Closes #64
This commit is contained in:
Patrik Svensson
2020-09-03 21:18:52 +02:00
committed by Patrik Svensson
parent bcaaa6b2d3
commit e946289bd9
12 changed files with 296 additions and 97 deletions

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console
@ -13,6 +11,16 @@ namespace Spectre.Console
{
private readonly Table _table;
/// <summary>
/// Gets the number of columns in the table.
/// </summary>
public int ColumnCount => _table.ColumnCount;
/// <summary>
/// Gets the number of rows in the table.
/// </summary>
public int RowCount => _table.RowCount;
/// <summary>
/// Initializes a new instance of the <see cref="Grid"/> class.
/// </summary>
@ -20,7 +28,7 @@ namespace Spectre.Console
{
_table = new Table
{
Border = BorderKind.None,
BorderKind = BorderKind.None,
ShowHeaders = false,
IsGrid = true,
PadRightCell = false,
@ -75,45 +83,6 @@ namespace Spectre.Console
});
}
/// <summary>
/// Adds a column to the grid.
/// </summary>
/// <param name="count">The number of columns to add.</param>
public void AddColumns(int count)
{
for (var index = 0; index < count; index++)
{
AddColumn(new GridColumn());
}
}
/// <summary>
/// Adds a column to the grid.
/// </summary>
/// <param name="columns">The columns to add.</param>
public void AddColumns(params GridColumn[] columns)
{
if (columns is null)
{
throw new ArgumentNullException(nameof(columns));
}
foreach (var column in columns)
{
AddColumn(column);
}
}
/// <summary>
/// Adds an empty row to the grid.
/// </summary>
public void AddEmptyRow()
{
var columns = new IRenderable[_table.ColumnCount];
Enumerable.Range(0, _table.ColumnCount).ForEach(index => columns[index] = Text.Empty);
AddRow(columns);
}
/// <summary>
/// Adds a new row to the grid.
/// </summary>

View File

@ -1,5 +1,7 @@
using System;
using System.Linq;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console
{
@ -8,6 +10,63 @@ namespace Spectre.Console
/// </summary>
public static class GridExtensions
{
/// <summary>
/// Adds a column to the grid.
/// </summary>
/// <param name="grid">The grid to add the column to.</param>
/// <param name="count">The number of columns to add.</param>
public static void AddColumns(this Grid grid, int count)
{
if (grid is null)
{
throw new ArgumentNullException(nameof(grid));
}
for (var index = 0; index < count; index++)
{
grid.AddColumn(new GridColumn());
}
}
/// <summary>
/// Adds a column to the grid.
/// </summary>
/// <param name="grid">The grid to add the column to.</param>
/// <param name="columns">The columns to add.</param>
public static void AddColumns(this Grid grid, params GridColumn[] columns)
{
if (grid is null)
{
throw new ArgumentNullException(nameof(grid));
}
if (columns is null)
{
throw new ArgumentNullException(nameof(columns));
}
foreach (var column in columns)
{
grid.AddColumn(column);
}
}
/// <summary>
/// Adds an empty row to the grid.
/// </summary>
/// <param name="grid">The grid to add the row to.</param>
public static void AddEmptyRow(this Grid grid)
{
if (grid is null)
{
throw new ArgumentNullException(nameof(grid));
}
var columns = new IRenderable[grid.ColumnCount];
Enumerable.Range(0, grid.ColumnCount).ForEach(index => columns[index] = Text.Empty);
grid.AddRow(columns);
}
/// <summary>
/// Adds a new row to the grid.
/// </summary>

View File

@ -16,13 +16,13 @@ namespace Spectre.Console
private readonly IRenderable _child;
/// <inheritdoc/>
public BorderKind Border { get; set; } = BorderKind.Square;
public BorderKind BorderKind { get; set; } = BorderKind.Square;
/// <inheritdoc/>
public bool SafeBorder { get; set; } = true;
/// <inheritdoc/>
public Color? BorderColor { get; set; }
public Style? BorderStyle { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not the panel should
@ -71,8 +71,8 @@ namespace Spectre.Console
/// <inheritdoc/>
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
var borderStyle = new Style(BorderColor, null, null);
var border = SpectreBorder.GetBorder(BorderKind, (context.LegacyConsole || !context.Unicode) && SafeBorder);
var borderStyle = BorderStyle ?? Style.Plain;
var paddingWidth = Padding.GetHorizontalPadding();
var childWidth = maxWidth - EdgeWidth - paddingWidth;

View File

@ -26,10 +26,10 @@ namespace Spectre.Console
public int RowCount => _rows.Count;
/// <inheritdoc/>
public BorderKind Border { get; set; } = BorderKind.Square;
public BorderKind BorderKind { get; set; } = BorderKind.Square;
/// <inheritdoc/>
public Color? BorderColor { get; set; }
public Style? BorderStyle { get; set; }
/// <inheritdoc/>
public bool SafeBorder { get; set; } = true;
@ -168,13 +168,13 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(context));
}
var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
var borderStyle = new Style(BorderColor, null, null);
var border = SpectreBorder.GetBorder(BorderKind, (context.LegacyConsole || !context.Unicode) && SafeBorder);
var borderStyle = BorderStyle ?? Style.Plain;
var tableWidth = maxWidth;
var showBorder = Border != BorderKind.None;
var hideBorder = Border == BorderKind.None;
var showBorder = BorderKind != BorderKind.None;
var hideBorder = BorderKind == BorderKind.None;
var hasRows = _rows.Count > 0;
if (Width != null)

View File

@ -8,13 +8,61 @@ namespace Spectre.Console.Rendering
public static class BorderExtensions
{
/// <summary>
/// Sets the border.
/// Do not display a border.
/// </summary>
/// <typeparam name="T">The object that has a border.</typeparam>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, BorderKind border)
public static T NoBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorderKind(obj, BorderKind.None);
}
/// <summary>
/// Display a square border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SquareBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorderKind(obj, BorderKind.Square);
}
/// <summary>
/// Display an ASCII border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T AsciiBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorderKind(obj, BorderKind.Ascii);
}
/// <summary>
/// Display a rounded border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T RoundedBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorderKind(obj, BorderKind.Rounded);
}
/// <summary>
/// Sets the border kind.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border kind to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorderKind<T>(this T obj, BorderKind border)
where T : class, IHasBorder
{
if (obj is null)
@ -22,14 +70,14 @@ namespace Spectre.Console.Rendering
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
obj.BorderKind = border;
return obj;
}
/// <summary>
/// Disables the safe border.
/// </summary>
/// <typeparam name="T">The object that has a border.</typeparam>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T NoSafeBorder<T>(this T obj)
@ -44,12 +92,31 @@ namespace Spectre.Console.Rendering
return obj;
}
/// <summary>
/// Sets the border style.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border color for.</param>
/// <param name="style">The border style to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorderStyle<T>(this T obj, Style style)
where T : class, IHasBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.BorderStyle = style;
return obj;
}
/// <summary>
/// Sets the border color.
/// </summary>
/// <typeparam name="T">The object that has a border.</typeparam>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border color for.</param>
/// <param name="color">The color to set.</param>
/// <param name="color">The border color to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorderColor<T>(this T obj, Color color)
where T : class, IHasBorder
@ -59,7 +126,7 @@ namespace Spectre.Console.Rendering
throw new ArgumentNullException(nameof(obj));
}
obj.BorderColor = color;
obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).WithForeground(color);
return obj;
}
}

View File

@ -15,11 +15,11 @@ namespace Spectre.Console
/// <summary>
/// Gets or sets the kind of border to use.
/// </summary>
public BorderKind Border { get; set; }
public BorderKind BorderKind { get; set; }
/// <summary>
/// Gets or sets the border color.
/// Gets or sets the border style.
/// </summary>
public Color? BorderColor { get; set; }
public Style? BorderStyle { get; set; }
}
}