Files
Terminal.Gui/UnitTests/Drawing/LineCanvasTests.cs
BDisp ea24de3a27 Fixes #2482. Refactor Redraw - Non-virtual with the right set of virtual OnXXX methods. (#2577)
* Fixes #2482. Refactor Redraw - Non-virtual with the right set of virtual OnXXX methods.

* Change documentation comments.

* Fixes #2575 - TableView to use interface instead of System.Data.DataTable (#2576)

* WIP: Add ITableDataSource

* WIP: Refactor TableView

* WIP: Port CSVEditor

* WIP: Port TableEditor

* WIP: Port MultiColouredTable scenario

* Fix bug of adding duplicate column styles

* Update tests to use DataTableSource

* Tidy up

* Add EnumerableTableDataSource<T>

* Add test for EnumerableTableDataSource

* Add test for EnumerableTableDataSource

* Add code example to xmldoc

* Add ProcessTable scenario

* Rename ITableDataSource to ITableSource and update docs

* Rename EnumerableTableDataSource to EnumerableTableSource

* Fixed Frame != Bounds; changed UICat Scenarios list to use tableview!

* Fix scroll resetting in ProcessTable scenario

* Fix unit tests by setting Frame to same as Bounds

* Document why we have to measure our data for use with TableView

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Fixes #2582 - Refactors FileDialog for cleaner data model (#2583)

* WIP: Add ITableDataSource

* WIP: Refactor TableView

* WIP: Port CSVEditor

* WIP: Port TableEditor

* WIP: Port MultiColouredTable scenario

* Fix bug of adding duplicate column styles

* Update tests to use DataTableSource

* Tidy up

* Add EnumerableTableDataSource<T>

* Add test for EnumerableTableDataSource

* Add test for EnumerableTableDataSource

* Add code example to xmldoc

* Add ProcessTable scenario

* Rename ITableDataSource to ITableSource and update docs

* Rename EnumerableTableDataSource to EnumerableTableSource

* Fixed Frame != Bounds; changed UICat Scenarios list to use tableview!

* Fix scroll resetting in ProcessTable scenario

* Fix unit tests by setting Frame to same as Bounds

* Document why we have to measure our data for use with TableView

* WIP: Simplify FileDialogs use of TableView

* WIP start migrating sorter

* WIP new filedialog table source mostly working

* WIP remove sorter class

* Refactor GetOrderByValue to be adjacent to GetColumnValue

* Fix collection navigator back so it ignores icon

* Fix unit tests

* Tidy up

* Fix UseColors

* Add test for UseColors

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Fixes #2196. TextView: Setting Text places cursor at beginning, unlike TextField (#2572)

* Fixes #2196. TextView: Setting Text places cursor at beginning, unlike TextField

* Change all private members to have the _prefix.

* Renamed local member to prevLayoutStyle.

* Helper function for SetNeedsDisplay.

* Fixes #2569. Borders scenarios needed to be refactored. (#2570)

* Fixes #2569. Borders scenarios needed to be refactored.

* Fix border title with width equal to 4 and thickness top grater than 1.

* Improves border manipulation on borders scenarios.

* Prevents null value on the margin, border and padding thickness on the border scenarios.

* Remove NStack using dependence and fix prior commit.

* Refactoring the Frames scenario.

* Deleted borders scenarios.

* I did not realize that it was changed to SetSubViewNeedsDisplay.

* Re-layout; fixed colorpicker; fixed radio group

* Remove Thickness.IsEmpty as requested.

