Skip to content

Commit 212068b

Browse files
committed
feat: support for dark app mode
Basic adaption of .net9 experimental dark app mode: SystemColorMode.Dark The themeing is adopted to use Windows dark app mode enabled in .net9. The .net9 dark mode does not allow override of any system colors. A number of adaptions of the application colors. There are some visual issues still, some due to .net, but also the application colors may require some tuning. Add dark+ theme, similar to VS Code Dark+ theme with darker panels and editor. highconstrast_dark theme was removed, no longer needed Refs: #12111 author highlight more subtle
1 parent 34af1a3 commit 212068b

30 files changed

+288
-128
lines changed

.editorconfig

+5-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,11 @@ csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimenta
296296
csharp_style_prefer_pattern_matching = true:silent
297297
csharp_style_prefer_not_pattern = true:suggestion
298298
csharp_style_prefer_extended_property_pattern = true:suggestion
299+
csharp_prefer_system_threading_lock = true:suggestion
299300

300301
# WFO1000: A property should determine its property content serialization with the DesignerSerializationVisibilityAttribute, DefaultValueAttribute or the ShouldSerializeProperty method
301302
# Silent for now, see https://github.com/dotnet/winforms/issues/12476
302-
dotnet_diagnostic.WFO1000.severity = silent
303+
dotnet_diagnostic.WFO1000.severity = silent
304+
305+
# WFO5001: Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
306+
dotnet_diagnostic.WFO5001.severity = silent

setup/installer/Product.wxs

+7-3
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,11 @@
314314
<Component Id="Themes.light_plus.css" Guid="*">
315315
<File Source="$(var.ArtifactsPublishPath)\Themes\light+.css" />
316316
</Component>
317-
<Component Id="Themes.highcontrast_dark.css" Guid="*">
318-
<File Source="$(var.ArtifactsPublishPath)\Themes\highcontrast_dark.css" />
317+
<Component Id="Themes.dark.css" Guid="*">
318+
<File Source="$(var.ArtifactsPublishPath)\Themes\dark.css" />
319+
</Component>
320+
<Component Id="Themes.dark_plus.css" Guid="*">
321+
<File Source="$(var.ArtifactsPublishPath)\Themes\dark+.css" />
319322
</Component>
320323
</DirectoryRef>
321324
<DirectoryRef Id="PluginsDir">
@@ -606,8 +609,9 @@
606609
<ComponentGroup Id="Component.Themes">
607610
<ComponentRef Id="Themes.README.md" />
608611
<ComponentRef Id="Themes.invariant.css" />
609-
<ComponentRef Id="Themes.highcontrast_dark.css" />
610612
<ComponentRef Id="Themes.light_plus.css" />
613+
<ComponentRef Id="Themes.dark.css" />
614+
<ComponentRef Id="Themes.dark_plus.css" />
611615
</ComponentGroup>
612616
<ComponentGroup Id="Component.Translation">
613617
<ComponentRef Id="English.gif" />

src/app/BugReporter/BugReportForm.cs

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using GitExtensions.Extensibility.Translations;
1515
using GitExtensions.Extensibility.Translations.Xliff;
1616
using GitExtUtils.GitUI;
17+
using GitExtUtils.GitUI.Theming;
1718
using GitUI;
1819
using Microsoft;
1920
using ResourceManager;
@@ -126,6 +127,12 @@ public DialogResult ShowDialog(IWin32Window? owner, SerializableException except
126127
return result;
127128
}
128129

130+
protected override void OnLoad(EventArgs e)
131+
{
132+
base.OnLoad(e);
133+
this.FixVisualStyle();
134+
}
135+
129136
protected override void OnShown(EventArgs e)
130137
{
131138
base.OnShown(e);

src/app/GitExtUtils/GitUI/Theming/AppColorDefaults.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static class AppColorDefaults
5858
{ AppColor.AnsiTerminalWhiteForeNormal, Color.FromArgb(0xbf, 0xbf, 0xbf) },
5959
{ AppColor.AnsiTerminalWhiteBackNormal, Color.FromArgb(0xe0, 0xe0, 0xe0) },
6060
{ AppColor.AnsiTerminalWhiteForeBold, Color.FromArgb(0xff, 0xff, 0xff) },
61-
{ AppColor.AnsiTerminalWhiteBackBold, Color.FromArgb(0xff, 0xff, 0xff) }
61+
{ AppColor.AnsiTerminalWhiteBackBold, Color.FromArgb(0xff, 0xff, 0xff) },
6262
};
6363

