Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More themes #2906

Merged
merged 15 commits into from
Mar 18, 2023
Merged

More themes #2906

merged 15 commits into from
Mar 18, 2023

Conversation

ltrzesniewski
Copy link
Contributor

@ltrzesniewski ltrzesniewski commented Feb 20, 2023

Fixes #2904

Problem

I'd like to have more theme choices than just light/dark.

Solution

  • Any comments on the approach taken, its consistency with surrounding code, etc.

    Basic approach:

    • Identify a theme by its name (instead of a bool)
    • Replace the "moon" button with a combo box (which should probably be moved to the settings dialog)
    • Remove duplicate xshd files
    • Allow to override the xshd colors from the theme resource dictionary

    Additional changes:

    • Made foreground, background and search results colors themeable
    • Added semantic highlighting for properties, events, variables and parameters
    • Allowed for methods and fields to have different colors for declarations and usages (I didn't end up using this in the themes I added though, I can revert if you prefer)
    • Added rules for IL labels and asm instruction addresses and bytes
    • Changed constructor highlighting to use the type color instead of the method color (same way as IDEs display them)
  • Which part of this PR is most in need of attention/improvement?

    • I made a small change in TextTokenWriter.IsDefinition I'm not 100% sure about, as I'm still unfamiliar with the AST.
    • I don't know the proper Chinese translation for "Theme". It is only displayed in the combo box tooltip, so that's probably not a big issue.
  • At least one test covering the code changed

    This is a visual change only.

@ltrzesniewski ltrzesniewski mentioned this pull request Feb 20, 2023
@ltrzesniewski
Copy link
Contributor Author

I added a theme based on the Light+ theme from VS Code, here's a preview:

@ltrzesniewski ltrzesniewski marked this pull request as ready for review February 22, 2023 21:02
@ltrzesniewski
Copy link
Contributor Author

ltrzesniewski commented Feb 22, 2023

This starts to look good, so I'm marking it as ready for review.

There are 6 themes in total: 3 light and 3 dark. I left the existing ones as-is, and added 4 more inspired by VS Code and ReSharper.

I left the theme selector combo box in the toolbar (at least for now), as it's easier to compare themes that way.

Also add a fallback mechanism for colors: if a color definition is empty, another one can be used instead.
@TERIHAX
Copy link

TERIHAX commented Feb 28, 2023

This looks pretty good, would like to see this be approved.

# Conflicts:
#	ILSpy/TextView/ILAsm-Mode-Dark.xshd
#	ILSpy/TextView/ILAsm-Mode.xshd

public void ApplyTo(HighlightingColor color)
{
color.Foreground = Foreground is { } foreground ? new SimpleHighlightingBrush(foreground) : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small nit: why use pattern matching here? The lhs of the pattern is already a correctly typed variable. Wouldn't Foreground is not null ? new SimpleHighlightingBrush(Foreground) : null be easier to read?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No good reason, I think I just started to use pattern matching a bit more than necessary recently. 😅

@siegfriedpammer siegfriedpammer merged commit b91355d into icsharpcode:master Mar 18, 2023
@siegfriedpammer
Copy link
Member

LGTM! Thanks! Sorry for taking so long to get to this...

@ltrzesniewski
Copy link
Contributor Author

No worries, that's not exactly a small change. Thanks for reviewing/accepting this. 🙂

@ltrzesniewski ltrzesniewski deleted the themes branch March 18, 2023 12:28
@dgrunwald
Copy link
Member

Unfortunately it looks like this PR is the cause of some performance issues (#2956).
You can also see in the Windows taskbar that several icon-less dummy windows are created and destroyed.

Investigating "who's calling CreateWindow there" lead us to this stack:

 # Child-SP          RetAddr               Call Site
00 0000002f`5bffb828 00007ff8`a361117e     USER32!CreateWindowExW
01 0000002f`5bffb830 00007ff8`a3611013     0x00007ff8`a361117e
02 0000002f`5bffb950 00007ff8`a360ff5f     AvalonDock!Standard.NativeMethods.CreateWindowEx+0x73
03 0000002f`5bffb9d0 00007ff8`a360e8f2     AvalonDock!Standard.MessageWindow..ctor+0x27f
04 0000002f`5bffbb60 00007ff8`a360e089     AvalonDock!Microsoft.Windows.Shell.SystemParameters2..ctor+0x132
05 0000002f`5bffbcb0 00007ff8`f0cb4e3d     AvalonDock!Microsoft.Windows.Shell.WindowChrome..ctor+0x109
06 0000002f`5bffbd40 00007ff8`f0cca91d     System_Private_CoreLib!System.RuntimeType.CreateInstanceDefaultCtor+0xbd [/_/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @ 3753] 
07 0000002f`5bffbda0 00007ff8`f0cb4c30     System_Private_CoreLib!System.Activator.CreateInstance+0x3d [/_/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs @ 100] 
08 0000002f`5bffbde0 00007ff8`f0cca6c5     System_Private_CoreLib!System.RuntimeType.CreateInstanceImpl+0x360 [/_/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @ 3704] 
09 0000002f`5bffbea0 00007ff8`f0cca482     System_Private_CoreLib!System.Activator.CreateInstance+0x85 [/_/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs @ 38] 
0a 0000002f`5bffbf00 00007ff8`f2405fb0     System_Private_CoreLib!System.Activator.CreateInstance+0x22 [/_/src/libraries/System.Private.CoreLib/src/System/Activator.cs @ 31] 
0b 0000002f`5bffbf40 00007ff8`f240acf0     System_Xaml!System.Xaml.Schema.SafeReflectionInvoker.CreateInstanceCritical+0x20 [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/SafeReflectionInvoker.cs @ 189] 
0c 0000002f`5bffbf70 00007ff8`f2412d48     System_Xaml!System.Xaml.Schema.XamlTypeInvoker.CreateInstance+0x80 [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlTypeInvoker.cs @ 141] 
0d 0000002f`5bffbfb0 00007ff8`f2412bcc     System_Xaml!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstanceWithCtor+0x28 [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/ClrObjectRuntime.cs @ 69] 
0e 0000002f`5bffbfe0 00007ff8`f23de1dc     System_Xaml!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance+0x5c [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/ClrObjectRuntime.cs @ 51] 
0f 0000002f`5bffc030 00007ff8`f23dca82     System_Xaml!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart+0x21c [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs @ 1167] 
10 0000002f`5bffc0b0 00007ff8`f23f7bdc     System_Xaml!System.Xaml.XamlObjectWriter.WriteStartMember+0x322 [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs @ 639] 
11 0000002f`5bffc100 00007ff8`dbc63f6d     System_Xaml!System.Xaml.XamlWriter.WriteNode+0xec [/_/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlWriter.cs @ 46] 
12 0000002f`5bffc140 00007ff8`dbc639e2     PresentationFramework!System.Windows.Markup.WpfXamlLoader.TransformNodes+0x4cd [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/WpfXamlLoader.cs @ 247] 
13 0000002f`5bffc280 00007ff8`dbb107a4     PresentationFramework!System.Windows.Markup.WpfXamlLoader.Load+0x1f2 [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/WpfXamlLoader.cs @ 148] 
14 0000002f`5bffc340 00007ff8`dbb0fd67     PresentationFramework!System.Windows.ResourceDictionary.CreateObject+0x94 [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 1385] 
15 0000002f`5bffc3a0 00007ff8`dbb0fc1d     PresentationFramework!System.Windows.ResourceDictionary.OnGettingValue+0xc7 [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 1035] 
16 0000002f`5bffc3f0 00007ff8`dbb0efcf     PresentationFramework!System.Windows.ResourceDictionary.OnGettingValuePrivate+0x5d [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 997] 
17 0000002f`5bffc440 00007ff8`dbb0ef0e     PresentationFramework!System.Windows.ResourceDictionary.GetValueWithoutLock+0x4f [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 508] 
18 0000002f`5bffc490 00007ff8`dbf10f04     PresentationFramework!System.Windows.ResourceDictionary.GetValue+0x5e [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 492] 
19 0000002f`5bffc4f0 00007ff8`dbf10e76     PresentationFramework!System.Windows.ResourceDictionary.ResourceDictionaryEnumerator.System.Collections.IDictionaryEnumerator.get_Entry+0x44 [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 2105] 
1a 0000002f`5bffc550 00007ff8`a35f6972     PresentationFramework!System.Windows.ResourceDictionary.ResourceDictionaryEnumerator.System.Collections.IEnumerator.get_Current+0x26 [/_/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs @ 2082] 
1b 0000002f`5bffc590 00007ff8`a35f6ab3     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.<UpdateTheme>g__ProcessDictionary|16_0+0x92 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 113] 
1c 0000002f`5bffc660 00007ff8`a35f6ab3     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.<UpdateTheme>g__ProcessDictionary|16_0+0x1d3 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 120] 
1d 0000002f`5bffc730 00007ff8`a35f6ab3     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.<UpdateTheme>g__ProcessDictionary|16_0+0x1d3 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 120] 
1e 0000002f`5bffc800 00007ff8`a35f6ab3     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.<UpdateTheme>g__ProcessDictionary|16_0+0x1d3 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 120] 
1f 0000002f`5bffc8d0 00007ff8`a35f2c33     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.<UpdateTheme>g__ProcessDictionary|16_0+0x1d3 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 120] 
20 0000002f`5bffc9a0 00007ff8`a35f29ad     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.UpdateTheme+0x263 [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 109] 
21 0000002f`5bffca60 00007ff8`a35f2949     ILSpy!ICSharpCode.ILSpy.Themes.ThemeManager.set_Theme+0x2d [C:\work\ILSpy\ILSpy\Themes\ThemeManager.cs @ 58] 
22 0000002f`5bffca90 00007ff8`a35ebdc7     ILSpy!ICSharpCode.ILSpy.SessionSettings.set_Theme+0x39 [C:\work\ILSpy\ILSpy\SessionSettings.cs @ 87] 
23 0000002f`5bffcac0 00007ff8`a35ea8bb     ILSpy!ICSharpCode.ILSpy.SessionSettings..ctor+0x867 [C:\work\ILSpy\ILSpy\SessionSettings.cs @ 67] 
24 0000002f`5bffce30 00007ff8`f0cb4e3d     ILSpy!ICSharpCode.ILSpy.MainWindow..ctor+0x11b [C:\work\ILSpy\ILSpy\MainWindow.xaml.cs @ 120] 
...

We may end up reverting this PR due to these issues.

@ltrzesniewski
Copy link
Contributor Author

ltrzesniewski commented Apr 8, 2023

This is very surprising given that this PR didn't change the way the light/dark theme switch worked - it works on the same principle. Also, I didn't notice any perf regression. 😕

@siegfriedpammer told me he found a solution, but I'll be happy to help if needed.

@dgrunwald
Copy link
Member

We currently suspect that iterating recursively over the MergedDictionaries (see stack trace) ends up eagerly instantiating parts of AvalonDock that we otherwise don't use, and that were not instantiated prior to this PR.

@dgrunwald
Copy link
Member

In particular, with @siegfriedpammer's proposed hack:

				foreach (ResourceDictionary mergedDictionary in resourceDictionary.MergedDictionaries)
				{
					if (mergedDictionary.Source.OriginalString.StartsWith("/AvalonDock", StringComparison.OrdinalIgnoreCase))
						continue;
					ProcessDictionary(mergedDictionary);
				}

then ILSpy loads seemingly without ever creating an instance of AvalonDock!Microsoft.Windows.Shell.WindowChrome.

@ltrzesniewski
Copy link
Contributor Author

Oh, I see. I thought those dictionaries only instantiated some brushes. Oops. 🤦‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More themes?
4 participants