diff --git a/Terminal.Gui/Configuration/ColorJsonConverter.cs b/Terminal.Gui/Configuration/ColorJsonConverter.cs index 6da4490d91..c490299167 100644 --- a/Terminal.Gui/Configuration/ColorJsonConverter.cs +++ b/Terminal.Gui/Configuration/ColorJsonConverter.cs @@ -1,6 +1,5 @@ using System.Text.Json; using System.Text.Json.Serialization; -using ColorHelper; namespace Terminal.Gui; @@ -40,11 +39,9 @@ public override Color Read (ref Utf8JsonReader reader, Type typeToConvert, JsonS // Get the color string ReadOnlySpan colorString = reader.GetString (); - // Check if the color string is a color name - if (ColorStrings.TryParseW3CColorName (colorString.ToString (), out Color color1)) + if (ColorStrings.TryParseNamedColor (colorString, out Color namedColor)) { - // Return the parsed color - return new (color1); + return namedColor; } if (Color.TryParse (colorString, null, out Color parsedColor)) diff --git a/Terminal.Gui/Drawing/Color/AnsiColorNameResolver.cs b/Terminal.Gui/Drawing/Color/AnsiColorNameResolver.cs new file mode 100644 index 0000000000..1b61ed0ddb --- /dev/null +++ b/Terminal.Gui/Drawing/Color/AnsiColorNameResolver.cs @@ -0,0 +1,70 @@ +#nullable enable + +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Terminal.Gui; + +/// +/// Color name resolver for . +/// +public class AnsiColorNameResolver : IColorNameResolver +{ + private static readonly ImmutableArray AnsiColorNames = ImmutableArray.Create(Enum.GetNames()); + + /// + public IEnumerable GetColorNames () + { + return AnsiColorNames; + } + + /// + public bool TryNameColor (Color color, [NotNullWhen (true)] out string? name) + { + if (Color.TryGetExactNamedColor16 (color, out ColorName16 colorName16)) + { + name = Color16Name (colorName16); + return true; + } + name = null; + return false; + } + + /// + public bool TryParseColor (ReadOnlySpan name, out Color color) + { + if (Enum.TryParse (name, ignoreCase: true, out ColorName16 colorName16) && + // Any numerical value converts to undefined enum value. + Enum.IsDefined (colorName16)) + { + color = new Color (colorName16); + return true; + } + color = default; + return false; + } + + private static string Color16Name (ColorName16 color16) + { + return color16 switch + { + ColorName16.Black => nameof (ColorName16.Black), + ColorName16.Blue => nameof (ColorName16.Blue), + ColorName16.Green => nameof (ColorName16.Green), + ColorName16.Cyan => nameof (ColorName16.Cyan), + ColorName16.Red => nameof (ColorName16.Red), + ColorName16.Magenta => nameof (ColorName16.Magenta), + ColorName16.Yellow => nameof (ColorName16.Yellow), + ColorName16.Gray => nameof (ColorName16.Gray), + ColorName16.DarkGray => nameof (ColorName16.DarkGray), + ColorName16.BrightBlue => nameof (ColorName16.BrightBlue), + ColorName16.BrightGreen => nameof (ColorName16.BrightGreen), + ColorName16.BrightCyan => nameof (ColorName16.BrightCyan), + ColorName16.BrightRed => nameof (ColorName16.BrightRed), + ColorName16.BrightMagenta => nameof (ColorName16.BrightMagenta), + ColorName16.BrightYellow => nameof (ColorName16.BrightYellow), + ColorName16.White => nameof (ColorName16.White), + _ => throw new NotSupportedException ($"ColorName16 '{color16}' is not supported.") + }; + } +} diff --git a/Terminal.Gui/Drawing/Color/Color.Formatting.cs b/Terminal.Gui/Drawing/Color/Color.Formatting.cs index dd775fe049..323ae14166 100644 --- a/Terminal.Gui/Drawing/Color/Color.Formatting.cs +++ b/Terminal.Gui/Drawing/Color/Color.Formatting.cs @@ -1,6 +1,5 @@ #nullable enable using System.Diagnostics.CodeAnalysis; -using System.Diagnostics.Contracts; using System.Globalization; using System.Runtime.CompilerServices; @@ -267,90 +266,79 @@ public static Color Parse (ReadOnlySpan text, IFormatProvider? formatProvi return text switch { // Null string or empty span provided - { IsEmpty: true } when formatProvider is null => throw new ColorParseException ( - in text, - "The text provided was null or empty.", - in text - ), + { IsEmpty: true } when formatProvider is null => + throw new ColorParseException (in text, "The text provided was null or empty.", in text), // A valid ICustomColorFormatter was specified and the text wasn't null or empty { IsEmpty: false } when formatProvider is ICustomColorFormatter f => f.Parse (text), // Input string is only whitespace - { Length: > 0 } when text.IsWhiteSpace () => throw new ColorParseException ( - in text, - "The text provided consisted of only whitespace characters.", - in text - ), + { Length: > 0 } when text.IsWhiteSpace () => + throw new ColorParseException (in text, "The text provided consisted of only whitespace characters.", in text), // Any string too short to possibly be any supported format. - { Length: > 0 and < 3 } => throw new ColorParseException ( - in text, - "Text was too short to be any possible supported format.", - in text - ), - - // The various hexadecimal cases - ['#', ..] hexString => hexString switch - { - // #RGB - ['#', var rChar, var gChar, var bChar] chars when chars [1..] - .IsAllAsciiHexDigits () => - new Color ( - byte.Parse ([rChar, rChar], NumberStyles.HexNumber), - byte.Parse ([gChar, gChar], NumberStyles.HexNumber), - byte.Parse ([bChar, bChar], NumberStyles.HexNumber) - ), - - // #ARGB - ['#', var aChar, var rChar, var gChar, var bChar] chars when chars [1..] - .IsAllAsciiHexDigits () => - new Color ( - byte.Parse ([rChar, rChar], NumberStyles.HexNumber), - byte.Parse ([gChar, gChar], NumberStyles.HexNumber), - byte.Parse ([bChar, bChar], NumberStyles.HexNumber), - byte.Parse ([aChar, aChar], NumberStyles.HexNumber) - ), - - // #RRGGBB - [ - '#', var r1Char, var r2Char, var g1Char, var g2Char, var b1Char, - var b2Char - ] chars when chars [1..].IsAllAsciiHexDigits () => - new Color ( - byte.Parse ([r1Char, r2Char], NumberStyles.HexNumber), - byte.Parse ([g1Char, g2Char], NumberStyles.HexNumber), - byte.Parse ([b1Char, b2Char], NumberStyles.HexNumber) - ), - - // #AARRGGBB - [ - '#', var a1Char, var a2Char, var r1Char, var r2Char, var g1Char, - var g2Char, var b1Char, var b2Char - ] chars when chars [1..].IsAllAsciiHexDigits () => - new Color ( - byte.Parse ([r1Char, r2Char], NumberStyles.HexNumber), - byte.Parse ([g1Char, g2Char], NumberStyles.HexNumber), - byte.Parse ([b1Char, b2Char], NumberStyles.HexNumber), - byte.Parse ([a1Char, a2Char], NumberStyles.HexNumber) - ), - _ => throw new ColorParseException ( - in hexString, - $"Color hex string {hexString} was not in a supported format", - in hexString - ) - }, - - // rgb(r,g,b) or rgb(r,g,b,a) - ['r', 'g', 'b', '(', .., ')'] => ParseRgbaFormat (in text, 4), - - // rgba(r,g,b,a) or rgba(r,g,b) - ['r', 'g', 'b', 'a', '(', .., ')'] => ParseRgbaFormat (in text, 5), - - // Attempt to parse as a named color from the ColorStrings resources - { } when char.IsLetter (text [0]) && ColorStrings.TryParseW3CColorName (text.ToString (), out Color color) => - new Color (color), + { Length: > 0 and < 3 } => + throw new ColorParseException (in text, "Text was too short to be any possible supported format.", in text), + // The various hexadecimal cases + ['#', ..] hexString => hexString switch + { + // #RGB + ['#', var rChar, var gChar, var bChar] chars when chars [1..] + .IsAllAsciiHexDigits () => + new Color ( + byte.Parse ([rChar, rChar], NumberStyles.HexNumber), + byte.Parse ([gChar, gChar], NumberStyles.HexNumber), + byte.Parse ([bChar, bChar], NumberStyles.HexNumber) + ), + + // #ARGB + ['#', var aChar, var rChar, var gChar, var bChar] chars when chars [1..] + .IsAllAsciiHexDigits () => + new Color ( + byte.Parse ([rChar, rChar], NumberStyles.HexNumber), + byte.Parse ([gChar, gChar], NumberStyles.HexNumber), + byte.Parse ([bChar, bChar], NumberStyles.HexNumber), + byte.Parse ([aChar, aChar], NumberStyles.HexNumber) + ), + + // #RRGGBB + [ + '#', var r1Char, var r2Char, var g1Char, var g2Char, var b1Char, var b2Char + ] chars when chars [1..].IsAllAsciiHexDigits () => + new Color ( + byte.Parse ([r1Char, r2Char], NumberStyles.HexNumber), + byte.Parse ([g1Char, g2Char], NumberStyles.HexNumber), + byte.Parse ([b1Char, b2Char], NumberStyles.HexNumber) + ), + + // #AARRGGBB + [ + '#', var a1Char, var a2Char, + var r1Char, var r2Char, + var g1Char, var g2Char, + var b1Char, var b2Char + ] chars when chars [1..].IsAllAsciiHexDigits () => + new Color ( + byte.Parse ([r1Char, r2Char], NumberStyles.HexNumber), + byte.Parse ([g1Char, g2Char], NumberStyles.HexNumber), + byte.Parse ([b1Char, b2Char], NumberStyles.HexNumber), + byte.Parse ([a1Char, a2Char], NumberStyles.HexNumber) + ), + _ => throw new ColorParseException ( + in hexString, + $"Color hex string {hexString} was not in a supported format", + in hexString + ) + }, + + // rgb(r,g,b) or rgb(r,g,b,a) + ['r', 'g', 'b', '(', .., ')'] => ParseRgbaFormat (in text, 4), + + // rgba(r,g,b,a) or rgba(r,g,b) + ['r', 'g', 'b', 'a', '(', .., ')'] => ParseRgbaFormat (in text, 5), + // Attempt named colors + { } when char.IsLetter (text [0]) && ColorStrings.TryParseNamedColor (text, out Color color) => color, // Any other input _ => throw new ColorParseException (in text, "Text did not match any expected format.", in text, []) }; @@ -585,11 +573,9 @@ public static bool TryParse (ReadOnlySpan utf8Text, IFormatProvider? provi [SkipLocalsInit] public override string ToString () { - string? name = ColorStrings.GetW3CColorName (this); - - if (name is { }) + if (ColorStrings.GetColorName (this) is string colorName) { - return name; + return colorName; } return $"#{R:X2}{G:X2}{B:X2}"; diff --git a/Terminal.Gui/Drawing/Color/Color.cs b/Terminal.Gui/Drawing/Color/Color.cs index d81254c73a..23c74c8779 100644 --- a/Terminal.Gui/Drawing/Color/Color.cs +++ b/Terminal.Gui/Drawing/Color/Color.cs @@ -1,7 +1,5 @@ #nullable enable using System.Collections.Frozen; -using System.Diagnostics.Contracts; -using System.Drawing; using System.Globalization; using System.Numerics; using System.Runtime.CompilerServices; @@ -236,6 +234,15 @@ internal static ColorName16 GetClosestNamedColor16 (Color inputColor) return ColorExtensions.ColorToName16Map.MinBy (pair => CalculateColorDistance (inputColor, pair.Key)).Value; } + /// Converts the given color value to exact named color represented by . + /// + /// Successfully converted named color. + /// True if conversion succeeded; otherwise false. + internal static bool TryGetExactNamedColor16 (Color inputColor, out ColorName16 colorName16) + { + return ColorExtensions.ColorToName16Map.TryGetValue (inputColor, out colorName16); + } + [SkipLocalsInit] private static float CalculateColorDistance (in Vector4 color1, in Vector4 color2) { return Vector4.Distance (color1, color2); } diff --git a/Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs b/Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs index 5c3bc6dba9..96316ac431 100644 --- a/Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs +++ b/Terminal.Gui/Drawing/Color/ColorScheme.Colors.cs @@ -185,6 +185,11 @@ public bool ContainsKey (string key) } } + /// + /// Copies the elements of the to an array, starting at a particular array index. + /// + /// The one-dimensional array that is the destination of the elements copied from . + /// The zero-based index in array at which copying begins. public void CopyTo (KeyValuePair [] array, int arrayIndex) { lock (_lock) @@ -193,6 +198,10 @@ public void CopyTo (KeyValuePair [] array, int arrayIndex) } } + /// + /// Returns an enumerator that iterates through the . + /// + /// An enumerator for the . public IEnumerator> GetEnumerator () { lock (_lock) @@ -206,6 +215,7 @@ IEnumerator IEnumerable.GetEnumerator () return GetEnumerator (); } + /// public bool Remove (KeyValuePair item) { lock (_lock) @@ -219,6 +229,7 @@ public bool Remove (KeyValuePair item) } } + /// public bool Remove (string key) { lock (_lock) @@ -245,7 +256,7 @@ public bool TryGetValue (string key, out ColorScheme? value) /// /// Resets the dictionary to its default values. /// - /// + /// The reset dictionary. public static Dictionary Reset () { lock (_lock) diff --git a/Terminal.Gui/Drawing/Color/ColorStrings.cs b/Terminal.Gui/Drawing/Color/ColorStrings.cs index 79ca9f357e..fc57b7a3e1 100644 --- a/Terminal.Gui/Drawing/Color/ColorStrings.cs +++ b/Terminal.Gui/Drawing/Color/ColorStrings.cs @@ -1,8 +1,5 @@ #nullable enable -using System.Collections; using System.Globalization; -using System.Resources; -using Terminal.Gui.Resources; namespace Terminal.Gui; @@ -11,7 +8,9 @@ namespace Terminal.Gui; /// public static class ColorStrings { - // PERFORMANCE: See https://stackoverflow.com/a/15521524/297526 for why GlobalResources.GetString is fast. + private static readonly AnsiColorNameResolver Ansi = new(); + private static readonly W3cColorNameResolver W3c = new(); + private static readonly MultiStandardColorNameResolver Multi = new(); /// /// Gets the W3C standard string for . @@ -20,7 +19,39 @@ public static class ColorStrings /// if there is no standard color name for the specified color. public static string? GetW3CColorName (Color color) { - return GlobalResources.GetString ($"#{color.R:X2}{color.G:X2}{color.B:X2}", CultureInfo.CurrentUICulture); + if (W3c.TryNameColor (color, out string? name)) + { + return name; + } + return null; + } + + /// + /// Gets the ANSI 4-bit (16) color name for . + /// + /// The color. + /// if there is no standard color name for the specified color. + public static string? GetANSIColor16Name (Color color) + { + if (Ansi.TryNameColor (color, out string? name)) + { + return name; + } + return null; + } + + /// + /// Gets backwards compatible color name for . + /// + /// The color. + /// Standard color name for the specified color; otherwise . + public static string? GetColorName (Color color) + { + if (Multi.TryNameColor (color, out string? name)) + { + return name; + } + return null; } /// @@ -29,54 +60,77 @@ public static class ColorStrings /// public static IEnumerable GetW3CColorNames () { - ResourceSet? resourceSet = GlobalResources.GetResourceSet (CultureInfo.CurrentUICulture, true, true); - if (resourceSet == null) + return W3c.GetColorNames (); + } + + /// + /// Parses and returns if name is a W3C standard named color. + /// + /// The name to parse. + /// If successful, the color. + /// if was parsed successfully. + public static bool TryParseW3CColorName (ReadOnlySpan name, out Color color) + { + if (W3c.TryParseColor (name, out color)) { - yield break; + return true; } + // Backwards compatibility: Also parse #RRGGBB. + return TryParseHexColor (name, out color); + } - foreach (DictionaryEntry entry in resourceSet) + /// + /// Parses and returns if name is a ANSI 4-bit standard named color. + /// + /// The name to parse. + /// If successful, the color. + /// if was parsed successfully. + public static bool TryParseColor16 (ReadOnlySpan name, out Color color) + { + if (Ansi.TryParseColor (name, out color)) { - if (entry is { Value: string colorName, Key: string key } && key.StartsWith ('#')) - { - yield return colorName; - } + return true; } + color = default; + return false; } /// - /// Parses and returns if name is a W3C standard named color. + /// Parses and returns if name is either ANSI 4-bit or W3C standard named color. /// /// The name to parse. /// If successful, the color. /// if was parsed successfully. - public static bool TryParseW3CColorName (string name, out Color color) + public static bool TryParseNamedColor (ReadOnlySpan name, out Color color) { - foreach (DictionaryEntry entry in GlobalResources.GetResourceSet (CultureInfo.CurrentUICulture, true, true)!) + if (Multi.TryParseColor (name, out color)) { - if (entry.Value is string colorName && colorName.Equals (name, StringComparison.OrdinalIgnoreCase)) - { - return TryParseColorKey (entry.Key.ToString (), out color); - } + return true; + } + // Backwards compatibility: Also parse #RRGGBB. + if (TryParseHexColor (name, out color)) + { + return true; } - return TryParseColorKey (name, out color); + color = default; + return false; + } - bool TryParseColorKey (string? key, out Color color) + private static bool TryParseHexColor (ReadOnlySpan name, out Color color) + { + if (name.Length == 7 && name [0] == '#') { - if (key != null && key.StartsWith ('#') && key.Length == 7) + if (int.TryParse (name.Slice (1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int r) && + int.TryParse (name.Slice (3, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int g) && + int.TryParse (name.Slice (5, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int b)) { - if (int.TryParse (key.AsSpan (1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int r) && - int.TryParse (key.AsSpan (3, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int g) && - int.TryParse (key.AsSpan (5, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int b)) - { - color = new Color (r, g, b); - return true; - } + color = new Color (r, g, b); + return true; } - - color = default (Color); - return false; } + + color = default; + return false; } } diff --git a/Terminal.Gui/Drawing/Color/IColorNameResolver.cs b/Terminal.Gui/Drawing/Color/IColorNameResolver.cs index 5af243ee4a..cbbe70985e 100644 --- a/Terminal.Gui/Drawing/Color/IColorNameResolver.cs +++ b/Terminal.Gui/Drawing/Color/IColorNameResolver.cs @@ -1,4 +1,8 @@ -namespace Terminal.Gui; +#nullable enable + +using System.Diagnostics.CodeAnalysis; + +namespace Terminal.Gui; /// /// When implemented by a class, allows mapping to @@ -20,7 +24,7 @@ public interface IColorNameResolver /// /// /// - bool TryNameColor (Color color, out string name); + bool TryNameColor (Color color, [NotNullWhen(true)]out string? name); /// /// Returns if is a recognized @@ -30,5 +34,5 @@ public interface IColorNameResolver /// /// /// - bool TryParseColor (string name, out Color color); + bool TryParseColor (ReadOnlySpan name, out Color color); } diff --git a/Terminal.Gui/Drawing/Color/MultiStandardColorNameResolver.cs b/Terminal.Gui/Drawing/Color/MultiStandardColorNameResolver.cs new file mode 100644 index 0000000000..01554bbb31 --- /dev/null +++ b/Terminal.Gui/Drawing/Color/MultiStandardColorNameResolver.cs @@ -0,0 +1,188 @@ +#nullable enable + +using System.Collections.Frozen; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Terminal.Gui; + +/// +/// Backwards compatible(-ish) color name resolver prioritizing ANSI 4-bit (16) colors with fallback to W3C colors. +/// +public class MultiStandardColorNameResolver : IColorNameResolver +{ + private static readonly AnsiColorNameResolver Ansi = new(); + private static readonly W3cColorNameResolver W3c = new(); + private static readonly FrozenSet W3cBlockedColors; + private static readonly ImmutableArray CombinedColorNames; + private static readonly FrozenDictionary W3cSubstituteColors; + + static MultiStandardColorNameResolver () + { + HashSet combinedNames = new(Ansi.GetColorNames()); + + HashSet w3cInconsistentColors = new(); + Dictionary w3cSubstituteColors = new(StringComparer.OrdinalIgnoreCase); + + IEnumerable enumerableW3cNames = W3c.GetColorNames (); + IReadOnlyList w3cNames = enumerableW3cNames is IReadOnlyList alreadyReadOnlyList + ? alreadyReadOnlyList + : [.. enumerableW3cNames]; + + Dictionary> w3cColorsWithAlternativeNames = w3cNames + .GroupBy(w3cName => + { + if (!W3c.TryParseColor(w3cName, out Color w3cColor)) + { + throw new InvalidOperationException ($"W3C color name '{w3cName}' does not resolve to any W3C color."); + } + return w3cColor; + }) + .Where(g => g.Count() > 1) + .ToDictionary(g => g.Key, g => g.ToHashSet()); + + // Gather inconsistencies between ANSI and W3C, filter out or substitute problematic W3C colors and names, + // and create additional blocklist for W3C colors. + // Blocking and filtering is only applied to W3C because this resolver prioritizes ANSI for backwards compatibility. + // It would be a lot simpler to just prioritize W3C colors and names. + foreach (string w3cName in w3cNames) + { + if (w3cSubstituteColors.ContainsKey (w3cName)) + { + // Already dealt with alternative name. + continue; + } + + if (!W3c.TryParseColor (w3cName, out Color w3cColor)) + { + // This condition is just inverted to reduce indentation. + // Also it should practically never happen if the W3C color name resolver is properly implemented. + throw new InvalidOperationException ($"W3C color name '{w3cName}' does not resolve to any color."); + } + + if (w3cColorsWithAlternativeNames.TryGetValue (w3cColor, out var names)) + { + bool substituted = false; + // Alternative names cause issues with ColorPicker etc. when combined with ANSI and prioritizing ANSI resolver. + // For example Aqua is not in ColorName16 but the actual color value resolves to ANSI Cyan + // so autocomplete for Aqua suddenly changes to Cyan because they happen to have same color value in both color scheme. + // Also DarkGrey would cause inconsistencies because the alternative DarkGray exists in ANSI and has different color value. + foreach (string name in names) + { + if (Ansi.TryParseColor (name, out Color substituteColor)) + { + // Block the W3C color when it is inconsistent with the substitute color + // so there is no situation where W3C color -> color name -> ANSI color. + if (w3cColor != substituteColor) + { + w3cInconsistentColors.Add (w3cColor); + } + + // Substitute all W3C alternatives to match with the ANSI color to keep colors consistent. + foreach (string alternativeName in names) + { + w3cSubstituteColors.Add (alternativeName, substituteColor); + combinedNames.Add (alternativeName); + } + substituted = true; + break; + } + } + + if (substituted) + { + // Already dealt with, continue to next W3C color name. + continue; + } + } + + // Same name, different ANSI value. + // For example both #767676 (ColorName16) and #A9A9A9 (W3C) resolve to DarkGray, + // although a bad example because it is already substituted due to also having alternative names. + if (Ansi.TryParseColor (w3cName, out Color ansiColor) && w3cColor != ansiColor) + { + w3cInconsistentColors.Add (w3cColor); + continue; + } + + combinedNames.Add (w3cName); + } + + // TODO: Utilize .NET 9 and later alternative lookup for matching ReadOnlySpan with string. + W3cSubstituteColors = w3cSubstituteColors.ToFrozenDictionary ( + // Workaround for alternative lookup not being available in .NET 8 by matching ReadOnlySpan hash code to string hash code. + keySelector: kvp => string.GetHashCode (kvp.Key, StringComparison.OrdinalIgnoreCase), + // The string element is for detecting hash collision. + elementSelector: kvp => (kvp.Key, kvp.Value)); + W3cBlockedColors = w3cInconsistentColors.ToFrozenSet (); + CombinedColorNames = combinedNames.Order ().ToImmutableArray (); + } + + /// + public IEnumerable GetColorNames () + { + return CombinedColorNames; + } + + /// + public bool TryNameColor (Color color, [NotNullWhen (true)] out string? name) + { + if (Ansi.TryNameColor (color, out string? ansiName)) + { + name = ansiName; + return true; + } + + if (!IsBlockedW3cColor (color) && + W3c.TryNameColor (color, out string? w3cName)) + { + name = w3cName; + return true; + } + + name = null; + return false; + } + + /// + public bool TryParseColor (ReadOnlySpan name, out Color color) + { + if (Ansi.TryParseColor (name, out color)) + { + return true; + } + + if (GetSubstituteW3cColor (name, out color)) + { + return true; + } + + if (W3c.TryParseColor (name, out color) && + !IsBlockedW3cColor (color)) + { + return true; + } + + color = default; + return false; + } + + private static bool GetSubstituteW3cColor (ReadOnlySpan name, out Color substituteColor) + { + int nameHashCode = string.GetHashCode(name, StringComparison.OrdinalIgnoreCase); + if (W3cSubstituteColors.TryGetValue (nameHashCode, out var match) && + match is (string matchName, Color matchColor) && + name.Equals (matchName, StringComparison.OrdinalIgnoreCase)) + { + substituteColor = matchColor; + return true; + } + substituteColor = default; + return false; + } + + private static bool IsBlockedW3cColor (Color color) + { + return W3cBlockedColors.Contains (color); + } +} diff --git a/Terminal.Gui/Drawing/Color/W3CColors.cs b/Terminal.Gui/Drawing/Color/W3CColors.cs deleted file mode 100644 index baa1a1101e..0000000000 --- a/Terminal.Gui/Drawing/Color/W3CColors.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Terminal.Gui; - -/// -/// Helper class that resolves w3c color names to their hex values -/// Based on https://www.w3schools.com/colors/color_tryit.asp -/// -public class W3CColors : IColorNameResolver -{ - /// - public IEnumerable GetColorNames () { return ColorStrings.GetW3CColorNames (); } - - /// - public bool TryParseColor (string name, out Color color) { return ColorStrings.TryParseW3CColorName (name, out color); } - - /// - public bool TryNameColor (Color color, out string name) - { - string answer = ColorStrings.GetW3CColorName (color); - - name = answer ?? string.Empty; - - return answer != null; - } -} diff --git a/Terminal.Gui/Drawing/Color/W3cColor.cs b/Terminal.Gui/Drawing/Color/W3cColor.cs new file mode 100644 index 0000000000..a2cc07dabd --- /dev/null +++ b/Terminal.Gui/Drawing/Color/W3cColor.cs @@ -0,0 +1,777 @@ +namespace Terminal.Gui; + +/// +/// Represents the W3C color names with their RGB values. +/// +/// +/// Based on https://www.w3schools.com/colors/color_tryit.asp page. +/// +public enum W3cColor +{ + /// + /// Alice blue RGB(240, 248, 255). + /// + AliceBlue = 0xF0F8FF, + + /// + /// Antique white RGB(250, 235, 215). + /// + AntiqueWhite = 0xFAEBD7, + + /// + /// Aqua RGB(0, 255, 255). + /// + Aqua = 0x00FFFF, + + /// + /// Aquamarine RGB(127, 255, 212). + /// + Aquamarine = 0x7FFFD4, + + /// + /// Azure RGB(240, 255, 255). + /// + Azure = 0xF0FFFF, + + /// + /// Beige RGB(245, 245, 220). + /// + Beige = 0xF5F5DC, + + /// + /// Bisque RGB(255, 228, 196). + /// + Bisque = 0xFFE4C4, + + /// + /// Black RGB(0, 0, 0). + /// + Black = 0x000000, + + /// + /// Blanched almond RGB(255, 235, 205). + /// + BlanchedAlmond = 0xFFEBCD, + + /// + /// Blue RGB(0, 0, 255). + /// + Blue = 0x0000FF, + + /// + /// Blue violet RGB(138, 43, 226). + /// + BlueViolet = 0x8A2BE2, + + /// + /// Brown RGB(165, 42, 42). + /// + Brown = 0xA52A2A, + + /// + /// Burly wood RGB(222, 184, 135). + /// + BurlyWood = 0xDEB887, + + /// + /// Cadet blue RGB(95, 158, 160). + /// + CadetBlue = 0x5F9EA0, + + /// + /// Chartreuse RGB(127, 255, 0). + /// + Chartreuse = 0x7FFF00, + + /// + /// Chocolate RGB(210, 105, 30). + /// + Chocolate = 0xD2691E, + + /// + /// Coral RGB(255, 127, 80). + /// + Coral = 0xFF7F50, + + /// + /// Cornflower blue RGB(100, 149, 237). + /// + CornflowerBlue = 0x6495ED, + + /// + /// Cornsilk RGB(255, 248, 220). + /// + Cornsilk = 0xFFF8DC, + + /// + /// Crimson RGB(220, 20, 60). + /// + Crimson = 0xDC143C, + + /// + /// Cyan RGB(0, 255, 255). + /// + /// + /// Same as . + /// + Cyan = Aqua, + + /// + /// Dark blue RGB(0, 0, 139). + /// + DarkBlue = 0x00008B, + + /// + /// Dark cyan RGB(0, 139, 139). + /// + DarkCyan = 0x008B8B, + + /// + /// Dark goldenrod RGB(184, 134, 11). + /// + DarkGoldenrod = 0xB8860B, + + /// + /// Dark gray RGB(169, 169, 169). + /// + DarkGray = 0xA9A9A9, + + /// + /// Dark green RGB(0, 100, 0). + /// + DarkGreen = 0x006400, + + /// + /// Dark grey RGB(169, 169, 169). + /// + /// + /// Same as . + /// + DarkGrey = DarkGray, + + /// + /// Dark khaki RGB(189, 183, 107). + /// + DarkKhaki = 0xBDB76B, + + /// + /// Dark magenta RGB(139, 0, 139). + /// + DarkMagenta = 0x8B008B, + + /// + /// Dark olive green RGB(85, 107, 47). + /// + DarkOliveGreen = 0x556B2F, + + /// + /// Dark orange RGB(255, 140, 0). + /// + DarkOrange = 0xFF8C00, + + /// + /// Dark orchid RGB(153, 50, 204). + /// + DarkOrchid = 0x9932CC, + + /// + /// Dark red RGB(139, 0, 0). + /// + DarkRed = 0x8B0000, + + /// + /// Dark salmon RGB(233, 150, 122). + /// + DarkSalmon = 0xE9967A, + + /// + /// Dark sea green RGB(143, 188, 143). + /// + DarkSeaGreen = 0x8FBC8F, + + /// + /// Dark slate blue RGB(72, 61, 139). + /// + DarkSlateBlue = 0x483D8B, + + /// + /// Dark slate gray RGB(47, 79, 79). + /// + DarkSlateGray = 0x2F4F4F, + + /// + /// Dark slate grey RGB(47, 79, 79). + /// + /// + /// Same as . + /// + DarkSlateGrey = DarkSlateGray, + + /// + /// Dark turquoise RGB(0, 206, 209). + /// + DarkTurquoise = 0x00CED1, + + /// + /// Dark violet RGB(148, 0, 211). + /// + DarkViolet = 0x9400D3, + + /// + /// Deep pink RGB(255, 20, 147). + /// + DeepPink = 0xFF1493, + + /// + /// Deep sky blue RGB(0, 191, 255). + /// + DeepSkyBlue = 0x00BFFF, + + /// + /// Dim gray RGB(105, 105, 105). + /// + DimGray = 0x696969, + + /// + /// Dim grey RGB(105, 105, 105). + /// + /// + /// Same as . + /// + DimGrey = DimGray, + + /// + /// Dodger blue RGB(30, 144, 255). + /// + DodgerBlue = 0x1E90FF, + + /// + /// Fire brick RGB(178, 34, 34). + /// + FireBrick = 0xB22222, + + /// + /// Floral white RGB(255, 250, 240). + /// + FloralWhite = 0xFFFAF0, + + /// + /// Forest green RGB(34, 139, 34). + /// + ForestGreen = 0x228B22, + + /// + /// Fuchsia RGB(255, 0, 255). + /// + /// + /// Same as . + /// + Fuchsia = Magenta, + + /// + /// Gainsboro RGB(220, 220, 220). + /// + Gainsboro = 0xDCDCDC, + + /// + /// Ghost white RGB(248, 248, 255). + /// + GhostWhite = 0xF8F8FF, + + /// + /// Gold RGB(255, 215, 0). + /// + Gold = 0xFFD700, + + /// + /// Goldenrod RGB(218, 165, 32). + /// + Goldenrod = 0xDAA520, + + /// + /// Gray RGB(128, 128, 128). + /// + Gray = 0x808080, + + /// + /// Green RGB(0, 128, 0). + /// + Green = 0x008000, + + /// + /// Green yellow RGB(173, 255, 47). + /// + GreenYellow = 0xADFF2F, + + /// + /// Grey RGB(128, 128, 128). + /// + /// + /// Same as . + /// + Grey = Gray, + + /// + /// Honey dew RGB(240, 255, 240). + /// + HoneyDew = 0xF0FFF0, + + /// + /// Hot pink RGB(255, 105, 180). + /// + HotPink = 0xFF69B4, + + /// + /// Indian red RGB(205, 92, 92). + /// + IndianRed = 0xCD5C5C, + + /// + /// Indigo RGB(75, 0, 130). + /// + Indigo = 0x4B0082, + + /// + /// Ivory RGB(255, 255, 240). + /// + Ivory = 0xFFFFF0, + + /// + /// Khaki RGB(240, 230, 140). + /// + Khaki = 0xF0E68C, + + /// + /// Lavender RGB(230, 230, 250). + /// + Lavender = 0xE6E6FA, + + /// + /// Lavender blush RGB(255, 240, 245). + /// + LavenderBlush = 0xFFF0F5, + + /// + /// Lawn green RGB(124, 252, 0). + /// + LawnGreen = 0x7CFC00, + + /// + /// Lemon chiffon RGB(255, 250, 205). + /// + LemonChiffon = 0xFFFACD, + + /// + /// Light blue RGB(173, 216, 230). + /// + LightBlue = 0xADD8E6, + + /// + /// Light coral RGB(240, 128, 128). + /// + LightCoral = 0xF08080, + + /// + /// Light cyan RGB(224, 255, 255). + /// + LightCyan = 0xE0FFFF, + + /// + /// Light goldenrod yellow RGB(250, 250, 210). + /// + LightGoldenrodYellow = 0xFAFAD2, + + /// + /// Light gray RGB(211, 211, 211). + /// + LightGray = 0xD3D3D3, + + /// + /// Light green RGB(144, 238, 144). + /// + LightGreen = 0x90EE90, + + /// + /// Light grey RGB(211, 211, 211). + /// + /// + /// Same as . + /// + LightGrey = LightGray, + + /// + /// Light pink RGB(255, 182, 193). + /// + LightPink = 0xFFB6C1, + + /// + /// Light salmon RGB(255, 160, 122). + /// + LightSalmon = 0xFFA07A, + + /// + /// Light sea green RGB(32, 178, 170). + /// + LightSeaGreen = 0x20B2AA, + + /// + /// Light sky blue RGB(135, 206, 250). + /// + LightSkyBlue = 0x87CEFA, + + /// + /// Light slate gray RGB(119, 136, 153). + /// + LightSlateGray = 0x778899, + + /// + /// Light slate grey RGB(119, 136, 153). + /// + /// + /// Same as . + /// + LightSlateGrey = LightSlateGray, + + /// + /// Light steel blue RGB(176, 196, 222). + /// + LightSteelBlue = 0xB0C4DE, + + /// + /// Light yellow RGB(255, 255, 224). + /// + LightYellow = 0xFFFFE0, + + /// + /// Lime RGB(0, 255, 0). + /// + Lime = 0x00FF00, + + /// + /// Lime green RGB(50, 205, 50). + /// + LimeGreen = 0x32CD32, + + /// + /// Linen RGB(250, 240, 230). + /// + Linen = 0xFAF0E6, + + /// + /// Magenta RGB(255, 0, 255). + /// + Magenta = 0xFF00FF, + + /// + /// Maroon RGB(128, 0, 0). + /// + Maroon = 0x800000, + + /// + /// Medium aqua marine RGB(102, 205, 170). + /// + MediumAquaMarine = 0x66CDAA, + + /// + /// Medium blue RGB(0, 0, 205). + /// + MediumBlue = 0x0000CD, + + /// + /// Medium orchid RGB(186, 85, 211). + /// + MediumOrchid = 0xBA55D3, + + /// + /// Medium purple RGB(147, 112, 219). + /// + MediumPurple = 0x9370DB, + + /// + /// Medium sea green RGB(60, 179, 113). + /// + MediumSeaGreen = 0x3CB371, + + /// + /// Medium slate blue RGB(123, 104, 238). + /// + MediumSlateBlue = 0x7B68EE, + + /// + /// Medium spring green RGB(0, 250, 154). + /// + MediumSpringGreen = 0x00FA9A, + + /// + /// Medium turquoise RGB(72, 209, 204). + /// + MediumTurquoise = 0x48D1CC, + + /// + /// Medium violet red RGB(199, 21, 133). + /// + MediumVioletRed = 0xC71585, + + /// + /// Midnight blue RGB(25, 25, 112). + /// + MidnightBlue = 0x191970, + + /// + /// Mint cream RGB(245, 255, 250). + /// + MintCream = 0xF5FFFA, + + /// + /// Misty rose RGB(255, 228, 225). + /// + MistyRose = 0xFFE4E1, + + /// + /// Moccasin RGB(255, 228, 181). + /// + Moccasin = 0xFFE4B5, + + /// + /// Navajo white RGB(255, 222, 173). + /// + NavajoWhite = 0xFFDEAD, + + /// + /// Navy RGB(0, 0, 128). + /// + Navy = 0x000080, + + /// + /// Old lace RGB(253, 245, 230). + /// + OldLace = 0xFDF5E6, + + /// + /// Olive RGB(128, 128, 0). + /// + Olive = 0x808000, + + /// + /// Olive drab RGB(107, 142, 35). + /// + OliveDrab = 0x6B8E23, + + /// + /// Orange RGB(255, 165, 0). + /// + Orange = 0xFFA500, + + /// + /// Orange red RGB(255, 69, 0). + /// + OrangeRed = 0xFF4500, + + /// + /// Orchid RGB(218, 112, 214). + /// + Orchid = 0xDA70D6, + + /// + /// Pale goldenrod RGB(238, 232, 170). + /// + PaleGoldenrod = 0xEEE8AA, + + /// + /// Pale green RGB(152, 251, 152). + /// + PaleGreen = 0x98FB98, + + /// + /// Pale turquoise RGB(175, 238, 238). + /// + PaleTurquoise = 0xAFEEEE, + + /// + /// Pale violet red RGB(219, 112, 147). + /// + PaleVioletRed = 0xDB7093, + + /// + /// Papaya whip RGB(255, 239, 213). + /// + PapayaWhip = 0xFFEFD5, + + /// + /// Peach puff RGB(255, 218, 185). + /// + PeachPuff = 0xFFDAB9, + + /// + /// Peru RGB(205, 133, 63). + /// + Peru = 0xCD853F, + + /// + /// Pink RGB(255, 192, 203). + /// + Pink = 0xFFC0CB, + + /// + /// Plum RGB(221, 160, 221). + /// + Plum = 0xDDA0DD, + + /// + /// Powder blue RGB(176, 224, 230). + /// + PowderBlue = 0xB0E0E6, + + /// + /// Purple RGB(128, 0, 128). + /// + Purple = 0x800080, + + /// + /// Rebecca purple RGB(102, 51, 153). + /// + RebeccaPurple = 0x663399, + + /// + /// Red RGB(255, 0, 0). + /// + Red = 0xFF0000, + + /// + /// Rosy brown RGB(188, 143, 143). + /// + RosyBrown = 0xBC8F8F, + + /// + /// Royal blue RGB(65, 105, 225). + /// + RoyalBlue = 0x4169E1, + + /// + /// Saddle brown RGB(139, 69, 19). + /// + SaddleBrown = 0x8B4513, + + /// + /// Salmon RGB(250, 128, 114). + /// + Salmon = 0xFA8072, + + /// + /// Sandy brown RGB(244, 164, 96). + /// + SandyBrown = 0xF4A460, + + /// + /// Sea green RGB(46, 139, 87). + /// + SeaGreen = 0x2E8B57, + + /// + /// Sea shell RGB(255, 245, 238). + /// + SeaShell = 0xFFF5EE, + + /// + /// Sienna RGB(160, 82, 45). + /// + Sienna = 0xA0522D, + + /// + /// Silver RGB(192, 192, 192). + /// + Silver = 0xC0C0C0, + + /// + /// Sky blue RGB(135, 206, 235). + /// + SkyBlue = 0x87CEEB, + + /// + /// Slate blue RGB(106, 90, 205). + /// + SlateBlue = 0x6A5ACD, + + /// + /// Slate gray RGB(112, 128, 144). + /// + SlateGray = 0x708090, + + /// + /// Slate grey RGB(112, 128, 144). + /// + /// + /// Same as . + /// + SlateGrey = SlateGray, + + /// + /// Snow RGB(255, 250, 250). + /// + Snow = 0xFFFAFA, + + /// + /// Spring green RGB(0, 255, 127). + /// + SpringGreen = 0x00FF7F, + + /// + /// Steel blue RGB(70, 130, 180). + /// + SteelBlue = 0x4682B4, + + /// + /// Tan RGB(210, 180, 140). + /// + Tan = 0xD2B48C, + + /// + /// Teal RGB(0, 128, 128). + /// + Teal = 0x008080, + + /// + /// Thistle RGB(216, 191, 216). + /// + Thistle = 0xD8BFD8, + + /// + /// Tomato RGB(255, 99, 71). + /// + Tomato = 0xFF6347, + + /// + /// Turquoise RGB(64, 224, 208). + /// + Turquoise = 0x40E0D0, + + /// + /// Violet RGB(238, 130, 238). + /// + Violet = 0xEE82EE, + + /// + /// Wheat RGB(245, 222, 179). + /// + Wheat = 0xF5DEB3, + + /// + /// White RGB(255, 255, 255). + /// + White = 0xFFFFFF, + + /// + /// White smoke RGB(245, 245, 245). + /// + WhiteSmoke = 0xF5F5F5, + + /// + /// Yellow RGB(255, 255, 0). + /// + Yellow = 0xFFFF00, + + /// + /// Yellow green RGB(154, 205, 50). + /// + YellowGreen = 0x9ACD32 +} diff --git a/Terminal.Gui/Drawing/Color/W3cColorNameResolver.cs b/Terminal.Gui/Drawing/Color/W3cColorNameResolver.cs new file mode 100644 index 0000000000..446e425726 --- /dev/null +++ b/Terminal.Gui/Drawing/Color/W3cColorNameResolver.cs @@ -0,0 +1,110 @@ +#nullable enable + +using System.Collections.Frozen; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Terminal.Gui; + +/// +/// W3C color name resolver. +/// +public class W3cColorNameResolver : IColorNameResolver +{ + /// + public IEnumerable GetColorNames () => + W3cColors.GetColorNames (); + + /// + public bool TryParseColor (ReadOnlySpan name, out Color color) => + W3cColors.TryParseColor (name, out color); + + /// + public bool TryNameColor (Color color, [NotNullWhen (true)] out string? name) => + W3cColors.TryNameColor (color, out name); +} + +/// +/// Helper class for transforming to and from enum. +/// +internal static class W3cColors +{ + private static readonly ImmutableArray Names; + private static readonly FrozenDictionary ArgbNameMap; + + static W3cColors () + { + // Populate based on names because enums with same numerical value + // are not otherwise distinguishable from each other. + string[] w3cNames = Enum.GetNames ().Order().ToArray(); + + Dictionary map = new(w3cNames.Length); + foreach (string name in w3cNames) + { + W3cColor w3c = Enum.Parse(name); + uint argb = GetArgb(w3c); + // TODO: Collect aliases? + _ = map.TryAdd (argb, name); + } + + Names = ImmutableArray.Create (w3cNames); + ArgbNameMap = map.ToFrozenDictionary (); + } + + /// + /// Gets read-only list of the W3C colors in alphabetical order. + /// + public static IReadOnlyList GetColorNames () + { + return Names; + } + + /// + /// Converts the given W3C color name to equivalent color value. + /// + /// W3C color name. + /// The successfully converted W3C color value. + /// True if the conversion succeeded; otherwise false. + public static bool TryParseColor (ReadOnlySpan name, out Color color) + { + if (!Enum.TryParse (name, ignoreCase: true, out W3cColor w3cColor) || + // Any numerical value converts to undefined enum value. + !Enum.IsDefined (w3cColor)) + { + color = default; + return false; + } + + uint argb = GetArgb (w3cColor); + color = new Color (argb); + return true; + } + + /// + /// Converts the given color value to a W3C color name. + /// + /// Color value to match W3C color. + /// The successfully converted W3C color name. + /// True if conversion succeeded; otherwise false. + public static bool TryNameColor (Color color, [NotNullWhen (true)] out string? name) + { + if (ArgbNameMap.TryGetValue (color.Argb, out name)) + { + return true; + } + + name = null; + return false; + } + + private static uint GetArgb (W3cColor w3cColor) + { + const int alphaShift = 24; + const uint alphaMask = 0xFFU << alphaShift; + + int rgb = (int)w3cColor; + + uint argb = (uint)rgb | alphaMask; + return argb; + } +} diff --git a/Terminal.Gui/Resources/Strings.Designer.cs b/Terminal.Gui/Resources/Strings.Designer.cs index e329b718e7..e88ae567cd 100644 --- a/Terminal.Gui/Resources/Strings.Designer.cs +++ b/Terminal.Gui/Resources/Strings.Designer.cs @@ -60,1320 +60,6 @@ internal Strings() { } } - /// - /// Looks up a localized string similar to Black. - /// - internal static string _000000 { - get { - return ResourceManager.GetString("#000000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Navy. - /// - internal static string _000080 { - get { - return ResourceManager.GetString("#000080", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkBlue. - /// - internal static string _00008B { - get { - return ResourceManager.GetString("#00008B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumBlue. - /// - internal static string _0000CD { - get { - return ResourceManager.GetString("#0000CD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Blue. - /// - internal static string _0000FF { - get { - return ResourceManager.GetString("#0000FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkGreen. - /// - internal static string _006400 { - get { - return ResourceManager.GetString("#006400", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Green. - /// - internal static string _008000 { - get { - return ResourceManager.GetString("#008000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Teal. - /// - internal static string _008080 { - get { - return ResourceManager.GetString("#008080", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkCyan. - /// - internal static string _008B8B { - get { - return ResourceManager.GetString("#008B8B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DeepSkyBlue. - /// - internal static string _00BFFF { - get { - return ResourceManager.GetString("#00BFFF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkTurquoise. - /// - internal static string _00CED1 { - get { - return ResourceManager.GetString("#00CED1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumSpringGreen. - /// - internal static string _00FA9A { - get { - return ResourceManager.GetString("#00FA9A", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Lime. - /// - internal static string _00FF00 { - get { - return ResourceManager.GetString("#00FF00", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SpringGreen. - /// - internal static string _00FF7F { - get { - return ResourceManager.GetString("#00FF7F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cyan. - /// - internal static string _00FFFF { - get { - return ResourceManager.GetString("#00FFFF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightGreen. - /// - internal static string _16C60C { - get { - return ResourceManager.GetString("#16C60C", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MidnightBlue. - /// - internal static string _191970 { - get { - return ResourceManager.GetString("#191970", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DodgerBlue. - /// - internal static string _1E90FF { - get { - return ResourceManager.GetString("#1E90FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightSeaGreen. - /// - internal static string _20B2AA { - get { - return ResourceManager.GetString("#20B2AA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ForestGreen. - /// - internal static string _228B22 { - get { - return ResourceManager.GetString("#228B22", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SeaGreen. - /// - internal static string _2E8B57 { - get { - return ResourceManager.GetString("#2E8B57", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkSlateGrey. - /// - internal static string _2F4F4F { - get { - return ResourceManager.GetString("#2F4F4F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LimeGreen. - /// - internal static string _32CD32 { - get { - return ResourceManager.GetString("#32CD32", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightBlue. - /// - internal static string _3B78FF { - get { - return ResourceManager.GetString("#3B78FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumSeaGreen. - /// - internal static string _3CB371 { - get { - return ResourceManager.GetString("#3CB371", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Turquoise. - /// - internal static string _40E0D0 { - get { - return ResourceManager.GetString("#40E0D0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to RoyalBlue. - /// - internal static string _4169E1 { - get { - return ResourceManager.GetString("#4169E1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SteelBlue. - /// - internal static string _4682B4 { - get { - return ResourceManager.GetString("#4682B4", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkSlateBlue. - /// - internal static string _483D8B { - get { - return ResourceManager.GetString("#483D8B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumTurquoise. - /// - internal static string _48D1CC { - get { - return ResourceManager.GetString("#48D1CC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Indigo. - /// - internal static string _4B0082 { - get { - return ResourceManager.GetString("#4B0082", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkOliveGreen. - /// - internal static string _556B2F { - get { - return ResourceManager.GetString("#556B2F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to CadetBlue. - /// - internal static string _5F9EA0 { - get { - return ResourceManager.GetString("#5F9EA0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightCyan. - /// - internal static string _61D6D6 { - get { - return ResourceManager.GetString("#61D6D6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to CornflowerBlue. - /// - internal static string _6495ED { - get { - return ResourceManager.GetString("#6495ED", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to RebeccaPurple. - /// - internal static string _663399 { - get { - return ResourceManager.GetString("#663399", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumAquaMarine. - /// - internal static string _66CDAA { - get { - return ResourceManager.GetString("#66CDAA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DimGray. - /// - internal static string _696969 { - get { - return ResourceManager.GetString("#696969", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SlateBlue. - /// - internal static string _6A5ACD { - get { - return ResourceManager.GetString("#6A5ACD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to OliveDrab. - /// - internal static string _6B8E23 { - get { - return ResourceManager.GetString("#6B8E23", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SlateGray. - /// - internal static string _708090 { - get { - return ResourceManager.GetString("#708090", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkGray. - /// - internal static string _767676 { - get { - return ResourceManager.GetString("#767676", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightSlateGrey. - /// - internal static string _778899 { - get { - return ResourceManager.GetString("#778899", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumSlateBlue. - /// - internal static string _7B68EE { - get { - return ResourceManager.GetString("#7B68EE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LawnGreen. - /// - internal static string _7CFC00 { - get { - return ResourceManager.GetString("#7CFC00", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Chartreuse. - /// - internal static string _7FFF00 { - get { - return ResourceManager.GetString("#7FFF00", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Aquamarine. - /// - internal static string _7FFFD4 { - get { - return ResourceManager.GetString("#7FFFD4", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maroon. - /// - internal static string _800000 { - get { - return ResourceManager.GetString("#800000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Purple. - /// - internal static string _800080 { - get { - return ResourceManager.GetString("#800080", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Olive. - /// - internal static string _808000 { - get { - return ResourceManager.GetString("#808000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gray. - /// - internal static string _808080 { - get { - return ResourceManager.GetString("#808080", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SkyBlue. - /// - internal static string _87CEEB { - get { - return ResourceManager.GetString("#87CEEB", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightSkyBlue. - /// - internal static string _87CEFA { - get { - return ResourceManager.GetString("#87CEFA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BlueViolet. - /// - internal static string _8A2BE2 { - get { - return ResourceManager.GetString("#8A2BE2", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkRed. - /// - internal static string _8B0000 { - get { - return ResourceManager.GetString("#8B0000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkMagenta. - /// - internal static string _8B008B { - get { - return ResourceManager.GetString("#8B008B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SaddleBrown. - /// - internal static string _8B4513 { - get { - return ResourceManager.GetString("#8B4513", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkSeaGreen. - /// - internal static string _8FBC8F { - get { - return ResourceManager.GetString("#8FBC8F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightGreen. - /// - internal static string _90EE90 { - get { - return ResourceManager.GetString("#90EE90", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumPurple. - /// - internal static string _9370DB { - get { - return ResourceManager.GetString("#9370DB", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkViolet. - /// - internal static string _9400D3 { - get { - return ResourceManager.GetString("#9400D3", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PaleGreen. - /// - internal static string _98FB98 { - get { - return ResourceManager.GetString("#98FB98", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkOrchid. - /// - internal static string _9932CC { - get { - return ResourceManager.GetString("#9932CC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to YellowGreen. - /// - internal static string _9ACD32 { - get { - return ResourceManager.GetString("#9ACD32", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Sienna. - /// - internal static string _A0522D { - get { - return ResourceManager.GetString("#A0522D", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Brown. - /// - internal static string _A52A2A { - get { - return ResourceManager.GetString("#A52A2A", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkGrey. - /// - internal static string _A9A9A9 { - get { - return ResourceManager.GetString("#A9A9A9", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightBlue. - /// - internal static string _ADD8E6 { - get { - return ResourceManager.GetString("#ADD8E6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to GreenYellow. - /// - internal static string _ADFF2F { - get { - return ResourceManager.GetString("#ADFF2F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PaleTurquoise. - /// - internal static string _AFEEEE { - get { - return ResourceManager.GetString("#AFEEEE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightSteelBlue. - /// - internal static string _B0C4DE { - get { - return ResourceManager.GetString("#B0C4DE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PowderBlue. - /// - internal static string _B0E0E6 { - get { - return ResourceManager.GetString("#B0E0E6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FireBrick. - /// - internal static string _B22222 { - get { - return ResourceManager.GetString("#B22222", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightMagenta. - /// - internal static string _B4009E { - get { - return ResourceManager.GetString("#B4009E", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkGoldenRod. - /// - internal static string _B8860B { - get { - return ResourceManager.GetString("#B8860B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumOrchid. - /// - internal static string _BA55D3 { - get { - return ResourceManager.GetString("#BA55D3", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to RosyBrown. - /// - internal static string _BC8F8F { - get { - return ResourceManager.GetString("#BC8F8F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkKhaki. - /// - internal static string _BDB76B { - get { - return ResourceManager.GetString("#BDB76B", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Silver. - /// - internal static string _C0C0C0 { - get { - return ResourceManager.GetString("#C0C0C0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MediumVioletRed. - /// - internal static string _C71585 { - get { - return ResourceManager.GetString("#C71585", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to IndianRed. - /// - internal static string _CD5C5C { - get { - return ResourceManager.GetString("#CD5C5C", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Peru. - /// - internal static string _CD853F { - get { - return ResourceManager.GetString("#CD853F", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Chocolate. - /// - internal static string _D2691E { - get { - return ResourceManager.GetString("#D2691E", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tan. - /// - internal static string _D2B48C { - get { - return ResourceManager.GetString("#D2B48C", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightGray. - /// - internal static string _D3D3D3 { - get { - return ResourceManager.GetString("#D3D3D3", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Thistle. - /// - internal static string _D8BFD8 { - get { - return ResourceManager.GetString("#D8BFD8", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Orchid. - /// - internal static string _DA70D6 { - get { - return ResourceManager.GetString("#DA70D6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to GoldenRod. - /// - internal static string _DAA520 { - get { - return ResourceManager.GetString("#DAA520", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PaleVioletRed. - /// - internal static string _DB7093 { - get { - return ResourceManager.GetString("#DB7093", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Crimson. - /// - internal static string _DC143C { - get { - return ResourceManager.GetString("#DC143C", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gainsboro. - /// - internal static string _DCDCDC { - get { - return ResourceManager.GetString("#DCDCDC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Plum. - /// - internal static string _DDA0DD { - get { - return ResourceManager.GetString("#DDA0DD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BurlyWood. - /// - internal static string _DEB887 { - get { - return ResourceManager.GetString("#DEB887", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightCyan. - /// - internal static string _E0FFFF { - get { - return ResourceManager.GetString("#E0FFFF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Lavender. - /// - internal static string _E6E6FA { - get { - return ResourceManager.GetString("#E6E6FA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightRed. - /// - internal static string _E74856 { - get { - return ResourceManager.GetString("#E74856", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkSalmon. - /// - internal static string _E9967A { - get { - return ResourceManager.GetString("#E9967A", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Violet. - /// - internal static string _EE82EE { - get { - return ResourceManager.GetString("#EE82EE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PaleGoldenRod. - /// - internal static string _EEE8AA { - get { - return ResourceManager.GetString("#EEE8AA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightCoral. - /// - internal static string _F08080 { - get { - return ResourceManager.GetString("#F08080", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Khaki. - /// - internal static string _F0E68C { - get { - return ResourceManager.GetString("#F0E68C", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to AliceBlue. - /// - internal static string _F0F8FF { - get { - return ResourceManager.GetString("#F0F8FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to HoneyDew. - /// - internal static string _F0FFF0 { - get { - return ResourceManager.GetString("#F0FFF0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Azure. - /// - internal static string _F0FFFF { - get { - return ResourceManager.GetString("#F0FFFF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SandyBrown. - /// - internal static string _F4A460 { - get { - return ResourceManager.GetString("#F4A460", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Wheat. - /// - internal static string _F5DEB3 { - get { - return ResourceManager.GetString("#F5DEB3", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Beige. - /// - internal static string _F5F5DC { - get { - return ResourceManager.GetString("#F5F5DC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to WhiteSmoke. - /// - internal static string _F5F5F5 { - get { - return ResourceManager.GetString("#F5F5F5", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MintCream. - /// - internal static string _F5FFFA { - get { - return ResourceManager.GetString("#F5FFFA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to GhostWhite. - /// - internal static string _F8F8FF { - get { - return ResourceManager.GetString("#F8F8FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BrightYellow. - /// - internal static string _F9F1A5 { - get { - return ResourceManager.GetString("#F9F1A5", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Salmon. - /// - internal static string _FA8072 { - get { - return ResourceManager.GetString("#FA8072", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to AntiqueWhite. - /// - internal static string _FAEBD7 { - get { - return ResourceManager.GetString("#FAEBD7", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Linen. - /// - internal static string _FAF0E6 { - get { - return ResourceManager.GetString("#FAF0E6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightGoldenRodYellow. - /// - internal static string _FAFAD2 { - get { - return ResourceManager.GetString("#FAFAD2", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to OldLace. - /// - internal static string _FDF5E6 { - get { - return ResourceManager.GetString("#FDF5E6", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Red. - /// - internal static string _FF0000 { - get { - return ResourceManager.GetString("#FF0000", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Magenta. - /// - internal static string _FF00FF { - get { - return ResourceManager.GetString("#FF00FF", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DeepPink. - /// - internal static string _FF1493 { - get { - return ResourceManager.GetString("#FF1493", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to OrangeRed. - /// - internal static string _FF4500 { - get { - return ResourceManager.GetString("#FF4500", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tomato. - /// - internal static string _FF6347 { - get { - return ResourceManager.GetString("#FF6347", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to HotPink. - /// - internal static string _FF69B4 { - get { - return ResourceManager.GetString("#FF69B4", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Coral. - /// - internal static string _FF7F50 { - get { - return ResourceManager.GetString("#FF7F50", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DarkOrange. - /// - internal static string _FF8C00 { - get { - return ResourceManager.GetString("#FF8C00", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightSalmon. - /// - internal static string _FFA07A { - get { - return ResourceManager.GetString("#FFA07A", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Orange. - /// - internal static string _FFA500 { - get { - return ResourceManager.GetString("#FFA500", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightPink. - /// - internal static string _FFB6C1 { - get { - return ResourceManager.GetString("#FFB6C1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Pink. - /// - internal static string _FFC0CB { - get { - return ResourceManager.GetString("#FFC0CB", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Gold. - /// - internal static string _FFD700 { - get { - return ResourceManager.GetString("#FFD700", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PeachPuff. - /// - internal static string _FFDAB9 { - get { - return ResourceManager.GetString("#FFDAB9", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to NavajoWhite. - /// - internal static string _FFDEAD { - get { - return ResourceManager.GetString("#FFDEAD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Moccasin. - /// - internal static string _FFE4B5 { - get { - return ResourceManager.GetString("#FFE4B5", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Bisque. - /// - internal static string _FFE4C4 { - get { - return ResourceManager.GetString("#FFE4C4", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MistyRose. - /// - internal static string _FFE4E1 { - get { - return ResourceManager.GetString("#FFE4E1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BlanchedAlmond. - /// - internal static string _FFEBCD { - get { - return ResourceManager.GetString("#FFEBCD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PapayaWhip. - /// - internal static string _FFEFD5 { - get { - return ResourceManager.GetString("#FFEFD5", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LavenderBlush. - /// - internal static string _FFF0F5 { - get { - return ResourceManager.GetString("#FFF0F5", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SeaShell. - /// - internal static string _FFF5EE { - get { - return ResourceManager.GetString("#FFF5EE", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cornsilk. - /// - internal static string _FFF8DC { - get { - return ResourceManager.GetString("#FFF8DC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LemonChiffon. - /// - internal static string _FFFACD { - get { - return ResourceManager.GetString("#FFFACD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FloralWhite. - /// - internal static string _FFFAF0 { - get { - return ResourceManager.GetString("#FFFAF0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Snow. - /// - internal static string _FFFAFA { - get { - return ResourceManager.GetString("#FFFAFA", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Yellow. - /// - internal static string _FFFF00 { - get { - return ResourceManager.GetString("#FFFF00", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LightYellow. - /// - internal static string _FFFFE0 { - get { - return ResourceManager.GetString("#FFFFE0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Ivory. - /// - internal static string _FFFFF0 { - get { - return ResourceManager.GetString("#FFFFF0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to White. - /// - internal static string _FFFFFF { - get { - return ResourceManager.GetString("#FFFFFF", resourceCulture); - } - } - /// /// Looks up a localized string similar to _Cancel. /// diff --git a/Terminal.Gui/Resources/Strings.resx b/Terminal.Gui/Resources/Strings.resx index 773ee55937..e241b11f8e 100644 --- a/Terminal.Gui/Resources/Strings.resx +++ b/Terminal.Gui/Resources/Strings.resx @@ -280,444 +280,6 @@ Date Picker - - AliceBlue - - - AntiqueWhite - - - Aquamarine - - - Azure - - - Beige - - - Bisque - - - Black - - - BlanchedAlmond - - - Blue - - - BlueViolet - - - Brown - - - BurlyWood - - - CadetBlue - - - Chartreuse - - - Chocolate - - - Coral - - - CornflowerBlue - - - Cornsilk - - - Crimson - - - Cyan - - - DarkBlue - - - DarkCyan - - - DarkGoldenRod - - - DarkGrey - - - DarkGreen - - - DarkKhaki - - - DarkMagenta - - - DarkOliveGreen - - - DarkOrange - - - DarkOrchid - - - DarkRed - - - DarkSalmon - - - DarkSeaGreen - - - DarkSlateBlue - - - DarkSlateGrey - - - DarkTurquoise - - - DarkViolet - - - DeepPink - - - DeepSkyBlue - - - DimGray - - - DodgerBlue - - - FireBrick - - - FloralWhite - - - ForestGreen - - - Gainsboro - - - GhostWhite - - - Gold - - - GoldenRod - - - Gray - - - Green - - - GreenYellow - - - HoneyDew - - - HotPink - - - IndianRed - - - Indigo - - - Ivory - - - Khaki - - - Lavender - - - LavenderBlush - - - LawnGreen - - - LemonChiffon - - - LightBlue - - - LightCoral - - - LightCyan - - - LightGoldenRodYellow - - - LightGray - - - LightGreen - - - LightPink - - - LightSalmon - - - LightSeaGreen - - - LightSkyBlue - - - LightSlateGrey - - - LightSteelBlue - - - LightYellow - - - Lime - - - LimeGreen - - - Linen - - - Magenta - - - Maroon - - - MediumAquaMarine - - - MediumBlue - - - MediumOrchid - - - MediumPurple - - - MediumSeaGreen - - - MediumSlateBlue - - - MediumSpringGreen - - - MediumTurquoise - - - MediumVioletRed - - - MidnightBlue - - - MintCream - - - MistyRose - - - Moccasin - - - NavajoWhite - - - Navy - - - OldLace - - - Olive - - - OliveDrab - - - Orange - - - OrangeRed - - - Orchid - - - PaleGoldenRod - - - PaleGreen - - - PaleTurquoise - - - PaleVioletRed - - - PapayaWhip - - - PeachPuff - - - Peru - - - Pink - - - Plum - - - PowderBlue - - - Purple - - - RebeccaPurple - - - Red - - - RosyBrown - - - RoyalBlue - - - SaddleBrown - - - Salmon - - - SandyBrown - - - SeaGreen - - - SeaShell - - - Sienna - - - Silver - - - SkyBlue - - - SlateBlue - - - SlateGray - - - Snow - - - SpringGreen - - - SteelBlue - - - Tan - - - Teal - - - Thistle - - - Tomato - - - Turquoise - - - Violet - - - Wheat - - - White - - - WhiteSmoke - - - Yellow - - - YellowGreen - - - BrightBlue - - - BrightCyan - - - BrightRed - - - BrightGreen - - - BrightMagenta - - - BrightYellow - - - DarkGray - Co_lors diff --git a/Terminal.Gui/Views/ColorPicker.cs b/Terminal.Gui/Views/ColorPicker.cs index 415fc1acd1..2bd102085c 100644 --- a/Terminal.Gui/Views/ColorPicker.cs +++ b/Terminal.Gui/Views/ColorPicker.cs @@ -1,7 +1,5 @@ #nullable enable -using System; - namespace Terminal.Gui; /// @@ -34,7 +32,7 @@ public ColorPicker () private Color _selectedColor = Color.Black; // TODO: Add interface - private readonly IColorNameResolver _colorNameResolver = new W3CColors (); + private readonly IColorNameResolver _colorNameResolver = new MultiStandardColorNameResolver (); private List _bars = new (); @@ -64,7 +62,7 @@ public void ApplyStyleChanges () Width = textFieldWidth }; tfValue.HasFocusChanged += UpdateSingleBarValueFromTextField; - tfValue.Accepting += (s, _)=>UpdateSingleBarValueFromTextField(s); + tfValue.Accepting += (s, _) => UpdateSingleBarValueFromTextField (s); _textFields.Add (bar, tfValue); } @@ -182,7 +180,7 @@ private void CreateTextField () Add (_tfHex); _tfHex.HasFocusChanged += UpdateValueFromTextField; - _tfHex.Accepting += (_,_)=> UpdateValueFromTextField(); + _tfHex.Accepting += (_, _) => UpdateValueFromTextField (); } private void DisposeOldViews () @@ -266,7 +264,7 @@ private void SyncSubViewValues (bool syncBars) if (_tfName != null) { - _tfName.Text = _colorNameResolver.TryNameColor (_selectedColor, out string name) ? name : string.Empty; + _tfName.Text = _colorNameResolver.TryNameColor (_selectedColor, out string? name) ? name : string.Empty; } if (_tfHex != null) @@ -312,7 +310,7 @@ private void UpdateValueFromName (object? sender, HasFocusEventArgs e) } // it is a leave event so update - UpdateValueFromName(); + UpdateValueFromName (); } private void UpdateValueFromName () { diff --git a/Tests/UnitTests/Resources/ResourceManagerTests.cs b/Tests/UnitTests/Resources/ResourceManagerTests.cs index 1c49b3447f..15ebb0bdda 100644 --- a/Tests/UnitTests/Resources/ResourceManagerTests.cs +++ b/Tests/UnitTests/Resources/ResourceManagerTests.cs @@ -9,10 +9,6 @@ namespace Terminal.Gui.ResourcesTests; public class ResourceManagerTests { - private const string DODGER_BLUE_COLOR_KEY = "DodgerBlue"; - private const string DODGER_BLUE_COLOR_NAME = "DodgerBlue"; - private const string NO_NAMED_COLOR_KEY = "#1E80FF"; - private const string NO_NAMED_COLOR_NAME = "#1E80FF"; private const string EXISTENT_CULTURE = "pt-PT"; private const string NO_EXISTENT_CULTURE = "de-DE"; private const string NO_EXISTENT_KEY = "blabla"; @@ -50,51 +46,6 @@ public void GetObject_FallBack_To_Default_For_Not_Translated_Existent_Culture_Fi RestoreCurrentCultures (); } - [Fact] - public void GetResourceSet_FallBack_To_Default_For_No_Existent_Culture_File () - { - CultureInfo.CurrentCulture = new (NO_EXISTENT_CULTURE); - CultureInfo.CurrentUICulture = new (NO_EXISTENT_CULTURE); - - // W3CColors.GetColorNames also calls ColorStrings.GetW3CColorNames - string [] colorNames = new W3CColors ().GetColorNames ().ToArray (); - Assert.Contains (DODGER_BLUE_COLOR_NAME, colorNames); - Assert.DoesNotContain (NO_TRANSLATED_VALUE, colorNames); - - RestoreCurrentCultures (); - } - - [Fact] - public void GetResourceSet_FallBack_To_Default_For_Not_Translated_Existent_Culture_File () - { - CultureInfo.CurrentCulture = new (EXISTENT_CULTURE); - CultureInfo.CurrentUICulture = new (EXISTENT_CULTURE); - - // These aren't already translated - // ColorStrings.GetW3CColorNames method uses GetResourceSet method to retrieve color names - IEnumerable colorNames = ColorStrings.GetW3CColorNames (); - Assert.NotEmpty (colorNames); - - // W3CColors.GetColorNames also calls ColorStrings.GetW3CColorNames - colorNames = new W3CColors ().GetColorNames ().ToArray (); - Assert.Contains (DODGER_BLUE_COLOR_NAME, colorNames); - Assert.DoesNotContain (NO_TRANSLATED_VALUE, colorNames); - - // ColorStrings.TryParseW3CColorName method uses GetResourceSet method to retrieve a color value - Assert.True (ColorStrings.TryParseW3CColorName (DODGER_BLUE_COLOR_NAME, out Color color)); - Assert.Equal (DODGER_BLUE_COLOR_KEY, color.ToString ()); - - // W3CColors.GetColorNames also calls ColorStrings.GetW3CColorNames for no-named colors - colorNames = new W3CColors ().GetColorNames ().ToArray (); - Assert.DoesNotContain (NO_NAMED_COLOR_NAME, colorNames); - - // ColorStrings.TryParseW3CColorName method uses GetResourceSet method to retrieve a color value for no-named colors - Assert.True (ColorStrings.TryParseW3CColorName (NO_NAMED_COLOR_NAME, out color)); - Assert.Equal (NO_NAMED_COLOR_KEY, color.ToString ()); - - RestoreCurrentCultures (); - } - [Fact] public void GetResourceSet_With_Filter_Does_Not_Overflows_If_Key_Does_Not_Exist () { diff --git a/Tests/UnitTests/Views/ColorPickerTests.cs b/Tests/UnitTests/Views/ColorPickerTests.cs index 121696ff1d..5de5cb0bcf 100644 --- a/Tests/UnitTests/Views/ColorPickerTests.cs +++ b/Tests/UnitTests/Views/ColorPickerTests.cs @@ -749,7 +749,15 @@ public void ColorPicker_TabCompleteColorName () // Auto complete the color name Application.RaiseKeyDownEvent (Key.Tab); - Assert.Equal ("Aquamarine", name.Text); + // Match cyan alternative name + Assert.Equal ("Aqua", name.Text); + + Assert.True (name.HasFocus); + + Application.RaiseKeyDownEvent (Key.Tab); + + // Resolves to cyan color + Assert.Equal ("Cyan", name.Text); // Tab out of the text field Application.RaiseKeyDownEvent (Key.Tab); @@ -757,7 +765,7 @@ public void ColorPicker_TabCompleteColorName () Assert.False (name.HasFocus); Assert.NotSame (name, cp.Focused); - Assert.Equal ("#7FFFD4", hex.Text); + Assert.Equal ("#00FFFF", hex.Text); Application.Top?.Dispose (); Application.ResetState (true); @@ -817,14 +825,6 @@ public static IEnumerable ColorPickerTestData_WithTextFields () }; } - [Fact] - public void TestColorNames () - { - var colors = new W3CColors (); - Assert.Contains ("Aquamarine", colors.GetColorNames ()); - Assert.DoesNotContain ("Save as", colors.GetColorNames ()); - } - private ColorBar GetColorBar (ColorPicker cp, ColorPickerPart toGet) { if (toGet <= ColorPickerPart.Bar3) @@ -845,7 +845,7 @@ private ColorPicker GetColorPicker (ColorModel colorModel, bool showTextFields, Application.Navigation = new (); - Application.Top = new() { Width = 20, Height = 5 }; + Application.Top = new () { Width = 20, Height = 5 }; Application.Top.Add (cp); Application.Top.LayoutSubViews (); diff --git a/Tests/UnitTestsParallelizable/Drawing/Color/AnsiColorNameResolverTests.cs b/Tests/UnitTestsParallelizable/Drawing/Color/AnsiColorNameResolverTests.cs new file mode 100644 index 0000000000..76e8e34bfe --- /dev/null +++ b/Tests/UnitTestsParallelizable/Drawing/Color/AnsiColorNameResolverTests.cs @@ -0,0 +1,124 @@ +#nullable enable + +namespace Terminal.Gui.DrawingTests; + +public class AnsiColorNameResolverTests +{ + private readonly AnsiColorNameResolver _candidate = new(); + + [Fact] + public void GetNames_Returns16ColorNames () + { + string[] expected = Enum.GetNames(); + + string[] actual = _candidate.GetColorNames ().ToArray(); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (0, 0, 0, nameof (ColorName16.Black))] + [InlineData (0, 0, 255, nameof (ColorName16.Blue))] + [InlineData (59, 120, 255, nameof (ColorName16.BrightBlue))] + [InlineData (97, 214, 214, nameof (ColorName16.BrightCyan))] + [InlineData (22, 198, 12, nameof (ColorName16.BrightGreen))] + [InlineData (180, 0, 158, nameof (ColorName16.BrightMagenta))] + [InlineData (231, 72, 86, nameof (ColorName16.BrightRed))] + [InlineData (249, 241, 165, nameof (ColorName16.BrightYellow))] + [InlineData (0, 255, 255, nameof (ColorName16.Cyan))] + [InlineData (118, 118, 118, nameof (ColorName16.DarkGray))] + [InlineData (128, 128, 128, nameof (ColorName16.Gray))] + [InlineData (0, 128, 0, nameof (ColorName16.Green))] + [InlineData (255, 0, 255, nameof (ColorName16.Magenta))] + [InlineData (255, 0, 0, nameof (ColorName16.Red))] + [InlineData (255, 255, 255, nameof (ColorName16.White))] + [InlineData (255, 255, 0, nameof (ColorName16.Yellow))] + public void TryNameColor_ReturnsExpectedColorName (byte r, byte g, byte b, string expectedName) + { + var expected = (true, expectedName); + + bool actualSuccess = _candidate.TryNameColor(new Color(r, g, b), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Fact] + public void TryNameColor_NoMatchFails () + { + (bool, string?) expected = (false, null); + + bool actualSuccess = _candidate.TryNameColor (new Color (1, 2, 3), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (nameof (ColorName16.Black), 0, 0, 0)] + [InlineData (nameof (ColorName16.Blue), 0, 0, 255)] + [InlineData (nameof (ColorName16.BrightBlue), 59, 120, 255)] + [InlineData (nameof (ColorName16.BrightCyan), 97, 214, 214)] + [InlineData (nameof (ColorName16.BrightGreen), 22, 198, 12)] + [InlineData (nameof (ColorName16.BrightMagenta), 180, 0, 158)] + [InlineData (nameof (ColorName16.BrightRed), 231, 72, 86)] + [InlineData (nameof (ColorName16.BrightYellow), 249, 241, 165)] + [InlineData (nameof (ColorName16.Cyan), 0, 255, 255)] + [InlineData (nameof (ColorName16.DarkGray), 118, 118, 118)] + [InlineData (nameof (ColorName16.Gray), 128, 128, 128)] + [InlineData (nameof (ColorName16.Green), 0, 128, 0)] + [InlineData (nameof (ColorName16.Magenta), 255, 0, 255)] + [InlineData (nameof (ColorName16.Red), 255, 0, 0)] + [InlineData (nameof (ColorName16.White), 255, 255, 255)] + [InlineData (nameof (ColorName16.Yellow), 255, 255, 0)] + // Case-insensitive + [InlineData ("BRIGHTBLUE", 59, 120, 255)] + [InlineData ("brightblue", 59, 120, 255)] + public void TryParseColor_ReturnsExpectedColor (string inputName, byte r, byte g, byte b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("12", 231, 72, 86)] // ColorName16.BrightRed + public void TryParseColor_ResolvesValidEnumNumber (string inputName, byte r, byte g, byte b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (null)] + [InlineData ("")] + [InlineData ("brightlight")] + public void TryParseColor_FailsOnInvalidColorName (string? invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("-12")] + public void TryParseColor_FailsOnInvalidEnumNumber (string invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } +} diff --git a/Tests/UnitTestsParallelizable/Drawing/Color/MultiStandardColorNameResolverTests.cs b/Tests/UnitTestsParallelizable/Drawing/Color/MultiStandardColorNameResolverTests.cs new file mode 100644 index 0000000000..0e7677d659 --- /dev/null +++ b/Tests/UnitTestsParallelizable/Drawing/Color/MultiStandardColorNameResolverTests.cs @@ -0,0 +1,232 @@ +#nullable enable + +namespace Terminal.Gui.DrawingTests; + +public class MultiStandardColorNameResolverTests +{ + private readonly MultiStandardColorNameResolver _candidate = new(); + + [Theory] + // ANSI color names. + [InlineData (nameof (ColorName16.Black))] + [InlineData (nameof (ColorName16.White))] + [InlineData (nameof (ColorName16.Red))] + [InlineData (nameof (ColorName16.Green))] + [InlineData (nameof (ColorName16.Blue))] + [InlineData (nameof (ColorName16.Cyan))] + [InlineData (nameof (ColorName16.Magenta))] + [InlineData (nameof (ColorName16.DarkGray))] + [InlineData (nameof (ColorName16.BrightGreen))] + [InlineData (nameof (ColorName16.BrightMagenta))] + // Regular W3C color. + [InlineData (nameof (W3cColor.AliceBlue))] + [InlineData (nameof (W3cColor.BlanchedAlmond))] + [InlineData (nameof (W3cColor.CadetBlue))] + [InlineData (nameof (W3cColor.DarkBlue))] + [InlineData (nameof (W3cColor.FireBrick))] + [InlineData (nameof (W3cColor.Gainsboro))] + [InlineData (nameof (W3cColor.HoneyDew))] + [InlineData (nameof (W3cColor.Indigo))] + [InlineData (nameof (W3cColor.Khaki))] + [InlineData (nameof (W3cColor.Lavender))] + [InlineData (nameof (W3cColor.Maroon))] + [InlineData (nameof (W3cColor.Navy))] + [InlineData (nameof (W3cColor.Olive))] + [InlineData (nameof (W3cColor.Plum))] + [InlineData (nameof (W3cColor.RoyalBlue))] + [InlineData (nameof (W3cColor.Silver))] + [InlineData (nameof (W3cColor.Tomato))] + [InlineData (nameof (W3cColor.Violet))] + [InlineData (nameof (W3cColor.WhiteSmoke))] + [InlineData (nameof (W3cColor.YellowGreen))] + // W3C alternatives. + [InlineData (nameof (W3cColor.Grey))] + [InlineData (nameof (W3cColor.DarkGrey))] + [InlineData (nameof (W3cColor.Aqua))] + [InlineData (nameof (W3cColor.Fuchsia))] + [InlineData (nameof (W3cColor.DarkSlateGray))] + [InlineData (nameof (W3cColor.DarkSlateGrey))] + [InlineData (nameof (W3cColor.DimGray))] + [InlineData (nameof (W3cColor.DimGrey))] + [InlineData (nameof (W3cColor.LightGray))] + [InlineData (nameof (W3cColor.LightGrey))] + [InlineData (nameof (W3cColor.SlateGray))] + [InlineData (nameof (W3cColor.SlateGrey))] + public void GetNames_ContainsCombinationOfAnsiAndW3cNames (string name) + { + string[] names = _candidate.GetColorNames ().ToArray(); + Assert.Contains (name, names); + } + + [Theory] + // ANSI color names + [InlineData (0, 0, 0, nameof (ColorName16.Black))] + [InlineData (0, 0, 255, nameof (ColorName16.Blue))] + [InlineData (59, 120, 255, nameof (ColorName16.BrightBlue))] + [InlineData (97, 214, 214, nameof (ColorName16.BrightCyan))] + [InlineData (22, 198, 12, nameof (ColorName16.BrightGreen))] + [InlineData (180, 0, 158, nameof (ColorName16.BrightMagenta))] + [InlineData (231, 72, 86, nameof (ColorName16.BrightRed))] + [InlineData (249, 241, 165, nameof (ColorName16.BrightYellow))] + [InlineData (0, 255, 255, nameof (ColorName16.Cyan))] + [InlineData (118, 118, 118, nameof (ColorName16.DarkGray))] + [InlineData (128, 128, 128, nameof (ColorName16.Gray))] + [InlineData (0, 128, 0, nameof (ColorName16.Green))] + [InlineData (255, 0, 255, nameof (ColorName16.Magenta))] + [InlineData (255, 0, 0, nameof (ColorName16.Red))] + [InlineData (255, 255, 255, nameof (ColorName16.White))] + [InlineData (255, 255, 0, nameof (ColorName16.Yellow))] + // W3C color names + [InlineData (240, 248, 255, nameof (W3cColor.AliceBlue))] + [InlineData (255, 235, 205, nameof (W3cColor.BlanchedAlmond))] + [InlineData (95, 158, 160, nameof (W3cColor.CadetBlue))] + [InlineData (0, 0, 139, nameof (W3cColor.DarkBlue))] + [InlineData (178, 34, 34, nameof (W3cColor.FireBrick))] + [InlineData (220, 220, 220, nameof (W3cColor.Gainsboro))] + [InlineData (240, 255, 240, nameof (W3cColor.HoneyDew))] + [InlineData (75, 0, 130, nameof (W3cColor.Indigo))] + [InlineData (240, 230, 140, nameof (W3cColor.Khaki))] + [InlineData (230, 230, 250, nameof (W3cColor.Lavender))] + [InlineData (128, 0, 0, nameof (W3cColor.Maroon))] + [InlineData (0, 0, 128, nameof (W3cColor.Navy))] + [InlineData (128, 128, 0, nameof (W3cColor.Olive))] + [InlineData (221, 160, 221, nameof (W3cColor.Plum))] + [InlineData (65, 105, 225, nameof (W3cColor.RoyalBlue))] + [InlineData (192, 192, 192, nameof (W3cColor.Silver))] + [InlineData (255, 99, 71, nameof (W3cColor.Tomato))] + [InlineData (238, 130, 238, nameof (W3cColor.Violet))] + [InlineData (245, 245, 245, nameof (W3cColor.WhiteSmoke))] + [InlineData (154, 205, 50, nameof (W3cColor.YellowGreen))] + public void TryNameColor_ReturnsExpectedColorNames (byte r, byte g, byte b, string expectedName) + { + var expected = (true, expectedName); + + bool actualSuccess = _candidate.TryNameColor(new Color(r, g, b), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (169, 169, 169)] // W3cColor.DarkGr(a|e)y + public void TryNameColor_OmitsBlockedW3cColors (byte r, byte g, byte b) + { + (bool, string?) expected = (false, null); + + bool actualSuccess = _candidate.TryNameColor (new Color (r, g, b), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Fact] + public void TryNameColor_NoMatchFails () + { + (bool, string?) expected = (false, null); + + bool actualSuccess = _candidate.TryNameColor (new Color (1, 2, 3), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Theory] + // ANSI colors + [InlineData (nameof (ColorName16.Black), 0, 0, 0)] + [InlineData (nameof (ColorName16.Blue), 0, 0, 255)] + [InlineData (nameof (ColorName16.BrightBlue), 59, 120, 255)] + [InlineData (nameof (ColorName16.BrightCyan), 97, 214, 214)] + [InlineData (nameof (ColorName16.BrightGreen), 22, 198, 12)] + [InlineData (nameof (ColorName16.BrightMagenta), 180, 0, 158)] + [InlineData (nameof (ColorName16.BrightRed), 231, 72, 86)] + [InlineData (nameof (ColorName16.BrightYellow), 249, 241, 165)] + [InlineData (nameof (ColorName16.Cyan), 0, 255, 255)] + [InlineData (nameof (ColorName16.DarkGray), 118, 118, 118)] + [InlineData (nameof (ColorName16.Gray), 128, 128, 128)] + [InlineData (nameof (ColorName16.Green), 0, 128, 0)] + [InlineData (nameof (ColorName16.Magenta), 255, 0, 255)] + [InlineData (nameof (ColorName16.Red), 255, 0, 0)] + [InlineData (nameof (ColorName16.White), 255, 255, 255)] + [InlineData (nameof (ColorName16.Yellow), 255, 255, 0)] + // W3C color name => substituted ANSI color + [InlineData (nameof (W3cColor.Fuchsia), 255, 0, 255)] // ANSI Magenta + [InlineData (nameof (W3cColor.DarkGrey), 118, 118, 118)] // ANSI Dark Gray + [InlineData (nameof (W3cColor.Grey), 128, 128, 128)] // ANSI Gray + [InlineData (nameof (W3cColor.Aqua), 0, 255, 255)] // ANSI Cyan + // W3C colors + [InlineData (nameof (W3cColor.AliceBlue), 240, 248, 255)] + [InlineData (nameof (W3cColor.BlanchedAlmond), 255, 235, 205)] + [InlineData (nameof (W3cColor.CadetBlue), 95, 158, 160)] + [InlineData (nameof (W3cColor.DarkBlue), 0, 0, 139)] + [InlineData (nameof (W3cColor.FireBrick), 178, 34, 34)] + [InlineData (nameof (W3cColor.Gainsboro), 220, 220, 220)] + [InlineData (nameof (W3cColor.HoneyDew), 240, 255, 240)] + [InlineData (nameof (W3cColor.Indigo), 75, 0, 130)] + [InlineData (nameof (W3cColor.Khaki), 240, 230, 140)] + [InlineData (nameof (W3cColor.Lavender), 230, 230, 250)] + [InlineData (nameof (W3cColor.Maroon), 128, 0, 0)] + [InlineData (nameof (W3cColor.Navy), 0, 0, 128)] + [InlineData (nameof (W3cColor.Olive), 128, 128, 0)] + [InlineData (nameof (W3cColor.Plum), 221, 160, 221)] + [InlineData (nameof (W3cColor.RoyalBlue), 65, 105, 225)] + [InlineData (nameof (W3cColor.Silver), 192, 192, 192)] + [InlineData (nameof (W3cColor.Tomato), 255, 99, 71)] + [InlineData (nameof (W3cColor.Violet), 238, 130, 238)] + [InlineData (nameof (W3cColor.WhiteSmoke), 245, 245, 245)] + [InlineData (nameof (W3cColor.YellowGreen), 154, 205, 50)] + // Case-insensitive + [InlineData ("BRIGHTBLUE", 59, 120, 255)] + [InlineData ("brightblue", 59, 120, 255)] + [InlineData ("TOMATO", 255, 99, 71)] + [InlineData ("tomato", 255, 99, 71)] + + public void TryParseColor_ResolvesCombinationOfAnsiAndW3cColors (string inputName, byte r, byte g, byte b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("12", 231, 72, 86)] // ColorName16.BrightRed + [InlineData ("16737095", 255, 99, 71)] // W3cColor.Tomato + public void TryParseColor_ResolvesValidEnumNumber (string inputName, byte r, byte g, byte b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (null)] + [InlineData ("")] + [InlineData ("brightlight")] + public void TryParseColor_FailsOnInvalidColorName (string? invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("-12")] + [InlineData ("-16737095")] + public void TryParseColor_FailsOnInvalidEnumNumber (string invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } +} diff --git a/Tests/UnitTestsParallelizable/Drawing/Color/W3cColorNameResolverTests.cs b/Tests/UnitTestsParallelizable/Drawing/Color/W3cColorNameResolverTests.cs new file mode 100644 index 0000000000..527c0be4ea --- /dev/null +++ b/Tests/UnitTestsParallelizable/Drawing/Color/W3cColorNameResolverTests.cs @@ -0,0 +1,150 @@ +#nullable enable + +namespace Terminal.Gui.DrawingTests; + +public class W3cColorNameResolverTests +{ + private readonly W3cColorNameResolver _candidate = new(); + + [Fact] + public void GetColorNames_NamesAreInAlphabeticalOrder () + { + string[] alphabeticallyOrderedNames = Enum.GetNames ().Order ().ToArray (); + + Assert.Equal (alphabeticallyOrderedNames, _candidate.GetColorNames ()); + } + + [Theory] + [InlineData (nameof (W3cColor.Aqua))] + [InlineData (nameof (W3cColor.Cyan))] + [InlineData (nameof (W3cColor.DarkGray))] + [InlineData (nameof (W3cColor.DarkGrey))] + [InlineData (nameof (W3cColor.DarkSlateGray))] + [InlineData (nameof (W3cColor.DarkSlateGrey))] + [InlineData (nameof (W3cColor.DimGray))] + [InlineData (nameof (W3cColor.DimGrey))] + [InlineData (nameof (W3cColor.Fuchsia))] + [InlineData (nameof (W3cColor.LightGray))] + [InlineData (nameof (W3cColor.LightGrey))] + [InlineData (nameof (W3cColor.LightSlateGray))] + [InlineData (nameof (W3cColor.LightSlateGrey))] + [InlineData (nameof (W3cColor.Magenta))] + [InlineData (nameof (W3cColor.SlateGray))] + [InlineData (nameof (W3cColor.SlateGrey))] + public void GetColorNames_IncludesNamesWithSameValues (string name) + { + string[] names = _candidate.GetColorNames ().ToArray(); + + Assert.True (names.Contains (name), $"W3C color names is missing '{name}'."); + } + + [Theory] + [InlineData (240, 248, 255, nameof (W3cColor.AliceBlue))] + [InlineData (0, 255, 255, nameof (W3cColor.Aqua))] + [InlineData (255, 0, 0, nameof (W3cColor.Red))] + [InlineData (0, 128, 0, nameof (W3cColor.Green))] + [InlineData (0, 0, 255, nameof (W3cColor.Blue))] + [InlineData (0, 255, 0, nameof (W3cColor.Lime))] + [InlineData (0, 0, 0, nameof (W3cColor.Black))] + [InlineData (255, 255, 255, nameof (W3cColor.White))] + [InlineData (154, 205, 50, nameof (W3cColor.YellowGreen))] + public void TryNameColor_ReturnsExpectedColorName (int r, int g, int b, string expectedName) + { + var expected = (true, expectedName); + + Color inputColor = new(r, g, b); + bool actualSuccess = _candidate.TryNameColor (inputColor, out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Fact] + public void TryNameColor_NoMatchFails () + { + (bool, string?) expected = (false, null); + + bool actualSuccess = _candidate.TryNameColor (new Color (1, 2, 3), out string? actualName); + var actual = (actualSuccess, actualName); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (nameof (W3cColor.AliceBlue), 240, 248, 255)] + [InlineData (nameof (W3cColor.BlanchedAlmond), 255, 235, 205)] + [InlineData (nameof (W3cColor.CadetBlue), 95, 158, 160)] + [InlineData (nameof (W3cColor.DarkBlue), 0, 0, 139)] + [InlineData (nameof (W3cColor.FireBrick), 178, 34, 34)] + [InlineData (nameof (W3cColor.Gainsboro), 220, 220, 220)] + [InlineData (nameof (W3cColor.HoneyDew), 240, 255, 240)] + [InlineData (nameof (W3cColor.Indigo), 75, 0, 130)] + [InlineData (nameof (W3cColor.Khaki), 240, 230, 140)] + [InlineData (nameof (W3cColor.Lavender), 230, 230, 250)] + [InlineData (nameof (W3cColor.Maroon), 128, 0, 0)] + [InlineData (nameof (W3cColor.Navy), 0, 0, 128)] + [InlineData (nameof (W3cColor.Olive), 128, 128, 0)] + [InlineData (nameof (W3cColor.Plum), 221, 160, 221)] + [InlineData (nameof (W3cColor.RoyalBlue), 65, 105, 225)] + [InlineData (nameof (W3cColor.Silver), 192, 192, 192)] + [InlineData (nameof (W3cColor.Tomato), 255, 99, 71)] + [InlineData (nameof (W3cColor.Violet), 238, 130, 238)] + [InlineData (nameof (W3cColor.WhiteSmoke), 245, 245, 245)] + [InlineData (nameof (W3cColor.YellowGreen), 154, 205, 50)] + // Aliases also work + [InlineData (nameof (W3cColor.Aqua), 0, 255, 255)] + [InlineData (nameof (W3cColor.Cyan), 0, 255, 255)] + [InlineData (nameof (W3cColor.DarkGray), 169, 169, 169)] + [InlineData (nameof (W3cColor.DarkGrey), 169, 169, 169)] + // Case-insensitive + [InlineData ("Red", 255, 0, 0)] + [InlineData ("red", 255, 0, 0)] + [InlineData ("RED", 255, 0, 0)] + public void TryParseColor_ReturnsExpectedColor (string inputName, int r, int g, int b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("16737095", 255, 99, 71)] // W3cColor.Tomato + public void TryParseColor_ResolvesValidEnumNumber (string inputName, byte r, byte g, byte b) + { + var expected = (true, new Color(r, g, b)); + + bool actualSuccess = _candidate.TryParseColor (inputName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData (null)] + [InlineData ("")] + [InlineData ("brightlight")] + public void TryParseColor_FailsOnInvalidColorName (string? invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } + + [Theory] + [InlineData ("-16737095")] + public void TryParseColor_FailsOnInvalidEnumNumber (string invalidName) + { + var expected = (false, default(Color)); + + bool actualSuccess = _candidate.TryParseColor (invalidName, out Color actualColor); + var actual = (actualSuccess, actualColor); + + Assert.Equal (expected, actual); + } +}