namespace DataTablePrettyPrinter
{
using System;
///
/// An extension class providing utility methods for pretty printing to a string.
///
internal static class CharExtensions
{
///
/// Draws a border on a canvas given a bounding box specified by coordinates.
///
///
///
/// The canvas to draw on which is assumed to be large enough.
///
///
///
/// The x coordinate of the beginning of the bounding box to draw.
///
///
///
/// The y coordinate of the beginning of the bounding box to draw.
///
///
///
/// The x coordinate of the end of the bounding box to draw.
///
///
///
/// The y coordinate of the end of the bounding box to draw.
///
///
///
/// The border flags which dictate which border to draw.
///
internal static void DrawBorder(this char[,] canvas, int x1, int y1, int x2, int y2, Border border)
{
if (border.HasFlag(Border.Top))
{
canvas.DrawLine(x1, y1, x2, y1);
}
if (border.HasFlag(Border.Bottom))
{
canvas.DrawLine(x1, y2, x2, y2);
}
if (border.HasFlag(Border.Left))
{
canvas.DrawLine(x1, y1, x1, y2);
}
if (border.HasFlag(Border.Right))
{
canvas.DrawLine(x2, y1, x2, y2);
}
}
///
/// Draws a line on a canvas given a beginning and an end coordinate.
///
///
///
/// The canvas to draw on which is assumed to be large enough.
///
///
///
/// The x coordinate of the beginning of the line to draw.
///
///
///
/// The y coordinate of the beginning of the line to draw.
///
///
///
/// The x coordinate of the end of the line to draw.
///
///
///
/// The y coordinate of the end of the line to draw.
///
///
///
/// If this line crosses any other line drawn on the canvas then a '+' is inserted on the crossing boundary.
///
///
///
/// Thrown when the line is neither horizontal nor vertical.
///
internal static void DrawLine(this char[,] canvas, int x1, int y1, int x2, int y2)
{
if (x1 != x2 && y1 != y2)
{
throw new ArgumentException("Cannot draw non-horizontal or non-vertical lines");
}
if (x1 == x2)
{
if (y1 > y2)
{
Utilities.Swap(ref y1, ref y2);
}
for (var y = y1; y <= y2; ++y)
{
canvas[y, x1] = (y == y1 || y == y2 || canvas[y, x1] == '─' || canvas[y, x1] == '+') ? '+' : '|';
}
}
else
{
if (x1 > x2)
{
Utilities.Swap(ref x1, ref x2);
}
for (var x = x1; x <= x2; ++x)
{
canvas[y1, x] = (x == x1 || x == x2 || canvas[y1, x] == '|' || canvas[y1, x] == '+') ? ' ' : '─';
}
}
}
///
/// Draws a string on a canvas with alignment specified.
///
///
///
/// The canvas to draw on which is assumed to be large enough.
///
///
///
/// The x coordinate of the beginning of the string to draw.
///
///
///
/// The y coordinate of the beginning of the string to draw.
///
///
///
/// The x coordinate of the end of the string to draw.
///
///
///
/// The y coordinate of the end of the string to draw.
///
///
///
/// The text to draw.
///
///
///
/// The alignment of the to draw.
///
///
///
/// If the text cannot be contained within the bounding box specified by the coordinates then either nothing is
/// drawn or the input string is truncated and '..' is added to the end.
///
internal static void DrawText(this char[,] canvas, int x1, int y1, int x2, int y2, string text, TextAlignment alignment)
{
// Truncate the text if it will not fit in the text box bounds
if (text.Length > x2 - x1 + 1)
{
if (x2 - x1 >= 1)
{
text = text.Substring(0, x2 - x1 - 1) + "..";
}
else
{
return;
}
}
// Update the coordinates based the text alignment
switch (alignment)
{
case TextAlignment.Center:
{
y1 = (y2 + y1) / 2;
x1 += (x2 - x1 + 1 - text.Length) / 2;
break;
}
case TextAlignment.Left:
{
y1 = (y2 + y1) / 2;
break;
}
case TextAlignment.Right:
{
y1 = (y2 + y1) / 2;
x1 = x2 - text.Length + 1;
break;
}
default:
{
throw new InvalidOperationException("Unreachable case reached");
}
}
for (var x = x1; x < x1 + text.Length; ++x)
{
canvas[y1, x] = text[x - x1];
}
}
}
}