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]; } } } }