diff --git a/examples/Table/Program.cs b/examples/Table/Program.cs
index 6a84a7b..eaf8af9 100644
--- a/examples/Table/Program.cs
+++ b/examples/Table/Program.cs
@@ -1,10 +1,11 @@
using Spectre.Console;
+using Spectre.Console.Rendering;
namespace TableExample
{
- class Program
+ public static class Program
{
- static void Main(string[] args)
+ public static void Main(string[] args)
{
// A simple table
RenderSimpleTable();
@@ -35,7 +36,7 @@ namespace TableExample
private static void RenderBigTable()
{
// Create the table.
- var table = new Table { Border = BorderKind.Rounded };
+ var table = new Table().SetBorder(BorderKind.Rounded);
table.AddColumn("[red underline]Foo[/]");
table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true });
@@ -57,7 +58,7 @@ namespace TableExample
private static void RenderNestedTable()
{
// Create simple table.
- var simple = new Table { Border = BorderKind.Rounded };
+ var simple = new Table().SetBorder(BorderKind.Rounded).SetBorderColor(Color.Red);
simple.AddColumn(new TableColumn("[u]Foo[/]").Centered());
simple.AddColumn(new TableColumn("[u]Bar[/]"));
simple.AddColumn(new TableColumn("[u]Baz[/]"));
@@ -66,7 +67,7 @@ namespace TableExample
simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
// Create other table.
- var second = new Table { Border = BorderKind.Square };
+ var second = new Table().SetBorder(BorderKind.Square).SetBorderColor(Color.Green);
second.AddColumn(new TableColumn("[u]Foo[/]"));
second.AddColumn(new TableColumn("[u]Bar[/]"));
second.AddColumn(new TableColumn("[u]Baz[/]"));
@@ -74,10 +75,10 @@ namespace TableExample
second.AddRow(simple, new Text("Whaaat"), new Text("Lolz"));
second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
- var table = new Table { Border = BorderKind.Rounded };
- table.AddColumn(new TableColumn(new Panel("[u]Foo[/]")));
- table.AddColumn(new TableColumn(new Panel("[u]Bar[/]")));
- table.AddColumn(new TableColumn(new Panel("[u]Baz[/]")));
+ var table = new Table().SetBorder(BorderKind.Rounded);
+ table.AddColumn(new TableColumn(new Panel("[u]Foo[/]").SetBorderColor(Color.Red)));
+ table.AddColumn(new TableColumn(new Panel("[u]Bar[/]").SetBorderColor(Color.Green)));
+ table.AddColumn(new TableColumn(new Panel("[u]Baz[/]").SetBorderColor(Color.Blue)));
// Add some rows
table.AddRow(new Text("Hello").Centered(), new Markup("[red]World![/] 🌍"), Text.Empty);
diff --git a/src/Spectre.Console/Rendering/AlignableExtensions.cs b/src/Spectre.Console/Rendering/AlignableExtensions.cs
index 5193a50..aa14f93 100644
--- a/src/Spectre.Console/Rendering/AlignableExtensions.cs
+++ b/src/Spectre.Console/Rendering/AlignableExtensions.cs
@@ -1,4 +1,4 @@
-namespace Spectre.Console
+namespace Spectre.Console
{
///
/// Contains extension methods for .
@@ -8,54 +8,74 @@
///
/// Sets the alignment for an object.
///
- /// The alignable type.
- /// The alignable object.
+ /// The alignable object type.
+ /// The alignable object.
/// The alignment.
- /// The same alignable object.
- public static T WithAlignment(this T alignable, Justify alignment)
- where T : IAlignable
+ /// The same instance.
+ public static T SetAlignment(this T obj, Justify alignment)
+ where T : class, IAlignable
{
- alignable.Alignment = alignment;
- return alignable;
+ if (obj is null)
+ {
+ throw new System.ArgumentNullException(nameof(obj));
+ }
+
+ obj.Alignment = alignment;
+ return obj;
}
///
/// Sets the object to be left aligned.
///
/// The alignable type.
- /// The alignable object.
- /// The same alignable object.
- public static T LeftAligned(this T alignable)
- where T : IAlignable
+ /// The alignable object.
+ /// The same instance.
+ public static T LeftAligned(this T obj)
+ where T : class, IAlignable
{
- alignable.Alignment = Justify.Left;
- return alignable;
+ if (obj is null)
+ {
+ throw new System.ArgumentNullException(nameof(obj));
+ }
+
+ obj.Alignment = Justify.Left;
+ return obj;
}
///
/// Sets the object to be centered.
///
/// The alignable type.
- /// The alignable object.
- /// The same alignable object.
- public static T Centered(this T alignable)
- where T : IAlignable
+ /// The alignable object.
+ /// The same instance.
+ public static T Centered(this T obj)
+ where T : class, IAlignable
{
- alignable.Alignment = Justify.Center;
- return alignable;
+ if (obj is null)
+ {
+ throw new System.ArgumentNullException(nameof(obj));
+ }
+
+ obj.Alignment = Justify.Center;
+ return obj;
}
///
/// Sets the object to be right aligned.
///
/// The alignable type.
- /// The alignable object.
- /// The same alignable object.
- public static T RightAligned(this T alignable)
- where T : IAlignable
+ /// The alignable object.
+ /// The same instance.
+ public static T RightAligned(this T obj)
+ where T : class, IAlignable
{
- alignable.Alignment = Justify.Right;
- return alignable;
+ if (obj is null)
+ {
+ throw new System.ArgumentNullException(nameof(obj));
+ }
+
+ obj.Alignment = Justify.Right;
+ return obj;
}
}
}
diff --git a/src/Spectre.Console/Rendering/BorderExtensions.cs b/src/Spectre.Console/Rendering/BorderExtensions.cs
new file mode 100644
index 0000000..f963c16
--- /dev/null
+++ b/src/Spectre.Console/Rendering/BorderExtensions.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Spectre.Console.Rendering
+{
+ ///
+ /// Contains extension methods for .
+ ///
+ public static class BorderExtensions
+ {
+ ///
+ /// Sets the border.
+ ///
+ /// The object that has a border.
+ /// The object to set the border for.
+ /// The border to use.
+ /// The same instance.
+ public static T SetBorder(this T obj, BorderKind border)
+ where T : class, IHasBorder
+ {
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ obj.Border = border;
+ return obj;
+ }
+
+ ///
+ /// Disables the safe border.
+ ///
+ /// The object that has a border.
+ /// The object to set the border for.
+ /// The same instance.
+ public static T NoSafeBorder(this T obj)
+ where T : class, IHasBorder
+ {
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ obj.SafeBorder = false;
+ return obj;
+ }
+
+ ///
+ /// Sets the border color.
+ ///
+ /// The object that has a border.
+ /// The object to set the border color for.
+ /// The color to set.
+ /// The same instance.
+ public static T SetBorderColor(this T obj, Color color)
+ where T : class, IHasBorder
+ {
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ obj.BorderColor = color;
+ return obj;
+ }
+ }
+}
diff --git a/src/Spectre.Console/Rendering/IHasBorder.cs b/src/Spectre.Console/Rendering/IHasBorder.cs
new file mode 100644
index 0000000..b69a79d
--- /dev/null
+++ b/src/Spectre.Console/Rendering/IHasBorder.cs
@@ -0,0 +1,25 @@
+namespace Spectre.Console
+{
+ ///
+ /// Represents something that has a border.
+ ///
+ public interface IHasBorder
+ {
+ ///
+ /// Gets or sets a value indicating whether or not to use
+ /// a "safe" border on legacy consoles that might not be able
+ /// to render non-ASCII characters.
+ ///
+ bool SafeBorder { get; set; }
+
+ ///
+ /// Gets or sets the kind of border to use.
+ ///
+ public BorderKind Border { get; set; }
+
+ ///
+ /// Gets or sets the border color.
+ ///
+ public Color? BorderColor { get; set; }
+ }
+}
diff --git a/src/Spectre.Console/Rendering/Panel.cs b/src/Spectre.Console/Rendering/Panel.cs
index f1b8b21..4fab57f 100644
--- a/src/Spectre.Console/Rendering/Panel.cs
+++ b/src/Spectre.Console/Rendering/Panel.cs
@@ -8,23 +8,20 @@ namespace Spectre.Console
///
/// A renderable panel.
///
- public sealed class Panel : Renderable
+ public sealed class Panel : Renderable, IHasBorder
{
private const int EdgeWidth = 2;
private readonly IRenderable _child;
- ///
- /// Gets or sets a value indicating whether or not to use
- /// a "safe" border on legacy consoles that might not be able
- /// to render non-ASCII characters. Defaults to true.
- ///
+ ///
+ public BorderKind Border { get; set; } = BorderKind.Square;
+
+ ///
public bool SafeBorder { get; set; } = true;
- ///
- /// Gets or sets the kind of border to use.
- ///
- public BorderKind Border { get; set; } = BorderKind.Square;
+ ///
+ public Color? BorderColor { get; set; }
///
/// Gets or sets the alignment of the panel contents.
@@ -74,6 +71,7 @@ namespace Spectre.Console
protected override IEnumerable Render(RenderContext context, int maxWidth)
{
var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
+ var borderStyle = new Style(BorderColor, null, null);
var paddingWidth = Padding.GetHorizontalPadding();
var childWidth = maxWidth - EdgeWidth - paddingWidth;
@@ -89,9 +87,9 @@ namespace Spectre.Console
// Panel top
var result = new List
{
- new Segment(border.GetPart(BorderPart.HeaderTopLeft)),
- new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth)),
- new Segment(border.GetPart(BorderPart.HeaderTopRight)),
+ new Segment(border.GetPart(BorderPart.HeaderTopLeft), borderStyle),
+ new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth), borderStyle),
+ new Segment(border.GetPart(BorderPart.HeaderTopRight), borderStyle),
Segment.LineBreak,
};
@@ -102,7 +100,7 @@ namespace Spectre.Console
// Split the child segments into lines.
foreach (var line in Segment.SplitLines(childSegments, panelWidth))
{
- result.Add(new Segment(border.GetPart(BorderPart.CellLeft)));
+ result.Add(new Segment(border.GetPart(BorderPart.CellLeft), borderStyle));
// Left padding
if (Padding.Left > 0)
@@ -129,14 +127,14 @@ namespace Spectre.Console
result.Add(new Segment(new string(' ', Padding.Right)));
}
- result.Add(new Segment(border.GetPart(BorderPart.CellRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.CellRight), borderStyle));
result.Add(Segment.LineBreak);
}
// Panel bottom
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft)));
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth)));
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft), borderStyle));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth), borderStyle));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight), borderStyle));
result.Add(Segment.LineBreak);
return result;
diff --git a/src/Spectre.Console/Rendering/SegmentLineIterator.cs b/src/Spectre.Console/Rendering/SegmentLineIterator.cs
index eacc3f9..fef5e80 100644
--- a/src/Spectre.Console/Rendering/SegmentLineIterator.cs
+++ b/src/Spectre.Console/Rendering/SegmentLineIterator.cs
@@ -33,7 +33,7 @@ namespace Spectre.Console.Rendering
return false;
}
- _currentIndex += 1;
+ _currentIndex++;
// Did we go past the end of the line?
if (_currentIndex > _lines[_currentLine].Count - 1)
@@ -57,7 +57,7 @@ namespace Spectre.Console.Rendering
}
// Increase the line and reset the index.
- _currentLine += 1;
+ _currentLine++;
_currentIndex = 0;
_lineBreakEmitted = false;
@@ -71,7 +71,7 @@ namespace Spectre.Console.Rendering
// Nothing on the line?
while (_currentIndex > _lines[_currentLine].Count - 1)
{
- _currentLine += 1;
+ _currentLine++;
_currentIndex = 0;
if (_currentLine > _lines.Count - 1)
diff --git a/src/Spectre.Console/Rendering/Table.cs b/src/Spectre.Console/Rendering/Table.cs
index 145143a..4f5e22c 100644
--- a/src/Spectre.Console/Rendering/Table.cs
+++ b/src/Spectre.Console/Rendering/Table.cs
@@ -10,7 +10,7 @@ namespace Spectre.Console
///
/// A renderable table.
///
- public sealed partial class Table : Renderable
+ public sealed partial class Table : Renderable, IHasBorder
{
private readonly List _columns;
private readonly List> _rows;
@@ -25,11 +25,15 @@ namespace Spectre.Console
///
public int RowCount => _rows.Count;
- ///
- /// Gets or sets the kind of border to use.
- ///
+ ///
public BorderKind Border { get; set; } = BorderKind.Square;
+ ///
+ public Color? BorderColor { get; set; }
+
+ ///
+ public bool SafeBorder { get; set; } = true;
+
///
/// Gets or sets a value indicating whether or not table headers should be shown.
///
@@ -47,13 +51,6 @@ namespace Spectre.Console
///
public int? Width { get; set; }
- ///
- /// Gets or sets a value indicating whether or not to use
- /// a "safe" border on legacy consoles that might not be able
- /// to render non-ASCII characters. Defaults to true.
- ///
- public bool SafeBorder { get; set; } = true;
-
// Whether this is a grid or not.
internal bool IsGrid { get; set; }
@@ -172,6 +169,8 @@ namespace Spectre.Console
}
var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
+ var borderStyle = new Style(BorderColor, null, null);
+
var tableWidth = maxWidth;
var showBorder = Border != BorderKind.None;
@@ -222,22 +221,22 @@ namespace Spectre.Console
// Show top of header?
if (firstRow && showBorder)
{
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft), borderStyle));
foreach (var (columnIndex, _, lastColumn, columnWidth) in columnWidths.Enumerate())
{
var padding = _columns[columnIndex].Padding;
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Left))); // Left padding
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, columnWidth)));
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Right))); // Right padding
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Left), borderStyle)); // Left padding
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, columnWidth), borderStyle));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Right), borderStyle)); // Right padding
if (!lastColumn)
{
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTopSeparator)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTopSeparator), borderStyle));
}
}
- result.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight), borderStyle));
result.Add(Segment.LineBreak);
}
@@ -252,7 +251,7 @@ namespace Spectre.Console
if (firstCell && showBorder)
{
// Show left column edge
- result.Add(new Segment(border.GetPart(BorderPart.CellLeft)));
+ result.Add(new Segment(border.GetPart(BorderPart.CellLeft), borderStyle));
}
// Pad column on left side.
@@ -288,12 +287,12 @@ namespace Spectre.Console
if (lastCell && showBorder)
{
// Add right column edge
- result.Add(new Segment(border.GetPart(BorderPart.CellRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.CellRight), borderStyle));
}
else if (showBorder)
{
// Add column separator
- result.Add(new Segment(border.GetPart(BorderPart.CellSeparator)));
+ result.Add(new Segment(border.GetPart(BorderPart.CellSeparator), borderStyle));
}
}
@@ -303,44 +302,44 @@ namespace Spectre.Console
// Show header separator?
if (firstRow && showBorder && ShowHeaders && hasRows)
{
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomLeft)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomLeft), borderStyle));
foreach (var (columnIndex, first, lastColumn, columnWidth) in columnWidths.Enumerate())
{
var padding = _columns[columnIndex].Padding;
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Left))); // Left padding
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, columnWidth)));
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Right))); // Right padding
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Left), borderStyle)); // Left padding
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, columnWidth), borderStyle));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Right), borderStyle)); // Right padding
if (!lastColumn)
{
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomSeparator)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomSeparator), borderStyle));
}
}
- result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomRight), borderStyle));
result.Add(Segment.LineBreak);
}
// Show bottom of footer?
if (lastRow && showBorder)
{
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft)));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft), borderStyle));
foreach (var (columnIndex, first, lastColumn, columnWidth) in columnWidths.Enumerate())
{
var padding = _columns[columnIndex].Padding;
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Left))); // Left padding
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, columnWidth)));
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Right))); // Right padding
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Left), borderStyle)); // Left padding
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, columnWidth), borderStyle));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Right), borderStyle)); // Right padding
if (!lastColumn)
{
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottomSeparator)));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottomSeparator), borderStyle));
}
}
- result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight)));
+ result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight), borderStyle));
result.Add(Segment.LineBreak);
}
}