diff --git a/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs b/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs index bcac3838..ffb9e07d 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs @@ -19,12 +19,13 @@ public partial class CustomHighlighter : SyntaxHighlighter public EditorThemeColorSet ColourSetForTheme = null!; - public void UpdateThemeColorCache(LightOrDarkTheme themeType) + public void UpdateThemeColorCache(IdeTheme themeType) { ColourSetForTheme = themeType switch { - LightOrDarkTheme.Light => EditorThemeColours.Light, - LightOrDarkTheme.Dark => EditorThemeColours.Dark, + IdeTheme.Light => EditorThemeColours.Light, + IdeTheme.Dark => EditorThemeColours.Dark, + IdeTheme.ExtraDark => EditorThemeColours.ExtraDark, _ => throw new NotImplementedException("Unknown theme type") }; } diff --git a/src/SharpIDE.Godot/Features/CodeEditor/EditorThemeColours.cs b/src/SharpIDE.Godot/Features/CodeEditor/EditorThemeColours.cs index 89f851b5..95f8f769 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/EditorThemeColours.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/EditorThemeColours.cs @@ -45,6 +45,27 @@ public static class EditorThemeColours RazorMetaCodePurple = TextEditorDotnetColoursDark.RazorMetaCodePurple, HtmlDelimiterGray = TextEditorDotnetColoursDark.HtmlDelimiterGray }; + + public static readonly EditorThemeColorSet ExtraDark = new EditorThemeColorSet + { + Orange = TextEditorDotnetColoursDark.Orange, + White = TextEditorDotnetColoursDark.White, + Yellow = TextEditorDotnetColoursDark.Yellow, + CommentGreen = TextEditorDotnetColoursDark.CommentGreen, + KeywordBlue = TextEditorDotnetColoursDark.KeywordBlue, + LightOrangeBrown = TextEditorDotnetColoursDark.LightOrangeBrown, + NumberGreen = TextEditorDotnetColoursDark.NumberGreen, + InterfaceGreen = TextEditorDotnetColoursDark.InterfaceGreen, + ClassGreen = TextEditorDotnetColoursDark.ClassGreen, + VariableBlue = TextEditorDotnetColoursDark.VariableBlue, + Gray = TextEditorDotnetColoursDark.Gray, + Pink = TextEditorDotnetColoursDark.Pink, + ErrorRed = TextEditorDotnetColoursDark.ErrorRed, + + RazorComponentGreen = TextEditorDotnetColoursDark.RazorComponentGreen, + RazorMetaCodePurple = TextEditorDotnetColoursDark.RazorMetaCodePurple, + HtmlDelimiterGray = TextEditorDotnetColoursDark.HtmlDelimiterGray + }; } public class EditorThemeColorSet diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_Theme.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_Theme.cs index 9c2cd16c..88e838d2 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_Theme.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_Theme.cs @@ -5,9 +5,6 @@ namespace SharpIDE.Godot.Features.CodeEditor; public partial class SharpIdeCodeEdit { - private static readonly StringName ThemeInfoStringName = "ThemeInfo"; - private static readonly StringName IsLight1OrDark2StringName = "IsLight1OrDark2"; - private void UpdateEditorThemeForCurrentTheme() { var ideTheme = Singletons.AppState.IdeSettings.Theme; @@ -15,14 +12,15 @@ private void UpdateEditorThemeForCurrentTheme() } // Only async for the EventWrapper subscription - private Task UpdateEditorThemeAsync(LightOrDarkTheme lightOrDarkTheme) + private Task UpdateEditorThemeAsync(IdeTheme theme) { - UpdateEditorTheme(lightOrDarkTheme); + UpdateEditorTheme(theme); return Task.CompletedTask; } - private void UpdateEditorTheme(LightOrDarkTheme lightOrDarkTheme) + + private void UpdateEditorTheme(IdeTheme theme) { - _syntaxHighlighter.UpdateThemeColorCache(lightOrDarkTheme); + _syntaxHighlighter.UpdateThemeColorCache(theme); SyntaxHighlighter = null; SyntaxHighlighter = _syntaxHighlighter; // Reassign to trigger redraw } diff --git a/src/SharpIDE.Godot/Features/IdeSettings/AppState.cs b/src/SharpIDE.Godot/Features/IdeSettings/AppState.cs index bf5f7526..e5b7e539 100644 --- a/src/SharpIDE.Godot/Features/IdeSettings/AppState.cs +++ b/src/SharpIDE.Godot/Features/IdeSettings/AppState.cs @@ -15,11 +15,11 @@ public class IdeSettings public string? DebuggerExecutablePath { get; set; } public bool DebuggerUseSharpDbg { get; set; } = true; public float UiScale { get; set; } = 1.0f; - public LightOrDarkTheme Theme { get; set; } = LightOrDarkTheme.Dark; + public IdeTheme Theme { get; set; } = IdeTheme.Dark; } [JsonConverter(typeof(JsonStringEnumConverter))] -public enum LightOrDarkTheme { Light, Dark } +public enum IdeTheme { Light, Dark, ExtraDark } public record RecentSln { diff --git a/src/SharpIDE.Godot/Features/Settings/SetTheme.cs b/src/SharpIDE.Godot/Features/Settings/SetTheme.cs index e8b3495f..f2683ec0 100644 --- a/src/SharpIDE.Godot/Features/Settings/SetTheme.cs +++ b/src/SharpIDE.Godot/Features/Settings/SetTheme.cs @@ -9,19 +9,26 @@ public static class SetTheme private static readonly Color LightThemeClearColor = new Color("fdfdfd"); private static readonly Theme DarkTheme = ResourceLoader.Load("uid://epmt8kq6efrs"); private static readonly Color DarkThemeClearColor = new Color("4d4d4d"); + private static readonly Theme ExtraDarkTheme = ResourceLoader.Load("uid://k1h5yus8dekc"); + private static readonly Color ExtraDarkThemeClearColor = new Color("#000000"); - public static void SetIdeTheme(this Node node, LightOrDarkTheme theme) + public static void SetIdeTheme(this Node node, IdeTheme theme) { var rootWindow = node.GetTree().GetRoot(); - if (theme is LightOrDarkTheme.Light) + if (theme is IdeTheme.Light) { RenderingServer.Singleton.SetDefaultClearColor(LightThemeClearColor); rootWindow.Theme = LightTheme; } - else if (theme is LightOrDarkTheme.Dark) + else if (theme is IdeTheme.Dark) { RenderingServer.Singleton.SetDefaultClearColor(DarkThemeClearColor); rootWindow.Theme = DarkTheme; } + else if (theme is IdeTheme.ExtraDark) + { + RenderingServer.Singleton.SetDefaultClearColor(ExtraDarkThemeClearColor); + rootWindow.Theme = ExtraDarkTheme; + } } } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/Settings/SettingsWindow.cs b/src/SharpIDE.Godot/Features/Settings/SettingsWindow.cs index c4dcc87c..c39d5e5a 100644 --- a/src/SharpIDE.Godot/Features/Settings/SettingsWindow.cs +++ b/src/SharpIDE.Godot/Features/Settings/SettingsWindow.cs @@ -57,8 +57,9 @@ private void OnThemeItemSelected(long index) var selectedTheme = _themeOptionButton.GetItemText((int)index); var lightOrDarkTheme = selectedTheme switch { - "Light" => LightOrDarkTheme.Light, - "Dark" => LightOrDarkTheme.Dark, + "Light" => IdeTheme.Light, + "Dark" => IdeTheme.Dark, + "Extra Dark" => IdeTheme.ExtraDark, _ => throw new InvalidOperationException($"Unknown theme selected: {selectedTheme}") }; Singletons.AppState.IdeSettings.Theme = lightOrDarkTheme; diff --git a/src/SharpIDE.Godot/Features/Settings/SettingsWindow.tscn b/src/SharpIDE.Godot/Features/Settings/SettingsWindow.tscn index 9c841ba9..5d986628 100644 --- a/src/SharpIDE.Godot/Features/Settings/SettingsWindow.tscn +++ b/src/SharpIDE.Godot/Features/Settings/SettingsWindow.tscn @@ -142,11 +142,13 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 selected = 0 -item_count = 2 -popup/item_0/text = "Dark" -popup/item_0/id = 0 -popup/item_1/text = "Light" -popup/item_1/id = 1 +item_count = 3 +popup/item_0/text = "Light" +popup/item_0/id = 1 +popup/item_1/text = "Dark" +popup/item_1/id = 0 +popup/item_2/text = "Extra Dark" +popup/item_2/id = 2 [node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/PanelContainer/MarginContainer/VBoxContainer2/VBoxContainer4" unique_id=1201262823] layout_mode = 2 diff --git a/src/SharpIDE.Godot/GodotGlobalEvents.cs b/src/SharpIDE.Godot/GodotGlobalEvents.cs index a5937752..dbc80436 100644 --- a/src/SharpIDE.Godot/GodotGlobalEvents.cs +++ b/src/SharpIDE.Godot/GodotGlobalEvents.cs @@ -14,5 +14,5 @@ public class GodotGlobalEvents public EventWrapper BottomPanelVisibilityChangeRequested { get; } = new(_ => Task.CompletedTask); public EventWrapper FileSelected { get; } = new((_, _) => Task.CompletedTask); public EventWrapper FileExternallySelected { get; } = new((_, _) => Task.CompletedTask); - public EventWrapper TextEditorThemeChanged { get; } = new(_ => Task.CompletedTask); + public EventWrapper TextEditorThemeChanged { get; } = new(_ => Task.CompletedTask); } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Resources/ExtraDarkTheme.tres b/src/SharpIDE.Godot/Resources/ExtraDarkTheme.tres new file mode 100644 index 00000000..f39500bc --- /dev/null +++ b/src/SharpIDE.Godot/Resources/ExtraDarkTheme.tres @@ -0,0 +1,167 @@ +[gd_resource type="Theme" format=3 uid="uid://k1h5yus8dekc"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_38n5o"] +bg_color = Color(0.16862746, 0.1764706, 0.1882353, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.24313726, 0.2509804, 0.27058825, 1) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 +expand_margin_left = -2.0 +expand_margin_top = -2.0 +expand_margin_right = -2.0 +expand_margin_bottom = -2.0 +shadow_color = Color(0, 0, 0, 0.5) +shadow_size = 2 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_82udi"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.117647, 0.117647, 0.117647, 1) +border_color = Color(0, 0, 0, 0.6) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_21uq4"] +content_margin_left = 10.0 +content_margin_top = 4.0 +content_margin_right = 10.0 +content_margin_bottom = 4.0 +bg_color = Color(0.1, 0.1, 0.1, 0.6) +border_width_bottom = 2 +border_color = Color(1, 1, 1, 0.75) +corner_detail = 1 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5oigc"] +bg_color = Color(0.11764706, 0.11764706, 0.11764706, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dvhtt"] +content_margin_left = 12.0 +content_margin_top = 10.0 +content_margin_right = 12.0 +content_margin_bottom = 10.0 +bg_color = Color(0.16862746, 0.1764706, 0.1882353, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.24313726, 0.2509804, 0.27058825, 1) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 +expand_margin_left = -2.0 +expand_margin_top = -2.0 +expand_margin_right = -2.0 +expand_margin_bottom = -2.0 +shadow_color = Color(0, 0, 0, 0.5019608) +shadow_size = 2 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hrgw7"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.1, 0.1, 0.1, 0.6) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dsk6k"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0.1, 0.1, 0.1, 0.6) +draw_center = false +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_njudc"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(0, 0, 0, 0.39215687) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3gh6f"] +content_margin_left = 0.0 +content_margin_top = 0.0 +content_margin_right = 0.0 +content_margin_bottom = 0.0 +bg_color = Color(0.1, 0.1, 0.1, 0.6) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6e8is"] +content_margin_left = 0.0 +content_margin_top = 0.0 +content_margin_right = 0.0 +content_margin_bottom = 0.0 +bg_color = Color(0.1, 0.1, 0.1, 0.6) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amw38"] +bg_color = Color(0.1764706, 0.1764706, 0.1764706, 1) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 +shadow_color = Color(0, 0, 0, 0.11764706) +shadow_size = 4 + +[resource] +CodeEdit/colors/completion_background_color = Color(1, 1, 1, 0) +CodeEdit/colors/completion_selected_color = Color(0.18039216, 0.2627451, 0.43137255, 1) +CodeEdit/colors/current_line_color = Color(0.05882353, 0.05882353, 0.05882353, 1) +CodeEdit/colors/font_readonly_color = Color(1, 1, 1, 1) +CodeEdit/colors/selection_color = Color(0.14117648, 0.35686275, 0.50980395, 1) +CodeEdit/styles/completion = SubResource("StyleBoxFlat_38n5o") +CodeEdit/styles/normal = SubResource("StyleBoxFlat_82udi") +CodeEdit/styles/read_only = SubResource("StyleBoxFlat_82udi") +CodeEditorTabContainer/base_type = &"TabContainer" +CodeEditorTabContainer/styles/tab_selected = SubResource("StyleBoxFlat_21uq4") +CodeEditorTabContainer/styles/tabbar_background = SubResource("StyleBoxFlat_5oigc") +EditorHoverPopupPanelContainer/base_type = &"PanelContainer" +EditorHoverPopupPanelContainer/styles/panel = SubResource("StyleBoxFlat_dvhtt") +FoldableContainer/styles/title_collapsed_panel = SubResource("StyleBoxFlat_hrgw7") +Gray500Label/base_type = &"Label" +Gray500Label/colors/font_color = Color(0.5137255, 0.5137255, 0.5137255, 1) +Gray600Label/base_type = &"Label" +Gray600Label/colors/font_color = Color(0.67058825, 0.67058825, 0.67058825, 1) +Gray700Label/base_type = &"Label" +Gray700Label/colors/font_color = Color(0.83137256, 0.83137256, 0.83137256, 1) +IdeSidebarButton/base_type = &"Button" +IdeSidebarButton/styles/normal = SubResource("StyleBoxFlat_dsk6k") +IdeSidebarButton/styles/pressed = SubResource("StyleBoxFlat_njudc") +Panel/styles/panel = SubResource("StyleBoxFlat_3gh6f") +PanelContainer/styles/panel = SubResource("StyleBoxFlat_6e8is") +PopupPanel/styles/panel = SubResource("StyleBoxFlat_amw38") +ThemeInfo/constants/IsLight1OrDark2 = 2 +Tree/colors/font_color = Color(0.83137256, 0.83137256, 0.83137256, 1)