Skip to content

Commit 0ea2a1e

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 workarounds done, but the experimental mode is still incomplete with some text hard to read. Add dark+, similar to VS Code Dark+ theme with darker panels and editor. highconstrast_dark theme was removed, no longer needed Refs: gitextensions#12111
1 parent d1f78f6 commit 0ea2a1e

24 files changed

+239
-92
lines changed

setup/installer/Product.wxs

Lines changed: 7 additions & 3 deletions
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/Program.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ private static void Main()
1616
Application.EnableVisualStyles();
1717
Application.SetCompatibleTextRenderingDefault(false);
1818

19+
// Not adapted to themes, many overrides required for .net9
20+
#pragma warning disable WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
21+
Application.SetColorMode(SystemColorMode.Classic);
22+
#pragma warning restore WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
23+
1924
// This form created to obtain UI synchronization context only
2025
using (new Form())
2126
{

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,6 @@ public enum AppColor
6161
AnsiTerminalWhiteBackNormal,
6262
AnsiTerminalWhiteForeBold,
6363
AnsiTerminalWhiteBackBold,
64+
DarkModePseudoColor, // This color is used to determine if the theme is dark or light.
6465
}
6566
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ 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) },
62+
{ AppColor.DarkModePseudoColor, Color.Empty },
6263
};
6364

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

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 20 additions & 4 deletions
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,17 @@ 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+
#pragma warning disable WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
90+
if (Application.IsDarkModeEnabled && button.FlatStyle == FlatStyle.Standard)
91+
{
92+
// In addition to not setting the BackColor (TouchBackColor() will fix),
93+
// FlatStyle.Standard buttons look ugly in dark mode
94+
button.FlatStyle = FlatStyle.Flat;
95+
}
96+
#pragma warning restore WFO5001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
8797
}
8898

8999
private static void SetupTabControl(TabControl tabControl)
@@ -101,6 +111,12 @@ private static void SetupTabPage(TabPage page)
101111
}
102112
}
103113

114+
private static void SetupDataGridView(DataGridView view)
115+
{
116+
view.EnableHeadersVisualStyles = false;
117+
view.ColumnHeadersDefaultCellStyle.BackColor = view.ColumnHeadersDefaultCellStyle.BackColor;
118+
}
119+
104120
private static void SetupTreeView(TreeView view)
105121
{
106122
}

src/app/GitUI/CommandsDialogs/FormCommit.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using GitUI.Properties;
2222
using GitUI.ScriptsEngine;
2323
using GitUI.SpellChecker;
24+
using GitUI.Theming;
2425
using GitUI.UserControls;
2526
using GitUIPluginInterfaces;
2627
using Microsoft;
@@ -205,10 +206,13 @@ private CommitKind CommitKind
205206
_commitKind = value;
206207

207208
modifyCommitMessageButton.Visible = _useFormCommitMessage && CommitKind is not (CommitKind.Normal or CommitKind.Amend);
209+
modifyCommitMessageButton.ForeColor = ThemeModule.IsDarkTheme ? SystemColors.ControlText : SystemColors.HotTrack;
210+
208211
bool messageCanBeChanged = _useFormCommitMessage && CommitKind is (CommitKind.Normal or CommitKind.Amend);
209212
Message.Enabled = messageCanBeChanged;
210213
commitMessageToolStripMenuItem.Enabled = messageCanBeChanged;
211214
commitTemplatesToolStripMenuItem.Enabled = messageCanBeChanged;
215+
Message.EvaluateForecolor();
212216
}
213217
}
214218

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

349353
toolStripStatusBranchIcon.AdaptImageLightness();
350354

355+
// Change the link color
356+
commitAuthorStatus.LinkColor = ThemeModule.IsDarkTheme ? Color.CornflowerBlue : Color.FromArgb(0, 0, 0xff);
357+
remoteNameLabel.LinkColor = ThemeModule.IsDarkTheme ? Color.CornflowerBlue : Color.Blue;
358+
351359
splitLeft.Panel1.BackColor = OtherColors.PanelBorderColor;
352360
splitLeft.Panel2.BackColor = OtherColors.PanelBorderColor;
353361
splitRight.Panel1.BackColor = OtherColors.PanelBorderColor;

src/app/GitUI/CommandsDialogs/FormRebase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using GitExtensions.Extensibility.Git;
55
using GitExtUtils.GitUI.Theming;
66
using GitUI.HelperDialogs;
7+
using GitUI.Theming;
78
using ResourceManager;
89