6464
private static readonly Dictionary<string, Dictionary<AppColor, Color>> _variations = new()

src/app/GitExtUtils/GitUI/Theming/Theme.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private Color GetSysColor(KnownColor name) =>
5555
/// </summary>
5656
private static IReadOnlyCollection<KnownColor> SysColorNames { get; } =
5757
new HashSet<KnownColor>(
58-
Enum.GetValues(typeof(KnownColor))
58+
Enum.GetValues<KnownColor>()
5959
.Cast<KnownColor>()
6060
.Where(c => IsSystemColor(c)));
6161

src/app/GitExtUtils/GitUI/Theming/ThemeFix.cs

+18-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ public static void FixVisualStyle(this Control container)
2121
return;
2222
}
2323

24-
container.DescendantsToFix<GroupBox>()
25-
.ForEach(SetupGroupBox);
24+
container.DescendantsToFix<DataGridView>()
25+
.ForEach(SetupDataGridView);
2626
container.DescendantsToFix<TreeView>()
2727
.ForEach(SetupTreeView);
2828
container.DescendantsToFix<TabControl>()
@@ -33,6 +33,8 @@ public static void FixVisualStyle(this Control container)
3333
.ForEach(SetupLinkLabel);
3434
container.DescendantsToFix<ToolStrip>()
3535
.ForEach(SetupToolStrip);
36+
container.DescendantsToFix<Button>()
37+
.ForEach(SetupButton);
3638
container.ContextMenusToFix()
3739
.ForEach(SetupContextMenu);
3840
}
@@ -81,9 +83,15 @@ private static void SetupLinkLabel(this LinkLabel label)
8183
label.ActiveLinkColor = label.ActiveLinkColor.AdaptTextColor();
8284
}
8385

84-
private static void SetupGroupBox(this GroupBox box)
86+
private static void SetupButton(this Button button)
8587
{
86-
box.TouchForeColor();
88+
// .net9 fix for https://github.com/dotnet/winforms/issues/11949 (only supposed to occur for 100%)
89+
if (Application.IsDarkModeEnabled && button.FlatStyle == FlatStyle.Standard)
90+
{
91+
// In addition to not setting the BackColor (TouchBackColor() will fix),
92+
// FlatStyle.Standard buttons look ugly in dark mode
93+
button.FlatStyle = FlatStyle.Flat;
94+
}
8795
}
8896

8997
private static void SetupTabControl(TabControl tabControl)
@@ -101,6 +109,12 @@ private static void SetupTabPage(TabPage page)
101109
}
102110
}
103111

112+
private static void SetupDataGridView(DataGridView view)
113+
{
114+
view.EnableHeadersVisualStyles = false;
115+
view.ColumnHeadersDefaultCellStyle.BackColor = view.ColumnHeadersDefaultCellStyle.BackColor;
116+
}
117+
104118
private static void SetupTreeView(TreeView view)
105119
{
106120
}

src/app/GitUI/CommandsDialogs/BrowseDialog/DashboardControl/Dashboard.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using GitExtUtils.GitUI;
55
using GitExtUtils.GitUI.Theming;
66
using GitUI.Properties;
7-
using GitUI.Theming;
87
using ResourceManager;
98

109
namespace GitUI.CommandsDialogs.BrowseDialog.DashboardControl
@@ -56,7 +55,7 @@ protected override void OnVisibleChanged(EventArgs e)
5655

