Skip to content

Commit 4ea16d2

Browse files
committed
feat: 代码编辑器颜色设置
1 parent f08bb5d commit 4ea16d2

10 files changed

Lines changed: 211 additions & 23 deletions

File tree

UndertaleModTool/Editors/GmlDiagnosticsRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public void Draw(TextView textView, DrawingContext drawingContext)
106106
segmentsToDraw.Add(new KeyValuePair<TextSegment, bool>(segment, false));
107107
}
108108

109-
bool isDark = Settings.Instance?.EnableDarkMode ?? true;
109+
bool isDark = Settings.IsCodeEditorDark;
110110

111111
// Compute the visible offset range (if the visual lines are valid)
112112
int visibleStart = int.MinValue;

UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public UndertaleCodeEditor()
329329
DecompiledSearchReplacePanel.Initialize(DecompiledEditor.TextArea);
330330
DecompiledEditor.FontSize = ZoomFontSize;
331331

332-
LoadGMLHighlighting(Settings.Instance?.EnableDarkMode ?? false);
332+
LoadGMLHighlighting(Settings.IsCodeEditorDark);
333333

334334
DecompiledEditor.Options.ConvertTabsToSpaces = true;
335335

@@ -360,7 +360,7 @@ public UndertaleCodeEditor()
360360
DisassemblySearchReplacePanel.Initialize(DisassemblyEditor.TextArea);
361361
DisassemblyEditor.FontSize = ZoomFontSize;
362362

363-
LoadVMASMHighlighting(Settings.Instance?.EnableDarkMode ?? false);
363+
LoadVMASMHighlighting(Settings.IsCodeEditorDark);
364364

365365
textArea = DisassemblyEditor.TextArea;
366366
_disassemblyNameGenerator = new NameGenerator(this, textArea);
@@ -379,7 +379,7 @@ public UndertaleCodeEditor()
379379
_disassemblyModifiedRenderer.MarkDirty();
380380
};
381381

382-
ApplyEditorTheme(Settings.Instance?.EnableDarkMode ?? false);
382+
ApplyEditorTheme(Settings.IsCodeEditorDark);
383383

