/// <summary> /// Writes a collection of item for selecting. /// </summary> /// <typeparam name="T">The type of data.</typeparam> /// <param name="cli">The command line interface proxy.</param> /// <param name="collection">The collection data.</param> /// <param name="options">The selection display options.</param> /// <param name="select">The index of item selected.</param> /// <returns>The result of selection.</returns> private static SelectionResult <T> Select <T>(StyleConsole cli, SelectionData <T> collection, SelectionConsoleOptions options, int select) { var temp = (0, 0, 0, 0, false, false, 0, 0); var oldSelect = select; while (true) { var list = collection.ToList(); void resetSelect() { if (oldSelect < 0 || oldSelect >= list.Count) { return; } var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); var oldItem = list[oldSelect]; var y2 = Math.DivRem(oldSelect % temp.Item7, temp.Item4, out var x2) - h; x2 *= temp.Item8; cli.MoveCursorBy(x2, y2); RenderData(cli, oldItem, options, false, temp.Item8); cli.MoveCursorBy(-x2 - temp.Item8, -y2); }; if (temp.Item3 > 0 && select >= temp.Item1 && select < (temp.Item1 + temp.Item2)) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); if (oldSelect != select) { resetSelect(); } if (select < 0 || select >= list.Count) { select = 0; } var item = list[select]; var y = Math.DivRem(select % temp.Item7, temp.Item4, out var x) - h; x *= temp.Item8; cli.MoveCursorBy(x, y); RenderData(cli, item, options, true, temp.Item8); cli.MoveCursorBy(-x - temp.Item8, -y); RenderSelectResult(cli, item?.Title, options); } else { if (temp.Item3 > 0) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); for (var i = 0; i < h; i++) { cli.MoveCursorBy(0, -1); cli.Clear(StyleConsole.RelativeAreas.Line); } } temp = RenderData(cli, list, options, select); } oldSelect = select; ConsoleKeyInfo key; try { key = cli.ReadKey(); } catch (InvalidOperationException) { return(SelectByManualTyping(cli, collection, options)); } catch (IOException) { return(SelectByManualTyping(cli, collection, options)); } catch (SecurityException) { return(SelectByManualTyping(cli, collection, options)); } catch (NotSupportedException) { return(SelectByManualTyping(cli, collection, options)); } switch (key.Key) { case ConsoleKey.Enter: case ConsoleKey.Select: case ConsoleKey.Spacebar: if (select < 0 || select >= list.Count) { select = temp.Item1; if (select < 0 || select >= list.Count) { select = 0; } break; } var sel = list[select]; RenderSelectResult(cli, sel?.Title, options); cli.WriteLine(); return(new SelectionResult <T>(sel.Title, select, sel.Data, sel.Title)); case ConsoleKey.Backspace: case ConsoleKey.Delete: case ConsoleKey.Clear: cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); return(SelectByManualTyping(cli, collection, options)); case ConsoleKey.Escape: case ConsoleKey.Pause: cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, null, options); cli.WriteLine(); return(new SelectionResult <T>(string.Empty, SelectionResultTypes.Canceled)); case ConsoleKey.Help: case ConsoleKey.F1: { cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, "?", options); cli.WriteLine(); var item = collection.Get('?', out select); return(item == null ? new SelectionResult <T>("?", SelectionResultTypes.Selected) : new SelectionResult <T>("?", select, item.Data, item.Title)); } case ConsoleKey.F4: if (temp.Item3 > 0) { cli.BackspaceToBeginning(); var h = temp.Item3 + (temp.Item5 ? 2 : 1) + (temp.Item6 ? 1 : 0); for (var i = 0; i < h; i++) { cli.MoveCursorBy(0, -1); cli.Clear(StyleConsole.RelativeAreas.Line); } } return(SelectByManualTyping(cli, collection, options, true)); case ConsoleKey.F5: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } break; case ConsoleKey.F6: cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, null, options); cli.WriteLine(); if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } temp = RenderData(cli, list, options, select); break; case ConsoleKey.F12: { cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, "?", options); cli.WriteLine(); var item = collection.Get('?', out select); return(item == null ? new SelectionResult <T>("?", SelectionResultTypes.Canceled) : new SelectionResult <T>("?", select, item.Data, item.Title)); } case ConsoleKey.PageUp: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } else { select = Math.Max(0, temp.Item1 - temp.Item7); } break; case ConsoleKey.PageDown: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = list.Count - 1; } else { select = Math.Min(list.Count - 1, temp.Item1 + temp.Item7); } break; case ConsoleKey.UpArrow: if (select < temp.Item4) { select += list.Count - (list.Count % temp.Item4); if (select >= list.Count) { select -= temp.Item4; } if (select >= list.Count) { select = list.Count - 1; } else if (select < 0) { select = 0; } } else { select -= temp.Item4; } break; case ConsoleKey.DownArrow: select += temp.Item4; if (select >= list.Count) { select %= temp.Item4; if (select >= list.Count) { select = list.Count - 1; } } break; case ConsoleKey.LeftArrow: select--; if (select < 0) { select = list.Count - 1; } break; case ConsoleKey.RightArrow: select++; if (select >= list.Count) { select = 0; } break; case ConsoleKey.Home: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = 0; } else { select = temp.Item1; } break; case ConsoleKey.End: if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { select = list.Count - 1; } else { select = temp.Item1 + temp.Item2 - 1; } break; default: { var item = collection.Get(key.KeyChar, out select); if (item == null) { select = oldSelect; continue; } cli.WriteImmediately(' '); cli.BackspaceToBeginning(); resetSelect(); RenderSelectResult(cli, item.Title, options); cli.WriteLine(); return(new SelectionResult <T>(item.Title, select, item.Data, item.Title)); } } } }
private static string RenderData(StyleConsole cli, ConsoleProgressStyle style, string caption, OneProgress value, string status) { var maxWidth = GetBufferSafeWidth(cli); var width = style.Size switch { ConsoleProgressStyle.Sizes.None => 0, ConsoleProgressStyle.Sizes.Short => maxWidth > 70 ? 20 : 10, ConsoleProgressStyle.Sizes.Wide => maxWidth > 88 ? 60 : 40, ConsoleProgressStyle.Sizes.Full => maxWidth - 5, _ => maxWidth > 70 ? (maxWidth > 88 ? 40 : 30) : 20 }; var barChar = style.Kind switch { ConsoleProgressStyle.Kinds.AngleBracket => '>', ConsoleProgressStyle.Kinds.Plus => '+', ConsoleProgressStyle.Kinds.Sharp => '#', ConsoleProgressStyle.Kinds.X => 'x', ConsoleProgressStyle.Kinds.O => 'o', _ => ' ', }; var pendingChar = style.Kind switch { ConsoleProgressStyle.Kinds.AngleBracket => '=', ConsoleProgressStyle.Kinds.Plus => '-', ConsoleProgressStyle.Kinds.Sharp => '-', ConsoleProgressStyle.Kinds.X => '.', ConsoleProgressStyle.Kinds.O => '.', _ => ' ', }; var col = new List <ConsoleText>(); if (!string.IsNullOrWhiteSpace(caption)) { var sb = new StringBuilder(); var j = style.IgnoreCaptionSeparator ? 0 : 1; foreach (var c in caption) { var c2 = c; switch (c) { case '\t': case '\r': case '\n': j++; c2 = ' '; break; case '\0': case '\b': continue; default: j += GetLetterWidth(c); break; } sb.Append(c2); } if (!style.IgnoreCaptionSeparator) { sb.Append(' '); } col.Add(sb, new ConsoleTextStyle(style.CaptionRgbColor, style.CaptionConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); if (style.Size == ConsoleProgressStyle.Sizes.Full) { width -= j; } } var v = value?.Value ?? -1; if (v > 1) { v = 1; } if (double.IsNaN(v)) { cli.WriteLine(col); return(null); } var w = (int)Math.Round(width * v); if (w < 0) { w = 0; } var isError = value?.IsFailed == true || value?.IsNotSupported == true; var isSucc = !isError && value?.IsSuccessful == true; var newStatus = $"{(isError ? "e" : (isSucc ? "s" : "p"))}{w}/{maxWidth}"; if (status == newStatus) { cli.Flush(); cli.MoveCursorBy(0, 1); return(status); } if (barChar == ' ') { col.Add(barChar, w, new ConsoleTextStyle(null, null, isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor)); col.Add(pendingChar, width - w, new ConsoleTextStyle(null, null, style.PendingRgbColor, style.PendingConsoleColor)); } else { col.Add(barChar, w, new ConsoleTextStyle(isError ? style.ErrorRgbColor : style.BarRgbColor, isError ? style.ErrorConsoleColor : style.BarConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); col.Add(pendingChar, width - w, new ConsoleTextStyle(style.PendingRgbColor, style.PendingConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); } if (v >= 0) { var s = v.ToString("#0%"); if (s.Length > 3) { s = isSucc ? " √" : "99%"; } col.Add(" " + s, new ConsoleTextStyle(style.ValueRgbColor, style.ValueConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor)); } cli.Flush(); cli.Clear(StyleConsole.RelativeAreas.Line); cli.BackspaceToBeginning(); cli.WriteLine(col); return(status); } }
/// <summary> /// Writes a progress component, followed by the current line terminator, to the standard output stream. /// </summary> /// <param name="cli">The command line interface proxy.</param> /// <param name="caption">The caption; or null if no caption. It will be better if it is less than 20 characters.</param> /// <param name="style">The style.</param> /// <returns>The progress result.</returns> public static OneProgress WriteLine(this StyleConsole cli, ConsoleProgressStyle style, string caption) { if (cli == null) { cli = StyleConsole.Default; } if (cli.Mode == StyleConsole.Modes.Text && cli.Handler == null) { var progress2 = new OneProgress(); if (string.IsNullOrWhiteSpace(caption)) { cli.WriteLine(Resource.Loading); progress2.ProgressChanged += (sender, ev) => { if (progress2.IsFailed || progress2.IsNotSupported) { cli.WriteLine($"{ev:#0%} {Resource.Error}"); } else if (progress2.IsCompleted) { cli.WriteLine($"√"); } }; } else { cli.WriteLine($"{caption} \t{Resource.Loading}"); progress2.ProgressChanged += (sender, ev) => { if (progress2.IsFailed || progress2.IsNotSupported) { cli.WriteLine($"{caption} \t{ev:#0%} {Resource.Error}"); } else if (progress2.IsCompleted) { cli.WriteLine($"{caption} \t√"); } }; } return(progress2); } if (style == null) { style = new ConsoleProgressStyle(); } var status = RenderData(cli, style, caption, null, null); var progress = new OneProgress(); var top = TryGetCursorTop(cli) ?? -1; progress.ProgressChanged += (sender, ev) => { var top2 = TryGetCursorTop(cli) ?? -1; var left2 = TryGetCursorLeft(cli) ?? 0; cli.Flush(); if (cli.Mode == StyleConsole.Modes.Cmd && top >= 0 && top2 > top) { cli.MoveCursorBy(0, top - top2 - 1); } else { cli.MoveCursorBy(0, -1); } status = RenderData(cli, style, caption, progress, status); if (cli.Mode == StyleConsole.Modes.Cmd && top >= 0 && top2 > top) { cli.MoveCursorTo(left2, top2); } }; return(progress); }
/// <summary> /// Converts to boolean list and writes to the standard output stream. /// White represented as false, black represented as true. /// </summary> /// <param name="cli">The command line interface proxy.</param> /// <param name="style">The style that foreground represents black and background represents white.</param> /// <returns>The boolean list.</returns> /// <exception cref="InvalidOperationException">It was not an EAN-13 ro EAN-8 code.</exception> public List <bool> ToBarcode(StyleConsole cli, ConsoleTextStyle style = null) { List <bool> barcode; try { barcode = ToBarcode(); } catch (InvalidOperationException) { cli.WriteLine(style, value); throw; } var col = new List <ConsoleText>(); if (style == null) { style = new ConsoleTextStyle(System.Drawing.Color.FromArgb(16, 16, 16), ConsoleColor.Black, System.Drawing.Color.FromArgb(206, 206, 206), ConsoleColor.Gray); } var black = new ConsoleTextStyle(style.ForegroundRgbColor, style.ForegroundConsoleColor, style.ForegroundRgbColor, style.ForegroundConsoleColor); var white = new ConsoleTextStyle(style.BackgroundRgbColor, style.BackgroundConsoleColor, style.BackgroundRgbColor, style.BackgroundConsoleColor); var bg = new string(' ', 12 + barcode.Count); col.Add(bg, white); col.Add(Environment.NewLine); var s = value; cli.Flush(); if (cli.Mode == StyleConsole.Modes.Text && cli.Handler == null) { cli.WriteLine(style, s); return(barcode); } else if (barcode.Count + 12 > GetBufferSafeWidth(cli)) { col.Clear(); foreach (var b in barcode) { col.Add(' ', 1, b ? black : white); } col.Add(Environment.NewLine); col.Add(s, style); cli.WriteLine(col); return(barcode); } else if (barcode.Count == 95 && s.Length == 13) { for (var i = 0; i < 4; i++) { col.Add(' ', 7, white); foreach (var b in barcode) { col.Add(' ', 1, b ? black : white); } col.Add(' ', 5, white); col.Add(Environment.NewLine); } var isbn = false; if (s.StartsWith("97")) { if (s.StartsWith("9790")) { isbn = true; col.Add("ISMN 9 ", style); } else if (s.StartsWith("978") || s.StartsWith("979")) { isbn = true; col.Add("ISBN 9 ", style); } else if (s.StartsWith("977")) { isbn = true; col.Add("ISSN 9 ", style); } } if (!isbn) { col.Add(' ', 4, white); col.Add(s[0], 1, style); col.Add(' ', 2, white); } for (var i = 0; i < 3; i++) { col.Add(' ', 1, barcode[i] ? black : white); } for (var i = 1; i < 7; i++) { col.Add(' ', 3, white); col.Add(s[i], 1, style); col.Add(' ', 3, white); } for (var i = 45; i < 50; i++) { col.Add(' ', 1, barcode[i] ? black : white); } for (var i = 7; i < 13; i++) { col.Add(' ', 3, white); col.Add(s[i], 1, style); col.Add(' ', 3, white); } for (var i = 92; i < 95; i++) { col.Add(' ', 1, barcode[i] ? black : white); } col.Add(' ', 5, white); col.Add(Environment.NewLine); } else if (barcode.Count == 67 && s.Length == 8) { for (var i = 0; i < 4; i++) { col.Add(' ', 6, white); foreach (var b in barcode) { col.Add(' ', 1, b ? black : white); } col.Add(' ', 6, white); col.Add(Environment.NewLine); } col.Add(' ', 6, white); for (var i = 0; i < 3; i++) { col.Add(' ', 1, barcode[i] ? black : white); } for (var i = 0; i < 4; i++) { col.Add(' ', 3, white); col.Add(s[i], 1, style); col.Add(' ', 3, white); } for (var i = 31; i < 36; i++) { col.Add(' ', 1, barcode[i] ? black : white); } for (var i = 4; i < 8; i++) { col.Add(' ', 3, white); col.Add(s[i], 1, style); col.Add(' ', 3, white); } for (var i = 64; i < 67; i++) { col.Add(' ', 1, barcode[i] ? black : white); } col.Add(' ', 6, white); col.Add(Environment.NewLine); } else if ((barcode.Count == 48 && s.Length == 5) || (barcode.Count == 21 && s.Length == 2)) { col.Add(' ', 14, white); foreach (var c in s) { col.Add(c, 1, style); col.Add(' ', 8, white); } col.Add(' ', 1, white); col.Add(Environment.NewLine); for (var i = 0; i < 4; i++) { col.Add(' ', 6, white); foreach (var b in barcode) { col.Add(' ', 1, b ? black : white); } col.Add(' ', 6, white); col.Add(Environment.NewLine); } } else { for (var i = 0; i < 4; i++) { col.Add(' ', 6, white); foreach (var b in barcode) { col.Add(' ', 1, b ? black : white); } col.Add(' ', 6, white); col.Add(Environment.NewLine); } } col.Add(bg, white); (cli ?? StyleConsole.Default).WriteLine(col); return(barcode); }