set text editor theme on startup and change

This commit is contained in:
Matt Parker
2026-01-31 14:16:25 +10:00
parent 11c5bf2bcb
commit ccf55440ed
8 changed files with 58 additions and 8 deletions

View File

@@ -63,6 +63,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
public override void _Ready()
{
UpdateEditorThemeForCurrentTheme();
SyntaxHighlighter = _syntaxHighlighter;
_popupMenu = GetNode<PopupMenu>("CodeFixesMenu");
_aboveCanvasItem = GetNode<CanvasItem>("%AboveCanvasItem");
@@ -80,6 +81,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
SymbolLookup += OnSymbolLookup;
LinesEditedFrom += OnLinesEditedFrom;
GlobalEvents.Instance.SolutionAltered.Subscribe(OnSolutionAltered);
GodotGlobalEvents.Instance.TextEditorThemeChanged.Subscribe(UpdateEditorThemeAsync);
SetCodeRegionTags("#region", "#endregion");
//AddGitGutter();
}
@@ -162,6 +164,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
_currentFile?.FileDeleted.Unsubscribe(OnFileDeleted);
_projectDiagnosticsObserveDisposable?.Dispose();
GlobalEvents.Instance.SolutionAltered.Unsubscribe(OnSolutionAltered);
GodotGlobalEvents.Instance.TextEditorThemeChanged.Unsubscribe(UpdateEditorThemeAsync);
if (_currentFile is not null) _openTabsFileManager.CloseFile(_currentFile);
}

View File

@@ -0,0 +1,29 @@
using Godot;
using SharpIDE.Godot.Features.IdeSettings;
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;
UpdateEditorTheme(ideTheme);
}
// Only async for the EventWrapper subscription
private Task UpdateEditorThemeAsync(LightOrDarkTheme lightOrDarkTheme)
{
UpdateEditorTheme(lightOrDarkTheme);
return Task.CompletedTask;
}
private void UpdateEditorTheme(LightOrDarkTheme lightOrDarkTheme)
{
_syntaxHighlighter.UpdateThemeColorCache(lightOrDarkTheme);
SyntaxHighlighter = null;
SyntaxHighlighter = _syntaxHighlighter; // Reassign to trigger redraw
}
}

View File

@@ -0,0 +1 @@
uid://fk3w6vud5tlx

View File

@@ -1,4 +1,6 @@
namespace SharpIDE.Godot.Features.IdeSettings;
using System.Text.Json.Serialization;
namespace SharpIDE.Godot.Features.IdeSettings;
public class AppState
{
@@ -13,9 +15,12 @@ public class IdeSettings
public string? DebuggerExecutablePath { get; set; }
public bool DebuggerUseSharpDbg { get; set; } = true;
public float UiScale { get; set; } = 1.0f;
public string Theme { get; set; } = "Dark";
public LightOrDarkTheme Theme { get; set; } = LightOrDarkTheme.Dark;
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum LightOrDarkTheme { Light, Dark }
public record RecentSln
{
public required string Name { get; set; }

View File

@@ -1,4 +1,5 @@
using Godot;
using SharpIDE.Godot.Features.IdeSettings;
namespace SharpIDE.Godot.Features.Settings;
@@ -9,15 +10,15 @@ public static class SetTheme
private static readonly Theme DarkTheme = ResourceLoader.Load<Theme>("uid://epmt8kq6efrs");
private static readonly Color DarkThemeClearColor = new Color("4d4d4d");
public static void SetIdeTheme(this Node node, string theme)
public static void SetIdeTheme(this Node node, LightOrDarkTheme theme)
{
var rootWindow = node.GetTree().GetRoot();
if (theme is "Light")
if (theme is LightOrDarkTheme.Light)
{
RenderingServer.Singleton.SetDefaultClearColor(LightThemeClearColor);
rootWindow.Theme = LightTheme;
}
else if (theme is "Dark")
else if (theme is LightOrDarkTheme.Dark)
{
RenderingServer.Singleton.SetDefaultClearColor(DarkThemeClearColor);
rootWindow.Theme = DarkTheme;

View File

@@ -0,0 +1 @@
uid://qs50t6nvwar1

View File

@@ -1,4 +1,5 @@
using Godot;
using SharpIDE.Godot.Features.IdeSettings;
namespace SharpIDE.Godot.Features.Settings;
@@ -28,7 +29,7 @@ public partial class SettingsWindow : Window
_uiScaleSpinBox.Value = Singletons.AppState.IdeSettings.UiScale;
_debuggerFilePathLineEdit.Text = Singletons.AppState.IdeSettings.DebuggerExecutablePath;
_debuggerUseSharpDbgCheckButton.ButtonPressed = Singletons.AppState.IdeSettings.DebuggerUseSharpDbg;
var themeOptionIndex = _themeOptionButton.GetOptionIndexOrNullForString(Singletons.AppState.IdeSettings.Theme);
var themeOptionIndex = _themeOptionButton.GetOptionIndexOrNullForString(Singletons.AppState.IdeSettings.Theme.ToString());
if (themeOptionIndex is not null) _themeOptionButton.Selected = themeOptionIndex.Value;
}
@@ -54,7 +55,14 @@ public partial class SettingsWindow : Window
private void OnThemeItemSelected(long index)
{
var selectedTheme = _themeOptionButton.GetItemText((int)index);
Singletons.AppState.IdeSettings.Theme = selectedTheme;
this.SetIdeTheme(selectedTheme);
var lightOrDarkTheme = selectedTheme switch
{
"Light" => LightOrDarkTheme.Light,
"Dark" => LightOrDarkTheme.Dark,
_ => throw new InvalidOperationException($"Unknown theme selected: {selectedTheme}")
};
Singletons.AppState.IdeSettings.Theme = lightOrDarkTheme;
this.SetIdeTheme(lightOrDarkTheme);
GodotGlobalEvents.Instance.TextEditorThemeChanged.InvokeParallelFireAndForget(lightOrDarkTheme);
}
}

View File

@@ -2,6 +2,7 @@
using SharpIDE.Application.Features.Events;
using SharpIDE.Application.Features.SolutionDiscovery;
using SharpIDE.Godot.Features.BottomPanel;
using SharpIDE.Godot.Features.IdeSettings;
namespace SharpIDE.Godot;
@@ -13,4 +14,5 @@ public class GodotGlobalEvents
public EventWrapper<bool, Task> BottomPanelVisibilityChangeRequested { get; } = new(_ => Task.CompletedTask);
public EventWrapper<SharpIdeFile, SharpIdeFileLinePosition?, Task> FileSelected { get; } = new((_, _) => Task.CompletedTask);
public EventWrapper<SharpIdeFile, SharpIdeFileLinePosition?, Task> FileExternallySelected { get; } = new((_, _) => Task.CompletedTask);
public EventWrapper<LightOrDarkTheme, Task> TextEditorThemeChanged { get; } = new(_ => Task.CompletedTask);
}