Compare commits

...

2 Commits

Author SHA1 Message Date
Patrik Svensson
e429f6434b Update examples 2020-10-01 14:43:08 +02:00
Patrik Svensson
93ec7401c8 Add support for markdown tables
Closes #85

* Split Border into BoxBorder and TableBorder
* Change how different table parts are composed
* Add markdown table border
2020-10-01 14:43:08 +02:00
87 changed files with 2171 additions and 1120 deletions

View File

@@ -65,9 +65,9 @@ jobs:
run: |
dotnet tool restore
dotnet example info
dotnet example table
dotnet example grid
dotnet example panel
dotnet example tables
dotnet example grids
dotnet example panels
dotnet example colors
dotnet example emojis

View File

@@ -4,16 +4,30 @@ Order: 2
There is different built-in borders you can use for tables and panels.
# Built-in borders
# Table borders
<img src="../assets/images/borders.png" style="max-width: 100%;">
<img src="../assets/images/borders/table.png" style="max-width: 100%;">
# Usage
## Example
To create a table and set it's border to `SimpleHeavy` as seen in the
image above:
To set a table border to `SimpleHeavy`:
```csharp
var table = new Table();
table.Border = Border.SimpleHeavy;
table.Border = TableBorder.SimpleHeavy;
```
---
# Panel borders
<img src="../assets/images/borders/panel.png" style="max-width: 100%;">
## Example
To set a panel border to `Rounded`:
```csharp
var panel = new Panel("Hello World");
panel.Border = BoxBorder.Rounded;
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 KiB

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Borders</Title>
<Description>Demonstrates the different kind of borders.</Description>
</PropertyGroup>

View File

@@ -1,47 +1,89 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Borders
namespace BordersExample
{
public static class Program
{
public static void Main()
{
var items = new[]
{
Create("Ascii", Border.Ascii),
Create("Ascii2", Border.Ascii2),
Create("AsciiDoubleHead", Border.AsciiDoubleHead),
Create("Horizontal", Border.Horizontal),
Create("Simple", Border.Simple),
Create("SimpleHeavy", Border.SimpleHeavy),
Create("Minimal", Border.Minimal),
Create("MinimalHeavyHead", Border.MinimalHeavyHead),
Create("MinimalDoubleHead", Border.MinimalDoubleHead),
Create("Square", Border.Square),
Create("Rounded", Border.Rounded),
Create("Heavy", Border.Heavy),
Create("HeavyEdge", Border.HeavyEdge),
Create("HeavyHead", Border.HeavyHead),
Create("Double", Border.Double),
Create("DoubleEdge", Border.DoubleEdge),
};
// Render panel borders
AnsiConsole.WriteLine();
AnsiConsole.Render(new Columns(items).Collapse());
AnsiConsole.MarkupLine("[white bold underline]PANEL BORDERS[/]");
AnsiConsole.WriteLine();
RenderPanelBorders();
// Render table borders
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[white bold underline]TABLE BORDERS[/]");
AnsiConsole.WriteLine();
RenderTableBorders();
}
private static IRenderable Create(string name, Border border)
private static void RenderPanelBorders()
{
var table = new Table().SetBorder(border);
table.AddColumns("[yellow]Header 1[/]", "[yellow]Header 2[/]");
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
static IRenderable CreatePanel(string name, BoxBorder border)
{
return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
.SetBorderStyle(Style.Parse("grey"))
.SetBorder(border);
}
return new Panel(table)
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
.SetBorderStyle(Style.Parse("grey"))
.NoBorder();
var items = new[]
{
CreatePanel("Ascii", BoxBorder.Ascii),
CreatePanel("Square", BoxBorder.Square),
CreatePanel("Rounded", BoxBorder.Rounded),
CreatePanel("Heavy", BoxBorder.Heavy),
CreatePanel("Double", BoxBorder.Double),
CreatePanel("None", BoxBorder.None),
};
AnsiConsole.Render(
new Padder(
new Columns(items).PadRight(2),
new Padding(2,0,0,0)));
}
private static void RenderTableBorders()
{
static IRenderable CreateTable(string name, TableBorder border)
{
var table = new Table().SetBorder(border);
table.AddColumn("[yellow]Header 1[/]");
table.AddColumn("[yellow]Header 2[/]", col => col.RightAligned());
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
return new Panel(table)
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
.SetBorderStyle(Style.Parse("grey"))
.NoBorder();
}
var items = new[]
{
CreateTable("Ascii", TableBorder.Ascii),
CreateTable("Ascii2", TableBorder.Ascii2),
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
CreateTable("Horizontal", TableBorder.Horizontal),
CreateTable("Simple", TableBorder.Simple),
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy),
CreateTable("Minimal", TableBorder.Minimal),
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
CreateTable("Square", TableBorder.Square),
CreateTable("Rounded", TableBorder.Rounded),
CreateTable("Heavy", TableBorder.Heavy),
CreateTable("HeavyEdge", TableBorder.HeavyEdge),
CreateTable("HeavyHead", TableBorder.HeavyHead),
CreateTable("Double", TableBorder.Double),
CreateTable("DoubleEdge", TableBorder.DoubleEdge),
CreateTable("Markdown", TableBorder.Markdown),
};
AnsiConsole.Render(new Columns(items).Collapse());
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Colors</Title>
<Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description>
</PropertyGroup>

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Columns</Title>
<Description>Demonstrates how to render data into columns.</Description>
</PropertyGroup>

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Emojis</Title>
<Description>Demonstrates how to render emojis.</Description>
</PropertyGroup>

View File

@@ -1,7 +1,6 @@
using System;
using Spectre.Console;
namespace Emojis
namespace EmojiExample
{
public static class Program
{

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Grids</Title>
<Description>Demonstrates how to render grids in a console.</Description>
</PropertyGroup>

View File

@@ -1,25 +1,25 @@
using Spectre.Console;
namespace GridExample
{
public static class Program
{
public static void Main()
{
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
AnsiConsole.WriteLine();
var grid = new Grid();
grid.AddColumn(new GridColumn { NoWrap = true });
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 });
grid.AddColumn();
grid.AddRow("Options:", "", "");
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "", "Show command line help.");
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for.");
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
AnsiConsole.Render(grid);
}
}
}
using Spectre.Console;
namespace GridExample
{
public static class Program
{
public static void Main()
{
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
AnsiConsole.WriteLine();
var grid = new Grid();
grid.AddColumn(new GridColumn { NoWrap = true });
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 });
grid.AddColumn();
grid.AddRow("Options:", "", "");
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "", "Show command line help.");
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for.");
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
AnsiConsole.Render(grid);
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Info</Title>
<Description>Displays the capabilities of the current console.</Description>
</PropertyGroup>

View File

@@ -1,6 +1,6 @@
using Spectre.Console;
namespace Info
namespace InfoExample
{
public static class Program
{
@@ -9,19 +9,20 @@ namespace Info
var grid = new Grid()
.AddColumn(new GridColumn().NoWrap().PadRight(4))
.AddColumn()
.AddRow("[b]:artist_palette: Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
.AddRow("[b]:nail_polish: Supports ansi?[/]", $"{GetEmoji(AnsiConsole.Capabilities.SupportsAnsi)}")
.AddRow("[b]:top_hat: Legacy console?[/]", $"{GetEmoji(AnsiConsole.Capabilities.LegacyConsole)}")
.AddRow("[b]:left_right_arrow: Buffer width[/]", $"{AnsiConsole.Console.Width}")
.AddRow("[b]:up_down_arrow: Buffer height[/]", $"{AnsiConsole.Console.Height}");
.AddRow("[b]Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsAnsi)}")
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Capabilities.LegacyConsole)}")
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Width}")
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Height}");
AnsiConsole.Render(
new Panel(grid)
.SetHeader("Information"));
}
private static string GetEmoji(bool value) => value
? ":thumbs_up:"
: ":thumbs_down:";
private static string YesNo(bool value)
{
return value ? "Yes" : "No";
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Links</Title>
<Description>Demonstrates how to render links in a console.</Description>
</PropertyGroup>

View File

@@ -1,6 +1,6 @@
using Spectre.Console;
namespace Links
namespace LinkExample
{
public static class Program
{

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Panels</Title>
<Description>Demonstrates how to render items in panels.</Description>
</PropertyGroup>

View File

@@ -13,7 +13,7 @@ namespace PanelExample
AnsiConsole.Render(
new Panel(
new Panel(content)
.SetBorder(Border.Rounded)));
.SetBorder(BoxBorder.Rounded)));
// Left adjusted panel with text
AnsiConsole.Render(

View File

@@ -35,7 +35,7 @@ namespace TableExample
private static void RenderBigTable()
{
// Create the table.
var table = new Table().SetBorder(Border.Rounded);
var table = new Table().SetBorder(TableBorder.Rounded);
table.AddColumn("[red underline]Foo[/]");
table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true });
@@ -57,7 +57,7 @@ namespace TableExample
private static void RenderNestedTable()
{
// Create simple table.
var simple = new Table().SetBorder(Border.Rounded).SetBorderColor(Color.Red);
var simple = new Table().SetBorder(TableBorder.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 +66,7 @@ namespace TableExample
simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
// Create other table.
var second = new Table().SetBorder(Border.Square).SetBorderColor(Color.Green);
var second = new Table().SetBorder(TableBorder.Square).SetBorderColor(Color.Green);
second.AddColumn(new TableColumn("[u]Foo[/]"));
second.AddColumn(new TableColumn("[u]Bar[/]"));
second.AddColumn(new TableColumn("[u]Baz[/]"));
@@ -74,7 +74,7 @@ namespace TableExample
second.AddRow(simple, new Text("Whaaat"), new Text("Lolz"));
second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
var table = new Table().SetBorder(Border.Rounded);
var table = new Table().SetBorder(TableBorder.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)));

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Tables</Title>
<Description>Demonstrates how to render tables in a console.</Description>
</PropertyGroup>

View File

@@ -2,6 +2,6 @@
"projects": [ "src" ],
"sdk": {
"version": "3.1.301",
"rollForward": "latestMajor"
"rollForward": "latestPatch"
}
}

View File

@@ -0,0 +1,210 @@
using Shouldly;
using Spectre.Console.Rendering;
using Xunit;
namespace Spectre.Console.Tests.Unit
{
public sealed class BoxBorderTests
{
public sealed class NoBorder
{
public sealed class TheSafeGetBorderMethod
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.None.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.None);
}
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().NoBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe(" Greeting ");
console.Lines[1].ShouldBe(" Hello World ");
console.Lines[2].ShouldBe(" ");
}
}
public sealed class AsciiBorder
{
public sealed class TheSafeGetBorderMethod
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.Ascii.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.Ascii);
}
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().AsciiBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe("+-Greeting----+");
console.Lines[1].ShouldBe("| Hello World |");
console.Lines[2].ShouldBe("+-------------+");
}
}
public sealed class DoubleBorder
{
public sealed class TheSafeGetBorderMethod
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.Double.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.Double);
}
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().DoubleBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe("╔═Greeting════╗");
console.Lines[1].ShouldBe("║ Hello World ║");
console.Lines[2].ShouldBe("╚═════════════╝");
}
}
public sealed class HeavyBorder
{
public sealed class TheSafeGetBorderMethod
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.Heavy.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.Square);
}
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().HeavyBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe("┏━Greeting━━━━┓");
console.Lines[1].ShouldBe("┃ Hello World ┃");
console.Lines[2].ShouldBe("┗━━━━━━━━━━━━━┛");
}
}
public sealed class RoundedBorder
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.Rounded.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.Square);
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().RoundedBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe("╭─Greeting────╮");
console.Lines[1].ShouldBe("│ Hello World │");
console.Lines[2].ShouldBe("╰─────────────╯");
}
}
public sealed class SquareBorder
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = BoxBorder.Square.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(BoxBorder.Square);
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var panel = Fixture.GetPanel().SquareBorder();
// When
console.Render(panel);
// Then
console.Lines.Count.ShouldBe(3);
console.Lines[0].ShouldBe("┌─Greeting────┐");
console.Lines[1].ShouldBe("│ Hello World │");
console.Lines[2].ShouldBe("└─────────────┘");
}
}
private static class Fixture
{
public static Panel GetPanel()
{
return new Panel("Hello World")
.SetHeader("Greeting");
}
}
}
}

View File

@@ -4,7 +4,7 @@ using Xunit;
namespace Spectre.Console.Tests.Unit
{
public sealed class BorderTests
public sealed class TableBorderTests
{
public sealed class NoBorder
{
@@ -12,7 +12,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.None.Visible;
var visibility = TableBorder.None.Visible;
// Then
visibility.ShouldBeFalse();
@@ -24,10 +24,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.None.GetSafeBorder(safe: true);
var border = TableBorder.None.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.None);
border.ShouldBeSameAs(TableBorder.None);
}
}
@@ -55,7 +55,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Ascii.Visible;
var visibility = TableBorder.Ascii.Visible;
// Then
visibility.ShouldBeTrue();
@@ -67,10 +67,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Ascii.GetSafeBorder(safe: true);
var border = TableBorder.Ascii.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Ascii);
border.ShouldBeSameAs(TableBorder.Ascii);
}
}
@@ -101,7 +101,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Ascii2.Visible;
var visibility = TableBorder.Ascii2.Visible;
// Then
visibility.ShouldBeTrue();
@@ -113,10 +113,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Ascii2.GetSafeBorder(safe: true);
var border = TableBorder.Ascii2.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Ascii2);
border.ShouldBeSameAs(TableBorder.Ascii2);
}
}
@@ -147,7 +147,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.AsciiDoubleHead.Visible;
var visibility = TableBorder.AsciiDoubleHead.Visible;
// Then
visibility.ShouldBeTrue();
@@ -159,10 +159,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.AsciiDoubleHead.GetSafeBorder(safe: true);
var border = TableBorder.AsciiDoubleHead.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.AsciiDoubleHead);
border.ShouldBeSameAs(TableBorder.AsciiDoubleHead);
}
}
@@ -193,7 +193,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Square.Visible;
var visibility = TableBorder.Square.Visible;
// Then
visibility.ShouldBeTrue();
@@ -205,10 +205,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Square.GetSafeBorder(safe: true);
var border = TableBorder.Square.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Square);
border.ShouldBeSameAs(TableBorder.Square);
}
}
@@ -239,7 +239,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Rounded.Visible;
var visibility = TableBorder.Rounded.Visible;
// Then
visibility.ShouldBeTrue();
@@ -251,10 +251,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Rounded.GetSafeBorder(safe: true);
var border = TableBorder.Rounded.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Square);
border.ShouldBeSameAs(TableBorder.Square);
}
}
@@ -285,7 +285,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Minimal.Visible;
var visibility = TableBorder.Minimal.Visible;
// Then
visibility.ShouldBeTrue();
@@ -297,10 +297,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Minimal.GetSafeBorder(safe: true);
var border = TableBorder.Minimal.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Minimal);
border.ShouldBeSameAs(TableBorder.Minimal);
}
}
@@ -331,7 +331,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.MinimalHeavyHead.Visible;
var visibility = TableBorder.MinimalHeavyHead.Visible;
// Then
visibility.ShouldBeTrue();
@@ -343,10 +343,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.MinimalHeavyHead.GetSafeBorder(safe: true);
var border = TableBorder.MinimalHeavyHead.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Minimal);
border.ShouldBeSameAs(TableBorder.Minimal);
}
}
@@ -377,7 +377,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.MinimalDoubleHead.Visible;
var visibility = TableBorder.MinimalDoubleHead.Visible;
// Then
visibility.ShouldBeTrue();
@@ -389,10 +389,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.MinimalDoubleHead.GetSafeBorder(safe: true);
var border = TableBorder.MinimalDoubleHead.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.MinimalDoubleHead);
border.ShouldBeSameAs(TableBorder.MinimalDoubleHead);
}
}
@@ -423,7 +423,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Simple.Visible;
var visibility = TableBorder.Simple.Visible;
// Then
visibility.ShouldBeTrue();
@@ -435,10 +435,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Simple.GetSafeBorder(safe: true);
var border = TableBorder.Simple.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Simple);
border.ShouldBeSameAs(TableBorder.Simple);
}
}
@@ -469,7 +469,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Horizontal.Visible;
var visibility = TableBorder.Horizontal.Visible;
// Then
visibility.ShouldBeTrue();
@@ -481,10 +481,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Horizontal.GetSafeBorder(safe: true);
var border = TableBorder.Horizontal.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Horizontal);
border.ShouldBeSameAs(TableBorder.Horizontal);
}
}
@@ -515,7 +515,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.SimpleHeavy.Visible;
var visibility = TableBorder.SimpleHeavy.Visible;
// Then
visibility.ShouldBeTrue();
@@ -527,10 +527,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.SimpleHeavy.GetSafeBorder(safe: true);
var border = TableBorder.SimpleHeavy.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Simple);
border.ShouldBeSameAs(TableBorder.Simple);
}
}
@@ -561,7 +561,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Heavy.Visible;
var visibility = TableBorder.Heavy.Visible;
// Then
visibility.ShouldBeTrue();
@@ -573,10 +573,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Heavy.GetSafeBorder(safe: true);
var border = TableBorder.Heavy.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Square);
border.ShouldBeSameAs(TableBorder.Square);
}
}
@@ -607,7 +607,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.HeavyEdge.Visible;
var visibility = TableBorder.HeavyEdge.Visible;
// Then
visibility.ShouldBeTrue();
@@ -619,10 +619,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.HeavyEdge.GetSafeBorder(safe: true);
var border = TableBorder.HeavyEdge.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Square);
border.ShouldBeSameAs(TableBorder.Square);
}
}
@@ -653,7 +653,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.HeavyHead.Visible;
var visibility = TableBorder.HeavyHead.Visible;
// Then
visibility.ShouldBeTrue();
@@ -665,10 +665,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.HeavyHead.GetSafeBorder(safe: true);
var border = TableBorder.HeavyHead.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Square);
border.ShouldBeSameAs(TableBorder.Square);
}
}
@@ -699,7 +699,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.Double.Visible;
var visibility = TableBorder.Double.Visible;
// Then
visibility.ShouldBeTrue();
@@ -711,10 +711,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.Double.GetSafeBorder(safe: true);
var border = TableBorder.Double.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.Double);
border.ShouldBeSameAs(TableBorder.Double);
}
}
@@ -745,7 +745,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = Border.DoubleEdge.Visible;
var visibility = TableBorder.DoubleEdge.Visible;
// Then
visibility.ShouldBeTrue();
@@ -757,10 +757,10 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border()
{
// Given, When
var border = Border.DoubleEdge.GetSafeBorder(safe: true);
var border = TableBorder.DoubleEdge.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(Border.DoubleEdge);
border.ShouldBeSameAs(TableBorder.DoubleEdge);
}
}
@@ -785,12 +785,119 @@ namespace Spectre.Console.Tests.Unit
}
}
public sealed class MarkdownBorder
{
[Fact]
public void Should_Return_Correct_Visibility()
{
// Given, When
var visibility = TableBorder.Markdown.Visible;
// Then
visibility.ShouldBeTrue();
}
public sealed class TheSafeGetBorderMethod
{
[Fact]
public void Should_Return_Safe_Border()
{
// Given, When
var border = TableBorder.Markdown.GetSafeBorder(safe: true);
// Then
border.ShouldBeSameAs(TableBorder.Markdown);
}
}
[Fact]
public void Should_Render_As_Expected()
{
// Given
var console = new PlainConsole();
var table = Fixture.GetTable().MarkdownBorder();
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | -------- |");
console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" ");
}
[Fact]
public void Should_Render_Left_Aligned_Table_Columns_As_Expected()
{
// Given
var console = new PlainConsole();
var table = Fixture.GetTable(header2: Justify.Left).MarkdownBorder();
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | :------- |");
console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" ");
}
[Fact]
public void Should_Render_Center_Aligned_Table_Columns_As_Expected()
{
// Given
var console = new PlainConsole();
var table = Fixture.GetTable(header2: Justify.Center).MarkdownBorder();
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | :------: |");
console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" ");
}
[Fact]
public void Should_Render_Right_Aligned_Table_Columns_As_Expected()
{
// Given
var console = new PlainConsole();
var table = Fixture.GetTable(header2: Justify.Right).MarkdownBorder();
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | -------: |");
console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" ");
}
}
private static class Fixture
{
public static Table GetTable()
public static Table GetTable(Justify? header1 = null, Justify? header2 = null)
{
var table = new Table();
table.AddColumns("Header 1", "Header 2");
table.AddColumn("Header 1", c => c.Alignment = header1);
table.AddColumn("Header 2", c => c.Alignment = header2);
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
return table;

View File

@@ -173,7 +173,7 @@ namespace Spectre.Console.Tests.Unit
{
// A simple table
var console = new PlainConsole(width: 80);
var table = new Table() { Border = Border.Rounded };
var table = new Table() { Border = TableBorder.Rounded };
table.AddColumn("Foo");
table.AddColumn("Bar");
table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right });
@@ -183,7 +183,7 @@ namespace Spectre.Console.Tests.Unit
// Render a table in some panels.
console.Render(new Panel(new Panel(table)
{
Border = Border.Ascii,
Border = BoxBorder.Ascii,
}));
// Then
@@ -255,7 +255,7 @@ namespace Spectre.Console.Tests.Unit
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = Border.Ascii };
var table = new Table { Border = TableBorder.Ascii };
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
@@ -278,7 +278,7 @@ namespace Spectre.Console.Tests.Unit
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = Border.Rounded };
var table = new Table { Border = TableBorder.Rounded };
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
@@ -301,7 +301,7 @@ namespace Spectre.Console.Tests.Unit
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = Border.None };
var table = new Table { Border = TableBorder.None };
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");

View File

@@ -17,11 +17,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F0575243-121F-4DEE-9F6B-246E26DC0844}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Table", "..\examples\Table\Table.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tables", "..\examples\Tables\Tables.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panel", "..\examples\Panel\Panel.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panels", "..\examples\Panels\Panels.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grid", "..\examples\Grid\Grid.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grids", "..\examples\Grids\Grids.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}"
EndProject
@@ -33,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borders", "..\examples\Bord
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents another old school ASCII border.
/// </summary>
public sealed class Ascii2Border : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "+",
BorderPart.HeaderTop => "-",
BorderPart.HeaderTopSeparator => "+",
BorderPart.HeaderTopRight => "+",
BorderPart.HeaderLeft => "|",
BorderPart.HeaderSeparator => "|",
BorderPart.HeaderRight => "|",
BorderPart.HeaderBottomLeft => "|",
BorderPart.HeaderBottom => "-",
BorderPart.HeaderBottomSeparator => "+",
BorderPart.HeaderBottomRight => "|",
BorderPart.CellLeft => "|",
BorderPart.CellSeparator => "|",
BorderPart.CellRight => "|",
BorderPart.FooterBottomLeft => "+",
BorderPart.FooterBottom => "-",
BorderPart.FooterBottomSeparator => "+",
BorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an old school ASCII border.
/// </summary>
public sealed class AsciiBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "+",
BorderPart.HeaderTop => "-",
BorderPart.HeaderTopSeparator => "-",
BorderPart.HeaderTopRight => "+",
BorderPart.HeaderLeft => "|",
BorderPart.HeaderSeparator => "|",
BorderPart.HeaderRight => "|",
BorderPart.HeaderBottomLeft => "|",
BorderPart.HeaderBottom => "-",
BorderPart.HeaderBottomSeparator => "+",
BorderPart.HeaderBottomRight => "|",
BorderPart.CellLeft => "|",
BorderPart.CellSeparator => "|",
BorderPart.CellRight => "|",
BorderPart.FooterBottomLeft => "+",
BorderPart.FooterBottom => "-",
BorderPart.FooterBottomSeparator => "-",
BorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an old school ASCII border with a double header border.
/// </summary>
public sealed class AsciiDoubleHeadBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "+",
BorderPart.HeaderTop => "-",
BorderPart.HeaderTopSeparator => "+",
BorderPart.HeaderTopRight => "+",
BorderPart.HeaderLeft => "|",
BorderPart.HeaderSeparator => "|",
BorderPart.HeaderRight => "|",
BorderPart.HeaderBottomLeft => "|",
BorderPart.HeaderBottom => "=",
BorderPart.HeaderBottomSeparator => "+",
BorderPart.HeaderBottomRight => "|",
BorderPart.CellLeft => "|",
BorderPart.CellSeparator => "|",
BorderPart.CellRight => "|",
BorderPart.FooterBottomLeft => "+",
BorderPart.FooterBottom => "-",
BorderPart.FooterBottomSeparator => "+",
BorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a double border.
/// </summary>
public sealed class DoubleBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "╔",
BorderPart.HeaderTop => "═",
BorderPart.HeaderTopSeparator => "╦",
BorderPart.HeaderTopRight => "╗",
BorderPart.HeaderLeft => "║",
BorderPart.HeaderSeparator => "║",
BorderPart.HeaderRight => "║",
BorderPart.HeaderBottomLeft => "╠",
BorderPart.HeaderBottom => "═",
BorderPart.HeaderBottomSeparator => "╬",
BorderPart.HeaderBottomRight => "╣",
BorderPart.CellLeft => "║",
BorderPart.CellSeparator => "║",
BorderPart.CellRight => "║",
BorderPart.FooterBottomLeft => "╚",
BorderPart.FooterBottom => "═",
BorderPart.FooterBottomSeparator => "╩",
BorderPart.FooterBottomRight => "╝",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a double edge.
/// </summary>
public sealed class DoubleEdgeBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "╔",
BorderPart.HeaderTop => "═",
BorderPart.HeaderTopSeparator => "╤",
BorderPart.HeaderTopRight => "╗",
BorderPart.HeaderLeft => "║",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => "║",
BorderPart.HeaderBottomLeft => "╟",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "┼",
BorderPart.HeaderBottomRight => "╢",
BorderPart.CellLeft => "║",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => "║",
BorderPart.FooterBottomLeft => "╚",
BorderPart.FooterBottom => "═",
BorderPart.FooterBottomSeparator => "╧",
BorderPart.FooterBottomRight => "╝",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a heavy border.
/// </summary>
public sealed class HeavyBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder => Border.Square;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "┏",
BorderPart.HeaderTop => "━",
BorderPart.HeaderTopSeparator => "┳",
BorderPart.HeaderTopRight => "┓",
BorderPart.HeaderLeft => "┃",
BorderPart.HeaderSeparator => "┃",
BorderPart.HeaderRight => "┃",
BorderPart.HeaderBottomLeft => "┣",
BorderPart.HeaderBottom => "━",
BorderPart.HeaderBottomSeparator => "╋",
BorderPart.HeaderBottomRight => "┫",
BorderPart.CellLeft => "┃",
BorderPart.CellSeparator => "┃",
BorderPart.CellRight => "┃",
BorderPart.FooterBottomLeft => "┗",
BorderPart.FooterBottom => "━",
BorderPart.FooterBottomSeparator => "┻",
BorderPart.FooterBottomRight => "┛",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a heavy edge.
/// </summary>
public sealed class HeavyEdgeBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder => Border.Square;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "┏",
BorderPart.HeaderTop => "━",
BorderPart.HeaderTopSeparator => "┯",
BorderPart.HeaderTopRight => "┓",
BorderPart.HeaderLeft => "┃",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => "┃",
BorderPart.HeaderBottomLeft => "┠",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "┼",
BorderPart.HeaderBottomRight => "┨",
BorderPart.CellLeft => "┃",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => "┃",
BorderPart.FooterBottomLeft => "┗",
BorderPart.FooterBottom => "━",
BorderPart.FooterBottomSeparator => "┷",
BorderPart.FooterBottomRight => "┛",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a heavy header.
/// </summary>
public sealed class HeavyHeadBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder => Border.Square;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "┏",
BorderPart.HeaderTop => "━",
BorderPart.HeaderTopSeparator => "┳",
BorderPart.HeaderTopRight => "┓",
BorderPart.HeaderLeft => "┃",
BorderPart.HeaderSeparator => "┃",
BorderPart.HeaderRight => "┃",
BorderPart.HeaderBottomLeft => "┡",
BorderPart.HeaderBottom => "━",
BorderPart.HeaderBottomSeparator => "╇",
BorderPart.HeaderBottomRight => "┩",
BorderPart.CellLeft => "│",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => "│",
BorderPart.FooterBottomLeft => "└",
BorderPart.FooterBottom => "─",
BorderPart.FooterBottomSeparator => "┴",
BorderPart.FooterBottomRight => "┘",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a horizontal border.
/// </summary>
public sealed class HorizontalBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "─",
BorderPart.HeaderTop => "─",
BorderPart.HeaderTopSeparator => "─",
BorderPart.HeaderTopRight => "─",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => " ",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => "─",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "─",
BorderPart.HeaderBottomRight => "─",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => " ",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => "─",
BorderPart.FooterBottom => "─",
BorderPart.FooterBottomSeparator => "─",
BorderPart.FooterBottomRight => "─",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border.
/// </summary>
public sealed class MinimalBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => " ",
BorderPart.HeaderTop => " ",
BorderPart.HeaderTopSeparator => " ",
BorderPart.HeaderTopRight => " ",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => " ",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "┼",
BorderPart.HeaderBottomRight => " ",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => " ",
BorderPart.FooterBottom => " ",
BorderPart.FooterBottomSeparator => " ",
BorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border with a double header border.
/// </summary>
public sealed class MinimalDoubleHeadBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => " ",
BorderPart.HeaderTop => " ",
BorderPart.HeaderTopSeparator => " ",
BorderPart.HeaderTopRight => " ",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => " ",
BorderPart.HeaderBottom => "═",
BorderPart.HeaderBottomSeparator => "╪",
BorderPart.HeaderBottomRight => " ",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => " ",
BorderPart.FooterBottom => " ",
BorderPart.FooterBottomSeparator => " ",
BorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border with a heavy header.
/// </summary>
public sealed class MinimalHeavyHeadBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder => Border.Minimal;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => " ",
BorderPart.HeaderTop => " ",
BorderPart.HeaderTopSeparator => " ",
BorderPart.HeaderTopRight => " ",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => " ",
BorderPart.HeaderBottom => "━",
BorderPart.HeaderBottomSeparator => "┿",
BorderPart.HeaderBottomRight => " ",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => " ",
BorderPart.FooterBottom => " ",
BorderPart.FooterBottomSeparator => " ",
BorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a rounded border.
/// </summary>
public sealed class RoundedBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder { get; } = Border.Square;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "╭",
BorderPart.HeaderTop => "─",
BorderPart.HeaderTopSeparator => "┬",
BorderPart.HeaderTopRight => "╮",
BorderPart.HeaderLeft => "│",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => "│",
BorderPart.HeaderBottomLeft => "├",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "┼",
BorderPart.HeaderBottomRight => "┤",
BorderPart.CellLeft => "│",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => "│",
BorderPart.FooterBottomLeft => "╰",
BorderPart.FooterBottom => "─",
BorderPart.FooterBottomSeparator => "┴",
BorderPart.FooterBottomRight => "╯",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a simple border.
/// </summary>
public sealed class SimpleBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => " ",
BorderPart.HeaderTop => " ",
BorderPart.HeaderTopSeparator => " ",
BorderPart.HeaderTopRight => " ",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => " ",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => "─",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "─",
BorderPart.HeaderBottomRight => "─",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => " ",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => " ",
BorderPart.FooterBottom => " ",
BorderPart.FooterBottomSeparator => " ",
BorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,40 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a simple border with heavy lines.
/// </summary>
public sealed class SimpleHeavyBorder : Border
{
/// <inheritdoc/>
public override Border? SafeBorder => Border.Simple;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => " ",
BorderPart.HeaderTop => " ",
BorderPart.HeaderTopSeparator => " ",
BorderPart.HeaderTopRight => " ",
BorderPart.HeaderLeft => " ",
BorderPart.HeaderSeparator => " ",
BorderPart.HeaderRight => " ",
BorderPart.HeaderBottomLeft => "━",
BorderPart.HeaderBottom => "━",
BorderPart.HeaderBottomSeparator => "━",
BorderPart.HeaderBottomRight => "━",
BorderPart.CellLeft => " ",
BorderPart.CellSeparator => " ",
BorderPart.CellRight => " ",
BorderPart.FooterBottomLeft => " ",
BorderPart.FooterBottom => " ",
BorderPart.FooterBottomSeparator => " ",
BorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a square border.
/// </summary>
public sealed class SquareBorder : Border
{
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
{
return part switch
{
BorderPart.HeaderTopLeft => "┌",
BorderPart.HeaderTop => "─",
BorderPart.HeaderTopSeparator => "┬",
BorderPart.HeaderTopRight => "┐",
BorderPart.HeaderLeft => "│",
BorderPart.HeaderSeparator => "│",
BorderPart.HeaderRight => "│",
BorderPart.HeaderBottomLeft => "├",
BorderPart.HeaderBottom => "─",
BorderPart.HeaderBottomSeparator => "┼",
BorderPart.HeaderBottomRight => "┤",
BorderPart.CellLeft => "│",
BorderPart.CellSeparator => "│",
BorderPart.CellRight => "│",
BorderPart.FooterBottomLeft => "└",
BorderPart.FooterBottom => "─",
BorderPart.FooterBottomSeparator => "┴",
BorderPart.FooterBottomRight => "┘",
_ => throw new InvalidOperationException("Unknown box part."),
};
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Diagnostics.CodeAnalysis;
using Spectre.Console.Rendering;
namespace Spectre.Console
{
/// <summary>
/// Represents a border.
/// </summary>
public abstract partial class BoxBorder
{
/// <summary>
/// Gets an invisible border.
/// </summary>
public static BoxBorder None { get; } = new NoBoxBorder();
/// <summary>
/// Gets an ASCII border.
/// </summary>
public static BoxBorder Ascii { get; } = new AsciiBoxBorder();
/// <summary>
/// Gets a double border.
/// </summary>
[SuppressMessage("Naming", "CA1720:Identifier contains type name")]
public static BoxBorder Double { get; } = new DoubleBoxBorder();
/// <summary>
/// Gets a heavy border.
/// </summary>
public static BoxBorder Heavy { get; } = new HeavyBoxBorder();
/// <summary>
/// Gets a rounded border.
/// </summary>
public static BoxBorder Rounded { get; } = new RoundedBoxBorder();
/// <summary>
/// Gets a square border.
/// </summary>
public static BoxBorder Square { get; } = new SquareBoxBorder();
}
}

View File

@@ -9,45 +9,40 @@ namespace Spectre.Console
/// <summary>
/// Represents a border.
/// </summary>
public abstract partial class Border
public abstract partial class BoxBorder
{
private readonly Dictionary<BorderPart, string> _lookup;
/// <summary>
/// Gets a value indicating whether or not the border is visible.
/// </summary>
public virtual bool Visible { get; } = true;
private readonly Dictionary<BoxBorderPart, string> _lookup;
/// <summary>
/// Gets the safe border for this border or <c>null</c> if none exist.
/// </summary>
public virtual Border? SafeBorder { get; }
public virtual BoxBorder? SafeBorder { get; }
/// <summary>
/// Initializes a new instance of the <see cref="Border"/> class.
/// Initializes a new instance of the <see cref="BoxBorder"/> class.
/// </summary>
protected Border()
protected BoxBorder()
{
_lookup = Initialize();
}
private Dictionary<BorderPart, string> Initialize()
private Dictionary<BoxBorderPart, string> Initialize()
{
var lookup = new Dictionary<BorderPart, string>();
foreach (BorderPart? part in Enum.GetValues(typeof(BorderPart)))
var lookup = new Dictionary<BoxBorderPart, string>();
foreach (BoxBorderPart? part in Enum.GetValues(typeof(BoxBorderPart)))
{
if (part == null)
{
continue;
}
var text = GetBoxPart(part.Value);
var text = GetBorderPart(part.Value);
if (text.Length > 1)
{
throw new InvalidOperationException("A box part cannot contain more than one character.");
}
lookup.Add(part.Value, GetBoxPart(part.Value));
lookup.Add(part.Value, GetBorderPart(part.Value));
}
return lookup;
@@ -59,10 +54,10 @@ namespace Spectre.Console
/// <param name="part">The part to get a string representation for.</param>
/// <param name="count">The number of repetitions.</param>
/// <returns>A string representation of the specified border part.</returns>
public string GetPart(BorderPart part, int count)
public string GetPart(BoxBorderPart part, int count)
{
// TODO: This need some optimization...
return string.Join(string.Empty, Enumerable.Repeat(GetBoxPart(part)[0], count));
return string.Join(string.Empty, Enumerable.Repeat(GetBorderPart(part)[0], count));
}
/// <summary>
@@ -70,7 +65,7 @@ namespace Spectre.Console
/// </summary>
/// <param name="part">The part to get a string representation for.</param>
/// <returns>A string representation of the specified border part.</returns>
public string GetPart(BorderPart part)
public string GetPart(BoxBorderPart part)
{
return _lookup[part].ToString(CultureInfo.InvariantCulture);
}
@@ -80,6 +75,6 @@ namespace Spectre.Console
/// </summary>
/// <param name="part">The part to get the character representation for.</param>
/// <returns>A character representation of the specified border part.</returns>
protected abstract string GetBoxPart(BorderPart part);
protected abstract string GetBorderPart(BoxBorderPart part);
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Security.Cryptography;
using Spectre.Console.Internal;
namespace Spectre.Console

View File

@@ -3,7 +3,7 @@ using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Contains extension methods for <see cref="Border"/>.
/// Contains extension methods for <see cref="TableBorder"/>.
/// </summary>
public static class BorderExtensions
{
@@ -13,7 +13,7 @@ namespace Spectre.Console.Rendering
/// <param name="border">The border to get the safe border for.</param>
/// <param name="safe">Whether or not to return the safe border.</param>
/// <returns>The safe border if one exist, otherwise the original border.</returns>
public static Border GetSafeBorder(this Border border, bool safe)
public static TableBorder GetSafeBorder(this TableBorder border, bool safe)
{
if (border is null)
{

View File

@@ -0,0 +1,31 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Contains extension methods for <see cref="BoxBorder"/>.
/// </summary>
public static class BoxExtensions
{
/// <summary>
/// Gets the safe border for a border.
/// </summary>
/// <param name="border">The border to get the safe border for.</param>
/// <param name="safe">Whether or not to return the safe border.</param>
/// <returns>The safe border if one exist, otherwise the original border.</returns>
public static BoxBorder GetSafeBorder(this BoxBorder border, bool safe)
{
if (border is null)
{
throw new ArgumentNullException(nameof(border));
}
if (safe && border.SafeBorder != null)
{
border = border.SafeBorder;
}
return border;
}
}
}

View File

@@ -7,229 +7,6 @@ namespace Spectre.Console
/// </summary>
public static class HasBorderExtensions
{
/// <summary>
/// Do not display a 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 NoBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.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 SetBorder(obj, Border.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 SetBorder(obj, Border.Ascii);
}
/// <summary>
/// Display another 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 Ascii2Border<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Ascii2);
}
/// <summary>
/// Display an ASCII border with a double header 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 AsciiDoubleHeadBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.AsciiDoubleHead);
}
/// <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 SetBorder(obj, Border.Rounded);
}
/// <summary>
/// Display a minimal 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 MinimalBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Minimal);
}
/// <summary>
/// Display a minimal border with a heavy head.
/// </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 MinimalHeavyHeadBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.MinimalHeavyHead);
}
/// <summary>
/// Display a minimal border with a double header 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 MinimalDoubleHeadBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.MinimalDoubleHead);
}
/// <summary>
/// Display a simple 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 SimpleBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Simple);
}
/// <summary>
/// Display a simple border with heavy lines.
/// </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 SimpleHeavyBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.SimpleHeavy);
}
/// <summary>
/// Display a simple 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 HorizontalBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Horizontal);
}
/// <summary>
/// Display a heavy 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 HeavyBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Heavy);
}
/// <summary>
/// Display a border with a heavy edge.
/// </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 HeavyEdgeBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.HeavyEdge);
}
/// <summary>
/// Display a border with a heavy header.
/// </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 HeavyHeadBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.HeavyHead);
}
/// <summary>
/// Display a double 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 DoubleBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.Double);
}
/// <summary>
/// Display a border with a double edge.
/// </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 DoubleEdgeBorder<T>(this T obj)
where T : class, IHasBorder
{
return SetBorder(obj, Border.DoubleEdge);
}
/// <summary>
/// Sets the border.
/// </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 to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, Border border)
where T : class, IHasBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
/// <summary>
/// Disables the safe border.
/// </summary>

View File

@@ -0,0 +1,101 @@
using System;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasBoxBorder"/>.
/// </summary>
public static class HasBoxBorderExtensions
{
/// <summary>
/// Do not display a 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 NoBorder<T>(this T obj)
where T : class, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.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, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.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, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.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, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.Rounded);
}
/// <summary>
/// Display a heavy 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 HeavyBorder<T>(this T obj)
where T : class, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.Heavy);
}
/// <summary>
/// Display a double 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 DoubleBorder<T>(this T obj)
where T : class, IHasBoxBorder
{
return SetBorder(obj, BoxBorder.Double);
}
/// <summary>
/// Sets the border.
/// </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 to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, BoxBorder border)
where T : class, IHasBoxBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
}
}

View File

@@ -0,0 +1,245 @@
using System;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasTableBorder"/>.
/// </summary>
public static class HasTableBorderExtensions
{
/// <summary>
/// Do not display a 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 NoBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.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, IHasTableBorder
{
return SetBorder(obj, TableBorder.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, IHasTableBorder
{
return SetBorder(obj, TableBorder.Ascii);
}
/// <summary>
/// Display another 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 Ascii2Border<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Ascii2);
}
/// <summary>
/// Display an ASCII border with a double header 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 AsciiDoubleHeadBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.AsciiDoubleHead);
}
/// <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, IHasTableBorder
{
return SetBorder(obj, TableBorder.Rounded);
}
/// <summary>
/// Display a minimal 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 MinimalBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Minimal);
}
/// <summary>
/// Display a minimal border with a heavy head.
/// </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 MinimalHeavyHeadBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.MinimalHeavyHead);
}
/// <summary>
/// Display a minimal border with a double header 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 MinimalDoubleHeadBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.MinimalDoubleHead);
}
/// <summary>
/// Display a simple 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 SimpleBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Simple);
}
/// <summary>
/// Display a simple border with heavy lines.
/// </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 SimpleHeavyBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.SimpleHeavy);
}
/// <summary>
/// Display a simple 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 HorizontalBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Horizontal);
}
/// <summary>
/// Display a heavy 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 HeavyBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Heavy);
}
/// <summary>
/// Display a border with a heavy edge.
/// </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 HeavyEdgeBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.HeavyEdge);
}
/// <summary>
/// Display a border with a heavy header.
/// </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 HeavyHeadBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.HeavyHead);
}
/// <summary>
/// Display a double 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 DoubleBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Double);
}
/// <summary>
/// Display a border with a double edge.
/// </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 DoubleEdgeBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.DoubleEdge);
}
/// <summary>
/// Display a markdown 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 MarkdownBorder<T>(this T obj)
where T : class, IHasTableBorder
{
return SetBorder(obj, TableBorder.Markdown);
}
/// <summary>
/// Sets the border.
/// </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 to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, TableBorder border)
where T : class, IHasTableBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
}
}

View File

@@ -13,12 +13,7 @@ namespace Spectre.Console
bool UseSafeBorder { get; set; }
/// <summary>
/// Gets or sets the border.
/// </summary>
public Border Border { get; set; }
/// <summary>
/// Gets or sets the border style.
/// Gets or sets the box style.
/// </summary>
public Style? BorderStyle { get; set; }
}

View File

@@ -0,0 +1,13 @@
namespace Spectre.Console
{
/// <summary>
/// Represents something that has a box border.
/// </summary>
public interface IHasBoxBorder : IHasBorder
{
/// <summary>
/// Gets or sets the box.
/// </summary>
public BoxBorder Border { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace Spectre.Console
{
/// <summary>
/// Represents something that has a border.
/// </summary>
public interface IHasTableBorder : IHasBorder
{
/// <summary>
/// Gets or sets the border.
/// </summary>
public TableBorder Border { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spectre.Console.Rendering;
@@ -80,27 +81,24 @@ namespace Spectre.Console.Internal
return result.ToArray();
}
// https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/
public static int GetDeterministicHashCode(this string str)
public static string Multiply(this string text, int count)
{
unchecked
if (text is null)
{
var hash1 = (5381 << 16) + 5381;
var hash2 = hash1;
for (var i = 0; i < str.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1)
{
break;
}
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
}
return hash1 + (hash2 * 1566083941);
throw new ArgumentNullException(nameof(text));
}
if (count <= 0)
{
return string.Empty;
}
if (count == 1)
{
return text;
}
return string.Concat(Enumerable.Repeat(text, count));
}
}
}

View File

@@ -0,0 +1,48 @@
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents the different parts of a box border.
/// </summary>
public enum BoxBorderPart
{
/// <summary>
/// The top left part of a box.
/// </summary>
TopLeft,
/// <summary>
/// The top part of a box.
/// </summary>
Top,
/// <summary>
/// The top right part of a box.
/// </summary>
TopRight,
/// <summary>
/// The left part of a box.
/// </summary>
Left,
/// <summary>
/// The right part of a box.
/// </summary>
Right,
/// <summary>
/// The bottom left part of a box.
/// </summary>
BottomLeft,
/// <summary>
/// The bottom part of a box.
/// </summary>
Bottom,
/// <summary>
/// The bottom right part of a box.
/// </summary>
BottomRight,
}
}

View File

@@ -0,0 +1,27 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an old school ASCII border.
/// </summary>
public sealed class AsciiBoxBorder : BoxBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return part switch
{
BoxBorderPart.TopLeft => "+",
BoxBorderPart.Top => "-",
BoxBorderPart.TopRight => "+",
BoxBorderPart.Left => "|",
BoxBorderPart.Right => "|",
BoxBorderPart.BottomLeft => "+",
BoxBorderPart.Bottom => "-",
BoxBorderPart.BottomRight => "+",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a double border.
/// </summary>
public sealed class DoubleBoxBorder : BoxBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return part switch
{
BoxBorderPart.TopLeft => "╔",
BoxBorderPart.Top => "═",
BoxBorderPart.TopRight => "╗",
BoxBorderPart.Left => "║",
BoxBorderPart.Right => "║",
BoxBorderPart.BottomLeft => "╚",
BoxBorderPart.Bottom => "═",
BoxBorderPart.BottomRight => "╝",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a heavy border.
/// </summary>
public sealed class HeavyBoxBorder : BoxBorder
{
/// <inheritdoc/>
public override BoxBorder? SafeBorder => BoxBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return part switch
{
BoxBorderPart.TopLeft => "┏",
BoxBorderPart.Top => "━",
BoxBorderPart.TopRight => "┓",
BoxBorderPart.Left => "┃",
BoxBorderPart.Right => "┃",
BoxBorderPart.BottomLeft => "┗",
BoxBorderPart.Bottom => "━",
BoxBorderPart.BottomRight => "┛",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an invisible border.
/// </summary>
public sealed class NoBoxBorder : BoxBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return " ";
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a rounded border.
/// </summary>
public sealed class RoundedBoxBorder : BoxBorder
{
/// <inheritdoc/>
public override BoxBorder? SafeBorder => BoxBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return part switch
{
BoxBorderPart.TopLeft => "╭",
BoxBorderPart.Top => "─",
BoxBorderPart.TopRight => "╮",
BoxBorderPart.Left => "│",
BoxBorderPart.Right => "│",
BoxBorderPart.BottomLeft => "╰",
BoxBorderPart.Bottom => "─",
BoxBorderPart.BottomRight => "╯",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a square border.
/// </summary>
public sealed class SquareBoxBorder : BoxBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(BoxBorderPart part)
{
return part switch
{
BoxBorderPart.TopLeft => "┌",
BoxBorderPart.Top => "─",
BoxBorderPart.TopRight => "┐",
BoxBorderPart.Left => "│",
BoxBorderPart.Right => "│",
BoxBorderPart.BottomLeft => "└",
BoxBorderPart.Bottom => "─",
BoxBorderPart.BottomRight => "┘",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -1,9 +1,9 @@
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents the different border parts.
/// Represents the different parts of a table border.
/// </summary>
public enum BorderPart
public enum TableBorderPart
{
/// <summary>
/// The top left part of a header.

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents another old school ASCII border.
/// </summary>
public sealed class Ascii2TableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "+",
TableBorderPart.HeaderTop => "-",
TableBorderPart.HeaderTopSeparator => "+",
TableBorderPart.HeaderTopRight => "+",
TableBorderPart.HeaderLeft => "|",
TableBorderPart.HeaderSeparator => "|",
TableBorderPart.HeaderRight => "|",
TableBorderPart.HeaderBottomLeft => "|",
TableBorderPart.HeaderBottom => "-",
TableBorderPart.HeaderBottomSeparator => "+",
TableBorderPart.HeaderBottomRight => "|",
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
TableBorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an old school ASCII border with a double header border.
/// </summary>
public sealed class AsciiDoubleHeadTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "+",
TableBorderPart.HeaderTop => "-",
TableBorderPart.HeaderTopSeparator => "+",
TableBorderPart.HeaderTopRight => "+",
TableBorderPart.HeaderLeft => "|",
TableBorderPart.HeaderSeparator => "|",
TableBorderPart.HeaderRight => "|",
TableBorderPart.HeaderBottomLeft => "|",
TableBorderPart.HeaderBottom => "=",
TableBorderPart.HeaderBottomSeparator => "+",
TableBorderPart.HeaderBottomRight => "|",
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
TableBorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents an old school ASCII border.
/// </summary>
public sealed class AsciiTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "+",
TableBorderPart.HeaderTop => "-",
TableBorderPart.HeaderTopSeparator => "-",
TableBorderPart.HeaderTopRight => "+",
TableBorderPart.HeaderLeft => "|",
TableBorderPart.HeaderSeparator => "|",
TableBorderPart.HeaderRight => "|",
TableBorderPart.HeaderBottomLeft => "|",
TableBorderPart.HeaderBottom => "-",
TableBorderPart.HeaderBottomSeparator => "+",
TableBorderPart.HeaderBottomRight => "|",
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "-",
TableBorderPart.FooterBottomRight => "+",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a double edge.
/// </summary>
public sealed class DoubleEdgeTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "╔",
TableBorderPart.HeaderTop => "═",
TableBorderPart.HeaderTopSeparator => "╤",
TableBorderPart.HeaderTopRight => "╗",
TableBorderPart.HeaderLeft => "║",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => "║",
TableBorderPart.HeaderBottomLeft => "╟",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "┼",
TableBorderPart.HeaderBottomRight => "╢",
TableBorderPart.CellLeft => "║",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "║",
TableBorderPart.FooterBottomLeft => "╚",
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╧",
TableBorderPart.FooterBottomRight => "╝",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a double border.
/// </summary>
public sealed class DoubleTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "╔",
TableBorderPart.HeaderTop => "═",
TableBorderPart.HeaderTopSeparator => "╦",
TableBorderPart.HeaderTopRight => "╗",
TableBorderPart.HeaderLeft => "║",
TableBorderPart.HeaderSeparator => "║",
TableBorderPart.HeaderRight => "║",
TableBorderPart.HeaderBottomLeft => "╠",
TableBorderPart.HeaderBottom => "═",
TableBorderPart.HeaderBottomSeparator => "╬",
TableBorderPart.HeaderBottomRight => "╣",
TableBorderPart.CellLeft => "║",
TableBorderPart.CellSeparator => "║",
TableBorderPart.CellRight => "║",
TableBorderPart.FooterBottomLeft => "╚",
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╩",
TableBorderPart.FooterBottomRight => "╝",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a heavy edge.
/// </summary>
public sealed class HeavyEdgeTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "┏",
TableBorderPart.HeaderTop => "━",
TableBorderPart.HeaderTopSeparator => "┯",
TableBorderPart.HeaderTopRight => "┓",
TableBorderPart.HeaderLeft => "┃",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => "┃",
TableBorderPart.HeaderBottomLeft => "┠",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "┼",
TableBorderPart.HeaderBottomRight => "┨",
TableBorderPart.CellLeft => "┃",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "┃",
TableBorderPart.FooterBottomLeft => "┗",
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┷",
TableBorderPart.FooterBottomRight => "┛",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a border with a heavy header.
/// </summary>
public sealed class HeavyHeadTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "┏",
TableBorderPart.HeaderTop => "━",
TableBorderPart.HeaderTopSeparator => "┳",
TableBorderPart.HeaderTopRight => "┓",
TableBorderPart.HeaderLeft => "┃",
TableBorderPart.HeaderSeparator => "┃",
TableBorderPart.HeaderRight => "┃",
TableBorderPart.HeaderBottomLeft => "┡",
TableBorderPart.HeaderBottom => "━",
TableBorderPart.HeaderBottomSeparator => "╇",
TableBorderPart.HeaderBottomRight => "┩",
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
TableBorderPart.FooterBottomLeft => "└",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "┘",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a heavy border.
/// </summary>
public sealed class HeavyTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "┏",
TableBorderPart.HeaderTop => "━",
TableBorderPart.HeaderTopSeparator => "┳",
TableBorderPart.HeaderTopRight => "┓",
TableBorderPart.HeaderLeft => "┃",
TableBorderPart.HeaderSeparator => "┃",
TableBorderPart.HeaderRight => "┃",
TableBorderPart.HeaderBottomLeft => "┣",
TableBorderPart.HeaderBottom => "━",
TableBorderPart.HeaderBottomSeparator => "╋",
TableBorderPart.HeaderBottomRight => "┫",
TableBorderPart.CellLeft => "┃",
TableBorderPart.CellSeparator => "┃",
TableBorderPart.CellRight => "┃",
TableBorderPart.FooterBottomLeft => "┗",
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┻",
TableBorderPart.FooterBottomRight => "┛",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a horizontal border.
/// </summary>
public sealed class HorizontalTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "─",
TableBorderPart.HeaderTop => "─",
TableBorderPart.HeaderTopSeparator => "─",
TableBorderPart.HeaderTopRight => "─",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => " ",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => "─",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "─",
TableBorderPart.HeaderBottomRight => "─",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => "─",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "─",
TableBorderPart.FooterBottomRight => "─",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Text;
using Spectre.Console.Internal;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a Markdown border.
/// </summary>
public sealed class MarkdownTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => "|",
TableBorderPart.HeaderSeparator => "|",
TableBorderPart.HeaderRight => "|",
TableBorderPart.HeaderBottomLeft => "|",
TableBorderPart.HeaderBottom => "-",
TableBorderPart.HeaderBottomSeparator => "|",
TableBorderPart.HeaderBottomRight => "|",
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
/// <inheritdoc/>
public override string GetColumnRow(TablePart part, IReadOnlyList<int> widths, IReadOnlyList<IColumn> columns)
{
if (part != TablePart.Separator)
{
return base.GetColumnRow(part, widths, columns);
}
var (left, center, separator, right) = GetTableParts(part);
var builder = new StringBuilder();
builder.Append(left);
foreach (var (columnIndex, _, lastColumn, columnWidth) in widths.Enumerate())
{
var padding = columns[columnIndex].Padding;
if (padding.Left > 0)
{
// Left padding
builder.Append(" ".Multiply(padding.Left));
}
var justification = columns[columnIndex].Alignment;
if (justification == null)
{
// No alignment
builder.Append(center.Multiply(columnWidth));
}
else if (justification.Value == Justify.Left)
{
// Left
builder.Append(':');
builder.Append(center.Multiply(columnWidth - 1));
}
else if (justification.Value == Justify.Center)
{
// Centered
builder.Append(':');
builder.Append(center.Multiply(columnWidth - 2));
builder.Append(':');
}
else if (justification.Value == Justify.Right)
{
// Right
builder.Append(center.Multiply(columnWidth - 1));
builder.Append(':');
}
// Right padding
if (padding.Right > 0)
{
builder.Append(" ".Multiply(padding.Right));
}
if (!lastColumn)
{
builder.Append(separator);
}
}
builder.Append(right);
return builder.ToString();
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border with a double header border.
/// </summary>
public sealed class MinimalDoubleHeadTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => " ",
TableBorderPart.HeaderBottom => "═",
TableBorderPart.HeaderBottomSeparator => "╪",
TableBorderPart.HeaderBottomRight => " ",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border with a heavy header.
/// </summary>
public sealed class MinimalHeavyHeadTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Minimal;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => " ",
TableBorderPart.HeaderBottom => "━",
TableBorderPart.HeaderBottomSeparator => "┿",
TableBorderPart.HeaderBottomRight => " ",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a minimal border.
/// </summary>
public sealed class MinimalTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => " ",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "┼",
TableBorderPart.HeaderBottomRight => " ",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -3,13 +3,13 @@ namespace Spectre.Console.Rendering
/// <summary>
/// Represents an invisible border.
/// </summary>
public sealed class NoBorder : Border
public sealed class NoTableBorder : TableBorder
{
/// <inheritdoc/>
public override bool Visible => false;
/// <inheritdoc/>
protected override string GetBoxPart(BorderPart part)
protected override string GetBorderPart(TableBorderPart part)
{
return " ";
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a rounded border.
/// </summary>
public sealed class RoundedTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Square;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "╭",
TableBorderPart.HeaderTop => "─",
TableBorderPart.HeaderTopSeparator => "┬",
TableBorderPart.HeaderTopRight => "╮",
TableBorderPart.HeaderLeft => "│",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => "│",
TableBorderPart.HeaderBottomLeft => "├",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "┼",
TableBorderPart.HeaderBottomRight => "┤",
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
TableBorderPart.FooterBottomLeft => "╰",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "╯",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a simple border with heavy lines.
/// </summary>
public sealed class SimpleHeavyTableBorder : TableBorder
{
/// <inheritdoc/>
public override TableBorder? SafeBorder => TableBorder.Simple;
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => " ",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => "━",
TableBorderPart.HeaderBottom => "━",
TableBorderPart.HeaderBottomSeparator => "━",
TableBorderPart.HeaderBottomRight => "━",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a simple border.
/// </summary>
public sealed class SimpleTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => " ",
TableBorderPart.HeaderTop => " ",
TableBorderPart.HeaderTopSeparator => " ",
TableBorderPart.HeaderTopRight => " ",
TableBorderPart.HeaderLeft => " ",
TableBorderPart.HeaderSeparator => " ",
TableBorderPart.HeaderRight => " ",
TableBorderPart.HeaderBottomLeft => "─",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "─",
TableBorderPart.HeaderBottomRight => "─",
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents a square border.
/// </summary>
public sealed class SquareTableBorder : TableBorder
{
/// <inheritdoc/>
protected override string GetBorderPart(TableBorderPart part)
{
return part switch
{
TableBorderPart.HeaderTopLeft => "┌",
TableBorderPart.HeaderTop => "─",
TableBorderPart.HeaderTopSeparator => "┬",
TableBorderPart.HeaderTopRight => "┐",
TableBorderPart.HeaderLeft => "│",
TableBorderPart.HeaderSeparator => "│",
TableBorderPart.HeaderRight => "│",
TableBorderPart.HeaderBottomLeft => "├",
TableBorderPart.HeaderBottom => "─",
TableBorderPart.HeaderBottomSeparator => "┼",
TableBorderPart.HeaderBottomRight => "┤",
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
TableBorderPart.FooterBottomLeft => "└",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "┘",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
}
}

View File

@@ -0,0 +1,23 @@
namespace Spectre.Console.Rendering
{
/// <summary>
/// Represents different parts of a table.
/// </summary>
public enum TablePart
{
/// <summary>
/// The top of a table.
/// </summary>
Top,
/// <summary>
/// The separator between the header and the cells.
/// </summary>
Separator,
/// <summary>
/// The bottom of a table.
/// </summary>
Bottom,
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
@@ -14,12 +14,15 @@
<Compile Update="AnsiConsole.*.cs">
<DependentUpon>AnsiConsole.cs</DependentUpon>
</Compile>
<Compile Update="Color.*.cs">
<DependentUpon>Color.cs</DependentUpon>
</Compile>
<Compile Update="Border.*.cs">
<DependentUpon>Border.cs</DependentUpon>
</Compile>
<Compile Update="BoxBorder.*.cs">
<DependentUpon>BoxBorder.cs</DependentUpon>
</Compile>
<Compile Update="Color.*.cs">
<DependentUpon>Color.cs</DependentUpon>
</Compile>
<Compile Update="Emoji.*.cs">
<DependentUpon>Emoji.cs</DependentUpon>
</Compile>
@@ -39,6 +42,12 @@
</ItemGroup>
<ItemGroup>
<Compile Update="BoxBorder.Known.cs">
<DependentUpon>BoxBorder.cs</DependentUpon>
</Compile>
<Compile Update="TableBorder.Known.cs">
<DependentUpon>TableBorder.cs</DependentUpon>
</Compile>
<Compile Update="Extensions\AnsiConsoleExtensions.Markup.cs">
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
</Compile>

View File

@@ -6,92 +6,97 @@ namespace Spectre.Console
/// <summary>
/// Represents a border.
/// </summary>
public abstract partial class Border
public abstract partial class TableBorder
{
/// <summary>
/// Gets an invisible border.
/// </summary>
public static Border None { get; } = new NoBorder();
public static TableBorder None { get; } = new NoTableBorder();
/// <summary>
/// Gets an ASCII border.
/// </summary>
public static Border Ascii { get; } = new AsciiBorder();
public static TableBorder Ascii { get; } = new AsciiTableBorder();
/// <summary>
/// Gets another ASCII border.
/// Gets an ASCII border.
/// </summary>
public static Border Ascii2 { get; } = new Ascii2Border();
public static TableBorder Ascii2 { get; } = new Ascii2TableBorder();
/// <summary>
/// Gets an ASCII border with a double header border.
/// </summary>
public static Border AsciiDoubleHead { get; } = new AsciiDoubleHeadBorder();
public static TableBorder AsciiDoubleHead { get; } = new AsciiDoubleHeadTableBorder();
/// <summary>
/// Gets a square border.
/// </summary>
public static Border Square { get; } = new SquareBorder();
public static TableBorder Square { get; } = new SquareTableBorder();
/// <summary>
/// Gets a rounded border.
/// </summary>
public static Border Rounded { get; } = new RoundedBorder();
public static TableBorder Rounded { get; } = new RoundedTableBorder();
/// <summary>
/// Gets a minimal border.
/// </summary>
public static Border Minimal { get; } = new MinimalBorder();
public static TableBorder Minimal { get; } = new MinimalTableBorder();
/// <summary>
/// Gets a minimal border with a heavy head.
/// </summary>
public static Border MinimalHeavyHead { get; } = new MinimalHeavyHeadBorder();
public static TableBorder MinimalHeavyHead { get; } = new MinimalHeavyHeadTableBorder();
/// <summary>
/// Gets a minimal border with a double header border.
/// </summary>
public static Border MinimalDoubleHead { get; } = new MinimalDoubleHeadBorder();
public static TableBorder MinimalDoubleHead { get; } = new MinimalDoubleHeadTableBorder();
/// <summary>
/// Gets a simple border.
/// </summary>
public static Border Simple { get; } = new SimpleBorder();
public static TableBorder Simple { get; } = new SimpleTableBorder();
/// <summary>
/// Gets a simple border with heavy lines.
/// </summary>
public static Border SimpleHeavy { get; } = new SimpleHeavyBorder();
public static TableBorder SimpleHeavy { get; } = new SimpleHeavyTableBorder();
/// <summary>
/// Gets a horizontal border.
/// </summary>
public static Border Horizontal { get; } = new HorizontalBorder();
public static TableBorder Horizontal { get; } = new HorizontalTableBorder();
/// <summary>
/// Gets a heavy border.
/// </summary>
public static Border Heavy { get; } = new HeavyBorder();
public static TableBorder Heavy { get; } = new HeavyTableBorder();
/// <summary>
/// Gets a border with a heavy edge.
/// </summary>
public static Border HeavyEdge { get; } = new HeavyEdgeBorder();
public static TableBorder HeavyEdge { get; } = new HeavyEdgeTableBorder();
/// <summary>
/// Gets a border with a heavy header.
/// </summary>
public static Border HeavyHead { get; } = new HeavyHeadBorder();
public static TableBorder HeavyHead { get; } = new HeavyHeadTableBorder();
/// <summary>
/// Gets a double border.
/// </summary>
[SuppressMessage("Naming", "CA1720:Identifier contains type name")]
public static Border Double { get; } = new DoubleBorder();
public static TableBorder Double { get; } = new DoubleTableBorder();
/// <summary>
/// Gets a border with a double edge.
/// </summary>
public static Border DoubleEdge { get; } = new DoubleEdgeBorder();
public static TableBorder DoubleEdge { get; } = new DoubleEdgeTableBorder();
/// <summary>
/// Gets a markdown border.
/// </summary>
public static TableBorder Markdown { get; } = new MarkdownTableBorder();
}
}

View File

@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console
{
/// <summary>
/// Represents a border.
/// </summary>
public abstract partial class TableBorder
{
private readonly Dictionary<TableBorderPart, string> _lookup;
/// <summary>
/// Gets a value indicating whether or not the border is visible.
/// </summary>
public virtual bool Visible { get; } = true;
/// <summary>
/// Gets the safe border for this border or <c>null</c> if none exist.
/// </summary>
public virtual TableBorder? SafeBorder { get; }
/// <summary>
/// Initializes a new instance of the <see cref="TableBorder"/> class.
/// </summary>
protected TableBorder()
{
_lookup = Initialize();
}
private Dictionary<TableBorderPart, string> Initialize()
{
var lookup = new Dictionary<TableBorderPart, string>();
foreach (TableBorderPart? part in Enum.GetValues(typeof(TableBorderPart)))
{
if (part == null)
{
continue;
}
var text = GetBorderPart(part.Value);
if (text.Length > 1)
{
throw new InvalidOperationException("A box part cannot contain more than one character.");
}
lookup.Add(part.Value, GetBorderPart(part.Value));
}
return lookup;
}
/// <summary>
/// Gets the string representation of a specific border part.
/// </summary>
/// <param name="part">The part to get a string representation for.</param>
/// <param name="count">The number of repetitions.</param>
/// <returns>A string representation of the specified border part.</returns>
public string GetPart(TableBorderPart part, int count)
{
// TODO: This need some optimization...
return string.Join(string.Empty, Enumerable.Repeat(GetBorderPart(part)[0], count));
}
/// <summary>
/// Gets a whole column row for the specific column row part.
/// </summary>
/// <param name="part">The column row part.</param>
/// <param name="widths">The column widths.</param>
/// <param name="columns">The columns.</param>
/// <returns>A string representing the column row.</returns>
public virtual string GetColumnRow(TablePart part, IReadOnlyList<int> widths, IReadOnlyList<IColumn> columns)
{
if (widths is null)
{
throw new ArgumentNullException(nameof(widths));
}
if (columns is null)
{
throw new ArgumentNullException(nameof(columns));
}
var (left, center, separator, right) = GetTableParts(part);
var builder = new StringBuilder();
builder.Append(left);
foreach (var (columnIndex, _, lastColumn, columnWidth) in widths.Enumerate())
{
var padding = columns[columnIndex].Padding;
var centerWidth = padding.Left + columnWidth + padding.Right;
builder.Append(center.Multiply(centerWidth));
if (!lastColumn)
{
builder.Append(separator);
}
}
builder.Append(right);
return builder.ToString();
}
/// <summary>
/// Gets the string representation of a specific border part.
/// </summary>
/// <param name="part">The part to get a string representation for.</param>
/// <returns>A string representation of the specified border part.</returns>
public string GetPart(TableBorderPart part)
{
return _lookup[part].ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets the character representing the specified border part.
/// </summary>
/// <param name="part">The part to get the character representation for.</param>
/// <returns>A character representation of the specified border part.</returns>
protected abstract string GetBorderPart(TableBorderPart part);
/// <summary>
/// Gets the table parts used to render a specific table row.
/// </summary>
/// <param name="part">The table part.</param>
/// <returns>The table parts used to render the specific table row.</returns>
protected (string Left, string Center, string Separator, string Right)
GetTableParts(TablePart part)
{
return part switch
{
// Top part
TablePart.Top =>
(GetPart(TableBorderPart.HeaderTopLeft), GetPart(TableBorderPart.HeaderTop),
GetPart(TableBorderPart.HeaderTopSeparator), GetPart(TableBorderPart.HeaderTopRight)),
// Separator between header and cells
TablePart.Separator =>
(GetPart(TableBorderPart.HeaderBottomLeft), GetPart(TableBorderPart.HeaderBottom),
GetPart(TableBorderPart.HeaderBottomSeparator), GetPart(TableBorderPart.HeaderBottomRight)),
// Bottom part
TablePart.Bottom =>
(GetPart(TableBorderPart.FooterBottomLeft), GetPart(TableBorderPart.FooterBottom),
GetPart(TableBorderPart.FooterBottomSeparator), GetPart(TableBorderPart.FooterBottomRight)),
// Unknown
_ => throw new NotSupportedException("Unknown column row part"),
};
}
}
}

View File

@@ -35,7 +35,7 @@ namespace Spectre.Console
{
_table = new Table
{
Border = Border.None,
Border = TableBorder.None,
ShowHeaders = false,
IsGrid = true,
PadRightCell = false,

View File

@@ -8,14 +8,14 @@ namespace Spectre.Console
/// <summary>
/// A renderable panel.
/// </summary>
public sealed class Panel : Renderable, IHasBorder, IExpandable, IPaddable
public sealed class Panel : Renderable, IHasBoxBorder, IExpandable, IPaddable
{
private const int EdgeWidth = 2;
private readonly IRenderable _child;
/// <inheritdoc/>
public Border Border { get; set; } = Border.Square;
public BoxBorder Border { get; set; } = BoxBorder.Square;
/// <inheritdoc/>
public bool UseSafeBorder { get; set; } = true;
@@ -95,7 +95,7 @@ namespace Spectre.Console
var childSegments = ((IRenderable)child).Render(context, childWidth);
foreach (var line in Segment.SplitLines(childSegments, panelWidth))
{
result.Add(new Segment(border.GetPart(BorderPart.CellLeft), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.Left), borderStyle));
var content = new List<Segment>();
content.AddRange(line);
@@ -110,7 +110,7 @@ namespace Spectre.Console
result.AddRange(content);
result.Add(new Segment(border.GetPart(BorderPart.CellRight), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.Right), borderStyle));
result.Add(Segment.LineBreak);
}
@@ -120,17 +120,17 @@ namespace Spectre.Console
return result;
}
private static void AddBottomBorder(List<Segment> result, Border border, Style borderStyle, int panelWidth)
private static void AddBottomBorder(List<Segment> result, BoxBorder border, Style borderStyle, int panelWidth)
{
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft), borderStyle));
result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth - EdgeWidth), borderStyle));
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomLeft), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.Bottom, panelWidth - EdgeWidth), borderStyle));
result.Add(new Segment(border.GetPart(BoxBorderPart.BottomRight), borderStyle));
result.Add(Segment.LineBreak);
}
private void AddTopBorder(List<Segment> segments, RenderContext context, Border border, Style borderStyle, int panelWidth)
private void AddTopBorder(List<Segment> segments, RenderContext context, BoxBorder border, Style borderStyle, int panelWidth)
{
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft), borderStyle));
segments.Add(new Segment(border.GetPart(BoxBorderPart.TopLeft), borderStyle));
if (Header != null)
{
@@ -160,16 +160,16 @@ namespace Spectre.Console
}
}
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTop, leftSpacing + 1), borderStyle));
segments.Add(new Segment(border.GetPart(BoxBorderPart.Top, leftSpacing + 1), borderStyle));
segments.Add(header);
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTop, rightSpacing + 1), borderStyle));
segments.Add(new Segment(border.GetPart(BoxBorderPart.Top, rightSpacing + 1), borderStyle));
}
else
{
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth - EdgeWidth), borderStyle));
segments.Add(new Segment(border.GetPart(BoxBorderPart.Top, panelWidth - EdgeWidth), borderStyle));
}
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight), borderStyle));
segments.Add(new Segment(border.GetPart(BoxBorderPart.TopRight), borderStyle));
segments.Add(Segment.LineBreak);
}
}

View File

@@ -9,7 +9,7 @@ namespace Spectre.Console
/// <summary>
/// A renderable table.
/// </summary>
public sealed class Table : Renderable, IHasBorder, IExpandable
public sealed class Table : Renderable, IHasTableBorder, IExpandable
{
private const int EdgeCount = 2;
@@ -27,7 +27,7 @@ namespace Spectre.Console
public int RowCount => _rows.Count;
/// <inheritdoc/>
public Border Border { get; set; } = Border.Square;
public TableBorder Border { get; set; } = TableBorder.Square;
/// <inheritdoc/>
public Style? BorderStyle { get; set; }
@@ -202,22 +202,8 @@ namespace Spectre.Console
// Show top of header?
if (firstRow && showBorder)
{
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), 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), borderStyle));
}
}
result.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight), borderStyle));
var separator = border.GetColumnRow(TablePart.Top, columnWidths, _columns);
result.Add(new Segment(separator, borderStyle));
result.Add(Segment.LineBreak);
}
@@ -232,7 +218,7 @@ namespace Spectre.Console
if (firstCell && showBorder)
{
// Show left column edge
var part = firstRow && ShowHeaders ? BorderPart.HeaderLeft : BorderPart.CellLeft;
var part = firstRow && ShowHeaders ? TableBorderPart.HeaderLeft : TableBorderPart.CellLeft;
result.Add(new Segment(border.GetPart(part), borderStyle));
}
@@ -269,13 +255,13 @@ namespace Spectre.Console
if (lastCell && showBorder)
{
// Add right column edge
var part = firstRow && ShowHeaders ? BorderPart.HeaderRight : BorderPart.CellRight;
var part = firstRow && ShowHeaders ? TableBorderPart.HeaderRight : TableBorderPart.CellRight;
result.Add(new Segment(border.GetPart(part), borderStyle));
}
else if (showBorder)
{
// Add column separator
var part = firstRow && ShowHeaders ? BorderPart.HeaderSeparator : BorderPart.CellSeparator;
var part = firstRow && ShowHeaders ? TableBorderPart.HeaderSeparator : TableBorderPart.CellSeparator;
result.Add(new Segment(border.GetPart(part), borderStyle));
}
}
@@ -286,44 +272,16 @@ namespace Spectre.Console
// Show header separator?
if (firstRow && showBorder && ShowHeaders && hasRows)
{
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), 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), borderStyle));
}
}
result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomRight), borderStyle));
var separator = border.GetColumnRow(TablePart.Separator, columnWidths, _columns);
result.Add(new Segment(separator, borderStyle));
result.Add(Segment.LineBreak);
}
// Show bottom of footer?
if (lastRow && showBorder)
{
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), 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), borderStyle));
}
}
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight), borderStyle));
var separator = border.GetColumnRow(TablePart.Bottom, columnWidths, _columns);
result.Add(new Segment(separator, borderStyle));
result.Add(Segment.LineBreak);
}
}