5756
public void RefreshContent()
5857
{
59-
DashboardTheme selectedTheme = ThemeModule.IsDarkTheme ? DashboardTheme.Dark : DashboardTheme.Light;
58+
DashboardTheme selectedTheme = Application.IsDarkModeEnabled ? DashboardTheme.Dark : DashboardTheme.Light;
6059

6160
InitDashboardLayout();
6261
ApplyTheme();

src/app/GitUI/CommandsDialogs/FormCommit.cs

+7
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,13 @@ private CommitKind CommitKind
205205
_commitKind = value;
206206

207207
modifyCommitMessageButton.Visible = _useFormCommitMessage && CommitKind is not (CommitKind.Normal or CommitKind.Amend);
208+
modifyCommitMessageButton.ForeColor = Application.IsDarkModeEnabled ? SystemColors.ControlText : SystemColors.HotTrack;
209+
208210
bool messageCanBeChanged = _useFormCommitMessage && CommitKind is (CommitKind.Normal or CommitKind.Amend);
209211
Message.Enabled = messageCanBeChanged;
210212
commitMessageToolStripMenuItem.Enabled = messageCanBeChanged;
211213
commitTemplatesToolStripMenuItem.Enabled = messageCanBeChanged;
214+
Message.EvaluateForecolor();
212215
}
213216
}
214217