384384
_foldingTimer = new System.Windows.Threading.DispatcherTimer
385385
{
@@ -472,6 +472,8 @@ private void LoadVMASMHighlighting(bool isDark)
472472

473473
private void ApplyEditorTheme(bool isDark)
474474
{
475+
ApplyEditorBackground();
476+
475477
void ApplyTo(TextEditor editor)
476478
{
477479
editor.Foreground = isDark
@@ -901,7 +903,7 @@ private Border BuildNumberHoverContent(string numText, UndertaleData data)
901903
}
902904

903905
StackPanel panel = new() { MaxWidth = 320 };
904-
bool isDarkMode = Settings.Instance.EnableDarkMode;
906+
bool isDarkMode = Settings.IsCodeEditorDark;
905907
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
906908
Brush subTextBrush = isDarkMode ? Brushes.LightGray : Brushes.DarkGray;
907909

@@ -1073,7 +1075,7 @@ private Border BuildNameHoverContent(string nameText, UndertaleData data, bool i
10731075
}
10741076

10751077
StackPanel panel = new() { MaxWidth = 320 };
1076-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1078+
bool isDarkMode = Settings.IsCodeEditorDark;
10771079
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
10781080
Brush subTextBrush = isDarkMode ? Brushes.LightGray : Brushes.DarkGray;
10791081

@@ -1152,7 +1154,7 @@ private Border AppendInferredArgumentHover(Border hoverContent, string numText,
11521154
if (perArgTypes is null || argIndex >= perArgTypes.Length || perArgTypes[argIndex] is not IMacroType argType)
11531155
return hoverContent;
11541156

1155-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1157+
bool isDarkMode = Settings.IsCodeEditorDark;
11561158
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
11571159
Brush typeBrush = isDarkMode
11581160
? new SolidColorBrush(Color.FromRgb(78, 201, 176))
@@ -1209,7 +1211,7 @@ private Border AppendInferredFunctionTypesHover(Border hoverContent, string func
12091211
if (description.Length > 120)
12101212
description = description.Substring(0, 117) + "...";
12111213

1212-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1214+
bool isDarkMode = Settings.IsCodeEditorDark;
12131215
Brush typeBrush = isDarkMode
12141216
? new SolidColorBrush(Color.FromRgb(78, 201, 176))
12151217
: new SolidColorBrush(Color.FromRgb(0, 128, 0));
@@ -1389,7 +1391,7 @@ private static string ResolveMacroValueName(IMacroType type, int value, Undertal
13891391

13901392
private Border CreateHoverBorder(UIElement content)
13911393
{
1392-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1394+
bool isDarkMode = Settings.IsCodeEditorDark;
13931395
Brush bgBrush = isDarkMode
13941396
? new SolidColorBrush(Color.FromRgb(45, 45, 48))
13951397
: new SolidColorBrush(Color.FromRgb(240, 240, 240));
@@ -1410,7 +1412,7 @@ private Border CreateHoverBorder(UIElement content)
14101412

14111413
private Border BuildBuiltinFunctionHover(string nameText)
14121414
{
1413-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1415+
bool isDarkMode = Settings.IsCodeEditorDark;
14141416
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
14151417
Brush subTextBrush = isDarkMode ? Brushes.LightGray : Brushes.DarkGray;
14161418
Brush paramBrush = isDarkMode
@@ -1523,7 +1525,7 @@ private Border BuildBuiltinFunctionHover(string nameText)
15231525

15241526
private Border BuildBuiltinVariableHover(string nameText)
15251527
{
1526-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1528+
bool isDarkMode = Settings.IsCodeEditorDark;
15271529
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
15281530
Brush subTextBrush = isDarkMode ? Brushes.LightGray : Brushes.DarkGray;
15291531
Brush typeBrush = isDarkMode
@@ -1590,7 +1592,7 @@ private Border BuildBuiltinVariableHover(string nameText)
15901592

15911593
private Border BuildBuiltinConstantHover(string nameText)
15921594
{
1593-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1595+
bool isDarkMode = Settings.IsCodeEditorDark;
15941596
Brush textBrush = isDarkMode ? Brushes.White : Brushes.Black;
15951597
Brush subTextBrush = isDarkMode ? Brushes.LightGray : Brushes.DarkGray;
15961598
Brush typeBrush = isDarkMode
@@ -1652,9 +1654,24 @@ private Border BuildBuiltinConstantHover(string nameText)
16521654

16531655
public void SetBackgroundTransparency(bool enable)
16541656
{
1655-
bool isDarkMode = Settings.Instance.EnableDarkMode;
1657+
_editorBackgroundTransparent = enable;
1658+
ApplyEditorBackground();
1659+
}
1660+
1661+
/// <summary>
1662+
/// Whether the editor backgrounds are currently semi-transparent (custom background image active).
1663+
/// </summary>
1664+
private bool _editorBackgroundTransparent;
1665+
1666+
/// <summary>
1667+
/// Applies the editor background brush for the current code editor theme
1668+
/// (opaque unless a custom background image is active).
1669+
/// </summary>
1670+
private void ApplyEditorBackground()
1671+
{
1672+
bool isDarkMode = Settings.IsCodeEditorDark;
16561673
Brush bg;
1657-
if (enable)
1674+
if (_editorBackgroundTransparent)
16581675
{
16591676
// Semi-transparent: dark mode = dark tint, light mode = white tint
16601677
bg = isDarkMode
@@ -1677,7 +1694,7 @@ void ApplyToEditor(ICSharpCode.AvalonEdit.TextEditor editor)
16771694
ApplyToEditor(DisassemblyEditor);
16781695

16791696
// Make the TabControl content panel transparent so background image shows through
1680-
CodeModeTabs.SetBackgroundTransparency(enable);
1697+
CodeModeTabs.SetBackgroundTransparency(_editorBackgroundTransparent);
16811698
}
16821699

16831700
private void InitializeIntellisense()
@@ -2244,7 +2261,7 @@ private void UndertaleCodeEditor_Unloaded(object sender, RoutedEventArgs e)
22442261
private void UndertaleCodeEditor_Loaded(object sender, RoutedEventArgs e)
22452262
{
22462263
// Make sure the colors match the theme if it changed while this editor was hidden
2247-
ApplyTheme(Settings.Instance?.EnableDarkMode ?? false);
2264+
ApplyTheme(Settings.IsCodeEditorDark);
22482265
FillInCodeViewer();
22492266
}
22502267
private void FillInCodeViewer(bool overrideFirst = false)
@@ -3469,7 +3486,7 @@ public NameGenerator(UndertaleCodeEditor codeEditorInst, TextArea textAreaInst)
34693486
highlighterInst = textAreaInst.GetService(typeof(IHighlighter)) as IHighlighter;
34703487
textEditorInst = textAreaInst.GetService(typeof(TextEditor)) as TextEditor;
34713488

3472-
UpdateBrushTheme(Settings.Instance?.EnableDarkMode ?? false);
3489+
UpdateBrushTheme(Settings.IsCodeEditorDark);
34733490
}
34743491

34753492
/// <summary>
@@ -3945,7 +3962,7 @@ private static class CompletionItemStyle
39453962
private static readonly Dictionary<string, Brush> _darkBrushes = new();
39463963
private static readonly Dictionary<string, Brush> _lightBrushes = new();
39473964

3948-
private static bool IsDark => Settings.Instance?.EnableDarkMode ?? true;
3965+
private static bool IsDark => Settings.IsCodeEditorDark;
39493966

39503967
public static ImageSource GetIcon(string kind)
39513968
{

UndertaleModTool/Editors/UndertaleShaderEditor.xaml.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ private void TextEditor_Loaded(object sender, RoutedEventArgs e)
4444
}
4545

4646
// Apply the theme colors to the editor chrome (hardcoded in XAML for the dark theme)
47-
bool isDarkMode = Settings.Instance.EnableDarkMode;
47+
bool isDarkMode = Settings.IsCodeEditorDark;
4848
editor.Foreground = isDarkMode
4949
? new SolidColorBrush(Color.FromRgb(0xC0, 0xC0, 0xC0))
5050
: new SolidColorBrush(Colors.Black);
@@ -53,14 +53,19 @@ private void TextEditor_Loaded(object sender, RoutedEventArgs e)
5353
: new SolidColorBrush(Color.FromRgb(0x2B, 0x2B, 0x2B));
5454

5555
// Apply background transparency if custom background is active
56+
Brush bg;
5657
if (Settings.Instance is not null && !string.IsNullOrEmpty(Settings.Instance.BackgroundImagePath))
5758
{
58-
var bg = isDarkMode
59+
bg = isDarkMode
5960
? new SolidColorBrush(Color.FromArgb(200, 32, 32, 32))
6061
: new SolidColorBrush(Color.FromArgb(200, 255, 255, 255));
61-
editor.Background = bg;
62-
editor.TextArea.Background = bg;
6362
}
63+
else
64+
{
65+
bg = isDarkMode ? shaderEditorDefaultDarkBg : shaderEditorDefaultLightBg;
66+
}
67+
editor.Background = bg;
68+
editor.TextArea.Background = bg;
6469

6570
var srcString = editor.DataContext as UndertaleString;
6671
if (srcString is null)

UndertaleModTool/MainWindow.xaml.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,12 +715,21 @@ public static void SetDarkMode(bool enable, bool isStartup = false)
715715
ApplyBackgroundTransparency(true);
716716

717717
// Re-apply the code editor theme to every open window
718+
ApplyCodeEditorThemes();
719+
}
720+
721+
/// <summary>
722+
/// Re-applies the theme of every currently open code editor,
723+
/// resolved from the code editor theme setting.
724+
/// </summary>
725+
public static void ApplyCodeEditorThemes()
726+
{
718727
foreach (Window w in Application.Current.Windows)
719728
{
720729
if (w is not IWindowHost host)
721730
continue;
722731
UndertaleCodeEditor codeEditor = FindVisualChild<UndertaleCodeEditor>(host.DataEditor);
723-
codeEditor?.ApplyTheme(enable);
732+
codeEditor?.ApplyTheme(Settings.IsCodeEditorDark);
724733
}
725734
}
726735
private static void SetDarkTitleBarForWindows(bool enable)

UndertaleModTool/Settings.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@
1313

1414
namespace UndertaleModTool
1515
{
16+
/// <summary>
17+
/// Theme mode of the code editor (independently of the main app theme).
18+
/// </summary>
19+
[JsonConverter(typeof(JsonStringEnumConverter<CodeEditorThemeKind>))]
20+
public enum CodeEditorThemeKind
21+
{
22+
/// <summary>Match the main app dark mode setting.</summary>
23+
FollowApp,
24+
/// <summary>Always use the light editor theme.</summary>
25+
Light,
26+
/// <summary>Always use the dark editor theme.</summary>
27+
Dark,
28+
/// <summary>Use the opposite of the main app dark mode setting.</summary>
29+
InverseApp
30+
}
31+
1632
public class Settings
1733
{
1834
public static readonly string AppDataFolder = Path.Join(
@@ -56,6 +72,7 @@ public class Settings
5672
public string BackgroundStretchMode { get; set; } = "UniformToFill";
5773

5874
public bool EnableDarkMode { get; set; } = false;
75+
public CodeEditorThemeKind CodeEditorTheme { get; set; } = CodeEditorThemeKind.FollowApp;
5976
public bool TabMultiLine { get; set; } = false;
6077
public bool ShowDebuggerOption { get; set; } = false;
6178
public DecompilerSettings DecompilerSettings { get; set; }
@@ -83,6 +100,27 @@ public class Settings
83100

84101
public static Settings Instance { get; private set; }
85102

103+
/// <summary>
104+
/// Whether the code editor should currently use its dark theme,
105+
/// resolved from the code editor theme setting and the app dark mode setting.
106+
/// </summary>
107+
public static bool IsCodeEditorDark
108+
{
109+
get
110+
{
111+
if (Instance is null)
112+
return false;
113+
114+
return Instance.CodeEditorTheme switch
115+
{
116+
CodeEditorThemeKind.Light => false,
117+
CodeEditorThemeKind.Dark => true,
118+
CodeEditorThemeKind.InverseApp => !Instance.EnableDarkMode,
119+
_ => Instance.EnableDarkMode
120+
};
121+
}
122+
}
123+
86124
public static JsonSerializerOptions JsonOptions = new()
87125
{
88126
WriteIndented = true,

UndertaleModTool/Windows/SettingsWindow.xaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,20 @@
112112

113113
<StackPanel Grid.Column="0">
114114
<CheckBox IsChecked="{Binding EnableDarkMode}" Content="{loc:Loc Settings_EnableDarkMode}" ToolTip="{loc:Loc Settings_EnableDarkModeToolTip}"/>
115+
<Grid ToolTip="{loc:Loc Settings_CodeEditorThemeToolTip}">
116+
<Grid.ColumnDefinitions>
117+
<ColumnDefinition Width="Auto"/>
118+
<ColumnDefinition Width="*"/>
119+
</Grid.ColumnDefinitions>
120+
<TextBlock Text="{loc:Loc Settings_CodeEditorTheme}" VerticalAlignment="Center" Margin="3"/>
121+
<local:ComboBoxDark x:Name="CodeEditorThemeComboBox" Grid.Column="1" Margin="3" MinWidth="160" HorizontalAlignment="Left"
122+
SelectionChanged="CodeEditorThemeComboBox_SelectionChanged">
123+
<ComboBoxItem Content="{loc:Loc Settings_CodeEditorTheme_FollowApp}" Tag="FollowApp"/>
124+
<ComboBoxItem Content="{loc:Loc Settings_CodeEditorTheme_Light}" Tag="Light"/>
125+
<ComboBoxItem Content="{loc:Loc Settings_CodeEditorTheme_Dark}" Tag="Dark"/>
126+
<ComboBoxItem Content="{loc:Loc Settings_CodeEditorTheme_InverseApp}" Tag="InverseApp"/>
127+
</local:ComboBoxDark>
128+
</Grid>
115129
<StackPanel Orientation="Horizontal">
116130
<TextBlock Text="{loc:Loc Settings_TransparencyGridColors}"/>
117131
<local:TextBoxDark Width="80" Text="{Binding TransparencyGridColor1}" />

UndertaleModTool/Windows/SettingsWindow.xaml.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ public SettingsWindow()
348348
break;
349349
}
350350
}
351+
352+
CodeEditorThemeComboBox.SelectedIndex = (int)Settings.Instance.CodeEditorTheme;
351353
}
352354

353355
private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
@@ -375,6 +377,19 @@ private void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEv
375377
}
376378
}
377379

380+
private void CodeEditorThemeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
381+
{
382+
if (CodeEditorThemeComboBox?.SelectedItem is ComboBoxItem item
383+
&& Enum.TryParse(item.Tag as string, out CodeEditorThemeKind theme)
384+
&& Settings.Instance is not null)
385+
{
386+
Settings.Instance.CodeEditorTheme = theme;
387+
Settings.Save();
388+
389+
MainWindow.ApplyCodeEditorThemes();
390+
}
391+
}
392+
378393
private void AppDataButton_Click(object sender, RoutedEventArgs e)
379394
{
380395
MainWindow.OpenFolder(Settings.AppDataFolder);

0 commit comments

Comments
 (0)