* Change the Frames scenario as requested.

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Builds CollectionNavigator support into UI Catalog for TableView (#2584)

* Builds collectionnav support into UI cat for TableView

* Fixes keyboard mapping

* MultiSelect = false for TableView

* MultiSelect = false doesn't unbind ctrl-a

* Fixes #2581 Refactor CollectionNavigator so it supports TableView (#2586)

* Refactor CollectionNavigator to a base and a collection implementation

* Refactor CollectionNavigatorBase to look for first match smartly

* Add TableCollectionNavigator

* Make TableCollectionNavigator a core part of TableView

* Fix bad merge

* Added tests for tableview collection navigator

* Add FileDialogCollectionNavigator which ignores . and directory separator prefixes on file names

* whitespace fixes

---------

Co-authored-by: Tig <tig@users.noreply.github.com>

* Resolving merge conflicts.

* Fix merge errors.

* Fix merge errors.

* Add Command.Accept and snap to the selected glyph when ShowHorizontalScrollIndicator change to true.

* Reformat.

* Reformat again.

---------

Co-authored-by: Thomas Nind <31306100+tznind@users.noreply.github.com>
Co-authored-by: Tig Kindel <tig@users.noreply.github.com>
2023-05-04 13:17:59 +02:00

1004 lines
33 KiB
C#

using NStack;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
using Xunit.Abstractions;
namespace Terminal.Gui.DrawingTests {
public class LineCanvasTests {
readonly ITestOutputHelper output;
public LineCanvasTests (ITestOutputHelper output)
{
this.output = output;
}
[InlineData (0, 0, 0,
0, 0, 1, 1)]
[InlineData (0, 0, 1,
0, 0, 1, 1)]
[InlineData (0, 0, 2,
0, 0, 2, 1)]
[InlineData (0, 0, 3,
0, 0, 3, 1)]
[InlineData (0, 0, -1,
0, 0, 1, 1)]
[InlineData (0, 0, -2,
-1, 0, 2, 1)]
[InlineData (0, 0, -3,
-2, 0, 3, 1)]
[Theory, SetupFakeDriver]
public void Bounds_H_Line (int x, int y, int length,
int expectedX, int expectedY, int expectedWidth, int expectedHeight)
{
var canvas = new LineCanvas ();
canvas.AddLine (new Point (x, y), length, Orientation.Horizontal, LineStyle.Single);
Assert.Equal (new Rect (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
}
[InlineData (0, 0, 0,
0, 0, 1, 1)]
[InlineData (0, 0, 1,
0, 0, 1, 1)]
[InlineData (0, 0, 2,
0, 0, 2, 2)]
[InlineData (0, 0, 3,
0, 0, 3, 3)]
[InlineData (0, 0, -1,
0, 0, 1, 1)]
[InlineData (0, 0, -2,
-1, -1, 2, 2)]
[InlineData (0, 0, -3,
-2, -2, 3, 3)]
[Theory, SetupFakeDriver]
public void Bounds_H_And_V_Lines_Both_Positive (int x, int y, int length,
int expectedX, int expectedY, int expectedWidth, int expectedHeight)
{
var canvas = new LineCanvas ();
canvas.AddLine (new Point (x, y), length, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (x, y), length, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
}
[Fact, SetupFakeDriver]
public void Canvas_Updates_On_Changes ()
{
var lc = new LineCanvas ();
Assert.Equal (Rect.Empty, lc.Bounds);
lc.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Double);
Assert.NotEqual (Rect.Empty, lc.Bounds);
lc.Clear ();
Assert.Equal (Rect.Empty, lc.Bounds);
}
[Fact, SetupFakeDriver]
public void Bounds_Specific ()
{
// Draw at 1,1 within client area of View (i.e. leave a top and left margin of 1)
// This proves we aren't drawing excess above
int x = 1;
int y = 2;
int width = 3;
int height = 2;
var lc = new LineCanvas ();
// 01230
// ╔╡╞╗1
// ║ ║2
// Add a short horiz line for ╔╡
lc.AddLine (new Point (x, y), 2, Orientation.Horizontal, LineStyle.Double);
Assert.Equal (new Rect (x, y, 2, 1), lc.Bounds);
//LHS line down
lc.AddLine (new Point (x, y), height, Orientation.Vertical, LineStyle.Double);
Assert.Equal (new Rect (x, y, 2, 2), lc.Bounds);
//Vertical line before Title, results in a ╡
lc.AddLine (new Point (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (x, y, 2, 2), lc.Bounds);
//Vertical line after Title, results in a ╞
lc.AddLine (new Point (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (x, y, 3, 2), lc.Bounds);
// remainder of top line
lc.AddLine (new Point (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
Assert.Equal (new Rect (x, y, 4, 2), lc.Bounds);
//RHS line down
lc.AddLine (new Point (x + width, y), height, Orientation.Vertical, LineStyle.Double);
Assert.Equal (new Rect (x, y, 4, 2), lc.Bounds);
TestHelpers.AssertEqual (output, @"
╔╡╞╗
║ ║",
$"{Environment.NewLine}{lc}");
}
[Fact, SetupFakeDriver]
public void Bounds_Specific_With_Ustring ()
{
// Draw at 1,1 within client area of View (i.e. leave a top and left margin of 1)
// This proves we aren't drawing excess above
int x = 1;
int y = 2;
int width = 3;
int height = 2;
var lc = new LineCanvas ();
// 01230
// ╔╡╞╗1
// ║ ║2
// Add a short horiz line for ╔╡
lc.AddLine (new Point (x, y), 2, Orientation.Horizontal, LineStyle.Double);
Assert.Equal (new Rect (x, y, 2, 1), lc.Bounds);
//LHS line down
lc.AddLine (new Point (x, y), height, Orientation.Vertical, LineStyle.Double);
Assert.Equal (new Rect (x, y, 2, 2), lc.Bounds);
//Vertical line before Title, results in a ╡
lc.AddLine (new Point (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (x, y, 2, 2), lc.Bounds);
//Vertical line after Title, results in a ╞
lc.AddLine (new Point (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (x, y, 3, 2), lc.Bounds);
// remainder of top line
lc.AddLine (new Point (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
Assert.Equal (new Rect (x, y, 4, 2), lc.Bounds);
//RHS line down
lc.AddLine (new Point (x + width, y), height, Orientation.Vertical, LineStyle.Double);
Assert.Equal (new Rect (x, y, 4, 2), lc.Bounds);
TestHelpers.AssertEqual (output, @"
╔╡╞╗
║ ║",
ustring.Make ($"{Environment.NewLine}{lc}"));
}
[Fact, SetupFakeDriver]
public void ToString_Empty ()
{
var lc = new LineCanvas ();
TestHelpers.AssertEqual (output, string.Empty, lc.ToString ());
}
// 012
[InlineData (0, 0, "═══")]
[InlineData (1, 0, "═══")]
[InlineData (0, 1, "═══")]
[InlineData (1, 1, "═══")]
[InlineData (2, 2, "═══")]
[InlineData (-1, 0, "═══")]
[InlineData (0, -1, "═══")]
[InlineData (-1, -1, "═══")]
[InlineData (-2, -2, "═══")]
[Theory, SetupFakeDriver]
public void ToString_Positive_Horizontal_1Line_Offset (int x, int y, string expected)
{
var lc = new LineCanvas ();
lc.AddLine (new Point (x, y), 3, Orientation.Horizontal, LineStyle.Double);
TestHelpers.AssertEqual (output, expected, $"{lc}");
}
[InlineData (0, 0, 0, 0, "═══")]
[InlineData (1, 0, 1, 0, "═══")]
[InlineData (-1, 0, -1, 0, "═══")]
[InlineData (0, 0, 1, 0, "════")]
[InlineData (1, 0, 3, 0, "═════")]
[InlineData (1, 0, 4, 0, "══════")]
[InlineData (1, 0, 5, 0, "═══ ═══")]
[InlineData (0, 0, 0, 1, $"═══\r\n═══")]
[InlineData (0, 0, 1, 1, "═══ \r\n ═══")]
[InlineData (0, 0, 2, 1, "═══ \r\n ═══")]
[InlineData (1, 0, 0, 1, " ═══\r\n═══ ")]
[InlineData (0, 1, 0, 1, "═══")]
[InlineData (1, 1, 0, 1, "════")]
[InlineData (2, 2, 0, 1, "═══ \r\n ═══")]
[Theory, SetupFakeDriver]
public void ToString_Positive_Horizontal_2Line_Offset (int x1, int y1, int x2, int y2, string expected)
{
var lc = new LineCanvas ();
lc.AddLine (new Point (x1, y1), 3, Orientation.Horizontal, LineStyle.Double);
lc.AddLine (new Point (x2, y2), 3, Orientation.Horizontal, LineStyle.Double);
TestHelpers.AssertEqual (output, expected, $"{lc}");
}
[InlineData (0, 0, Orientation.Horizontal, "─")]
[InlineData (1, 0, Orientation.Horizontal, "─")]
[InlineData (0, 1, Orientation.Horizontal, "─")]
[InlineData (0, 0, Orientation.Vertical, "│")]
[InlineData (1, 0, Orientation.Vertical, "│")]
[InlineData (0, 1, Orientation.Vertical, "│")]
[Theory, SetupFakeDriver]
public void Length_Zero_Alone_Is_Line (int x, int y, Orientation orientation, string expected)
{
var lc = new LineCanvas ();
// Add a line at 0, 0 that's has length of 0
lc.AddLine (new Point (0, 0), 0, orientation, LineStyle.Single);
TestHelpers.AssertEqual (output, expected, $"{lc}");
}
[InlineData (0, 0, Orientation.Horizontal, "┼")]
[InlineData (1, 0, Orientation.Horizontal, "┼")]
[InlineData (0, 1, Orientation.Horizontal, "┼")]
[InlineData (0, 0, Orientation.Vertical, "┼")]
[InlineData (1, 0, Orientation.Vertical, "┼")]
[InlineData (0, 1, Orientation.Vertical, "┼")]
[Theory, SetupFakeDriver]
public void Length_Zero_Cross_Is_Cross (int x, int y, Orientation orientation, string expected)
{
var lc = new LineCanvas ();
// Add point at opposite orientation
lc.AddLine (new Point (0, 0), 0, orientation == Orientation.Horizontal ? Orientation.Vertical : Orientation.Horizontal, LineStyle.Single);
// Add a line at 0, 0 that's has length of 0
lc.AddLine (new Point (0, 0), 0, orientation, LineStyle.Single);
TestHelpers.AssertEqual (output, expected, $"{lc}");
}
[InlineData (0, 0, Orientation.Horizontal, "╥")]
[InlineData (1, 0, Orientation.Horizontal, "╥")]
[InlineData (0, 1, Orientation.Horizontal, "╥")]
[InlineData (0, 0, Orientation.Vertical, "╞")]
[InlineData (1, 0, Orientation.Vertical, "╞")]
[InlineData (0, 1, Orientation.Vertical, "╞")]
[Theory, SetupFakeDriver]
public void Length_Zero_NextTo_Opposite_Is_T (int x, int y, Orientation orientation, string expected)
{
var lc = new LineCanvas ();
// Add line with length of 1 in opposite orientation starting at same location
if (orientation == Orientation.Horizontal) {
lc.AddLine (new Point (0, 0), 1, Orientation.Vertical, LineStyle.Double);
} else {
lc.AddLine (new Point (0, 0), 1, Orientation.Horizontal, LineStyle.Double);
}
// Add a line at 0, 0 that's has length of 0
lc.AddLine (new Point (0, 0), 0, orientation, LineStyle.Single);
TestHelpers.AssertEqual (output, expected, $"{lc}");
}
[InlineData (0, 0, Orientation.Horizontal, "─")]
[InlineData (1, 0, Orientation.Horizontal, "─")]
[InlineData (0, 1, Orientation.Horizontal, "─")]
[InlineData (-1, 0, Orientation.Horizontal, "─")]
[InlineData (0, -1, Orientation.Horizontal, "─")]
[InlineData (-1, -1, Orientation.Horizontal, "─")]
[InlineData (0, 0, Orientation.Vertical, "│")]
[InlineData (1, 0, Orientation.Vertical, "│")]
[InlineData (0, 1, Orientation.Vertical, "│")]
[InlineData (0, -1, Orientation.Vertical, "│")]
[InlineData (-1, 0, Orientation.Vertical, "│")]
[InlineData (-1, -1, Orientation.Vertical, "│")]
[Theory, SetupFakeDriver]
public void Length_0_Is_1_Long (int x, int y, Orientation orientation, string expected)
{
var canvas = new LineCanvas ();
// Add a line at 5, 5 that's has length of 1
canvas.AddLine (new Point (x, y), 1, orientation, LineStyle.Single);
TestHelpers.AssertEqual (output, $"{expected}", $"{canvas}");
}
// X is offset by 2
[InlineData (0, 0, 1, Orientation.Horizontal, "─")]
[InlineData (1, 0, 1, Orientation.Horizontal, "─")]
[InlineData (0, 1, 1, Orientation.Horizontal, "─")]
[InlineData (0, 0, 1, Orientation.Vertical, "│")]
[InlineData (1, 0, 1, Orientation.Vertical, "│")]
[InlineData (0, 1, 1, Orientation.Vertical, "│")]
[InlineData (-1, 0, 1, Orientation.Horizontal, "─")]
[InlineData (0, -1, 1, Orientation.Horizontal, "─")]
[InlineData (-1, 0, 1, Orientation.Vertical, "│")]
[InlineData (0, -1, 1, Orientation.Vertical, "│")]
[InlineData (0, 0, -1, Orientation.Horizontal, "─")]
[InlineData (1, 0, -1, Orientation.Horizontal, "─")]
[InlineData (0, 1, -1, Orientation.Horizontal, "─")]
[InlineData (0, 0, -1, Orientation.Vertical, "│")]
[InlineData (1, 0, -1, Orientation.Vertical, "│")]
[InlineData (0, 1, -1, Orientation.Vertical, "│")]
[InlineData (-1, 0, -1, Orientation.Horizontal, "─")]
[InlineData (0, -1, -1, Orientation.Horizontal, "─")]
[InlineData (-1, 0, -1, Orientation.Vertical, "│")]
[InlineData (0, -1, -1, Orientation.Vertical, "│")]
[InlineData (0, 0, 2, Orientation.Horizontal, "──")]
[InlineData (1, 0, 2, Orientation.Horizontal, "──")]
[InlineData (0, 1, 2, Orientation.Horizontal, "──")]
[InlineData (1, 1, 2, Orientation.Horizontal, "──")]
[InlineData (0, 0, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (1, 0, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (0, 1, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (1, 1, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (-1, 0, 2, Orientation.Horizontal, "──")]
[InlineData (0, -1, 2, Orientation.Horizontal, "──")]
[InlineData (-1, 0, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (0, -1, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (-1, -1, 2, Orientation.Vertical, "│\r\n│")]
[InlineData (0, 0, -2, Orientation.Horizontal, "──")]
[InlineData (1, 0, -2, Orientation.Horizontal, "──")]
[InlineData (0, 1, -2, Orientation.Horizontal, "──")]
[InlineData (0, 0, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (1, 0, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (0, 1, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (1, 1, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (-1, 0, -2, Orientation.Horizontal, "──")]
[InlineData (0, -1, -2, Orientation.Horizontal, "──")]
[InlineData (-1, 0, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (0, -1, -2, Orientation.Vertical, "│\r\n│")]
[InlineData (-1, -1, -2, Orientation.Vertical, "│\r\n│")]
[Theory, SetupFakeDriver]
public void Length_n_Is_n_Long (int x, int y, int length, Orientation orientation, string expected)
{
var canvas = new LineCanvas ();
canvas.AddLine (new Point (x, y), length, orientation, LineStyle.Single);
var result = canvas.ToString ();
TestHelpers.AssertEqual (output, expected, result);
}
[Fact, SetupFakeDriver]
public void Length_Negative ()
{
var offset = new Point (5, 5);
var canvas = new LineCanvas ();
canvas.AddLine (offset, -3, Orientation.Horizontal, LineStyle.Single);
string looksLike = "───";
Assert.Equal (looksLike, $"{canvas}");
}
[Fact, SetupFakeDriver]
public void Zero_Length_Intersections ()
{
// Draw at 1,2 within client area of View (i.e. leave a top and left margin of 1)
// This proves we aren't drawing excess above
int x = 1;
int y = 2;
int width = 5;
int height = 2;
var lc = new LineCanvas ();
// ╔╡╞═════╗
// Add a short horiz line for ╔╡
lc.AddLine (new Point (x, y), 2, Orientation.Horizontal, LineStyle.Double);
//LHS line down
lc.AddLine (new Point (x, y), height, Orientation.Vertical, LineStyle.Double);
//Vertical line before Title, results in a ╡
lc.AddLine (new Point (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
//Vertical line after Title, results in a ╞
lc.AddLine (new Point (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
// remainder of top line
lc.AddLine (new Point (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
//RHS line down
lc.AddLine (new Point (x + width, y), height, Orientation.Vertical, LineStyle.Double);
string looksLike = @"
╔╡╞══╗
║ ║";
TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{lc}");
}
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
[Theory, AutoInitShutdown]
public void View_Draws_Horizontal (LineStyle style)
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, style);
v.Draw ();
string looksLike =
@"
──";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, AutoInitShutdown]
public void View_Draws_Horizontal_Double ()
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Double);
v.Draw ();
string looksLike =
@"
══";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
[Theory, AutoInitShutdown]
public void View_Draws_Vertical (LineStyle style)
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Vertical, style);
v.Draw ();
string looksLike =
@"
│";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, AutoInitShutdown]
public void View_Draws_Vertical_Double ()
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Vertical, LineStyle.Double);
v.Draw ();
string looksLike =
@"
║";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
/// <summary>
/// This test demonstrates that corners are only drawn when lines overlap.
/// Not when they terminate adjacent to one another.
/// </summary>
[Fact, AutoInitShutdown]
public void View_Draws_Corner_NoOverlap ()
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (0, 1), 2, Orientation.Vertical, LineStyle.Single);
v.Draw ();
string looksLike =
@"
──
│";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
/// <summary>
/// This test demonstrates how to correctly trigger a corner. By
/// overlapping the lines in the same cell
/// </summary>
[Fact, AutoInitShutdown]
public void View_Draws_Corner_Correct ()
{
var v = GetCanvas (out var canvas);
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (0, 0), 2, Orientation.Vertical, LineStyle.Single);
v.Draw ();
string looksLike =
@"
┌─
│";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, SetupFakeDriver]
public void Top_With_1Down ()
{
var canvas = new LineCanvas ();
// Top ─
canvas.AddLine (new Point (0, 0), 1, Orientation.Horizontal, LineStyle.Single);
// Bottom ─
canvas.AddLine (new Point (1, 1), -1, Orientation.Horizontal, LineStyle.Single);
//// Right down
//canvas.AddLine (new Point (9, 0), 3, Orientation.Vertical, LineStyle.Single);
//// Bottom
//canvas.AddLine (new Point (9, 3), -10, Orientation.Horizontal, LineStyle.Single);
//// Left Up
//canvas.AddLine (new Point (0, 3), -3, Orientation.Vertical, LineStyle.Single);
Assert.Equal (new Rect (0, 0, 2, 2), canvas.Bounds);
var map = canvas.GetMap ();
Assert.Equal (2, map.Count);
TestHelpers.AssertEqual (output, @"
─",
$"{Environment.NewLine}{canvas}");
}
[Fact, SetupFakeDriver]
public void Window ()
{
var canvas = new LineCanvas ();
// Frame
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Single);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Single);
// Cross
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Single);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Single);
string looksLike =
@"
┌────┬───┐
│ │ │
├────┼───┤
│ │ │
└────┴───┘";
TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
}
/// <summary>
/// Demonstrates when <see cref="LineStyle.Rounded"/> corners are used. Notice how
/// not all lines declare rounded. If there are 1+ lines intersecting and a corner is
/// to be used then if any of them are rounded a rounded corner is used.
/// </summary>
[Fact, AutoInitShutdown]
public void View_Draws_Window_Rounded ()
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Rounded);
// LineStyle.Single is ignored because corner overlaps with the above line which is Rounded
// this results in a rounded corner being used.
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Single);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Rounded);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Single);
// These lines say rounded but they will result in the T sections which are never rounded.
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Rounded);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Rounded);
v.Draw ();
string looksLike =
@"
╭────┬───╮
│ │ │
├────┼───┤
│ │ │
╰────┴───╯";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, AutoInitShutdown]
public void View_Draws_Window_Double ()
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Double);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Double);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Double);
v.Draw ();
string looksLike =
@"
╔════╦═══╗
║ ║ ║
╠════╬═══╣
║ ║ ║
╚════╩═══╝";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Theory, AutoInitShutdown]
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
public void View_Draws_Window_DoubleTop_SingleSides (LineStyle thinStyle)
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Double);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Double);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Double);
v.Draw ();
string looksLike =
@"
╒════╤═══╕
│ │ │
╞════╪═══╡
│ │ │
╘════╧═══╛
";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Theory, AutoInitShutdown]
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
public void View_Draws_Window_SingleTop_DoubleSides (LineStyle thinStyle)
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, thinStyle);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, thinStyle);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Double);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, thinStyle);
v.Draw ();
string looksLike =
@"
╓────╥───╖
║ ║ ║
╟────╫───╢
║ ║ ║
╙────╨───╜
";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, AutoInitShutdown]
public void TestLineCanvas_Window_Heavy ()
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Heavy);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Heavy);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Heavy);
v.Draw ();
string looksLike =
@"
┏━━━━┳━━━┓
┃ ┃ ┃
┣━━━━╋━━━┫
┃ ┃ ┃
┗━━━━┻━━━┛";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Theory, AutoInitShutdown]
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
public void TestLineCanvas_Window_HeavyTop_ThinSides (LineStyle thinStyle)
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, LineStyle.Heavy);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, LineStyle.Heavy);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, thinStyle);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, LineStyle.Heavy);
v.Draw ();
string looksLike =
@"
┍━━━━┯━━━┑
│ │ │
┝━━━━┿━━━┥
│ │ │
┕━━━━┷━━━┙
";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Theory, AutoInitShutdown]
[InlineData (LineStyle.Single)]
[InlineData (LineStyle.Rounded)]
public void TestLineCanvas_Window_ThinTop_HeavySides (LineStyle thinStyle)
{
var v = GetCanvas (out var canvas);
// outer box
canvas.AddLine (new Point (0, 0), 10, Orientation.Horizontal, thinStyle);
canvas.AddLine (new Point (9, 0), 5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (9, 4), -10, Orientation.Horizontal, thinStyle);
canvas.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (5, 0), 5, Orientation.Vertical, LineStyle.Heavy);
canvas.AddLine (new Point (0, 2), 10, Orientation.Horizontal, thinStyle);
v.Draw ();
string looksLike =
@"
┎────┰───┒
┃ ┃ ┃
┠────╂───┨
┃ ┃ ┃
┖────┸───┚
";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
[Fact, AutoInitShutdown]
public void TestLineCanvas_LeaveMargin_Top1_Left1 ()
{
var canvas = new LineCanvas ();
// Upper box
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (0, 0), 2, Orientation.Vertical, LineStyle.Single);
string looksLike =
@"
┌─
│ ";
TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
}
[Fact, SetupFakeDriver]
public void Top_Left_From_TopRight_LeftUp ()
{
var canvas = new LineCanvas ();
// Upper box
canvas.AddLine (new Point (0, 0), 2, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new Point (0, 1), -2, Orientation.Vertical, LineStyle.Single);
string looksLike =
@"
┌─
│ ";
TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
}
// [Fact, SetupFakeDriver]
// public void LeaveMargin_Top1_Left1 ()
// {
// var canvas = new LineCanvas ();
// // Upper box
// canvas.AddLine (new Point (0, 0), 9, Orientation.Horizontal, LineStyle.Single);
// canvas.AddLine (new Point (8, 0), 3, Orientation.Vertical, LineStyle.Single);
// canvas.AddLine (new Point (8, 3), -9, Orientation.Horizontal, LineStyle.Single);
// canvas.AddLine (new Point (0, 2), -3, Orientation.Vertical, LineStyle.Single);
// // Lower Box
// canvas.AddLine (new Point (5, 0), 2, Orientation.Vertical, LineStyle.Single);
// canvas.AddLine (new Point (0, 2), 9, Orientation.Horizontal, LineStyle.Single);
// string looksLike =
//@"
//┌────┬──┐
//│ │ │
//├────┼──┤
//└────┴──┘
//";
// Assert.Equal (looksLike, $"{Environment.NewLine}{canvas}");
// }
[InlineData (0, 0, 0, Orientation.Horizontal, LineStyle.Double, "═")]
[InlineData (0, 0, 0, Orientation.Vertical, LineStyle.Double, "║")]
[InlineData (0, 0, 0, Orientation.Horizontal, LineStyle.Single, "─")]
[InlineData (0, 0, 0, Orientation.Vertical, LineStyle.Single, "│")]
[InlineData (0, 0, 1, Orientation.Horizontal, LineStyle.Double, "═")]
[InlineData (0, 0, 1, Orientation.Vertical, LineStyle.Double, "║")]
[InlineData (0, 0, 1, Orientation.Horizontal, LineStyle.Single, "─")]
[InlineData (0, 0, 1, Orientation.Vertical, LineStyle.Single, "│")]
[InlineData (0, 0, 2, Orientation.Horizontal, LineStyle.Double, "══")]
[InlineData (0, 0, 2, Orientation.Vertical, LineStyle.Double, "║\n║")]
[InlineData (0, 0, 2, Orientation.Horizontal, LineStyle.Single, "──")]
[InlineData (0, 0, 2, Orientation.Vertical, LineStyle.Single, "│\n│")]
[AutoInitShutdown, Theory]
public void View_Draws_1LineTests (
int x1, int y1, int length, Orientation o1, LineStyle s1,
string expected
)
{
var v = GetCanvas (out var lc);
v.Width = 10;
v.Height = 10;
v.Bounds = new Rect (0, 0, 10, 10);
lc.AddLine (new Point (x1, y1), length, o1, s1);
v.Draw ();
TestHelpers.AssertDriverContentsAre (expected, output);
}
[Theory, AutoInitShutdown]
// Horizontal lines with a vertical zero-length
[InlineData (
0, 0, 1, Orientation.Horizontal, LineStyle.Double,
0, 0, 0, Orientation.Vertical, LineStyle.Single, "╞"
)]
[InlineData (
0, 0, -1, Orientation.Horizontal, LineStyle.Double,
0, 0, 0, Orientation.Vertical, LineStyle.Single, "╡"
)]
[InlineData (
0, 0, 1, Orientation.Horizontal, LineStyle.Single,
0, 0, 0, Orientation.Vertical, LineStyle.Double, "╟"
)]
[InlineData (
0, 0, -1, Orientation.Horizontal, LineStyle.Single,
0, 0, 0, Orientation.Vertical, LineStyle.Double, "╢"
)]
[InlineData (
0, 0, 1, Orientation.Horizontal, LineStyle.Single,
0, 0, 0, Orientation.Vertical, LineStyle.Single, "├"
)]
[InlineData (
0, 0, -1, Orientation.Horizontal, LineStyle.Single,
0, 0, 0, Orientation.Vertical, LineStyle.Single, "┤"
)]
[InlineData (
0, 0, 1, Orientation.Horizontal, LineStyle.Double,
0, 0, 0, Orientation.Vertical, LineStyle.Double, "╠"
)]
[InlineData (
0, 0, -1, Orientation.Horizontal, LineStyle.Double,
0, 0, 0, Orientation.Vertical, LineStyle.Double, "╣"
)]
// Vertical lines with a horizontal zero-length
[InlineData (
0, 0, 1, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "╥"
)]
[InlineData (
0, 0, -1, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "╨"
)]
[InlineData (
0, 0, 1, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╤"
)]
[InlineData (
0, 0, -1, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╧"
)]
[InlineData (
0, 0, 1, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "┬"
)]
[InlineData (
0, 0, -1, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "┴"
)]
[InlineData (
0, 0, 1, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╦"
)]
[InlineData (
0, 0, -1, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╩"
)]
// Crosses (two zero-length)
[InlineData (
0, 0, 0, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "╫"
)]
[InlineData (
0, 0, 0, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╪"
)]
[InlineData (
0, 0, 0, Orientation.Vertical, LineStyle.Single,
0, 0, 0, Orientation.Horizontal, LineStyle.Single, "┼"
)]
[InlineData (
0, 0, 0, Orientation.Vertical, LineStyle.Double,
0, 0, 0, Orientation.Horizontal, LineStyle.Double, "╬"
)]
public void Add_2_Lines (
int x1, int y1, int len1, Orientation o1, LineStyle s1,
int x2, int y2, int len2, Orientation o2, LineStyle s2,
string expected
)
{
var v = GetCanvas (out var lc);
v.Width = 10;
v.Height = 10;
v.Bounds = new Rect (0, 0, 10, 10);
lc.AddLine (new Point (x1, y1), len1, o1, s1);
lc.AddLine (new Point (x2, y2), len2, o2, s2);
TestHelpers.AssertEqual (output, expected, lc.ToString ());
}
// TODO: Remove this and make all LineCanvas tests independent of View
/// <summary>
/// Creates a new <see cref="View"/> into which a <see cref="LineCanvas"/> is rendered
/// at <see cref="View.DrawContentComplete"/> time.
/// </summary>
/// <param name="canvas">The <see cref="LineCanvas"/> you can draw into.</param>
/// <param name="offsetX">How far to offset drawing in X</param>
/// <param name="offsetY">How far to offset drawing in Y</param>
/// <returns></returns>
private View GetCanvas (out LineCanvas canvas, int offsetX = 0, int offsetY = 0)
{
var v = new View {
Width = 10,
Height = 5,
Bounds = new Rect (0, 0, 10, 5)
};
Application.Top.Add (v);
Application.Begin (Application.Top);
var canvasCopy = canvas = new LineCanvas ();
v.DrawContentComplete += (s, e) => {
v.Clear ();
foreach (var p in canvasCopy.GetMap ()) {
v.AddRune (
offsetX + p.Key.X,
offsetY + p.Key.Y,
p.Value);
}
canvasCopy.Clear ();
};
return v;
}
}
}