namespace InnovEnergy.Lib.Utils; public class TextBlock { private readonly IReadOnlyList _Lines; private TextBlock(params String[] lines) => _Lines = lines; public override String ToString() => _Lines.JoinLines(); public static TextBlock AlignLeft(IReadOnlyList things) { var lines = things .SelectMany(GetLines) .ToList(); var width = lines.Max(l => l.Length); var alignedLines = lines .Select(l => l.PadRight(width)) .ToArray(lines.Count); return new TextBlock(alignedLines); } private static TextBlock AlignRight(IReadOnlyList things) { var lines = things .SelectMany(GetLines) .ToList(); var width = lines.Max(l => l.Length); var alignedLines = lines .Select(l => l.PadLeft(width)) .ToArray(lines.Count); return new TextBlock(alignedLines); } public static TextBlock AlignCenterHorizontal(IReadOnlyList things) { var lines = things .SelectMany(GetLines) .ToList(); var width = lines.Max(l => l.Length); var alignedLines = lines .Select(l => l.PadLeft((width + l.Length) / 2).PadRight(width)) .ToArray(lines.Count); return new TextBlock(alignedLines); } public static TextBlock AlignTop(IReadOnlyList things) { var columns = things .Select(GetLines) .ToList(); var height = columns.Max(l => l.Count); var alignedLines = Enumerable .Range(0, height) .Select(l => columns.Select(c => c.ElementAtOr(l, Space(c[0].Length))).Join()) .ToArray(height); return new TextBlock(alignedLines); } public static TextBlock AlignBottom(IReadOnlyList things) { var columns = things .Select(GetLines) .ToList(); var height = columns.Max(l => l.Count); var alignedLines = Enumerable .Range(0, height) .Select(l => columns.Select(c => c.ElementAtOr(c.Count - height + l, Space(c[0].Length))).Join()) .ToArray(height); return new TextBlock(alignedLines); } public static TextBlock AlignCenterVertical(IReadOnlyList things) { var columns = things .Select(GetLines) .ToList(); var height = columns.Max(l => l.Count); var alignedLines = Enumerable .Range(0, height) .Select(l => columns.Select(c => c.ElementAtOr((c.Count - height) / 2 + l, Space(c[0].Length))).Join()) .ToArray(height); return new TextBlock(alignedLines); } public static TextBlock AlignLeft (params Object[] things) => AlignLeft ((IReadOnlyList) things); public static TextBlock AlignRight (params Object[] things) => AlignRight ((IReadOnlyList) things); public static TextBlock AlignTop (params Object[] things) => AlignTop ((IReadOnlyList) things); public static TextBlock AlignBottom (params Object[] things) => AlignBottom ((IReadOnlyList) things); public static TextBlock AlignCenterVertical (params Object[] things) => AlignCenterVertical ((IReadOnlyList) things); public static TextBlock AlignCenterHorizontal(params Object[] things) => AlignCenterHorizontal((IReadOnlyList) things); public static TextBlock FromString(String thing) => AlignLeft(thing); public TextBlock Box() { var width = _Lines.Max(l => l.Length); var hLine = "".PadRight(width + 2, '─'); var top = "┌" + hLine + "┐"; var bottom = "└" + hLine + "┘"; var lines = _Lines .Select(l => l.SurroundWith(" ")) .Select(l => l.SurroundWith("│")) .Prepend(top) .Append(bottom) .ToArray(_Lines.Count + 2); return new TextBlock(lines); } public TextBlock TitleBox(String title) { var linesWidth = _Lines.Max(l => l.Length); var titleWidth = title.Length; var width = Math.Max(linesWidth, titleWidth); var hLine = "".PadRight(width + 2, '─'); var top = "┌" + hLine + "┐"; var between = "├" + hLine + "┤"; var bottom = "└" + hLine + "┘"; var centeredTitle = "│ " + title.PadLeft((width + title.Length) / 2).PadRight(width) + " │"; var lines = _Lines .Select(l => l.PadRight(width)) .Select(l => l.SurroundWith(" ")) .Select(l => l.SurroundWith("│")) .Prepend(between) .Prepend(centeredTitle) .Prepend(top) .Append(bottom) .ToArray(); return new TextBlock(lines); } public static TextBlock Spacer(Int32 n) { return new TextBlock(Enumerable.Repeat("".PadRight(n), n).ToArray(n)); } public static TextBlock HorizontalSpace(Int32 n) { return new TextBlock("".PadRight(n)); } public static TextBlock VerticalSpace(Int32 n) { return new TextBlock(Enumerable.Repeat("", n).ToArray(n)); } private static IReadOnlyList GetLines(Object t) { return t is TextBlock tb ? tb._Lines : t.ToString()!.SplitLines(); } private static String Space(Int32 totalWidth) { return "".PadRight(totalWidth); } }