From 9f39cb8fa04c5ed7c1b22fa75b628d3d90874058 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Mon, 28 Feb 2022 14:48:42 +0100 Subject: [PATCH 01/16] define Attribute class instead of struct and thus more dynamic --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 2 ++ Terminal.Gui/Core/Border.cs | 2 +- Terminal.Gui/Core/ConsoleDriver.cs | 4 ++-- Terminal.Gui/Core/Graphs/Annotations.cs | 4 ++-- Terminal.Gui/Core/Graphs/GraphCellToRender.cs | 9 +-------- Terminal.Gui/Core/Graphs/Series.cs | 8 ++++---- Terminal.Gui/Views/GraphView.cs | 2 +- Terminal.Gui/Views/ListView.cs | 2 +- 8 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index f3bc804877..464e63c02e 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -60,6 +60,8 @@ public WindowsConsole () ConsoleMode = newConsoleMode; } + public bool SupportTrueColor { get; } = (Environment.OSVersion.Version.Build >= 14931); + public CharInfo [] OriginalStdOutChars; public bool WriteToConsole (Size size, CharInfo [] charInfoBuffer, Coord coords, SmallRect window) diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index 97b31cacd4..e7d269270b 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -440,7 +440,7 @@ public Point Effect3DOffset { /// /// Gets or sets the color for the /// - public Attribute? Effect3DBrush { get; set; } + public Attribute Effect3DBrush { get; set; } /// /// Calculate the sum of the and the diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 4ea70ea8b0..073923cf64 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -90,7 +90,7 @@ public enum Color { /// scenarios, they encode both the foreground and the background color and are used in the /// class to define color schemes that can be used in your application. /// - public struct Attribute { + public class Attribute { /// /// The color attribute value. /// @@ -159,7 +159,7 @@ public Attribute (Color color) : this (color, color) { } /// /// The integer value stored in the attribute. /// The attribute to convert - public static implicit operator int (Attribute c) => c.Value; + public static implicit operator int (Attribute c) => c?.Value ?? 0; /// /// Implicitly convert an integer value into an diff --git a/Terminal.Gui/Core/Graphs/Annotations.cs b/Terminal.Gui/Core/Graphs/Annotations.cs index 226aab8392..0ee52f11ea 100644 --- a/Terminal.Gui/Core/Graphs/Annotations.cs +++ b/Terminal.Gui/Core/Graphs/Annotations.cs @@ -172,7 +172,7 @@ public void Render (GraphView graph) foreach (var entry in entries) { - if (entry.Item1.Color.HasValue) { + if (entry.Item1.Color != null) { Application.Driver.SetAttribute (entry.Item1.Color.Value); } else { graph.SetDriverColorToGraphColor (); @@ -226,7 +226,7 @@ public class PathAnnotation : IAnnotation { /// /// Color for the line that connects points /// - public Attribute? LineColor { get; set; } + public Attribute LineColor { get; set; } /// /// The symbol that gets drawn along the line, defaults to '.' diff --git a/Terminal.Gui/Core/Graphs/GraphCellToRender.cs b/Terminal.Gui/Core/Graphs/GraphCellToRender.cs index 402fafef33..0a904f67f9 100644 --- a/Terminal.Gui/Core/Graphs/GraphCellToRender.cs +++ b/Terminal.Gui/Core/Graphs/GraphCellToRender.cs @@ -15,7 +15,7 @@ public class GraphCellToRender { /// /// Optional color to render the with /// - public Attribute? Color { get; set; } + public Attribute Color { get; set; } /// /// Creates instance and sets with default graph coloring @@ -34,12 +34,5 @@ public GraphCellToRender (Rune rune, Attribute color) : this (rune) { Color = color; } - /// - /// Creates instance and sets and (or default if null) - /// - public GraphCellToRender (Rune rune, Attribute? color) : this (rune) - { - Color = color; - } } } \ No newline at end of file diff --git a/Terminal.Gui/Core/Graphs/Series.cs b/Terminal.Gui/Core/Graphs/Series.cs index 48b66e37dc..c867c42161 100644 --- a/Terminal.Gui/Core/Graphs/Series.cs +++ b/Terminal.Gui/Core/Graphs/Series.cs @@ -42,7 +42,7 @@ public class ScatterSeries : ISeries { /// public void DrawSeries (GraphView graph, Rect drawBounds, RectangleF graphBounds) { - if (Fill.Color.HasValue) { + if (Fill.Color != null) { Application.Driver.SetAttribute (Fill.Color.Value); } @@ -173,7 +173,7 @@ public class BarSeries : ISeries { /// /// Overrides the with a fixed color /// - public Attribute? OverrideBarColor { get; set; } + public Attribute OverrideBarColor { get; set; } /// /// True to draw along the axis under the bar. Defaults @@ -188,7 +188,7 @@ public class BarSeries : ISeries { /// protected virtual GraphCellToRender AdjustColor (GraphCellToRender graphCellToRender) { - if (OverrideBarColor.HasValue) { + if (OverrideBarColor != null) { graphCellToRender.Color = OverrideBarColor; } @@ -274,7 +274,7 @@ protected virtual void DrawBarLine (GraphView graph, Point start, Point end, Bar { var adjusted = AdjustColor (beingDrawn.Fill); - if (adjusted.Color.HasValue) { + if (adjusted.Color != null) { Application.Driver.SetAttribute (adjusted.Color.Value); } diff --git a/Terminal.Gui/Views/GraphView.cs b/Terminal.Gui/Views/GraphView.cs index 80cb9702e0..b8d78a80b8 100644 --- a/Terminal.Gui/Views/GraphView.cs +++ b/Terminal.Gui/Views/GraphView.cs @@ -63,7 +63,7 @@ public class GraphView : View { /// /// The color of the background of the graph and axis/labels /// - public Attribute? GraphColor { get; set; } + public Attribute GraphColor { get; set; } /// /// Creates a new graph with a 1 to 1 graph space with absolute layout diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index 525d4c2508..46a670ab79 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -959,7 +959,7 @@ public class ListViewRowEventArgs : EventArgs { /// The used by current row or /// null to maintain the current attribute. /// - public Attribute? RowAttribute { get; set; } + public Attribute RowAttribute { get; set; } /// /// Initializes with the current row. From 52f28cde704fbf1ef898f0685a08f68258dd392b Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Tue, 1 Mar 2022 15:52:19 +0100 Subject: [PATCH 02/16] adapt TrueColor implementation for WindowsDriver --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 128 ++++++++++++++--- Terminal.Gui/Core/ConsoleDriver.cs | 138 ++++++++++++++++++- 2 files changed, 246 insertions(+), 20 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 464e63c02e..4075a7b7a4 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -58,19 +58,83 @@ public WindowsConsole () newConsoleMode &= ~(uint)ConsoleModes.EnableQuickEditMode; newConsoleMode &= ~(uint)ConsoleModes.EnableProcessedInput; ConsoleMode = newConsoleMode; + + uint newOutputConsoleMode = OutputConsoleMode; + newOutputConsoleMode |= (uint)(OutputConsoleModes.EnableProcessedOutput | OutputConsoleModes.EnableVirtualTerminalProcessing | OutputConsoleModes.DisableNewLineAutoReturn); + newOutputConsoleMode &= ~(uint)(OutputConsoleModes.EnableWrapAtEolOutput); + OutputConsoleMode = newOutputConsoleMode; } public bool SupportTrueColor { get; } = (Environment.OSVersion.Version.Build >= 14931); - public CharInfo [] OriginalStdOutChars; - - public bool WriteToConsole (Size size, CharInfo [] charInfoBuffer, Coord coords, SmallRect window) + public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord coords, SmallRect window) { if (ScreenBuffer == IntPtr.Zero) { ReadFromConsoleOutput (size, coords, ref window); } - return WriteConsoleOutput (ScreenBuffer, charInfoBuffer, coords, new Coord () { X = window.Left, Y = window.Top }, ref window); + if (!SupportTrueColor) { + var ci = charInfoBuffer.Select (info => + new CharInfo () { + Char = new CharUnion () { UnicodeChar = info.Char }, + Attributes = (ushort)(int)info.Attribute + }).ToArray (); + return WriteConsoleOutput (ScreenBuffer, ci, coords, new Coord () { X = window.Left, Y = window.Top }, ref window); + } + + return WriteConsoleTrueColor (charInfoBuffer); + } + + readonly System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder (256*1024); + readonly char [] SafeCursor = new [] { '\x1b', '7', '\x1b', '[', '0', ';', '0', 'H' }; + readonly char [] RestoreCursor = new [] { '\x1b', '8' }; + readonly char [] SendTrueColorFg = new [] { '\x1b', '[', '3', '8', ';', '2', ';' }; + readonly char [] SendTrueColorBg = new [] { ';', '4', '8', ';', '2', ';' }; + readonly char [] SendColorFg = new [] { '\x1b', '[', '3', '8', ';', '5', ';' }; + readonly char [] SendColorBg = new [] { ';', '4', '8', ';', '5', ';' }; + + private bool WriteConsoleTrueColor(ExtendedCharInfo [] charInfoBuffer) + { + stringBuilder.Clear (); + + stringBuilder.Append (SafeCursor); + + Attribute prev = null; + foreach (var info in charInfoBuffer) { + var attr = info.Attribute; + + if (attr != prev) { + prev = attr; + if (attr is TrueColorAttribute tca) { + stringBuilder.Append (SendTrueColorFg); + stringBuilder.Append (tca.TureColorForeground.R); + stringBuilder.Append (';'); + stringBuilder.Append (tca.TureColorForeground.G); + stringBuilder.Append (';'); + stringBuilder.Append (tca.TureColorForeground.B); + stringBuilder.Append (SendTrueColorBg); + stringBuilder.Append (tca.TrueColorBackground.R); + stringBuilder.Append (';'); + stringBuilder.Append (tca.TrueColorBackground.G); + stringBuilder.Append (';'); + stringBuilder.Append (tca.TrueColorBackground.B); + stringBuilder.Append ('m'); + } else { + stringBuilder.Append (SendColorFg); + stringBuilder.Append (TrueColor.Code4ToCode8 ((int)attr % 16)); + stringBuilder.Append (SendColorBg); + stringBuilder.Append (TrueColor.Code4ToCode8 ((int)attr / 16)); + stringBuilder.Append ('m'); + } + } + + stringBuilder.Append (info.Char != '\x1b' ? info.Char : ' '); + } + + stringBuilder.Append (RestoreCursor); + + string s = stringBuilder.ToString (); + return WriteConsole (ScreenBuffer, s, (uint)(s.Length), out uint _, null); } public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window) @@ -96,12 +160,6 @@ public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window if (!SetConsoleActiveScreenBuffer (ScreenBuffer)) { throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ()); } - - OriginalStdOutChars = new CharInfo [size.Height * size.Width]; - - if (!ReadConsoleOutput (ScreenBuffer, OriginalStdOutChars, coords, new Coord () { X = 0, Y = 0 }, ref window)) { - throw new System.ComponentModel.Win32Exception (Marshal.GetLastWin32Error ()); - } } public bool SetCursorPosition (Coord position) @@ -304,14 +362,33 @@ public uint ConsoleMode { } } + public uint OutputConsoleMode { + get { + GetConsoleMode (OutputHandle, out uint v); + return v; + } + set { + SetConsoleMode (OutputHandle, value); + } + } + [Flags] public enum ConsoleModes : uint { EnableProcessedInput = 1, + EnableWindowInput = 8, EnableMouseInput = 16, EnableQuickEditMode = 64, EnableExtendedFlags = 128, } + [Flags] + public enum OutputConsoleModes : uint { + EnableProcessedOutput = 1, + EnableWrapAtEolOutput = 2, + EnableVirtualTerminalProcessing = 4, + DisableNewLineAutoReturn = 8, + } + [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)] public struct KeyEventRecord { [FieldOffset (0), MarshalAs (UnmanagedType.Bool)] @@ -484,6 +561,11 @@ public struct CharInfo { [FieldOffset (2)] public ushort Attributes; } + public struct ExtendedCharInfo { + public char Char { get; set; } + public Attribute Attribute { get; set; } + } + [StructLayout (LayoutKind.Sequential)] public struct SmallRect { public short Left; @@ -576,6 +658,15 @@ static extern bool WriteConsoleOutput ( ref SmallRect lpWriteRegion ); + [DllImport ("kernel32.dll", EntryPoint = "WriteConsole", SetLastError = true, CharSet = CharSet.Unicode)] + static extern bool WriteConsole ( + IntPtr hConsoleOutput, + String lpbufer, + UInt32 NumberOfCharsToWriten, + out UInt32 lpNumberOfCharsWritten, + object lpReserved + ); + [DllImport ("kernel32.dll")] static extern bool SetConsoleCursorPosition (IntPtr hConsoleOutput, Coord dwCursorPosition); @@ -721,8 +812,9 @@ static extern Coord GetLargestConsoleWindowSize ( } internal class WindowsDriver : ConsoleDriver { + static bool sync = false; - WindowsConsole.CharInfo [] OutputBuffer; + WindowsConsole.ExtendedCharInfo [] OutputBuffer; int cols, rows, left, top; WindowsConsole.SmallRect damageRegion; IClipboard clipboard; @@ -1436,7 +1528,7 @@ public override void Init (Action terminalResized) void ResizeScreen () { - OutputBuffer = new WindowsConsole.CharInfo [Rows * Cols]; + OutputBuffer = new WindowsConsole.ExtendedCharInfo [Rows * Cols]; Clip = new Rect (0, 0, Cols, Rows); damageRegion = new WindowsConsole.SmallRect () { Top = 0, @@ -1453,10 +1545,10 @@ void UpdateOffScreen () for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int position = row * cols + col; - OutputBuffer [position].Attributes = (ushort)Colors.TopLevel.Normal; - OutputBuffer [position].Char.UnicodeChar = ' '; - contents [row, col, 0] = OutputBuffer [position].Char.UnicodeChar; - contents [row, col, 1] = OutputBuffer [position].Attributes; + OutputBuffer [position].Attribute = Colors.TopLevel.Normal; + OutputBuffer [position].Char = ' '; + contents [row, col, 0] = OutputBuffer [position].Char; + contents [row, col, 1] = OutputBuffer [position].Attribute; contents [row, col, 2] = 0; } } @@ -1475,8 +1567,8 @@ public override void AddRune (Rune rune) var position = crow * Cols + ccol; if (Clip.Contains (ccol, crow)) { - OutputBuffer [position].Attributes = (ushort)currentAttribute; - OutputBuffer [position].Char.UnicodeChar = (char)rune; + OutputBuffer [position].Attribute = currentAttribute; + OutputBuffer [position].Char = (char)rune; contents [crow, ccol, 0] = (int)(uint)rune; contents [crow, ccol, 1] = currentAttribute; contents [crow, ccol, 2] = 1; diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 073923cf64..680e401c7a 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -82,6 +82,117 @@ public enum Color { White } + /// + /// 24bit color. Support translate it to 4bit(Windows) and 8bit(Linux) color + /// + public struct TrueColor { + public int R { get; private set; } + public int G { get; private set; } + public int B { get; private set; } + public TrueColor (int r, int g, int b) + { + R = r; + G = g; + B = b; + } + + /// + /// Get color by code in 256 colors palette + /// + public static TrueColor Color8 (int code) + { + if (code == 7) + code = 8; + else if (code == 8) + code = 7; + if (code == 8) + return new TrueColor (192, 192, 192); + if (code <= 15) { + int k = 128; + if (code >= 9) + k = 255; + return new TrueColor (code % 2 * k, code / 2 % 2 * k, code / 4 % 2 * k); + } + if (code <= 231) { + code -= 16; + int b = code % 6 * 40; + if (b > 0) + b += 45; + int g = code / 6 % 6 * 40; + if (g > 0) + g += 45; + int r = code / 36 % 6 * 40; + if (r > 0) + r += 45; + return new TrueColor (r, g, b); + } + { + code -= 231; + return new TrueColor (8 + code * 10, 8 + code * 10, 8 + code * 10); + } + } + + /// + /// Get color by 16 colors palette + /// + public static TrueColor Color4 (int code) + { + if (code == 7) + code = 8; + else if (code == 8) + code = 7; + if (code == 8) + return new TrueColor (192, 192, 192); + int k = 128; + if (code >= 9) + k = 255; + return new TrueColor (code / 4 % 2 * k, code / 2 % 2 * k, code % 2 * k); + } + + /// + /// Return color diff + /// + public static int Diff (TrueColor c1, TrueColor c2) + { + //TODO: upgrade to CIEDE2000 + return (c1.R - c2.R) * (c1.R - c2.R) + (c1.G - c2.G) * (c1.G - c2.G) + (c1.B - c2.B) * (c1.B - c2.B); + } + + /// + /// Get color code in 256 colors palette (use approximation) + /// + public static int GetCode8 (TrueColor c) + { + int ans = 0; + for (int i = 1; i < 255; i++) + if (Diff (Color8 (i), c) < Diff (Color8 (ans), c)) + ans = i; + return ans; + } + + /// + /// Get color code in 16 colors palette (use approximation) + /// + public static int GetCode4 (TrueColor c) + { + int ans = 0; + for (int i = 1; i < 16; i++) + if (Diff (Color4 (i), c) < Diff (Color4 (ans), c)) + ans = i; + return ans; + } + + /// + /// Convert code in 16 colors palette to 256 colors palette + /// + public static int Code4ToCode8 (int code) + { + if (code == 0 || code == 7 || code == 8 || code == 15) + return code; + return (code & 8) + (code & 2) + 4 * (code & 1) + (code & 4) / 4; + } + } + /// /// Attributes are used as elements that contain both a foreground and a background or platform specific features /// @@ -98,11 +209,11 @@ public class Attribute { /// /// The foreground color. /// - public Color Foreground { get; } + public virtual Color Foreground { get; } /// /// The background color. /// - public Color Background { get; } + public virtual Color Background { get; } /// /// Initializes a new instance of the struct with only the value passed to @@ -193,6 +304,29 @@ public static Attribute Get () } } + /// + /// Defines a true color attribute. + /// + public class TrueColorAttribute : Attribute { + /// + /// The foreground color. + /// + public override Color Foreground => (Color)TrueColor.GetCode4 (TureColorForeground); + /// + /// The background color. + /// + public override Color Background => (Color)TrueColor.GetCode4 (TrueColorBackground); + + /// + /// The foreground color. + /// + public TrueColor TureColorForeground { get; set; } + /// + /// The background color. + /// + public TrueColor TrueColorBackground { get; set; } + } + /// /// Color scheme definitions, they cover some common scenarios and are used /// typically in containers such as and to set the scheme that is used by all the From 139f463f0040dd314cde79bcb87441f81d4f5fbc Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 11:09:50 +0100 Subject: [PATCH 03/16] use long field names in TrueColor struct --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 12 +++---- Terminal.Gui/Core/ConsoleDriver.cs | 34 ++++++++++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 4075a7b7a4..35c5562cab 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -107,17 +107,17 @@ private bool WriteConsoleTrueColor(ExtendedCharInfo [] charInfoBuffer) prev = attr; if (attr is TrueColorAttribute tca) { stringBuilder.Append (SendTrueColorFg); - stringBuilder.Append (tca.TureColorForeground.R); + stringBuilder.Append (tca.TureColorForeground.Red); stringBuilder.Append (';'); - stringBuilder.Append (tca.TureColorForeground.G); + stringBuilder.Append (tca.TureColorForeground.Green); stringBuilder.Append (';'); - stringBuilder.Append (tca.TureColorForeground.B); + stringBuilder.Append (tca.TureColorForeground.Blue); stringBuilder.Append (SendTrueColorBg); - stringBuilder.Append (tca.TrueColorBackground.R); + stringBuilder.Append (tca.TrueColorBackground.Red); stringBuilder.Append (';'); - stringBuilder.Append (tca.TrueColorBackground.G); + stringBuilder.Append (tca.TrueColorBackground.Green); stringBuilder.Append (';'); - stringBuilder.Append (tca.TrueColorBackground.B); + stringBuilder.Append (tca.TrueColorBackground.Blue); stringBuilder.Append ('m'); } else { stringBuilder.Append (SendColorFg); diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 680e401c7a..d05831db11 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -86,14 +86,30 @@ public enum Color { /// 24bit color. Support translate it to 4bit(Windows) and 8bit(Linux) color /// public struct TrueColor { - public int R { get; private set; } - public int G { get; private set; } - public int B { get; private set; } - public TrueColor (int r, int g, int b) + /// + /// Red color component. + /// + public int Red { get; } + /// + /// Green color component. + /// + public int Green { get; } + /// + /// Blue color component. + /// + public int Blue { get; } + + /// + /// Initializes a new instance of the struct. + /// + /// + /// + /// + public TrueColor (int red, int green, int blue) { - R = r; - G = g; - B = b; + Red = red; + Green = green; + Blue = blue; } /// @@ -155,7 +171,7 @@ public static TrueColor Color4 (int code) public static int Diff (TrueColor c1, TrueColor c2) { //TODO: upgrade to CIEDE2000 - return (c1.R - c2.R) * (c1.R - c2.R) + (c1.G - c2.G) * (c1.G - c2.G) + (c1.B - c2.B) * (c1.B - c2.B); + return (c1.Red - c2.Red) * (c1.Red - c2.Red) + (c1.Green - c2.Green) * (c1.Green - c2.Green) + (c1.Blue - c2.Blue) * (c1.Blue - c2.Blue); } /// @@ -216,7 +232,7 @@ public class Attribute { public virtual Color Background { get; } /// - /// Initializes a new instance of the struct with only the value passed to + /// Initializes a new instance of the class with only the value passed to /// and trying to get the colors if defined. /// /// Value. From 10204d45ba41ab66e491375f018f62198f8202c7 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 11:10:12 +0100 Subject: [PATCH 04/16] adapt TrueColor implementation for NetDriver --- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 62 ++++++++++++++++++------ 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 46f667c3aa..bf9685771a 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1153,6 +1153,9 @@ public struct InputResult { } internal class NetDriver : ConsoleDriver { + + Attribute [] OutputAttributeBuffer; + const int COLOR_BLACK = 30; const int COLOR_RED = 31; const int COLOR_GREEN = 32; @@ -1230,6 +1233,9 @@ public override void AddRune (Rune rune) rune = MakePrintable (rune); var runeWidth = Rune.ColumnWidth (rune); if (Clip.Contains (ccol, crow) && ccol + Math.Max (runeWidth, 1) <= Cols) { + var position = crow * Cols + ccol; + OutputAttributeBuffer [position] = currentAttribute; + contents [crow, ccol, 0] = (int)(uint)rune; contents [crow, ccol, 1] = currentAttribute; contents [crow, ccol, 2] = 1; @@ -1396,6 +1402,8 @@ void ResizeScreen () } } + OutputAttributeBuffer = new Attribute [Rows * Cols]; + Clip = new Rect (0, 0, Cols, Rows); contents = new int [Rows, Cols, 3]; @@ -1408,6 +1416,9 @@ void UpdateOffScreen () try { for (int row = 0; row < rows; row++) { for (int c = 0; c < cols; c++) { + int position = row * cols + c; + OutputAttributeBuffer [position] = Colors.TopLevel.Normal; + contents [row, c, 0] = ' '; contents [row, c, 1] = (ushort)Colors.TopLevel.Normal; contents [row, c, 2] = 0; @@ -1429,7 +1440,7 @@ public override void Refresh () UpdateScreen (); } - int redrawAttr = -1; + Attribute redrawAttr = null; public override void UpdateScreen () { @@ -1458,7 +1469,7 @@ public override void UpdateScreen () return; } for (; col < cols; col++) { - var attr = contents [row, col, 1]; + var attr = OutputAttributeBuffer [row * cols + col]; if (attr != redrawAttr) { output.Append (WriteAttributes (attr)); } @@ -1481,24 +1492,43 @@ public override void UpdateScreen () UpdateCursor (); } - System.Text.StringBuilder WriteAttributes (int attr) + System.Text.StringBuilder WriteAttributes (Attribute attr) { - const string CSI = "\x1b["; - int bg = 0; - int fg = 0; System.Text.StringBuilder sb = new System.Text.StringBuilder (); - redrawAttr = attr; - IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); - if (values.Contains (attr & 0xffff)) { - bg = MapColors ((ConsoleColor)(attr & 0xffff), false); - } - if (values.Contains ((attr >> 16) & 0xffff)) { - fg = MapColors ((ConsoleColor)((attr >> 16) & 0xffff)); + if (attr is TrueColorAttribute tca) { + sb.Append (new [] { '\x1b', '[', '3', '8', ';', '2', ';' }); + sb.Append (tca.TureColorForeground.Red); + sb.Append (';'); + sb.Append (tca.TureColorForeground.Green); + sb.Append (';'); + sb.Append (tca.TureColorForeground.Blue); + sb.Append (new [] { ';', '4', '8', ';', '2', ';' }); + sb.Append (tca.TrueColorBackground.Red); + sb.Append (';'); + sb.Append (tca.TrueColorBackground.Green); + sb.Append (';'); + sb.Append (tca.TrueColorBackground.Blue); + sb.Append ('m'); + } else { + + const string CSI = "\x1b["; + int bg = 0; + int fg = 0; + + IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) + .OfType () + .Select (s => (int)s); + if (values.Contains (attr & 0xffff)) { + bg = MapColors ((ConsoleColor)(attr & 0xffff), false); + } + if (values.Contains ((attr >> 16) & 0xffff)) { + fg = MapColors ((ConsoleColor)((attr >> 16) & 0xffff)); + } + sb.Append ($"{CSI}{bg};{fg}m"); } - sb.Append ($"{CSI}{bg};{fg}m"); + + redrawAttr = attr; return sb; } From f8e91d18d6a6e784eda901cfb9694e5012ee2411 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 12:15:57 +0100 Subject: [PATCH 05/16] improve basic color rendering speed in WindowsDriver --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 35c5562cab..bf806799c4 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -74,15 +74,19 @@ public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord } if (!SupportTrueColor) { - var ci = charInfoBuffer.Select (info => - new CharInfo () { + var i = 0; + var ci = new CharInfo [charInfoBuffer.Length]; + foreach (var info in charInfoBuffer) { + ci[i++] = new CharInfo () { Char = new CharUnion () { UnicodeChar = info.Char }, Attributes = (ushort)(int)info.Attribute - }).ToArray (); + }; + } + return WriteConsoleOutput (ScreenBuffer, ci, coords, new Coord () { X = window.Left, Y = window.Top }, ref window); } - return WriteConsoleTrueColor (charInfoBuffer); + return WriteConsoleTrueColorOutput (charInfoBuffer); } readonly System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder (256*1024); @@ -93,7 +97,7 @@ public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord readonly char [] SendColorFg = new [] { '\x1b', '[', '3', '8', ';', '5', ';' }; readonly char [] SendColorBg = new [] { ';', '4', '8', ';', '5', ';' }; - private bool WriteConsoleTrueColor(ExtendedCharInfo [] charInfoBuffer) + private bool WriteConsoleTrueColorOutput(ExtendedCharInfo [] charInfoBuffer) { stringBuilder.Clear (); @@ -120,10 +124,11 @@ private bool WriteConsoleTrueColor(ExtendedCharInfo [] charInfoBuffer) stringBuilder.Append (tca.TrueColorBackground.Blue); stringBuilder.Append ('m'); } else { + var cc = (int)attr; stringBuilder.Append (SendColorFg); - stringBuilder.Append (TrueColor.Code4ToCode8 ((int)attr % 16)); + stringBuilder.Append (TrueColor.Code4ToCode8 (cc % 16)); stringBuilder.Append (SendColorBg); - stringBuilder.Append (TrueColor.Code4ToCode8 ((int)attr / 16)); + stringBuilder.Append (TrueColor.Code4ToCode8 (cc / 16)); stringBuilder.Append ('m'); } } From 019629983d43db034516faf104c0af527abee7d2 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 16:13:35 +0100 Subject: [PATCH 06/16] expose TrueColor support properties --- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 7 +++++++ Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 9 ++++++--- Terminal.Gui/Core/ConsoleDriver.cs | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index bf9685771a..3f9e229829 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -18,6 +18,8 @@ internal class NetWinVTConsole { IntPtr InputHandle, OutputHandle, ErrorHandle; uint originalInputConsoleMode, originalOutputConsoleMode, originalErrorConsoleMode; + public bool SupportTrueColor { get; } = (Environment.OSVersion.Version.Build >= 14931); + public NetWinVTConsole () { InputHandle = GetStdHandle (STD_INPUT_HANDLE); @@ -1187,6 +1189,9 @@ internal class NetDriver : ConsoleDriver { public override IClipboard Clipboard { get; } internal override int [,,] Contents => contents; + readonly bool supportsTrueColorOutput; + public override bool SupportsTrueColorOutput => supportsTrueColorOutput; + int largestWindowHeight; public NetDriver () @@ -1195,6 +1200,7 @@ public NetDriver () if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) { IsWinPlatform = true; NetWinConsole = new NetWinVTConsole (); + supportsTrueColorOutput = NetWinConsole.SupportTrueColor; } //largestWindowHeight = Math.Max (Console.BufferHeight, largestWindowHeight); largestWindowHeight = Console.BufferHeight; @@ -1209,6 +1215,7 @@ public NetDriver () Clipboard = new CursesClipboard (); } } + UseTrueColor = true; } // The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index bf806799c4..afc4951ee2 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -67,13 +67,13 @@ public WindowsConsole () public bool SupportTrueColor { get; } = (Environment.OSVersion.Version.Build >= 14931); - public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord coords, SmallRect window) + public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord coords, SmallRect window, bool forceUseBasicColor) { if (ScreenBuffer == IntPtr.Zero) { ReadFromConsoleOutput (size, coords, ref window); } - if (!SupportTrueColor) { + if (!SupportTrueColor || forceUseBasicColor) { var i = 0; var ci = new CharInfo [charInfoBuffer.Length]; foreach (var info in charInfoBuffer) { @@ -833,6 +833,8 @@ internal class WindowsDriver : ConsoleDriver { public override IClipboard Clipboard => clipboard; internal override int [,,] Contents => contents; + public override bool SupportsTrueColorOutput => WinConsole.SupportTrueColor; + public WindowsConsole WinConsole { get; private set; } Action keyHandler; @@ -844,6 +846,7 @@ public WindowsDriver () { WinConsole = new WindowsConsole (); clipboard = new WindowsClipboard (); + UseTrueColor = true; } public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler) @@ -1665,7 +1668,7 @@ public override void UpdateScreen () //}; UpdateCursor (); - WinConsole.WriteToConsole (new Size (Cols, Rows), OutputBuffer, bufferCoords, damageRegion); + WinConsole.WriteToConsole (new Size (Cols, Rows), OutputBuffer, bufferCoords, damageRegion, !UseTrueColor); // System.Diagnostics.Debugger.Log (0, "debug", $"Region={damageRegion.Right - damageRegion.Left},{damageRegion.Bottom - damageRegion.Top}\n"); WindowsConsole.SmallRect.MakeEmpty (ref damageRegion); } diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index d05831db11..4ead6ebbae 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -818,6 +818,23 @@ public abstract class ConsoleDriver { // The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag internal abstract int [,,] Contents { get; } + + /// + /// Determinates if the current console driver supports TrueColor output- + /// + public virtual bool SupportsTrueColorOutput { get => false; } + + bool useTrueColor; + + /// + /// Controls the TureColor output mode. Can be only enabled if the underlying ConsoleDriver supports it. + /// Note this will be enabled automaticaly if supported. See also + /// + public bool UseTrueColor { + get => useTrueColor; + set => this.useTrueColor = value && SupportsTrueColorOutput; + } + /// /// Initializes the driver /// From 9e8da20ddf0ce9c82a5aaec75878b7c6a65f4612 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 22:47:17 +0100 Subject: [PATCH 07/16] fixup ColorScheme setup, allow to pass unit tests --- Terminal.Gui/Core/ConsoleDriver.cs | 102 +++++++++++++++-------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 4ead6ebbae..f0e3ed4bef 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -217,7 +217,7 @@ public static int Code4ToCode8 (int code) /// scenarios, they encode both the foreground and the background color and are used in the /// class to define color schemes that can be used in your application. /// - public class Attribute { + public class Attribute : IEquatable { /// /// The color attribute value. /// @@ -236,7 +236,7 @@ public class Attribute { /// and trying to get the colors if defined. /// /// Value. - public Attribute (int value) + public Attribute (int value = 0) { Color foreground = default; Color background = default; @@ -267,7 +267,7 @@ public Attribute (int value, Color foreground, Color background) /// /// Foreground /// Background - public Attribute (Color foreground = new Color (), Color background = new Color ()) + public Attribute (Color foreground, Color background) { Value = Make (foreground, background).Value; Foreground = foreground; @@ -318,6 +318,12 @@ public static Attribute Get () throw new InvalidOperationException ("The Application has not been initialized"); return Application.Driver.GetAttribute (); } + + /// + public bool Equals (Attribute other) + { + return (Value == other.Value) && (Foreground == other.Foreground) && (Background == other.Background); + } } /// @@ -396,18 +402,18 @@ Attribute SetAttribute (Attribute attribute, [CallerMemberName] string callerMem case "TopLevel": switch (callerMemberName) { case "Normal": - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); break; case "Focus": - HotFocus = Application.Driver.MakeAttribute (HotFocus.Foreground, attribute.Background); + HotFocus = Application.Driver.MakeAttribute (HotFocus?.Foreground ?? default, attribute.Background); break; case "HotNormal": - HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus.Background); + HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus?.Background ?? default); break; case "HotFocus": - HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal.Background); - if (Focus.Foreground != attribute.Background) - Focus = Application.Driver.MakeAttribute (Focus.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal?.Background ?? default); + if (Focus?.Foreground != attribute.Background) + Focus = Application.Driver.MakeAttribute (Focus?.Foreground ?? default, attribute.Background); break; } break; @@ -415,19 +421,19 @@ Attribute SetAttribute (Attribute attribute, [CallerMemberName] string callerMem case "Base": switch (callerMemberName) { case "Normal": - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); break; case "Focus": - HotFocus = Application.Driver.MakeAttribute (HotFocus.Foreground, attribute.Background); + HotFocus = Application.Driver.MakeAttribute (HotFocus?.Foreground ?? default, attribute.Background); break; case "HotNormal": - HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus.Background); - Normal = Application.Driver.MakeAttribute (Normal.Foreground, attribute.Background); + HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus?.Background ?? default); + Normal = Application.Driver.MakeAttribute (Normal?.Foreground ?? default, attribute.Background); break; case "HotFocus": - HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal.Background); - if (Focus.Foreground != attribute.Background) - Focus = Application.Driver.MakeAttribute (Focus.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal?.Background ?? default); + if (Focus?.Foreground != attribute.Background) + Focus = Application.Driver.MakeAttribute (Focus?.Foreground ?? default, attribute.Background); break; } break; @@ -435,31 +441,31 @@ Attribute SetAttribute (Attribute attribute, [CallerMemberName] string callerMem case "Menu": switch (callerMemberName) { case "Normal": - if (Focus.Background != attribute.Background) - Focus = Application.Driver.MakeAttribute (attribute.Foreground, Focus.Background); - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); - Disabled = Application.Driver.MakeAttribute (Disabled.Foreground, attribute.Background); + if (Focus?.Background != attribute.Background) + Focus = Application.Driver.MakeAttribute (attribute.Foreground, Focus?.Background ?? default); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); + Disabled = Application.Driver.MakeAttribute (Disabled?.Foreground ?? default, attribute.Background); break; case "Focus": - Normal = Application.Driver.MakeAttribute (attribute.Foreground, Normal.Background); - HotFocus = Application.Driver.MakeAttribute (HotFocus.Foreground, attribute.Background); + Normal = Application.Driver.MakeAttribute (attribute.Foreground, Normal?.Background ?? default); + HotFocus = Application.Driver.MakeAttribute (HotFocus?.Foreground ?? default, attribute.Background); break; case "HotNormal": - if (Focus.Background != attribute.Background) - HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus.Background); - Normal = Application.Driver.MakeAttribute (Normal.Foreground, attribute.Background); - Disabled = Application.Driver.MakeAttribute (Disabled.Foreground, attribute.Background); + if (Focus?.Background != attribute.Background) + HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus?.Background ?? default); + Normal = Application.Driver.MakeAttribute (Normal?.Foreground ?? default, attribute.Background); + Disabled = Application.Driver.MakeAttribute (Disabled?.Foreground ?? default, attribute.Background); break; case "HotFocus": - HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal.Background); - if (Focus.Foreground != attribute.Background) - Focus = Application.Driver.MakeAttribute (Focus.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal?.Background ?? default); + if (Focus?.Foreground != attribute.Background) + Focus = Application.Driver.MakeAttribute (Focus?.Foreground ?? default, attribute.Background); break; case "Disabled": - if (Focus.Background != attribute.Background) - HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus.Background); - Normal = Application.Driver.MakeAttribute (Normal.Foreground, attribute.Background); - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); + if (Focus?.Background != attribute.Background) + HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus?.Background ?? default); + Normal = Application.Driver.MakeAttribute (Normal?.Foreground ?? default, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); break; } break; @@ -467,24 +473,24 @@ Attribute SetAttribute (Attribute attribute, [CallerMemberName] string callerMem case "Dialog": switch (callerMemberName) { case "Normal": - if (Focus.Background != attribute.Background) - Focus = Application.Driver.MakeAttribute (attribute.Foreground, Focus.Background); - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); + if (Focus?.Background != attribute.Background) + Focus = Application.Driver.MakeAttribute (attribute.Foreground, Focus?.Background ?? default); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); break; case "Focus": - Normal = Application.Driver.MakeAttribute (attribute.Foreground, Normal.Background); - HotFocus = Application.Driver.MakeAttribute (HotFocus.Foreground, attribute.Background); + Normal = Application.Driver.MakeAttribute (attribute.Foreground, Normal?.Background ?? default); + HotFocus = Application.Driver.MakeAttribute (HotFocus?.Foreground ?? default, attribute.Background); break; case "HotNormal": - if (Focus.Background != attribute.Background) - HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus.Background); - if (Normal.Foreground != attribute.Background) - Normal = Application.Driver.MakeAttribute (Normal.Foreground, attribute.Background); + if (Focus?.Background != attribute.Background) + HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, HotFocus?.Background ?? default); + if (Normal?.Foreground != attribute.Background) + Normal = Application.Driver.MakeAttribute (Normal?.Foreground ?? default, attribute.Background); break; case "HotFocus": - HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal.Background); - if (Focus.Foreground != attribute.Background) - Focus = Application.Driver.MakeAttribute (Focus.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (attribute.Foreground, HotNormal?.Background ?? default); + if (Focus?.Foreground != attribute.Background) + Focus = Application.Driver.MakeAttribute (Focus?.Foreground ?? default, attribute.Background); break; } break; @@ -492,13 +498,13 @@ Attribute SetAttribute (Attribute attribute, [CallerMemberName] string callerMem case "Error": switch (callerMemberName) { case "Normal": - HotNormal = Application.Driver.MakeAttribute (HotNormal.Foreground, attribute.Background); - HotFocus = Application.Driver.MakeAttribute (HotFocus.Foreground, attribute.Background); + HotNormal = Application.Driver.MakeAttribute (HotNormal?.Foreground ?? default, attribute.Background); + HotFocus = Application.Driver.MakeAttribute (HotFocus?.Foreground ?? default, attribute.Background); break; case "HotNormal": case "HotFocus": HotFocus = Application.Driver.MakeAttribute (attribute.Foreground, attribute.Background); - Normal = Application.Driver.MakeAttribute (Normal.Foreground, attribute.Background); + Normal = Application.Driver.MakeAttribute (Normal?.Foreground ?? default, attribute.Background); break; } break; From 8d4a5694804a7c733fcd0ed30d6e666a22b9456e Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Wed, 2 Mar 2022 23:13:55 +0100 Subject: [PATCH 08/16] provide Default Attribute, allow to pass unit tests --- Terminal.Gui/Core/ConsoleDriver.cs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index f0e3ed4bef..0f48f21b84 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -281,6 +281,12 @@ public Attribute (Color foreground, Color background) /// The color. public Attribute (Color color) : this (color, color) { } + /// + public bool Equals (Attribute other) + { + return (Value == other.Value) && (Foreground == other.Foreground) && (Background == other.Background); + } + /// /// Implicit conversion from an to the underlying Int32 representation /// @@ -319,11 +325,10 @@ public static Attribute Get () return Application.Driver.GetAttribute (); } - /// - public bool Equals (Attribute other) - { - return (Value == other.Value) && (Foreground == other.Foreground) && (Background == other.Background); - } + /// + /// Default empty attribute. + /// + public static readonly Attribute Default = new Attribute (); } /// @@ -355,11 +360,11 @@ public class TrueColorAttribute : Attribute { /// views contained inside. /// public class ColorScheme : IEquatable { - Attribute _normal; - Attribute _focus; - Attribute _hotNormal; - Attribute _hotFocus; - Attribute _disabled; + Attribute _normal = Attribute.Default; + Attribute _focus = Attribute.Default; + Attribute _hotNormal = Attribute.Default; + Attribute _hotFocus = Attribute.Default; + Attribute _disabled = Attribute.Default; internal string caller = ""; /// From b2b7197819323801dba7ce541e5a325958ed128a Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Thu, 3 Mar 2022 17:23:11 +0100 Subject: [PATCH 09/16] adjust TrueColorAttribute impl to work also in basic color compatibility mode --- Terminal.Gui/Core/ConsoleDriver.cs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 0f48f21b84..2c2f78550d 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -225,11 +225,11 @@ public class Attribute : IEquatable { /// /// The foreground color. /// - public virtual Color Foreground { get; } + public Color Foreground { get; } /// /// The background color. /// - public virtual Color Background { get; } + public Color Background { get; } /// /// Initializes a new instance of the class with only the value passed to @@ -336,22 +336,32 @@ public static Attribute Get () /// public class TrueColorAttribute : Attribute { /// - /// The foreground color. + /// Initializes a new instance of the struct. /// - public override Color Foreground => (Color)TrueColor.GetCode4 (TureColorForeground); + /// Foreground + /// Background + public TrueColorAttribute (TrueColor foreground, TrueColor background) + : base((Color)TrueColor.GetCode4 (foreground), (Color)TrueColor.GetCode4 (background)) + { + TureColorForeground = foreground; + TrueColorBackground = background; + } + /// - /// The background color. + /// Initializes a new instance of the struct + /// with the same colors for the foreground and background. /// - public override Color Background => (Color)TrueColor.GetCode4 (TrueColorBackground); + /// The color. + public TrueColorAttribute (TrueColor color) : this(color, color) { } /// /// The foreground color. /// - public TrueColor TureColorForeground { get; set; } + public TrueColor TureColorForeground { get; } /// /// The background color. /// - public TrueColor TrueColorBackground { get; set; } + public TrueColor TrueColorBackground { get; } } /// From d355981e4655a249f298640f9a8160bb9e924634 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Fri, 4 Mar 2022 11:34:49 +0100 Subject: [PATCH 10/16] cleanup TrueColor struct, add unit tests --- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 1 - Terminal.Gui/Core/ConsoleDriver.cs | 77 +++++----------------- UnitTests/TureColorAttributeTests.cs | 84 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 UnitTests/TureColorAttributeTests.cs diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 3f9e229829..b7a2aa2e39 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1518,7 +1518,6 @@ System.Text.StringBuilder WriteAttributes (Attribute attr) sb.Append (tca.TrueColorBackground.Blue); sb.Append ('m'); } else { - const string CSI = "\x1b["; int bg = 0; int fg = 0; diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 2c2f78550d..512308e2e8 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -112,56 +112,18 @@ public TrueColor (int red, int green, int blue) Blue = blue; } - /// - /// Get color by code in 256 colors palette - /// - public static TrueColor Color8 (int code) - { - if (code == 7) - code = 8; - else if (code == 8) - code = 7; - if (code == 8) - return new TrueColor (192, 192, 192); - if (code <= 15) { - int k = 128; - if (code >= 9) - k = 255; - return new TrueColor (code % 2 * k, code / 2 % 2 * k, code / 4 % 2 * k); - } - if (code <= 231) { - code -= 16; - int b = code % 6 * 40; - if (b > 0) - b += 45; - int g = code / 6 % 6 * 40; - if (g > 0) - g += 45; - int r = code / 36 % 6 * 40; - if (r > 0) - r += 45; - return new TrueColor (r, g, b); - } - { - code -= 231; - return new TrueColor (8 + code * 10, 8 + code * 10, 8 + code * 10); - } - } - /// /// Get color by 16 colors palette /// public static TrueColor Color4 (int code) { - if (code == 7) - code = 8; - else if (code == 8) - code = 7; - if (code == 8) - return new TrueColor (192, 192, 192); - int k = 128; - if (code >= 9) - k = 255; + if (code == 7) { code = 8; } + else if (code == 8) { code = 7; } + + if (code == 8) { return new TrueColor (192, 192, 192); } + + int k = (code > 8) ? 255 : 128; + return new TrueColor (code / 4 % 2 * k, code / 2 % 2 * k, code % 2 * k); } @@ -170,20 +132,10 @@ public static TrueColor Color4 (int code) /// public static int Diff (TrueColor c1, TrueColor c2) { - //TODO: upgrade to CIEDE2000 - return (c1.Red - c2.Red) * (c1.Red - c2.Red) + (c1.Green - c2.Green) * (c1.Green - c2.Green) + (c1.Blue - c2.Blue) * (c1.Blue - c2.Blue); - } - - /// - /// Get color code in 256 colors palette (use approximation) - /// - public static int GetCode8 (TrueColor c) - { - int ans = 0; - for (int i = 1; i < 255; i++) - if (Diff (Color8 (i), c) < Diff (Color8 (ans), c)) - ans = i; - return ans; + // TODO: maybe use CIEDE2000 + return ((c1.Red - c2.Red) * (c1.Red - c2.Red)) + + ((c1.Green - c2.Green) * (c1.Green - c2.Green)) + + (c1.Blue - c2.Blue) * (c1.Blue - c2.Blue); } /// @@ -192,9 +144,10 @@ public static int GetCode8 (TrueColor c) public static int GetCode4 (TrueColor c) { int ans = 0; - for (int i = 1; i < 16; i++) - if (Diff (Color4 (i), c) < Diff (Color4 (ans), c)) - ans = i; + for (int i = 1; i < 16; i++) { + if (Diff (Color4 (i), c) < Diff (Color4 (ans), c)) { ans = i; } + } + return ans; } diff --git a/UnitTests/TureColorAttributeTests.cs b/UnitTests/TureColorAttributeTests.cs new file mode 100644 index 0000000000..3eabc1d79e --- /dev/null +++ b/UnitTests/TureColorAttributeTests.cs @@ -0,0 +1,84 @@ +using Xunit; + +// Alias Console to MockConsole so we don't accidentally use Console + +namespace Terminal.Gui.ConsoleDrivers { + + public class TrueColorAttributeTests { + + [Fact] + public void Constuctors_Constuct () + { + var driver = new FakeDriver (); + Application.Init (driver, new FakeMainLoop (() => FakeConsole.ReadKey (true))); + driver.Init (() => { }); + + // Test foreground, background + var fg = new TrueColor (255, 0, 0); + var bg = new TrueColor (0, 255, 0); + + var attr = new TrueColorAttribute (fg, bg); + + Assert.Equal (fg, attr.TureColorForeground); + Assert.Equal (bg, attr.TrueColorBackground); + + // Test unified color + attr = new TrueColorAttribute (fg); + Assert.Equal (fg, attr.TureColorForeground); + Assert.Equal (fg, attr.TrueColorBackground); + + attr = new TrueColorAttribute (bg); + Assert.Equal (bg, attr.TureColorForeground); + Assert.Equal (bg, attr.TrueColorBackground); + + driver.End (); + Application.Shutdown (); + } + + [Fact] + public void Basic_Colors_Fallback () + { + var driver = new FakeDriver (); + Application.Init (driver, new FakeMainLoop (() => FakeConsole.ReadKey (true))); + driver.Init (() => { }); + + // Test bright basic colors + var attr = new TrueColorAttribute (new TrueColor (128, 0, 0), new TrueColor (0, 128, 0)); + Assert.Equal (Color.Red, attr.Foreground); + Assert.Equal (Color.Green, attr.Background); + + attr = new TrueColorAttribute (new TrueColor (128, 128, 0), new TrueColor (0, 0, 128)); + Assert.Equal (Color.Brown, attr.Foreground); + Assert.Equal (Color.Blue, attr.Background); + + attr = new TrueColorAttribute (new TrueColor (128, 0, 128), new TrueColor (0, 128, 128)); + Assert.Equal (Color.Magenta, attr.Foreground); + Assert.Equal (Color.Cyan, attr.Background); + + // Test basic colors + attr = new TrueColorAttribute (new TrueColor (255, 0, 0), new TrueColor (0, 255, 0)); + Assert.Equal (Color.BrightRed, attr.Foreground); + Assert.Equal (Color.BrightGreen, attr.Background); + + attr = new TrueColorAttribute (new TrueColor (255, 255, 0), new TrueColor (0, 0, 255)); + Assert.Equal (Color.BrightYellow, attr.Foreground); + Assert.Equal (Color.BrightBlue, attr.Background); + + attr = new TrueColorAttribute (new TrueColor (255, 0, 255), new TrueColor (0, 255, 255)); + Assert.Equal (Color.BrightMagenta, attr.Foreground); + Assert.Equal (Color.BrightCyan, attr.Background); + + // Test gray basic colors + attr = new TrueColorAttribute (new TrueColor (128, 128, 128), new TrueColor (255, 255, 255)); + Assert.Equal (Color.DarkGray, attr.Foreground); + Assert.Equal (Color.White, attr.Background); + + attr = new TrueColorAttribute (new TrueColor (192, 192, 192), new TrueColor (0, 0, 0)); + Assert.Equal (Color.Gray, attr.Foreground); + Assert.Equal (Color.Black, attr.Background); + + driver.End (); + Application.Shutdown (); + } + } +} \ No newline at end of file From 9c5e8917c97a72c1e033c3de0fa2a4ee6eb4b581 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Mon, 7 Mar 2022 10:25:07 +0100 Subject: [PATCH 11/16] fix TrueColorForeground typo --- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 6 +++--- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 6 +++--- Terminal.Gui/Core/ConsoleDriver.cs | 4 ++-- UnitTests/TureColorAttributeTests.cs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index b7a2aa2e39..2cd5c3f1a5 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1505,11 +1505,11 @@ System.Text.StringBuilder WriteAttributes (Attribute attr) if (attr is TrueColorAttribute tca) { sb.Append (new [] { '\x1b', '[', '3', '8', ';', '2', ';' }); - sb.Append (tca.TureColorForeground.Red); + sb.Append (tca.TrueColorForeground.Red); sb.Append (';'); - sb.Append (tca.TureColorForeground.Green); + sb.Append (tca.TrueColorForeground.Green); sb.Append (';'); - sb.Append (tca.TureColorForeground.Blue); + sb.Append (tca.TrueColorForeground.Blue); sb.Append (new [] { ';', '4', '8', ';', '2', ';' }); sb.Append (tca.TrueColorBackground.Red); sb.Append (';'); diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index afc4951ee2..b59ee51840 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -111,11 +111,11 @@ private bool WriteConsoleTrueColorOutput(ExtendedCharInfo [] charInfoBuffer) prev = attr; if (attr is TrueColorAttribute tca) { stringBuilder.Append (SendTrueColorFg); - stringBuilder.Append (tca.TureColorForeground.Red); + stringBuilder.Append (tca.TrueColorForeground.Red); stringBuilder.Append (';'); - stringBuilder.Append (tca.TureColorForeground.Green); + stringBuilder.Append (tca.TrueColorForeground.Green); stringBuilder.Append (';'); - stringBuilder.Append (tca.TureColorForeground.Blue); + stringBuilder.Append (tca.TrueColorForeground.Blue); stringBuilder.Append (SendTrueColorBg); stringBuilder.Append (tca.TrueColorBackground.Red); stringBuilder.Append (';'); diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 512308e2e8..a59c12666b 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -296,7 +296,7 @@ public class TrueColorAttribute : Attribute { public TrueColorAttribute (TrueColor foreground, TrueColor background) : base((Color)TrueColor.GetCode4 (foreground), (Color)TrueColor.GetCode4 (background)) { - TureColorForeground = foreground; + TrueColorForeground = foreground; TrueColorBackground = background; } @@ -310,7 +310,7 @@ public TrueColorAttribute (TrueColor color) : this(color, color) { } /// /// The foreground color. /// - public TrueColor TureColorForeground { get; } + public TrueColor TrueColorForeground { get; } /// /// The background color. /// diff --git a/UnitTests/TureColorAttributeTests.cs b/UnitTests/TureColorAttributeTests.cs index 3eabc1d79e..0ac83b2395 100644 --- a/UnitTests/TureColorAttributeTests.cs +++ b/UnitTests/TureColorAttributeTests.cs @@ -19,16 +19,16 @@ public void Constuctors_Constuct () var attr = new TrueColorAttribute (fg, bg); - Assert.Equal (fg, attr.TureColorForeground); + Assert.Equal (fg, attr.TrueColorForeground); Assert.Equal (bg, attr.TrueColorBackground); // Test unified color attr = new TrueColorAttribute (fg); - Assert.Equal (fg, attr.TureColorForeground); + Assert.Equal (fg, attr.TrueColorForeground); Assert.Equal (fg, attr.TrueColorBackground); attr = new TrueColorAttribute (bg); - Assert.Equal (bg, attr.TureColorForeground); + Assert.Equal (bg, attr.TrueColorForeground); Assert.Equal (bg, attr.TrueColorBackground); driver.End (); From 55fa5db7ded1f2744140fac21d7702292c35efaf Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Mon, 7 Mar 2022 10:26:16 +0100 Subject: [PATCH 12/16] Add TrueColor demonstration scenario --- UICatalog/Scenarios/TrueColors.cs | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 UICatalog/Scenarios/TrueColors.cs diff --git a/UICatalog/Scenarios/TrueColors.cs b/UICatalog/Scenarios/TrueColors.cs new file mode 100644 index 0000000000..7abadad928 --- /dev/null +++ b/UICatalog/Scenarios/TrueColors.cs @@ -0,0 +1,109 @@ +using System; +using Terminal.Gui; + +namespace UICatalog.Scenarios { + + [ScenarioMetadata (Name: "True Colors", Description: "Demonstration of true color support.")] + [ScenarioCategory ("Colors")] + public class TrueColors : Scenario { + + public override void Setup () + { + var x = 2; + var y = 1; + + var canTrueColor = Application.Driver.SupportsTrueColorOutput; + + var cbSupportsTrueColor = new CheckBox ("Driver supports true color ") { + X = x, + Y = y++, + Checked = canTrueColor, + CanFocus = false + }; + Win.Add (cbSupportsTrueColor); + + var cbUseTrueColor = new CheckBox ("Use true color") { + X = x, + Y = y++, + Checked = Application.Driver.UseTrueColor, + Enabled = canTrueColor, + }; + cbUseTrueColor.Toggled += (_) => Application.Driver.UseTrueColor = cbUseTrueColor.Checked; + Win.Add (cbUseTrueColor); + + y += 2; + SetupGradient ("Red gradient", x, ref y, (i) => new TrueColor (i, 0, 0)); + SetupGradient ("Green gradient", x, ref y, (i) => new TrueColor (0, i, 0)); + SetupGradient ("Blue gradient", x, ref y, (i) => new TrueColor (0, 0, i)); + SetupGradient ("Yellow gradient", x, ref y, (i) => new TrueColor (i, i, 0)); + SetupGradient ("Magenta gradient", x, ref y, (i) => new TrueColor (i, 0, i)); + SetupGradient ("Cyan gradient", x, ref y, (i) => new TrueColor (0, i, i)); + SetupGradient ("Gray gradient", x, ref y, (i) => new TrueColor (i, i, i)); + + Win.Add (new Label ("Mouse over to get the gradient view color:") { + X = Pos.AnchorEnd (44), + Y = 2 + }); + Win.Add (new Label ("Red:") { + X = Pos.AnchorEnd (44), + Y = 4 + }); + Win.Add (new Label ("Green:") { + X = Pos.AnchorEnd (44), + Y = 5 + }); + Win.Add (new Label ("Blue:") { + X = Pos.AnchorEnd (44), + Y = 6 + }); + + var lblRed = new Label ("na") { + X = Pos.AnchorEnd (32), + Y = 4 + }; + Win.Add (lblRed); + var lblGreen = new Label ("na") { + X = Pos.AnchorEnd (32), + Y = 5 + }; + Win.Add (lblGreen); + var lblBlue = new Label ("na") { + X = Pos.AnchorEnd (32), + Y = 6 + }; + Win.Add (lblBlue); + + Application.RootMouseEvent = (e) => { + if (e.View != null) { + if (e.View.GetNormalColor () is TrueColorAttribute colorAttribute) { + lblRed.Text = colorAttribute.TrueColorForeground.Red.ToString(); + lblGreen.Text = colorAttribute.TrueColorForeground.Green.ToString (); + lblBlue.Text = colorAttribute.TrueColorForeground.Blue.ToString (); + } else { + lblRed.Text = "na"; + lblGreen.Text = "na"; + lblBlue.Text = "na"; + } + } + }; + } + + private void SetupGradient (string name, int x, ref int y, Func colorFunc) + { + var gradient = new Label (name) { + X = x, + Y = y++, + }; + Win.Add (gradient); + for (int dx = x, i = 0; i <= 256; i += 4) { + var l = new Label (" ") { + X = dx++, + Y = y, + ColorScheme = new ColorScheme () { Normal = new TrueColorAttribute (colorFunc(i > 255 ? 255 : i)) } + }; + Win.Add (l); + } + y+=2; + } + } +} \ No newline at end of file From 81adab281d17d416793a908008d08fc72da9755f Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Thu, 17 Mar 2022 21:50:59 +0100 Subject: [PATCH 13/16] adjust WSL detection, provide COLORTERM evaulation func --- .../ConsoleDrivers/CursesDriver/CursesDriver.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 777736e80c..721807e1f4 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -951,12 +951,22 @@ void UpdateOffScreen () public static bool Is_WSL_Platform () { var result = BashRunner.Run ("uname -a", runCurses: false); - if (result.Contains ("microsoft") && result.Contains ("WSL")) { + if (result.ToLower().Contains ("microsoft") && (Environment.GetEnvironmentVariable ("WSL_DISTRO_NAME") != null)) { return true; } return false; } + public static bool CanColorTermTrueColor () + { + if (Environment.GetEnvironmentVariable ("COLORTERM") is string value) { + value = value.ToLower (); + return value.Contains ("truecolor") || value.Contains ("24bit"); + } + + return false; + } + static int MapColor (Color color) { switch (color) { From 4c6cfad4171917a0b2cb045549b93839bc720ce3 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Thu, 17 Mar 2022 21:53:48 +0100 Subject: [PATCH 14/16] NetDriver: use COLORTERM for true color support detection, respect UseTrueColor during AttributeWrite --- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 2cd5c3f1a5..301756ee2a 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1214,6 +1214,7 @@ public NetDriver () } else { Clipboard = new CursesClipboard (); } + supportsTrueColorOutput = CursesDriver.CanColorTermTrueColor (); } UseTrueColor = true; } @@ -1503,7 +1504,7 @@ System.Text.StringBuilder WriteAttributes (Attribute attr) { System.Text.StringBuilder sb = new System.Text.StringBuilder (); - if (attr is TrueColorAttribute tca) { + if ((UseTrueColor) && (attr is TrueColorAttribute tca)) { sb.Append (new [] { '\x1b', '[', '3', '8', ';', '2', ';' }); sb.Append (tca.TrueColorForeground.Red); sb.Append (';'); From 7c36e2fe88251526530a82222f5fbeeb6c819d33 Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Thu, 17 Mar 2022 21:54:40 +0100 Subject: [PATCH 15/16] show current driver in TrueColor scene --- UICatalog/Scenarios/TrueColors.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/UICatalog/Scenarios/TrueColors.cs b/UICatalog/Scenarios/TrueColors.cs index 7abadad928..fc2fce3cb4 100644 --- a/UICatalog/Scenarios/TrueColors.cs +++ b/UICatalog/Scenarios/TrueColors.cs @@ -14,6 +14,13 @@ public override void Setup () var canTrueColor = Application.Driver.SupportsTrueColorOutput; + var lblDriverName = new Label($"Current driver is {Application.Driver.GetType().Name}") { + X = x, + Y = y++ + }; + Win.Add(lblDriverName); + y++; + var cbSupportsTrueColor = new CheckBox ("Driver supports true color ") { X = x, Y = y++, From 0e6f6c1801ee68cb6800a98354a102a38556207f Mon Sep 17 00:00:00 2001 From: Vitalij Mast Date: Tue, 29 Nov 2022 17:06:24 +0100 Subject: [PATCH 16/16] auto format code --- .../ConsoleDrivers/CursesDriver/CursesDriver.cs | 2 +- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 2 +- Terminal.Gui/Core/ConsoleDriver.cs | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 4c64021bcc..63e86d01d4 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -958,7 +958,7 @@ public static bool Is_WSL_Platform () return false; } var result = BashRunner.Run ("uname -a", runCurses: false); - if (result.ToLower().Contains ("microsoft") && (Environment.GetEnvironmentVariable ("WSL_DISTRO_NAME") != null)) { + if (result.ToLower ().Contains ("microsoft") && (Environment.GetEnvironmentVariable ("WSL_DISTRO_NAME") != null)) { return true; } return false; diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index ea99a428fa..c2ba8e1115 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1544,7 +1544,7 @@ System.Text.StringBuilder WriteAttributes (Attribute attr) const string CSI = "\x1b["; int bg = 0; int fg = 0; - + IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) .OfType () .Select (s => (int)s); diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index cd5024e4d0..6deaea8a8f 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -83,7 +83,7 @@ public enum Color { } /// - /// 24bit color. Support translate it to 4bit(Windows) and 8bit(Linux) color + /// Represents a 24bit color. Supports translating to 4bit (Windows) and 8bit (Linux) colors. /// public struct TrueColor { /// @@ -117,8 +117,7 @@ public TrueColor (int red, int green, int blue) /// public static TrueColor Color4 (int code) { - if (code == 7) { code = 8; } - else if (code == 8) { code = 7; } + if (code == 7) { code = 8; } else if (code == 8) { code = 7; } if (code == 8) { return new TrueColor (192, 192, 192); } @@ -294,7 +293,7 @@ public class TrueColorAttribute : Attribute { /// Foreground /// Background public TrueColorAttribute (TrueColor foreground, TrueColor background) - : base((Color)TrueColor.GetCode4 (foreground), (Color)TrueColor.GetCode4 (background)) + : base ((Color)TrueColor.GetCode4 (foreground), (Color)TrueColor.GetCode4 (background)) { TrueColorForeground = foreground; TrueColorBackground = background; @@ -305,7 +304,7 @@ public TrueColorAttribute (TrueColor foreground, TrueColor background) /// with the same colors for the foreground and background. /// /// The color. - public TrueColorAttribute (TrueColor color) : this(color, color) { } + public TrueColorAttribute (TrueColor color) : this (color, color) { } /// /// The foreground color. @@ -822,7 +821,7 @@ public bool UseTrueColor { /// Column to move the cursor to. /// Row to move the cursor to. public abstract void Move (int col, int row); - + /// /// Adds the specified rune to the display at the current cursor position. ///