/// <summary> /// Creates a <code>DrawCharacterSet</code> which uses single-lined box-drawing-characters /// </summary> /// <returns></returns> public static DrawCharacterSet GetSingleLinesSet() { var set = new DrawCharacterSet { TopLeftCorner = '\u250C', // ┌ TopRightCorner = '\u2510', // ┐ BottomLeftCorner = '\u2514', // └ BottomRightCorner = '\u2518', // ┘ VerticalEdge = '\u2502', // │ HorizontalEdge = '\u2500', // ─ ConnectionHorizontalUp = '\u2534', // ┴ ConnectionHorizontalDown = '\u252C', // ┬ ConnectionVerticalRight = '\u251C', // ├ ConnectionVerticalLeft = '\u2524', // ┤ ConnectionCross = '\u253C', // ┼ Empty = ' ' }; return set; }
/// <summary> /// Creates a <code>DrawCharacterSet</code> which uses double-lined box-drawing-characters /// </summary> /// <returns></returns> public static DrawCharacterSet GetDoubleLinesSet() { var set = new DrawCharacterSet { TopLeftCorner = '\u2554', // ╔ TopRightCorner = '\u2557', // ╗ BottomLeftCorner = '\u255A', // ╚ BottomRightCorner = '\u255D', // ╝ VerticalEdge = '\u2551', // ║ HorizontalEdge = '\u2550', // ═ ConnectionHorizontalUp = '\u2569', // ╩ ConnectionHorizontalDown = '\u2566', // ╦ ConnectionVerticalRight = '\u2560', // ╠ ConnectionVerticalLeft = '\u2563', // ╣ ConnectionCross = '\u256C', // ╬ Empty = ' ' }; return set; }
/// <summary> /// Creates a very simple <code>DrawCharacterSet</code>. /// </summary> /// <returns></returns> public static DrawCharacterSet GetSimpleSet() { var set = new DrawCharacterSet { TopLeftCorner = '.', TopRightCorner = '.', BottomLeftCorner = '`', BottomRightCorner = '´', VerticalEdge = '|', HorizontalEdge = '-', ConnectionHorizontalUp = '+', ConnectionHorizontalDown = '+', ConnectionVerticalRight = '+', ConnectionVerticalLeft = '+', ConnectionCross = '+', Empty = ' ' }; return set; }
/// <summary> /// Draws a box using the characters given in <paramref name="charSet"/>. /// The box will be filled with characters if <paramref name="fill"/> is true, /// this is a hugh performance plus if <paramref name="fColor"/> equals <paramref name="fFillColor"/> and <paramref name="bColor"/> equals <paramref name="bFillColor"/>. /// </summary> /// <param name="rect">The dimensions of the box</param> /// <param name="charSet">The characters to use to draw the box</param> /// <param name="boundary">The boundary to draw in, nothing will be drawn outside this area</param> /// <param name="fColor">The foreground color of the edges</param> /// <param name="bColor">The background color of the edges</param> /// <param name="fill">true if the box should be filled, otherwise false</param> /// <param name="fFillColor">The foreground color of the fill</param> /// <param name="bFillColor">The background color of the fill</param> public static void DrawBox(Rectangle rect, DrawCharacterSet charSet, Rectangle boundary = null, ConsoleColor fColor = ConsoleColor.Gray, ConsoleColor bColor = ConsoleColor.Black, bool fill = false, ConsoleColor fFillColor = ConsoleColor.Gray, ConsoleColor bFillColor = ConsoleColor.Black) { if(rect.Width == 0 || rect.Height == 0) return; #region Corners var topLine = charSet.TopLeftCorner + new string(charSet.HorizontalEdge, rect.Width - 2) + charSet.TopRightCorner; var bottomLine = charSet.BottomLeftCorner + new string(charSet.HorizontalEdge, rect.Width - 2) + charSet.BottomRightCorner; if(boundary != null && topLine.Length + rect.Left > boundary.Left + boundary.Width) { var charsInside = boundary.Width - (rect.Left - boundary.Left); topLine = topLine.Substring(0, charsInside); bottomLine = bottomLine.Substring(0, charsInside); } Write(rect.Left, rect.Top, topLine, null, fColor, bColor); var bottomLineTop = rect.Top + rect.Height - 1; if(boundary == null || bottomLineTop < boundary.Top + boundary.Height) Write(rect.Left, bottomLineTop, bottomLine, null, fColor, bColor); #endregion #region Left and right edge // Drawing of left and right edges is optimized to call Console.Write as few as possible. // This is only possible when the box should be filled and all fill-colors equals the edge-colors. // Fill = true // Colors same: // create a string which contains the whole line (edges and fill) => draw in one part // Colors different: // draw the line in 3 parts // TODO: draw edges with dummy chars in between + draw the actual filling afterwards (=> 2 parts instead of 3) // Fill = false // draw the line in 3 parts (existing characters which could be inside the box have to be preserved) string middleLine; if (fColor == fFillColor && bColor == bFillColor) middleLine = charSet.VerticalEdge + new string(charSet.Empty, rect.Width - 2) + charSet.VerticalEdge; else middleLine = new string(charSet.Empty, rect.Width - 2); if (boundary != null && middleLine.Length + rect.Left > boundary.Left + boundary.Width && (fColor == fFillColor && bColor == bFillColor)) { var charsInside = boundary.Width - (rect.Left - boundary.Left); middleLine = middleLine.Substring(0, charsInside); } var middleHeight = rect.Height - 1; if (boundary != null && rect.Top + middleHeight > boundary.Top + boundary.Height) { middleHeight = boundary.Height - (rect.Top - boundary.Top); } for (int i = 1; i < middleHeight; i++) { if (!fill || fColor != fFillColor || bColor == bFillColor) { Write(rect.Left, rect.Top + i, charSet.VerticalEdge, null, fColor, bColor); var left = rect.Left + rect.Width - 1; if(boundary == null || left < boundary.Left + boundary.Width) Write(left, rect.Top + i, charSet.VerticalEdge, null, fColor, bColor); } if(fill) { if (fColor == fFillColor && bColor == bFillColor) { Write(rect.Left, rect.Top + i, middleLine, null, fColor, bColor); } else { Write(rect.Left + 1, rect.Top + i, middleLine, null, fFillColor, bFillColor); } } } #endregion }