From c33736dfa63c0a9dc93bb6f52ed0c4a0a9abb142 Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 22 Sep 2024 13:20:22 -0600 Subject: [PATCH] Color schemes --- .../Configuration/ColorJsonConverter.cs | 10 +- Terminal.Gui/Drawing/ColorScheme.cs | 11 + Terminal.Gui/Resources/config.json | 361 ++++++++++++++++-- Terminal.Gui/View/View.Drawing.cs | 5 - Terminal.Gui/View/View.Mouse.cs | 40 +- Terminal.Gui/Views/Button.cs | 4 +- Terminal.Gui/Views/ProgressBar.cs | 8 +- Terminal.Gui/Views/Shortcut.cs | 6 +- UICatalog/Resources/config.json | 2 +- UnitTests/Configuration/SettingsScopeTests.cs | 2 +- UnitTests/Views/ProgressBarTests.cs | 8 +- 11 files changed, 385 insertions(+), 72 deletions(-) diff --git a/Terminal.Gui/Configuration/ColorJsonConverter.cs b/Terminal.Gui/Configuration/ColorJsonConverter.cs index 91f77040c..57dfb507c 100644 --- a/Terminal.Gui/Configuration/ColorJsonConverter.cs +++ b/Terminal.Gui/Configuration/ColorJsonConverter.cs @@ -15,7 +15,7 @@ internal class ColorJsonConverter : JsonConverter { if (_instance is null) { - _instance = new ColorJsonConverter (); + _instance = new (); } return _instance; @@ -31,10 +31,16 @@ internal class ColorJsonConverter : JsonConverter ReadOnlySpan colorString = reader.GetString (); // Check if the color string is a color name + if (ColorStrings.TryParseW3CColorName (colorString.ToString (), out Color color1)) + { + // Return the parsed color + return new (color1); + } + if (Enum.TryParse (colorString, true, out ColorName color)) { // Return the parsed color - return new Color (in color); + return new (in color); } if (Color.TryParse (colorString, null, out Color parsedColor)) diff --git a/Terminal.Gui/Drawing/ColorScheme.cs b/Terminal.Gui/Drawing/ColorScheme.cs index 603694eec..e9b64e0da 100644 --- a/Terminal.Gui/Drawing/ColorScheme.cs +++ b/Terminal.Gui/Drawing/ColorScheme.cs @@ -98,6 +98,17 @@ public record ColorScheme : IEqualityOperators init => _normal = value; } + public ColorScheme GetHighlightColorScheme () + { + return this with + { + Normal = new (Normal.Foreground.GetHighlightColor (), Normal.Background), + HotNormal = new (HotNormal.Foreground.GetHighlightColor (), HotNormal.Background), + Focus = new (Focus.Foreground.GetHighlightColor (), Focus.Background), + HotFocus = new (HotFocus.Foreground.GetHighlightColor (), HotFocus.Background), + }; + } + /// Compares two objects for equality. /// /// true if the two objects are equal diff --git a/Terminal.Gui/Resources/config.json b/Terminal.Gui/Resources/config.json index adba1e584..7a95bbd54 100644 --- a/Terminal.Gui/Resources/config.json +++ b/Terminal.Gui/Resources/config.json @@ -30,34 +30,35 @@ "Default": { "Dialog.DefaultButtonAlignment": "End", "Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems", + "Dialog.DefaultBorderStyle": "Heavy", + "Dialog.DefaultShadow": "Transparent", "FrameView.DefaultBorderStyle": "Single", "Window.DefaultBorderStyle": "Single", - "Dialog.DefaultBorderStyle": "Heavy", "MessageBox.DefaultButtonAlignment": "Center", "MessageBox.DefaultBorderStyle": "Heavy", - "Button.DefaultShadow": "None", + "Button.DefaultShadow": "Opaque", "ColorSchemes": [ { "TopLevel": { "Normal": { "Foreground": "BrightGreen", - "Background": "Black" + "Background": "#505050" // DarkerGray }, "Focus": { "Foreground": "White", - "Background": "Cyan" + "Background": "#696969" // DimGray }, "HotNormal": { "Foreground": "Yellow", - "Background": "Black" + "Background": "#505050" // DarkerGray }, "HotFocus": { - "Foreground": "Blue", - "Background": "Cyan" + "Foreground": "Yellow", + "Background": "#696969" // DimGray }, "Disabled": { "Foreground": "DarkGray", - "Background": "Black" + "Background": "#505050" // DarkerGray } } }, @@ -68,8 +69,8 @@ "Background": "Blue" }, "Focus": { - "Foreground": "Black", - "Background": "Gray" + "Foreground": "DarkBlue", + "Background": "LightGray" }, "HotNormal": { "Foreground": "BrightCyan", @@ -77,7 +78,7 @@ }, "HotFocus": { "Foreground": "BrightBlue", - "Background": "Gray" + "Background": "LightGray" }, "Disabled": { "Foreground": "DarkGray", @@ -89,19 +90,19 @@ "Dialog": { "Normal": { "Foreground": "Black", - "Background": "Gray" + "Background": "LightGray" }, "Focus": { - "Foreground": "White", - "Background": "DarkGray" + "Foreground": "DarkGray", + "Background": "LightGray" }, "HotNormal": { "Foreground": "Blue", - "Background": "Gray" + "Background": "LightGray" }, "HotFocus": { - "Foreground": "BrightYellow", - "Background": "DarkGray" + "Foreground": "BrightBlue", + "Background": "LightGray" }, "Disabled": { "Foreground": "Gray", @@ -113,19 +114,19 @@ "Menu": { "Normal": { "Foreground": "White", - "Background": "DarkGray" + "Background": "DarkBlue" }, "Focus": { "Foreground": "White", - "Background": "Black" + "Background": "Blue" }, "HotNormal": { - "Foreground": "BrightYellow", - "Background": "DarkGray" + "Foreground": "Yellow", + "Background": "DarkBlue" }, "HotFocus": { - "Foreground": "BrightYellow", - "Background": "Black" + "Foreground": "Yellow", + "Background": "Blue" }, "Disabled": { "Foreground": "Gray", @@ -137,18 +138,18 @@ "Error": { "Normal": { "Foreground": "Red", - "Background": "White" + "Background": "Pink" }, "Focus": { - "Foreground": "Black", + "Foreground": "White", "Background": "BrightRed" }, "HotNormal": { "Foreground": "Black", - "Background": "White" + "Background": "Pink" }, "HotFocus": { - "Foreground": "White", + "Foreground": "Pink", "Background": "BrightRed" }, "Disabled": { @@ -162,6 +163,15 @@ }, { "Dark": { + "Dialog.DefaultButtonAlignment": "End", + "Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems", + "Dialog.DefaultBorderStyle": "Heavy", + "Dialog.DefaultShadow": "Transparent", + "FrameView.DefaultBorderStyle": "Single", + "Window.DefaultBorderStyle": "Single", + "MessageBox.DefaultButtonAlignment": "Center", + "MessageBox.DefaultBorderStyle": "Heavy", + "Button.DefaultShadow": "Opaque", "ColorSchemes": [ { "TopLevel": { @@ -238,16 +248,16 @@ { "Menu": { "Normal": { - "Foreground": "White", - "Background": "DarkGray" + "Foreground": "LightGray", + "Background": "#505050" // DarkerGray }, "Focus": { "Foreground": "White", "Background": "Black" }, "HotNormal": { - "Foreground": "Gray", - "Background": "DarkGray" + "Foreground": "White", + "Background": "#505050" // DarkerGray }, "HotFocus": { "Foreground": "White", @@ -288,6 +298,15 @@ }, { "Light": { + "Dialog.DefaultButtonAlignment": "End", + "Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems", + "Dialog.DefaultBorderStyle": "Heavy", + "Dialog.DefaultShadow": "Transparent", + "FrameView.DefaultBorderStyle": "Single", + "Window.DefaultBorderStyle": "Single", + "MessageBox.DefaultButtonAlignment": "Center", + "MessageBox.DefaultBorderStyle": "Heavy", + "Button.DefaultShadow": "Opaque", "ColorSchemes": [ { "TopLevel": { @@ -316,7 +335,7 @@ { "Base": { "Normal": { - "Foreground": "DarkGray", + "Foreground": "#505050", // DarkerGray "Background": "White" }, "Focus": { @@ -365,19 +384,19 @@ "Menu": { "Normal": { "Foreground": "DarkGray", - "Background": "White" + "Background": "LightGray" }, "Focus": { "Foreground": "DarkGray", - "Background": "Gray" + "Background": "White" }, "HotNormal": { "Foreground": "BrightRed", - "Background": "White" + "Background": "LightGray" }, "HotFocus": { "Foreground": "BrightRed", - "Background": "Gray" + "Background": "White" }, "Disabled": { "Foreground": "Gray", @@ -411,6 +430,276 @@ } ] } + }, + { + "Black & White": { + "Dialog.DefaultShadow": "None", + "FrameView.DefaultBorderStyle": "Single", + "Window.DefaultBorderStyle": "Single", + "MessageBox.DefaultButtonAlignment": "Center", + "MessageBox.DefaultBorderStyle": "Heavy", + "Button.DefaultShadow": "None", + "ColorSchemes": [ + { + "TopLevel": { + "Normal": { + "Foreground": "White", + "Background": "Black" + }, + "Focus": { + "Foreground": "Black", + "Background": "White" + }, + "HotNormal": { + "Foreground": "Black", + "Background": "White" + }, + "HotFocus": { + "Foreground": "White", + "Background": "Black" + }, + "Disabled": { + "Foreground": "Black", + "Background": "Black" + } + } + }, + { + "Base": { + "Normal": { + "Foreground": "White", + "Background": "Black" + }, + "Focus": { + "Foreground": "Black", + "Background": "White" + }, + "HotNormal": { + "Foreground": "Black", + "Background": "White" + }, + "HotFocus": { + "Foreground": "White", + "Background": "Black" + }, + "Disabled": { + "Foreground": "Black", + "Background": "Black" + } + } + }, + { + "Dialog": { + "Normal": { + "Foreground": "Black", + "Background": "White" + }, + "Focus": { + "Foreground": "White", + "Background": "Black" + }, + "HotNormal": { + "Foreground": "White", + "Background": "Black" + }, + "HotFocus": { + "Foreground": "Black", + "Background": "White" + }, + "Disabled": { + "Foreground": "White", + "Background": "White" + } + } + }, + { + "Menu": { + "Normal": { + "Foreground": "Black", + "Background": "White" + }, + "Focus": { + "Foreground": "White", + "Background": "Black" + }, + "HotNormal": { + "Foreground": "White", + "Background": "Black" + }, + "HotFocus": { + "Foreground": "Black", + "Background": "White" + }, + "Disabled": { + "Foreground": "White", + "Background": "White" + } + } + }, + { + "Error": { + "Normal": { + "Foreground": "White", + "Background": "Black" + }, + "Focus": { + "Foreground": "Black", + "Background": "White" + }, + "HotNormal": { + "Foreground": "Black", + "Background": "White" + }, + "HotFocus": { + "Foreground": "White", + "Background": "Black" + }, + "Disabled": { + "Foreground": "Black", + "Background": "Black" + } + } + } + ] + } + }, + { + "Gray Scale": { + "Dialog.DefaultButtonAlignment": "End", + "Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems", + "Dialog.DefaultBorderStyle": "Heavy", + "Dialog.DefaultShadow": "Transparent", + "FrameView.DefaultBorderStyle": "Single", + "Window.DefaultBorderStyle": "Single", + "MessageBox.DefaultButtonAlignment": "Center", + "MessageBox.DefaultBorderStyle": "Heavy", + "Button.DefaultShadow": "Opaque", + "ColorSchemes": [ + { + "TopLevel": { + "Normal": { + "Foreground": "#A9A9A9", // DarkGray + "Background": "#505050" // DarkerGray + }, + "Focus": { + "Foreground": "White", + "Background": "#696969" // DimGray + }, + "HotNormal": { + "Foreground": "#808080", // Gray + "Background": "#505050" // DarkerGray + }, + "HotFocus": { + "Foreground": "White", + "Background": "#808080" // Gray + }, + "Disabled": { + "Foreground": "#505050", // DarkerGray + "Background": "Black" + } + } + }, + { + "Base": { + "Normal": { + "Foreground": "#A9A9A9", // DarkGray + "Background": "Black" + }, + "Focus": { + "Foreground": "White", + "Background": "#505050" // DarkerGray + }, + "HotNormal": { + "Foreground": "#808080", // Gray + "Background": "Black" + }, + "HotFocus": { + "Foreground": "White", + "Background": "#505050" // DarkerGray + }, + "Disabled": { + "Foreground": "#696969", // DimGray + "Background": "Black" + } + } + }, + { + "Dialog": { + "Normal": { + "Foreground": "#505050", // DarkerGray + "Background": "White" + }, + "Focus": { + "Foreground": "Black", + "Background": "#D3D3D3" // LightGray + }, + "HotNormal": { + "Foreground": "#808080", // Gray + "Background": "White" + }, + "HotFocus": { + "Foreground": "Black", + "Background": "#D3D3D3" // LightGray + }, + "Disabled": { + "Foreground": "#696969", // DimGray + "Background": "White" + } + } + }, + { + "Menu": { + "Normal": { + "Foreground": "#D3D3D3", // LightGray + "Background": "#505050" // DarkerGray + }, + "Focus": { + "Foreground": "White", + "Background": "#808080" // Gray + }, + "HotNormal": { + "Foreground": "#808080", // Gray + "Background": "#505050" // DarkerGray + }, + "HotFocus": { + "Foreground": "White", + "Background": "#808080" // Gray + }, + "Disabled": { + "Foreground": "#505050", // DarkerGray + "Background": "#505050" // DarkerGray + } + } + }, + { + "Error": { + "Normal": { + "Foreground": "Black", + "Background": "White" + }, + "Focus": { + "Foreground": "White", + "Background": "Black" + }, + "HotNormal": { + "Foreground": "Black", + "Background": "#D3D3D3" // LightGray + }, + "HotFocus": { + "Foreground": "White", + "Background": "Black" + }, + "Disabled": { + "Foreground": "#696969", // DimGray + "Background": "White" + } + } + } + ] + } } + + + ] } \ No newline at end of file diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs index 259abb081..c2a97e10a 100644 --- a/Terminal.Gui/View/View.Drawing.cs +++ b/Terminal.Gui/View/View.Drawing.cs @@ -406,11 +406,6 @@ public partial class View // Drawing APIs private Attribute GetColor (Attribute inputAttribute) { Attribute attr = inputAttribute; - if (HighlightStyle.HasFlag (HighlightStyle.Hover) && _Hover) - { - //attr = new (inputAttribute.Foreground.GetHighlightColor (), inputAttribute.Background); - } - if (Diagnostics.HasFlag (ViewDiagnosticFlags.Hover) && _Hover) { attr = new (attr.Foreground.GetDarkerColor (), attr.Background.GetDarkerColor ()); diff --git a/Terminal.Gui/View/View.Mouse.cs b/Terminal.Gui/View/View.Mouse.cs index df60c4678..c1abd2edf 100644 --- a/Terminal.Gui/View/View.Mouse.cs +++ b/Terminal.Gui/View/View.Mouse.cs @@ -161,17 +161,28 @@ public partial class View // Mouse APIs return true; } - if ((HighlightStyle.HasFlag(HighlightStyle.Hover) || Diagnostics.HasFlag (ViewDiagnosticFlags.Hover))) + if ((HighlightStyle.HasFlag (HighlightStyle.Hover) || Diagnostics.HasFlag (ViewDiagnosticFlags.Hover))) { HighlightStyle copy = HighlightStyle; HighlightStyle hover = HighlightStyle.Hover; CancelEventArgs args = new (ref copy, ref hover); - if (!RaiseHighlight (args)) - { - } - SetNeedsDisplay (); + RaiseHighlight (args); - return args.Cancel; + if (args.Cancel) + { + return args.Cancel; + } + + ColorScheme cs = ColorScheme; + + if (cs is null) + { + cs = new (); + } + + _savedNonHighlightColorScheme = cs; + + ColorScheme = ColorScheme.GetHighlightColorScheme (); } return false; @@ -255,11 +266,10 @@ public partial class View // Mouse APIs { HighlightStyle copy = HighlightStyle; HighlightStyle hover = HighlightStyle.None; - CancelEventArgs args = new (ref copy, ref hover); - if (!RaiseHighlight (args)) - { - SetNeedsDisplay (); - } + RaiseHighlight (new (ref copy, ref hover)); + + ColorScheme = _savedNonHighlightColorScheme; + _savedNonHighlightColorScheme = default; } } @@ -424,7 +434,7 @@ public partial class View // Mouse APIs } /// - /// Called when the view is to be highlighted. + /// Called when the view is to be highlighted. See . /// /// , if the event was handled, otherwise. protected virtual bool OnHighlight (CancelEventArgs args) @@ -433,11 +443,13 @@ public partial class View // Mouse APIs } /// - /// Fired when the view is highlighted. Set to - /// to implement a custom highlight scheme or prevent the view from being highlighted. + /// Fired when the view is highlighted. See . /// public event EventHandler>? Highlight; + private ColorScheme _savedNonHighlightColorScheme; + + /// /// Enables the highlight for the view when the mouse is pressed. Called from OnMouseEvent. diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 80179e2f2..a714cc5eb 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -60,7 +60,6 @@ public class Button : View, IDesignable Width = Dim.Auto (DimAutoStyle.Text); CanFocus = true; - HighlightStyle = DefaultHighlightStyle; // Override default behavior of View AddCommand (Command.HotKey, () => @@ -76,8 +75,9 @@ public class Button : View, IDesignable MouseClick += Button_MouseClick; ShadowStyle = DefaultShadow; + HighlightStyle = DefaultHighlightStyle; } - + private bool _wantContinuousButtonPressed; /// diff --git a/Terminal.Gui/Views/ProgressBar.cs b/Terminal.Gui/Views/ProgressBar.cs index a205bb830..78284b5be 100644 --- a/Terminal.Gui/Views/ProgressBar.cs +++ b/Terminal.Gui/Views/ProgressBar.cs @@ -263,10 +263,10 @@ public class ProgressBar : View, IDesignable private void ProgressBar_Initialized (object sender, EventArgs e) { - ColorScheme = new ColorScheme (ColorScheme ?? SuperView?.ColorScheme ?? Colors.ColorSchemes ["Base"]) - { - HotNormal = new Attribute (Color.BrightGreen, Color.Gray) - }; + //ColorScheme = new ColorScheme (ColorScheme ?? SuperView?.ColorScheme ?? Colors.ColorSchemes ["Base"]) + //{ + // HotNormal = new Attribute (Color.BrightGreen, Color.Gray) + //}; } private void SetInitialProperties () diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index 2f90f41f7..e92eafe3c 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -54,7 +54,6 @@ public class Shortcut : View, IOrientation, IDesignable { Id = "_shortcut"; HighlightStyle = HighlightStyle.Pressed; - //Highlight += Shortcut_Highlight; CanFocus = true; Width = GetWidthDimAuto (); Height = Dim.Auto (DimAutoStyle.Content, 1); @@ -154,11 +153,12 @@ public class Shortcut : View, IOrientation, IDesignable { if (args.NewValue.HasFlag (HighlightStyle.Hover)) { - SetColors (true); + SetColors (highlight: true); } else { - SetColors (false); + // If we have focus, act like we're highlighted + SetColors (highlight: HasFocus); } return true; diff --git a/UICatalog/Resources/config.json b/UICatalog/Resources/config.json index 6cb14897d..d82004ff2 100644 --- a/UICatalog/Resources/config.json +++ b/UICatalog/Resources/config.json @@ -75,7 +75,7 @@ }, "HotFocus": { "Foreground": "#FFFF00", - "Background": "White" + "Background": "Black" }, "Disabled": { "Foreground": "BrightGreen", diff --git a/UnitTests/Configuration/SettingsScopeTests.cs b/UnitTests/Configuration/SettingsScopeTests.cs index ca4f6b830..a5df19f35 100644 --- a/UnitTests/Configuration/SettingsScopeTests.cs +++ b/UnitTests/Configuration/SettingsScopeTests.cs @@ -57,7 +57,7 @@ public class SettingsScopeTests { Reset (); - Assert.Equal (3, ((Dictionary)Settings ["Themes"].PropertyValue).Count); + Assert.Equal (5, ((Dictionary)Settings ["Themes"].PropertyValue).Count); GetHardCodedDefaults (); Assert.NotEmpty (Themes); diff --git a/UnitTests/Views/ProgressBarTests.cs b/UnitTests/Views/ProgressBarTests.cs index 4ff1d23a5..b3e576abc 100644 --- a/UnitTests/Views/ProgressBarTests.cs +++ b/UnitTests/Views/ProgressBarTests.cs @@ -15,10 +15,10 @@ public class ProgressBarTests Assert.False (pb.CanFocus); Assert.Equal (0, pb.Fraction); - Assert.Equal ( - new Attribute (Color.BrightGreen, Color.Gray), - new Attribute (pb.ColorScheme.HotNormal.Foreground, pb.ColorScheme.HotNormal.Background) - ); + //Assert.Equal ( + // new Attribute (Color.BrightGreen, Color.Gray), + // new Attribute (pb.ColorScheme.HotNormal.Foreground, pb.ColorScheme.HotNormal.Background) + // ); Assert.Equal (Colors.ColorSchemes ["Base"].Normal, pb.ColorScheme.Normal); Assert.Equal (1, pb.Frame.Height); Assert.Equal (ProgressBarStyle.Blocks, pb.ProgressBarStyle);