910
namespace GitUI.CommandsDialogs
@@ -195,7 +196,7 @@ private void EnableButtons()
195196
AcceptButton = btnSolveConflicts;
196197
btnSolveConflicts.Focus();
197198
btnSolveConflicts.Text = _solveConflictsText2.Text;
198-
MergeToolPanel.BackColor = Color.Yellow.AdaptBackColor();
199+
MergeToolPanel.BackColor = ThemeModule.IsDarkTheme ? Color.FromArgb(136, 136, 0) : Color.Yellow.AdaptBackColor();
199200
}
200201
else if (Module.InTheMiddleOfRebase())
201202
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public override void OnPageShown()
177177
{
178178
if (icon.Value is Bitmap bitmap)
179179
{
180-
EmbeddedIcons.Images.Add(icon.Key.ToString()!, bitmap.AdaptLightness());
180+
EmbeddedIcons.Images.Add(icon.Key.ToString()!, bitmap);
181181
}
182182
}
183183

src/app/GitUI/Editor/FileViewer.cs

Lines changed: 3 additions & 2 deletions
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

Lines changed: 0 additions & 1 deletion
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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using GitExtensions.Extensibility.Git;
2-
using GitExtUtils.GitUI.Theming;
2+
using GitUI.Theming;
33
using ICSharpCode.TextEditor;
44
using ICSharpCode.TextEditor.Document;
55

@@ -18,15 +18,15 @@ internal sealed class RebaseTodoHighlightingStrategy : GitHighlightingStrategyBa
1818
d, drop = remove commit
1919
*/
2020