@@ -348,6 +351,10 @@ public FormCommit(IGitUICommands commands, CommitKind commitKind = CommitKind.No
348351

349352
toolStripStatusBranchIcon.AdaptImageLightness();
350353

354+
// Change the link color
355+
commitAuthorStatus.LinkColor = Application.IsDarkModeEnabled ? Color.CornflowerBlue : Color.FromArgb(0, 0, 0xff);
356+
remoteNameLabel.LinkColor = Application.IsDarkModeEnabled ? Color.CornflowerBlue : Color.Blue;
357+
351358
splitLeft.Panel1.BackColor = OtherColors.PanelBorderColor;
352359
splitLeft.Panel2.BackColor = OtherColors.PanelBorderColor;
353360
splitRight.Panel1.BackColor = OtherColors.PanelBorderColor;

src/app/GitUI/CommandsDialogs/FormRebase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ private void EnableButtons()
195195
AcceptButton = btnSolveConflicts;
196196
btnSolveConflicts.Focus();
197197
btnSolveConflicts.Text = _solveConflictsText2.Text;
198-
MergeToolPanel.BackColor = Color.Yellow.AdaptBackColor();
198+
MergeToolPanel.BackColor = Application.IsDarkModeEnabled ? Color.FromArgb(136, 136, 0) : Color.Yellow.AdaptBackColor();
199199
}
200200
else if (Module.InTheMiddleOfRebase())
201201
{

src/app/GitUI/CommandsDialogs/SettingsDialog/Pages/ScriptsSettingsPage.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using GitCommands.Utils;
88
using GitExtUtils;
99
using GitExtUtils.GitUI;
10-
using GitExtUtils.GitUI.Theming;
1110
using GitUI.ScriptsEngine;
1211
using Microsoft;
1312
using ResourceManager;
@@ -177,7 +176,7 @@ public override void OnPageShown()
177176
{
178177
if (icon.Value is Bitmap bitmap)
179178
{
180-
EmbeddedIcons.Images.Add(icon.Key.ToString()!, bitmap.AdaptLightness());
179+
EmbeddedIcons.Images.Add(icon.Key.ToString()!, bitmap);
181180
}
182181
}
183182

src/app/GitUI/Editor/Diff/AnsiEscapeUtilities.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Diagnostics;
2-
using System.Linq;
32
using System.Text;
43
using System.Text.RegularExpressions;
54
using GitExtensions.Extensibility;
@@ -13,7 +12,7 @@ public partial class AnsiEscapeUtilities
1312
{
1413
[GeneratedRegex(@"\u001b\[((?<escNo>\d+)\s*[:;]?\s*)*m", RegexOptions.ExplicitCapture)]
1514
private static partial Regex EscapeRegex();
16-
private static readonly int _defaultForeColorId = ThemeModule.IsDarkTheme ? _whiteId : _blackId;
15+
private static readonly int _defaultForeColorId = Application.IsDarkModeEnabled ? _whiteId : _blackId;
1716

1817
// Color code definitions
1918
private const int _blackId = 0;

src/app/GitUI/Editor/FileViewer.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using GitUI.CommandsDialogs;
1717
using GitUI.CommandsDialogs.SettingsDialog.Pages;
1818
using GitUI.Properties;
19-
using GitUI.Theming;
2019
using GitUI.UserControls;
2120
using GitUIPluginInterfaces;
2221
using ICSharpCode.TextEditor.Util;
@@ -436,7 +435,9 @@ public ArgumentString GetExtraDiffArguments(bool isRangeDiff = false, bool isCom
436435
// Difftastic coloring is always used (AppSettings.UseGitColoring.Value is not used).
437436
// Allow user to override with difftool command line options.
438437
SetEnvironmentVariable("DFT_COLOR", "always");
439-
SetEnvironmentVariable("DFT_BACKGROUND", ThemeModule.IsDarkTheme ? "dark" : "light");
438+
439+
// DFT_BACKGROUND="dark" applies bold-bold colors, "light" corresponds better with Git colors
440+
SetEnvironmentVariable("DFT_BACKGROUND", "light");
440441
SetEnvironmentVariable("DFT_SYNTAX_HIGHLIGHT", ShowSyntaxHighlightingInDiff ? "on" : "off");
441442
int contextLines = ShowEntireFile ? 9000 : NumberOfContextLines;
442443
SetEnvironmentVariable("DFT_CONTEXT", contextLines.ToString());

src/app/GitUI/Editor/GitHighlightingStrategyBase.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using GitExtensions.Extensibility.Git;
2-
using GitExtUtils.GitUI.Theming;
32
using ICSharpCode.TextEditor.Document;
43

54
namespace GitUI.Editor

src/app/GitUI/Editor/RebaseTodoHighlightingStrategy.cs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using GitExtensions.Extensibility.Git;
2-
using GitExtUtils.GitUI.Theming;
32
using ICSharpCode.TextEditor;
43
using ICSharpCode.TextEditor.Document;
54

@@ -18,15 +17,15 @@ internal sealed class RebaseTodoHighlightingStrategy : GitHighlightingStrategyBa
1817
d, drop = remove commit
1918
*/
2019

21-
private static readonly Dictionary<char, (string longForm, HighlightColor color, string[] options)> _commandByFirstChar = new()
20+
private readonly Dictionary<char, (string longForm, HighlightColor color, string[] options)> _commandByFirstChar = new()
2221
{
2322
{ 'p', ("pick", new HighlightColor(nameof(SystemColors.InfoText), bold: true, italic: false), Array.Empty<string>()) },
24-
{ 'r', ("reword", new HighlightColor(Color.Purple.AdaptTextColor(), bold: true, italic: false), Array.Empty<string>()) },
25-
{ 'e', ("edit", new HighlightColor(Color.DarkGray.AdaptTextColor(), bold: true, italic: false), Array.Empty<string>()) },
26-
{ 's', ("squash", new HighlightColor(Color.DarkBlue.AdaptTextColor(), bold: true, italic: false), Array.Empty<string>()) },
27-
{ 'f', ("fixup", new HighlightColor(Color.LightCoral.AdaptTextColor(), bold: true, italic: false), new[] { "-C", "-c" }) },
23+
{ 'r', ("reword", new HighlightColor(Application.IsDarkModeEnabled ? Color.MediumPurple : Color.Purple, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
24+
{ 'e', ("edit", new HighlightColor(Application.IsDarkModeEnabled ? Color.LightGray : Color.DarkGray, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
25+
{ 's', ("squash", new HighlightColor(Application.IsDarkModeEnabled ? Color.CornflowerBlue : Color.DarkBlue, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
26+
{ 'f', ("fixup", new HighlightColor(Application.IsDarkModeEnabled ? Color.Coral : Color.LightCoral, bold: true, italic: false, adaptable: false), new[] { "-C", "-c" }) },
2827
{ 'x', ("exec", new HighlightColor(nameof(SystemColors.GrayText), bold: true, italic: false), Array.Empty<string>()) },
29-
{ 'd', ("drop", new HighlightColor(Color.Red.AdaptTextColor(), bold: true, italic: false), Array.Empty<string>()) }
28+
{ 'd', ("drop", new HighlightColor(Application.IsDarkModeEnabled ? Color.IndianRed : Color.Red, bold: true, italic: false, adaptable: false), Array.Empty<string>()) }
3029
};
3130

3231
public RebaseTodoHighlightingStrategy(IGitModule module)
@@ -57,7 +56,7 @@ private enum State
5756
Id
5857
}
5958

60-
private static bool TryHighlightInteractiveRebaseCommand(IDocument document, LineSegment line)
59+
private bool TryHighlightInteractiveRebaseCommand(IDocument document, LineSegment line)
6160
{
6261
if (line.Length < 1)
6362
{

src/app/GitUI/GitUI.csproj

-6
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,4 @@
8282
</Content>
8383
</ItemGroup>
8484

85-
<ItemGroup>
86-
<Content Update="Themes\dark.css">
87-
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
88-
</Content>
89-
</ItemGroup>
90-
9185
</Project>

src/app/GitUI/LeftPanel/BaseRevisionNode.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Diagnostics;
22
using GitExtensions.Extensibility.Git;
3-
using GitExtUtils.GitUI.Theming;
43
using GitUI.Properties;
54

65
namespace GitUI.LeftPanel
@@ -9,7 +8,7 @@ namespace GitUI.LeftPanel
98
internal abstract class BaseRevisionNode : Node
109
{
1110
protected const char PathSeparator = '/';
12-
private static readonly Color _invisibleForeColor = Color.Silver.AdaptTextColor();
11+
private static readonly Color _invisibleForeColor = Application.IsDarkModeEnabled ? SystemColors.GrayText : Color.Silver;
1312

1413
protected BaseRevisionNode(Tree tree, string fullPath, bool visible)
1514
: base(tree)

src/app/GitUI/ScriptsEngine/SplitButton.cs

+1-5
Original file line numberDiff line numberDiff line change
@@ -292,21 +292,17 @@ protected override void OnPaint(PaintEventArgs pevent)
292292

293293
Graphics g = pevent.Graphics;
294294
Rectangle bounds = ClientRectangle;
295+
pevent.Graphics.Clear(SystemColors.Window);
295296

296297
// draw the button background as according to the current state.
297298
if (State != PushButtonState.Pressed && IsDefault && !Application.RenderWithVisualStyles)
298299
{
299300
Rectangle backgroundBounds = bounds;
300301
backgroundBounds.Inflate(-1, -1);
301-
ButtonRenderer.DrawButton(g, backgroundBounds, State);
302302

303303
// button renderer doesn't draw the black frame when themes are off
304304
g.DrawRectangle(SystemPens.WindowFrame, 0, 0, bounds.Width - 1, bounds.Height - 1);
305305
}
306-
else
307-
{
308-
ButtonRenderer.DrawButton(g, bounds, State);
309-
}
310306

311307
// calculate the current dropdown rectangle.
312308
_dropDownRectangle = new Rectangle(bounds.Right - SplitSectionWidth, 0, SplitSectionWidth, bounds.Height);

src/app/GitUI/SpellChecker/EditNetSpell.cs

+11
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,23 @@ public override string Text
9292
set
9393
{
9494
HideWatermark();
95+
EvaluateForecolor();
9596
TextBox.Text = value;
9697
ShowWatermark();
9798
OnTextAssigned();
9899
}
99100
}
100101

102+
public void EvaluateForecolor()
103+
{
104+
if (Application.IsDarkModeEnabled)
105+
{
106+
// In dark mode the background color is set to White, but still reported as SystemColors.Window (or adjusted)
107+
// The Forecolor must be changed manually
108+
TextBox.ForeColor = TextBox.Enabled ? SystemColors.WindowText : SystemColors.HighlightText;
109+
}
110+
}
111+
101112
private void OnTextAssigned()
102113
{
103114
TextAssigned?.Invoke(this, EventArgs.Empty);

0 commit comments

Comments
 (0)