21-
private static readonly Dictionary<char, (string longForm, HighlightColor color, string[] options)> _commandByFirstChar = new()
21+
private readonly Dictionary<char, (string longForm, HighlightColor color, string[] options)> _commandByFirstChar = new()
2222
{
2323
{ '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" }) },
24+
{ 'r', ("reword", new HighlightColor(ThemeModule.IsDarkTheme ? Color.MediumPurple : Color.Purple, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
25+
{ 'e', ("edit", new HighlightColor(ThemeModule.IsDarkTheme ? Color.LightGray : Color.DarkGray, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
26+
{ 's', ("squash", new HighlightColor(ThemeModule.IsDarkTheme ? Color.CornflowerBlue : Color.DarkBlue, bold: true, italic: false, adaptable: false), Array.Empty<string>()) },
27+
{ 'f', ("fixup", new HighlightColor(ThemeModule.IsDarkTheme ? Color.Coral : Color.LightCoral, bold: true, italic: false, adaptable: false), new[] { "-C", "-c" }) },
2828
{ '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>()) }
29+
{ 'd', ("drop", new HighlightColor(ThemeModule.IsDarkTheme ? Color.IndianRed : Color.Red, bold: true, italic: false, adaptable: false), Array.Empty<string>()) }
3030
};
3131

3232
public RebaseTodoHighlightingStrategy(IGitModule module)
@@ -57,7 +57,7 @@ private enum State
5757
Id
5858
}
5959

60-
private static bool TryHighlightInteractiveRebaseCommand(IDocument document, LineSegment line)
60+
private bool TryHighlightInteractiveRebaseCommand(IDocument document, LineSegment line)
6161
{
6262
if (line.Length < 1)
6363
{

src/app/GitUI/GitUI.csproj

Lines changed: 0 additions & 6 deletions
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
using System.Diagnostics;
22
using GitExtensions.Extensibility.Git;
3-
using GitExtUtils.GitUI.Theming;
43
using GitUI.Properties;
4+
using GitUI.Theming;
55

66
namespace GitUI.LeftPanel
77
{
88
[DebuggerDisplay("(Node) FullPath = {FullPath}")]
99
internal abstract class BaseRevisionNode : Node
1010
{
1111
protected const char PathSeparator = '/';
12-
private static readonly Color _invisibleForeColor = Color.Silver.AdaptTextColor();
12+
private static readonly Color _invisibleForeColor = ThemeModule.IsDarkTheme ? SystemColors.GrayText : Color.Silver;
1313

1414
protected BaseRevisionNode(Tree tree, string fullPath, bool visible)
1515
: base(tree)

src/app/GitUI/ScriptsEngine/SplitButton.cs

Lines changed: 1 addition & 5 deletions
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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using GitCommands.Settings;
55
using GitExtensions.Extensibility.Settings;
66
using GitUI.AutoCompletion;
7+
using GitUI.Theming;
78
using GitUI.UserControls;
89
using Microsoft;
910
using Microsoft.VisualStudio.Threading;
@@ -85,12 +86,23 @@ public override string Text
8586
set
8687
{
8788
HideWatermark();
89+
EvaluateForecolor();
8890
TextBox.Text = value;
8991
ShowWatermark();
9092
OnTextAssigned();
9193
}
9294
}
9395

96+
public void EvaluateForecolor()
97+
{
98+
if (ThemeModule.IsDarkTheme)
99+
{
100+
// In dark mode the background color is set to White, but still reported as SystemColors.Window (or adjusted)
101+
// The Forecolor must be changed manually
102+
TextBox.ForeColor = TextBox.Enabled ? SystemColors.WindowText : SystemColors.HighlightText;
103+
}
104+
}
105+
94106
private void OnTextAssigned()
95107
{
96108
TextAssigned?.Invoke(this, EventArgs.Empty);

src/app/GitUI/Themes/README.md

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# Overview
22

3-
Git Extensions supports color customization, specifically a user can choose between
4-
a default (operating system defined), a bright or a dark themes.
3+
Git Extensions supports color customization to some extent:
54

6-
There is a [Wiki page on Dark Theme](https://github.com/gitextensions/gitextensions/wiki/Dark-Theme)
7-
with some background information and a list of known issues.
5+
- Activate Windows light or dark app mode
6+
- Customize app spceific colors
7+
8+
There is no full theme support, system colors cannot be changed.
9+
10+
Git Extensions includes a light+ theme (slightly darker panels compared to the built-in light theme),
11+
a dark theme for system dark mode and a dark+ mode with slightly darker panels.
812

913
## Themes location
1014

@@ -37,15 +41,13 @@ It only uses pre-installed themes from `{App install}\Themes` directory.
3741

3842
## How to create a custom theme
3943

40-
Copy `Themes\dark.css` or `Theme\bright.css` and change color values. Use a text editor, preferably
44+
Copy `Themes\dark.css` or `Theme\invariant.css` and change color values. Use a text editor, preferably
4145
with .css syntax highlighting and inline color display.
4246

43-
Currently only application colors like branch labels in the revision grid and
44-
diff colors can be changed, the system colors listed in the templates will not be changed.
45-
Furthermore a dark theme is only usable if the Windows system theme is dark.
46-
(Dark mode in Windows settings is not sufficient to change system colors to be dark.)
47+
Only application colors like branch labels in the revision grid and
48+
diff colors can be changed, the system colors cannot be changed.
4749

48-
There is a plugin for Visual Studio to show .css colors inline.
50+
There is an extension for Visual Studio to show .css colors inline.
4951

5052
Visual Studio Code and JetBrains Rider displays .css colors inline out-of-the-box.
5153

@@ -56,21 +58,21 @@ Use .css import directive to reuse color values from another theme.
5658
- To import from a preinstalled theme:
5759

5860
```css
59-
@import url("bright.css");
61+
@import url("dark.css");
6062
```
6163

6264
- To import from a user-defined theme:
6365

6466
```css
65-
@import url("{UserAppData}/bright_custom.css");
67+
@import url("{UserAppData}/dark_custom.css");
6668
```
6769

6870
### Specify alternative color values for colorblind users
6971

7072
To keep the number of themes small, color variations for colorblind users are specified without
71-
creating a separate theme. See for example `bright.css`:
73+
creating a separate theme. See for example `dark.css`:
7274

7375
```css
74-
.Graph { color: #8a0000 } /* hsl(0, 100%, 27%) */
75-
.Graph.colorblind { color: #0600a8 } /* hsl(242, 100%, 33%) */
76+
.AnsiTerminalRedBackNormal { color: #620707; }
77+
.AnsiTerminalRedBackNormal.colorblind { color: #080646; }
7678
```

src/app/GitUI/Themes/dark+.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* See (App install)\Themes\README.md for instructions on how to create or modify a theme */
2+
3+
@import url("dark.css");
4+
5+
/* Application colors */
6+
.PanelBackground { color: #252526; }
7+
.EditorBackground { color: #1e1e1e; }
8+
.LineNumberBackground { color: #303030; }
9+
10+
.Branch { color: #00d76b; }
11+
.RemoteBranch { color: #ff8080; } /* hsl(0, 100%, 75%) */

0 commit comments

Comments
 (0)