diff --git a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs index 0562bcedd..d225feeaa 100644 --- a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs @@ -457,7 +457,7 @@ namespace ICSharpCode.Decompiler { if (node is EntityDeclaration && !(node.Parent is LocalFunctionDeclarationStatement)) return true; - if (node is VariableInitializer && node.Parent is FieldDeclaration) + if (node is VariableInitializer && node.Parent is FieldDeclaration or EventDeclaration) { node = node.Parent; return true; diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 276a32493..74f845893 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -64,16 +64,11 @@ license.txt - - - - - diff --git a/ILSpy/Images/DarkMode.png b/ILSpy/Images/DarkMode.png deleted file mode 100644 index 843dc5363..000000000 Binary files a/ILSpy/Images/DarkMode.png and /dev/null differ diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index e4ce9eba6..fe229607a 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -23,6 +23,7 @@ using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Syntax; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpyX.Extensions; @@ -55,9 +56,15 @@ namespace ICSharpCode.ILSpy HighlightingColor methodCallColor; HighlightingColor methodDeclarationColor; - HighlightingColor fieldDeclarationColor; HighlightingColor fieldAccessColor; + HighlightingColor propertyDeclarationColor; + HighlightingColor propertyAccessColor; + HighlightingColor eventDeclarationColor; + HighlightingColor eventAccessColor; + + HighlightingColor variableColor; + HighlightingColor parameterColor; HighlightingColor valueKeywordColor; HighlightingColor thisKeywordColor; @@ -95,12 +102,16 @@ namespace ICSharpCode.ILSpy this.enumerationTypeColor = highlighting.GetNamedColor("EnumTypes"); this.typeParameterTypeColor = highlighting.GetNamedColor("TypeParameters"); this.delegateTypeColor = highlighting.GetNamedColor("DelegateTypes"); - this.methodDeclarationColor = this.methodCallColor = highlighting.GetNamedColor("MethodCall"); - //this.eventDeclarationColor = this.eventAccessColor = defaultTextColor; - //this.propertyDeclarationColor = this.propertyAccessColor = defaultTextColor; - this.fieldDeclarationColor = this.fieldAccessColor = highlighting.GetNamedColor("FieldAccess"); - //this.variableDeclarationColor = this.variableAccessColor = defaultTextColor; - //this.parameterDeclarationColor = this.parameterAccessColor = defaultTextColor; + this.methodDeclarationColor = highlighting.GetNamedColor("MethodDeclaration"); + this.methodCallColor = highlighting.GetNamedColor("MethodCall"); + this.fieldDeclarationColor = highlighting.GetNamedColor("FieldDeclaration"); + this.fieldAccessColor = highlighting.GetNamedColor("FieldAccess"); + this.propertyDeclarationColor = highlighting.GetNamedColor("PropertyDeclaration"); + this.propertyAccessColor = highlighting.GetNamedColor("PropertyAccess"); + this.eventDeclarationColor = highlighting.GetNamedColor("EventDeclaration"); + this.eventAccessColor = highlighting.GetNamedColor("EventAccess"); + this.variableColor = highlighting.GetNamedColor("Variable"); + this.parameterColor = highlighting.GetNamedColor("Parameter"); this.valueKeywordColor = highlighting.GetNamedColor("NullOrValueKeywords"); this.thisKeywordColor = highlighting.GetNamedColor("ThisOrBaseReference"); this.trueKeywordColor = highlighting.GetNamedColor("TrueFalse"); @@ -338,13 +349,25 @@ namespace ICSharpCode.ILSpy public override void WriteIdentifier(Identifier identifier) { HighlightingColor color = null; - if (identifier.Name == "value" - && identifier.Parent?.GetResolveResult() is ILVariableResolveResult rr - && rr.Variable.Kind == Decompiler.IL.VariableKind.Parameter - && identifier.Ancestors.OfType().FirstOrDefault() is Accessor accessor - && accessor.Role != PropertyDeclaration.GetterRole) + if (identifier.Parent?.GetResolveResult() is ILVariableResolveResult rr) { - color = valueKeywordColor; + if (rr.Variable.Kind == VariableKind.Parameter) + { + if (identifier.Name == "value" + && identifier.Ancestors.OfType().FirstOrDefault() is { } accessor + && accessor.Role != PropertyDeclaration.GetterRole) + { + color = valueKeywordColor; + } + else + { + color = parameterColor; + } + } + else + { + color = variableColor; + } } if (identifier.Parent is AstType) { @@ -361,60 +384,40 @@ namespace ICSharpCode.ILSpy switch (GetCurrentDefinition()) { case ITypeDefinition t: - switch (t.Kind) - { - case TypeKind.Delegate: - color = delegateTypeColor; - break; - case TypeKind.Class: - color = referenceTypeColor; - break; - case TypeKind.Interface: - color = interfaceTypeColor; - break; - case TypeKind.Enum: - color = enumerationTypeColor; - break; - case TypeKind.Struct: - color = valueTypeColor; - break; - } + ApplyTypeColor(t, ref color); break; - case IMethod m: + case IMethod: color = methodDeclarationColor; break; - case IField f: + case IField: color = fieldDeclarationColor; break; + case IProperty: + color = propertyDeclarationColor; + break; + case IEvent: + color = eventDeclarationColor; + break; } switch (GetCurrentMemberReference()) { case IType t: - switch (t.Kind) - { - case TypeKind.Delegate: - color = delegateTypeColor; - break; - case TypeKind.Class: - color = referenceTypeColor; - break; - case TypeKind.Interface: - color = interfaceTypeColor; - break; - case TypeKind.Enum: - color = enumerationTypeColor; - break; - case TypeKind.Struct: - color = valueTypeColor; - break; - } + ApplyTypeColor(t, ref color); break; case IMethod m: color = methodCallColor; + if (m.IsConstructor) + ApplyTypeColor(m.DeclaringType, ref color); break; - case IField f: + case IField: color = fieldAccessColor; break; + case IProperty: + color = propertyAccessColor; + break; + case IEvent: + color = eventAccessColor; + break; } if (color != null) { @@ -427,6 +430,28 @@ namespace ICSharpCode.ILSpy } } + void ApplyTypeColor(IType type, ref HighlightingColor color) + { + switch (type?.Kind) + { + case TypeKind.Delegate: + color = delegateTypeColor; + break; + case TypeKind.Class: + color = referenceTypeColor; + break; + case TypeKind.Interface: + color = interfaceTypeColor; + break; + case TypeKind.Enum: + color = enumerationTypeColor; + break; + case TypeKind.Struct: + color = valueTypeColor; + break; + } + } + public override void WritePrimitiveValue(object value, Decompiler.CSharp.Syntax.LiteralFormat format) { HighlightingColor color = null; diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index bf9860abe..9335d38a1 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -92,8 +92,6 @@ - - @@ -164,17 +162,13 @@ @@ -209,9 +203,9 @@ ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Workspace.ActiveTabPage.FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/> - - - + diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index aa8eb92b2..eaa65475b 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -184,7 +184,7 @@ namespace ICSharpCode.ILSpy case nameof(SessionSettings.ActiveAssemblyList): ShowAssemblyList(sessionSettings.ActiveAssemblyList); break; - case nameof(SessionSettings.IsDarkMode): + case nameof(SessionSettings.Theme): // update syntax highlighting and force reload (AvalonEdit does not automatically refresh on highlighting change) DecompilerTextView.RegisterHighlighting(); DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState); diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 60114829a..f9002b35d 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -1,7 +1,6 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -567,15 +566,6 @@ namespace ICSharpCode.ILSpy.Properties { } } - /// - /// Looks up a localized string similar to Dark Mode. - /// - public static string DarkMode { - get { - return ResourceManager.GetString("DarkMode", resourceCulture); - } - } - /// /// Looks up a localized string similar to DEBUG -- Decompile All. /// @@ -2646,6 +2636,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// Looks up a localized string similar to Theme. + /// + public static string Theme { + get { + return ResourceManager.GetString("Theme", resourceCulture); + } + } + /// /// Looks up a localized string similar to Toggle All Folding. /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 9f873ec56..f9e949fa8 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -222,9 +222,6 @@ Are you sure you want to continue? DEBUG -- Dump PDB as XML - - Dark Mode - Debug Steps @@ -907,6 +904,9 @@ Do you want to continue? Tab size: + + Theme + Toggle All Folding diff --git a/ILSpy/Properties/Resources.zh-Hans.resx b/ILSpy/Properties/Resources.zh-Hans.resx index bf8f4d400..3715d1004 100644 --- a/ILSpy/Properties/Resources.zh-Hans.resx +++ b/ILSpy/Properties/Resources.zh-Hans.resx @@ -222,9 +222,6 @@ 调试 -- PDB 转储为 XML - - 深色 - 调试步骤 diff --git a/ILSpy/SessionSettings.cs b/ILSpy/SessionSettings.cs index a39262ee2..245dd99d1 100644 --- a/ILSpy/SessionSettings.cs +++ b/ILSpy/SessionSettings.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.ILSpy this.TopPaneSplitterPosition = FromString((string)doc.Element("TopPaneSplitterPosition"), 0.3); this.BottomPaneSplitterPosition = FromString((string)doc.Element("BottomPaneSplitterPosition"), 0.3); this.SelectedSearchMode = FromString((string)doc.Element("SelectedSearchMode"), SearchMode.TypeAndMember); - this.IsDarkMode = FromString((string)doc.Element(nameof(IsDarkMode)), false); + this.Theme = FromString((string)doc.Element(nameof(Theme)), ThemeManager.Current.DefaultTheme); string currentCulture = (string)doc.Element(nameof(CurrentCulture)); this.CurrentCulture = string.IsNullOrEmpty(currentCulture) ? null : currentCulture; @@ -81,10 +81,10 @@ namespace ICSharpCode.ILSpy public FilterSettings FilterSettings { get; internal set; } public SearchMode SelectedSearchMode { get; set; } - public bool IsDarkMode { - get => ThemeManager.Current.IsDarkMode; + public string Theme { + get => ThemeManager.Current.Theme; set { - ThemeManager.Current.IsDarkMode = value; + ThemeManager.Current.Theme = value; OnPropertyChanged(); } } @@ -149,7 +149,7 @@ namespace ICSharpCode.ILSpy doc.Add(new XElement("TopPaneSplitterPosition", ToString(this.TopPaneSplitterPosition))); doc.Add(new XElement("BottomPaneSplitterPosition", ToString(this.BottomPaneSplitterPosition))); doc.Add(new XElement("SelectedSearchMode", ToString(this.SelectedSearchMode))); - doc.Add(new XElement(nameof(IsDarkMode), ToString(this.IsDarkMode))); + doc.Add(new XElement(nameof(Theme), ToString(this.Theme))); if (this.CurrentCulture != null) { doc.Add(new XElement(nameof(CurrentCulture), this.CurrentCulture)); diff --git a/ILSpy/TextView/Asm-Mode-Dark.xshd b/ILSpy/TextView/Asm-Mode-Dark.xshd deleted file mode 100644 index 9953acbf0..000000000 --- a/ILSpy/TextView/Asm-Mode-Dark.xshd +++ /dev/null @@ -1,1211 +0,0 @@ - - - - - - - - - - - - - - aaa - aad - aam - aas - adc - add - and - call - cbw - cdqe - clc - cld - cli - cmc - cmp - cmps - cmpsb - cmpsw - cwd - daa - das - dec - div - esc - hlt - idiv - imul - in - inc - int - into - iret - ja - jae - jb - jbe - jc - jcxz - je - jg - jge - jl - jle - jmp - jna - jnae - jnb - jnbe - jnc - jne - jng - jnge - jnl - jnle - jno - jnp - jns - jnz - jo - jp - jpe - jpo - js - jz - lahf - lds - lea - les - lods - lodsb - lodsw - loop - loope - loopew - loopne - loopnew - loopnz - loopnzw - loopw - loopz - loopzw - mov - movabs - movs - movsb - movsw - mul - neg - nop - not - or - out - pop - popf - push - pushf - rcl - rcr - ret - retf - retn - rol - ror - sahf - sal - sar - sbb - scas - scasb - scasw - shl - shr - stc - std - sti - stos - stosb - stosw - sub - test - wait - xchg - xlat - xlatb - xor - bound - enter - ins - insb - insw - leave - outs - outsb - outsw - popa - pusha - pushw - arpl - lar - lsl - sgdt - sidt - sldt - smsw - str - verr - verw - clts - lgdt - lidt - lldt - lmsw - ltr - bsf - bsr - bt - btc - btr - bts - cdq - cmpsd - cwde - insd - iretd - iretdf - iretf - jecxz - lfs - lgs - lodsd - loopd - looped - loopned - loopnzd - loopzd - lss - movsd - movsx - movsxd - movzx - outsd - popad - popfd - pushad - pushd - pushfd - scasd - seta - setae - setb - setbe - setc - sete - setg - setge - setl - setle - setna - setnae - setnb - setnbe - setnc - setne - setng - setnge - setnl - setnle - setno - setnp - setns - setnz - seto - setp - setpe - setpo - sets - setz - shld - shrd - stosd - bswap - cmpxchg - invd - invlpg - wbinvd - xadd - lock - rep - repe - repne - repnz - repz - cflush - cpuid - emms - femms - cmovo - cmovno - cmovb - cmovc - cmovnae - cmovae - cmovnb - cmovnc - cmove - cmovz - cmovne - cmovnz - cmovbe - cmovna - cmova - cmovnbe - cmovs - cmovns - cmovp - cmovpe - cmovnp - cmovpo - cmovl - cmovnge - cmovge - cmovnl - cmovle - cmovng - cmovg - cmovnle - cmpxchg486 - cmpxchg8b - loadall - loadall286 - ibts - icebp - int1 - int3 - int01 - int03 - iretw - popaw - popfw - pushaw - pushfw - rdmsr - rdpmc - rdshr - rdtsc - rsdc - rsldt - rsm - rsts - salc - smi - smint - smintold - svdc - svldt - svts - syscall - sysenter - sysexit - sysret - ud0 - ud1 - ud2 - umov - xbts - wrmsr - wrshr - - - f2xm1 - fabs - fadd - faddp - fbld - fbstp - fchs - fclex - fcom - fcomp - fcompp - fdecstp - fdisi - fdiv - fdivp - fdivr - fdivrp - feni - ffree - fiadd - ficom - ficomp - fidiv - fidivr - fild - fimul - fincstp - finit - fist - fistp - fisub - fisubr - fld - fld1 - fldcw - fldenv - fldenvw - fldl2e - fldl2t - fldlg2 - fldln2 - fldpi - fldz - fmul - fmulp - fnclex - fndisi - fneni - fninit - fnop - fnsave - fnsavew - fnstcw - fnstenv - fnstenvw - fnstsw - fpatan - fprem - fptan - frndint - frstor - frstorw - fsave - fsavew - fscale - fsqrt - fst - fstcw - fstenv - fstenvw - fstp - fstsw - fsub - fsubp - fsubr - fsubrp - ftst - fwait - fxam - fxch - fxtract - fyl2x - fyl2xp1 - fsetpm - fcos - fldenvd - fnsaved - fnstenvd - fprem1 - frstord - fsaved - fsin - fsincos - fstenvd - fucom - fucomp - fucompp - fcomi - fcomip - ffreep - fcmovb - fcmove - fcmovbe - fcmovu - fcmovnb - fcmovne - fcmovnbe - fcmovnu - - - ah - al - ax - bh - bl - bp - bx - ch - cl - cr0 - cr2 - cr3 - cr4 - cs - cx - dh - di - dl - dr0 - dr1 - dr2 - dr3 - dr6 - dr7 - ds - dx - eax - ebp - ebx - ecx - edi - edx - es - esi - esp - fs - gs - rax - rbx - rcx - rdx - rdi - rsi - rbp - rsp - r8 - r9 - r10 - r11 - r12 - r13 - r14 - r15 - r8d - r9d - r10d - r11d - r12d - r13d - r14d - r15d - r8w - r9w - r10w - r11w - r12w - r13w - r14w - r15w - r8b - r9b - r10b - r11b - r12b - r13b - r14b - r15b - si - sp - ss - st - tr3 - tr4 - tr5 - tr6 - tr7 - st0 - st1 - st2 - st3 - st4 - st5 - st6 - st7 - mm0 - mm1 - mm2 - mm3 - mm4 - mm5 - mm6 - mm7 - xmm0 - xmm1 - xmm2 - xmm3 - xmm4 - xmm5 - xmm6 - xmm7 - xmm8 - xmm9 - xmm10 - xmm11 - xmm12 - xmm13 - xmm14 - xmm15 - - - .186 - .286 - .286c - .286p - .287 - .386 - .386c - .386p - .387 - .486 - .486p - .8086 - .8087 - .alpha - .break - .code - .const - .continue - .cref - .data - .data? - .dosseg - .else - .elseif - .endif - .endw - .err - .err1 - .err2 - .errb - .errdef - .errdif - .errdifi - .erre - .erridn - .erridni - .errnb - .errndef - .errnz - .exit - .fardata - .fardata? - .if - .lall - .lfcond - .list - .listall - .listif - .listmacro - .listmacroall - .model - .no87 - .nocref - .nolist - .nolistif - .nolistmacro - .radix - .repeat - .sall - .seq - .sfcond - .stack - .startup - .tfcond - .type - .until - .untilcxz - .while - .xall - .xcref - .xlist - alias - align - assume - catstr - comm - comment - db - dd - df - dosseg - dq - dt - dup - dw - echo - else - elseif - elseif1 - elseif2 - elseifb - elseifdef - elseifdif - elseifdifi - elseife - elseifidn - elseifidni - elseifnb - elseifndef - end - endif - endm - endp - ends - eq - equ - even - exitm - extern - externdef - extrn - for - forc - ge - goto - group - gt - high - highword - if - if1 - if2 - ifb - ifdef - ifdif - ifdifi - ife - ifidn - ifidni - ifnb - ifndef - include - includelib - instr - invoke - irp - irpc - label - le - length - lengthof - local - low - lowword - lroffset - lt - macro - mask - mod - .msfloat - name - ne - offset - opattr - option - org - %out - page - popcontext - proc - proto - ptr - public - purge - pushcontext - record - repeat - rept - seg - segment - short - size - sizeof - sizestr - struc - struct - substr - subtitle - subttl - textequ - this - title - type - typedef - union - while - width - resb - resw - resd - resq - rest - incbin - times - %define - %idefine - %xdefine - %xidefine - %undef - %assign - %iassign - %strlen - %substr - %macro - %imacro - %endmacro - %rotate - %if - %elif - %else - %endif - %ifdef - %ifndef - %elifdef - %elifndef - %ifmacro - %ifnmacro - %elifmacro - %elifnmacro - %ifctk - %ifnctk - %elifctk - %elifnctk - %ifidn - %ifnidn - %elifidn - %elifnidn - %ifidni - %ifnidni - %elifidni - %elifnidni - %ifid - %ifnid - %elifid - %elifnid - %ifstr - %ifnstr - %elifstr - %elifnstr - %ifnum - %ifnnum - %elifnum - %elifnnum - %error - %rep - %endrep - %exitrep - %include - %push - %pop - %repl - endstruc - istruc - at - iend - alignb - %arg - %stacksize - %local - %line - bits - use16 - use32 - section - absolute - global - common - cpu - import - export - - - $ - ? - @b - @f - addr - basic - byte - c - carry? - dword - far - far16 - fortran - fword - near - near16 - overflow? - parity? - pascal - qword - real4 - real8 - real10 - sbyte - sdword - sign? - stdcall - sword - syscall - tbyte - vararg - word - zero? - flat - near32 - far32 - abs - all - assumes - at - casemap - common - compact - cpu - dotname - emulator - epilogue - error - export - expr16 - expr32 - farstack - forceframe - huge - language - large - listing - ljmp - loadds - m510 - medium - memory - nearstack - nodotname - noemulator - nokeyword - noljmp - nom510 - none - nonunique - nooldmacros - nooldstructs - noreadonly - noscoped - nosignextend - nothing - notpublic - oldmacros - oldstructs - os_dos - para - private - prologue - radix - readonly - req - scoped - setif2 - smallstack - tiny - use16 - use32 - uses - a16 - a32 - o16 - o32 - nosplit - $$ - seq - wrt - small - .text - .data - .bss - %0 - %1 - %2 - %3 - %4 - %5 - %6 - %7 - %8 - %9 - - - addpd - addps - addsd - addss - andpd - andps - andnpd - andnps - cmpeqpd - cmpltpd - cmplepd - cmpunordpd - cmpnepd - cmpnltpd - cmpnlepd - cmpordpd - cmpeqps - cmpltps - cmpleps - cmpunordps - cmpneps - cmpnltps - cmpnleps - cmpordps - cmpeqsd - cmpltsd - cmplesd - cmpunordsd - cmpnesd - cmpnltsd - cmpnlesd - cmpordsd - cmpeqss - cmpltss - cmpless - cmpunordss - cmpness - cmpnltss - cmpnless - cmpordss - comisd - comiss - cvtdq2pd - cvtdq2ps - cvtpd2dq - cvtpd2pi - cvtpd2ps - cvtpi2pd - cvtpi2ps - cvtps2dq - cvtps2pd - cvtps2pi - cvtss2sd - cvtss2si - cvtsd2si - cvtsd2ss - cvtsi2sd - cvtsi2ss - cvttpd2dq - cvttpd2pi - cvttps2dq - cvttps2pi - cvttsd2si - cvttss2si - divpd - divps - divsd - divss - fxrstor - fxsave - ldmxscr - lfence - mfence - maskmovdqu - maskmovdq - maxpd - maxps - paxsd - maxss - minpd - minps - minsd - minss - movapd - movaps - movdq2q - movdqa - movdqu - movhlps - movhpd - movhps - movd - movq - movlhps - movlpd - movlps - movmskpd - movmskps - movntdq - movnti - movntpd - movntps - movntq - movq2dq - movsd - movss - movupd - movups - mulpd - mulps - mulsd - mulss - orpd - orps - packssdw - packsswb - packuswb - paddb - paddsb - paddw - paddsw - paddd - paddsiw - paddq - paddusb - paddusw - pand - pandn - pause - paveb - pavgb - pavgw - pavgusb - pdistib - pextrw - pcmpeqb - pcmpeqw - pcmpeqd - pcmpgtb - pcmpgtw - pcmpgtd - pf2id - pf2iw - pfacc - pfadd - pfcmpeq - pfcmpge - pfcmpgt - pfmax - pfmin - pfmul - pmachriw - pmaddwd - pmagw - pmaxsw - pmaxub - pminsw - pminub - pmovmskb - pmulhrwc - pmulhriw - pmulhrwa - pmulhuw - pmulhw - pmullw - pmuludq - pmvzb - pmvnzb - pmvlzb - pmvgezb - pfnacc - pfpnacc - por - prefetch - prefetchw - prefetchnta - prefetcht0 - prefetcht1 - prefetcht2 - pfrcp - pfrcpit1 - pfrcpit2 - pfrsqit1 - pfrsqrt - pfsub - pfsubr - pi2fd - pinsrw - psadbw - pshufd - pshufhw - pshuflw - pshufw - psllw - pslld - psllq - pslldq - psraw - psrad - psrlw - psrld - psrlq - psrldq - psubb - psubw - psubd - psubq - psubsb - psubsw - psubusb - psubusw - psubsiw - pswapd - punpckhbw - punpckhwd - punpckhdq - punpckhqdq - punpcklbw - punpcklwd - punpckldq - punpcklqdq - pxor - rcpps - rcpss - rsqrtps - rsqrtss - sfence - shufpd - shufps - sqrtpd - sqrtps - sqrtsd - sqrtss - stmxcsr - subpd - subps - subsd - subss - ucomisd - ucomiss - unpckhpd - unpckhps - unpcklpd - unpcklps - xorpd - xorps - - - ; - - - \b(0[xXhH])?[0-9a-fA-F_`]+[h]? # hex number - | - ( \b\d+(\.[0-9]+)? #number with optional floating point - | \.[0-9]+ #or just starting with floating point - ) - ([eE][+-]?[0-9]+)? # optional exponent - - - - - TODO - FIXME - - - HACK - UNDONE - - - \ No newline at end of file diff --git a/ILSpy/TextView/Asm-Mode.xshd b/ILSpy/TextView/Asm-Mode.xshd index 9bf688b83..8d4fb8c2f 100644 --- a/ILSpy/TextView/Asm-Mode.xshd +++ b/ILSpy/TextView/Asm-Mode.xshd @@ -8,7 +8,8 @@ - + + aaa @@ -1189,6 +1190,9 @@ ; + + ^ \s* [0-9A-F]+ \s+ [0-9A-F]+ + \b(0[xXhH])?[0-9a-fA-F_`]+[h]? # hex number | diff --git a/ILSpy/TextView/CSharp-Mode-Dark.xshd b/ILSpy/TextView/CSharp-Mode-Dark.xshd deleted file mode 100644 index 7d7c7aa73..000000000 --- a/ILSpy/TextView/CSharp-Mode-Dark.xshd +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TODO - FIXME - - - HACK - UNDONE - - - - - - - \# - - - - (define|undef|if|elif|else|endif|line)\b - - - - // - - - - - - (region|endregion|error|warning|pragma)\b - - - - - - - ///(?!/) - - - - - - - - // - - - - /\* - \*/ - - - - " - " - - - - - - - - ' - ' - - - - - - - - @" - " - - - - - - - - \$" - " - - - - - - - - - - - - \b0[xX][0-9a-fA-F]+ # hex number - | - ( \b\d+(\.[0-9]+)? #number with optional floating point - | \.[0-9]+ #or just starting with floating point - ) - ([eE][+-]?[0-9]+)? # optional exponent - - - diff --git a/ILSpy/TextView/CSharp-Mode.xshd b/ILSpy/TextView/CSharp-Mode.xshd index 5f5e0a2fd..d2db08534 100644 --- a/ILSpy/TextView/CSharp-Mode.xshd +++ b/ILSpy/TextView/CSharp-Mode.xshd @@ -39,8 +39,18 @@ + + + + + + + + + + diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 21991df25..b7e5f3211 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -127,6 +127,7 @@ namespace ICSharpCode.ILSpy.TextView // SearchPanel SearchPanel searchPanel = SearchPanel.Install(textEditor.TextArea); searchPanel.RegisterCommands(Application.Current.MainWindow.CommandBindings); + searchPanel.SetResourceReference(SearchPanel.MarkerBrushProperty, ResourceKeys.SearchResultBackgroundBrush); searchPanel.Loaded += (_, _) => { // HACK: fix the hardcoded but misaligned margin of the search text box. var textBox = searchPanel.VisualDescendants().OfType().FirstOrDefault(); @@ -139,10 +140,6 @@ namespace ICSharpCode.ILSpy.TextView ShowLineMargin(); SetHighlightCurrentLine(); - // add marker service & margin - textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); - textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); - ContextMenuProvider.Add(this); textEditor.TextArea.TextView.SetResourceReference(ICSharpCode.AvalonEdit.Rendering.TextView.LinkTextForegroundBrushProperty, ResourceKeys.LinkTextForegroundBrush); @@ -1364,15 +1361,8 @@ namespace ICSharpCode.ILSpy.TextView string[] extensions, string resourceName) { - if (ThemeManager.Current.IsDarkMode) - { - resourceName += "-Dark"; - } - - resourceName += ".xshd"; - Stream? resourceStream = typeof(DecompilerTextView).Assembly - .GetManifestResourceStream(typeof(DecompilerTextView), resourceName); + .GetManifestResourceStream(typeof(DecompilerTextView), resourceName + ".xshd"); if (resourceStream != null) { @@ -1382,7 +1372,9 @@ namespace ICSharpCode.ILSpy.TextView using (resourceStream) using (XmlTextReader reader = new XmlTextReader(resourceStream)) { - return HighlightingLoader.Load(reader, manager); + var highlightingDefinition = HighlightingLoader.Load(reader, manager); + ThemeManager.Current.ApplyHighlightingColors(highlightingDefinition); + return highlightingDefinition; } }); } diff --git a/ILSpy/TextView/DecompilerTextView.xaml b/ILSpy/TextView/DecompilerTextView.xaml index 6ff6d2130..4776d1397 100644 --- a/ILSpy/TextView/DecompilerTextView.xaml +++ b/ILSpy/TextView/DecompilerTextView.xaml @@ -6,7 +6,8 @@ xmlns:local="clr-namespace:ICSharpCode.ILSpy.TextView" xmlns:ae="clr-namespace:ICSharpCode.AvalonEdit;assembly=ICSharpCode.AvalonEdit" xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit" - xmlns:styles="urn:TomsToolbox.Wpf.Styles"> + xmlns:styles="urn:TomsToolbox.Wpf.Styles" + xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"> @@ -15,8 +16,8 @@ - - - - - - - - - - nop - break - ldarg.0 - ldarg.1 - ldarg.2 - ldarg.3 - ldloc.0 - ldloc.1 - ldloc.2 - ldloc.3 - stloc.0 - stloc.1 - stloc.2 - stloc.3 - ldarg.s - ldarga.s - starg.s - ldloc.s - ldloca.s - stloc.s - ldnull - ldc.i4.m1 - ldc.i4.0 - ldc.i4.1 - ldc.i4.2 - ldc.i4.3 - ldc.i4.4 - ldc.i4.5 - ldc.i4.6 - ldc.i4.7 - ldc.i4.8 - ldc.i4.s - ldc.i4 - ldc.i8 - ldc.r4 - ldc.r8 - dup - pop - jmp - call - calli - ret - br.s - brfalse.s - brtrue.s - beq.s - bge.s - bgt.s - ble.s - blt.s - bne.un.s - bge.un.s - bgt.un.s - ble.un.s - blt.un.s - br - brfalse - brtrue - beq - bge - bgt - ble - blt - bne.un - bge.un - bgt.un - ble.un - blt.un - switch - ldind.i1 - ldind.u1 - ldind.i2 - ldind.u2 - ldind.i4 - ldind.u4 - ldind.i8 - ldind.i - ldind.r4 - ldind.r8 - ldind.ref - stind.ref - stind.i1 - stind.i2 - stind.i4 - stind.i8 - stind.r4 - stind.r8 - add - sub - mul - div - div.un - rem - rem.un - and - or - xor - shl - shr - shr.un - neg - not - conv.i1 - conv.i2 - conv.i4 - conv.i8 - conv.r4 - conv.r8 - conv.u4 - conv.u8 - callvirt - cpobj - ldobj - ldstr - newobj - castclass - isinst - conv.r.un - unbox - throw - ldfld - ldflda - stfld - ldsfld - ldsflda - stsfld - stobj - conv.ovf.i1.un - conv.ovf.i2.un - conv.ovf.i4.un - conv.ovf.i8.un - conv.ovf.u1.un - conv.ovf.u2.un - conv.ovf.u4.un - conv.ovf.u8.un - conv.ovf.i.un - conv.ovf.u.un - box - newarr - ldlen - ldelema - ldelem - ldelem.i1 - ldelem.u1 - ldelem.i2 - ldelem.u2 - ldelem.i4 - ldelem.u4 - ldelem.i8 - ldelem.i - ldelem.r4 - ldelem.r8 - ldelem.ref - stelem - stelem.i - stelem.i1 - stelem.i2 - stelem.i4 - stelem.i8 - stelem.r4 - stelem.r8 - stelem.ref - conv.ovf.i1 - conv.ovf.u1 - conv.ovf.i2 - conv.ovf.u2 - conv.ovf.i4 - conv.ovf.u4 - conv.ovf.i8 - conv.ovf.u8 - refanyval - ckfinite - mkrefany - ldtoken - conv.u2 - conv.u1 - conv.i - conv.ovf.i - conv.ovf.u - add.ovf - add.ovf.un - mul.ovf - mul.ovf.un - sub.ovf - sub.ovf.un - endfinally - leave - leave.s - stind.i - conv.u - prefix7 - prefix6 - prefix5 - prefix4 - prefix3 - prefix2 - prefix1 - prefixref - arglist - ceq - cgt - cgt.un - clt - clt.un - ldftn - ldvirtftn - ldarg - ldarga - starg - ldloc - ldloca - stloc - localloc - endfilter - unaligned. - volatile. - tail. - initobj - cpblk - initblk - rethrow - sizeof - refanytype - illegal - endmac - brnull - brnull.s - brzero - brzero.s - brinst - brinst.s - ldind.u8 - ldelem.u8 - ldc.i4.M1 - endfault - - - void - bool - char - wchar - int - int8 - int16 - int32 - int64 - uint8 - uint16 - uint32 - uint64 - float - float32 - float64 - refany - typedref - object - string - native - unsigned - value - valuetype - class - const - vararg - default - stdcall - thiscall - fastcall - unmanaged - not_in_gc_heap - beforefieldinit - instance - filter - catch - static - public - private - synchronized - interface - extends - implements - handler - finally - fault - to - abstract - auto - sequential - explicit - wrapper - ansi - unicode - autochar - import - enum - virtual - notremotable - special - il - cil - optil - managed - preservesig - runtime - method - field - bytearray - final - sealed - specialname - family - assembly - famandassem - famorassem - privatescope - nested - hidebysig - newslot - rtspecialname - pinvokeimpl - unmanagedexp - reqsecobj - .ctor - .cctor - initonly - literal - notserialized - forwardref - internalcall - noinlining - aggressiveinlining - nomangle - lasterr - winapi - cdecl - stdcall - thiscall - fastcall - as - pinned - modreq - modopt - serializable - at - tls - true - false - strict - type - - - .class - .namespace - .method - .field - .emitbyte - .try - .maxstack - .locals - .entrypoint - .zeroinit - .pdirect - .data - .event - .addon - .removeon - .fire - .other - protected - .property - .set - .get - default - .import - .permission - .permissionset - .line - .language - .interfaceimpl - #line - - - request - demand - assert - deny - permitonly - linkcheck - inheritcheck - reqmin - reqopt - reqrefuse - prejitgrant - prejitdeny - noncasdemand - noncaslinkdemand - noncasinheritance - - - - .custom - - init - - .size - .pack - - .file - nometadata - .hash - .assembly - implicitcom - noappdomain - noprocess - nomachine - .publickey - .publickeytoken - algorithm - .ver - .locale - extern - .export - .manifestres - .mresource - .localized - - - .module - marshal - custom - sysstring - fixed - variant - currency - syschar - decimal - date - bstr - tbstr - lpstr - lpwstr - lptstr - objectref - iunknown - idispatch - struct - safearray - byvalstr - lpvoid - any - array - lpstruct - - - .vtfixup - fromunmanaged - callmostderived - .vtentry - - - in - out - opt - lcid - retval - .param - - - .override - with - - - null - error - hresult - carray - userdefined - record - filetime - blob - stream - storage - streamed_object - stored_object - blob_object - cf - clsid - vector - - - nullref - - - .subsystem - .corflags - .stackreserve - alignment - .imagebase - - - // - - - /\* - \*/ - - - " - " - - - ' - ' - - - - - TODO - FIXME - - - HACK - UNDONE - - - \ No newline at end of file diff --git a/ILSpy/TextView/ILAsm-Mode.xshd b/ILSpy/TextView/ILAsm-Mode.xshd index 0c2750f25..29e187b43 100644 --- a/ILSpy/TextView/ILAsm-Mode.xshd +++ b/ILSpy/TextView/ILAsm-Mode.xshd @@ -5,7 +5,8 @@ - + + nop @@ -522,6 +523,9 @@ ' ' + + ^ \s* \w+ : + diff --git a/ILSpy/TextView/XML-Mode-Dark.xshd b/ILSpy/TextView/XML-Mode-Dark.xshd deleted file mode 100644 index cea0680a7..000000000 --- a/ILSpy/TextView/XML-Mode-Dark.xshd +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - <!-- - --> - - - <!\[CDATA\[ - ]]> - - - <!DOCTYPE - > - - - <\? - \?> - - - < - > - - - - " - "|(?=<) - - - ' - '|(?=<) - - [\d\w_\-\.]+(?=(\s*=)) - = - - - - - - - - & - [\w\d\#]+ - ; - - - - & - [\w\d\#]* - #missing ; - - - \ No newline at end of file diff --git a/ILSpy/Themes/DarkTheme.xaml b/ILSpy/Themes/Base.Dark.xaml similarity index 92% rename from ILSpy/Themes/DarkTheme.xaml rename to ILSpy/Themes/Base.Dark.xaml index 94d96ab0b..4005dec0a 100644 --- a/ILSpy/Themes/DarkTheme.xaml +++ b/ILSpy/Themes/Base.Dark.xaml @@ -6,6 +6,10 @@ + + + + #333337 #464646 #252526 @@ -60,4 +64,6 @@ MediumVioletRed CornflowerBlue - \ No newline at end of file + + + diff --git a/ILSpy/Themes/LightTheme.xaml b/ILSpy/Themes/Base.Light.xaml similarity index 92% rename from ILSpy/Themes/LightTheme.xaml rename to ILSpy/Themes/Base.Light.xaml index e9c01f691..8e7e5076b 100644 --- a/ILSpy/Themes/LightTheme.xaml +++ b/ILSpy/Themes/Base.Light.xaml @@ -6,6 +6,10 @@ + + + LightGreen + #FCFCFC #D8D8E0 #F5F5F5 @@ -53,4 +57,5 @@ - \ No newline at end of file + + diff --git a/ILSpy/Themes/ResourceKeys.cs b/ILSpy/Themes/ResourceKeys.cs index e36346589..1d78f24dc 100644 --- a/ILSpy/Themes/ResourceKeys.cs +++ b/ILSpy/Themes/ResourceKeys.cs @@ -22,10 +22,14 @@ namespace ICSharpCode.ILSpy.Themes { public static class ResourceKeys { - public static ResourceKey TextMarkerBackgroundColor = new ComponentResourceKey(typeof(ResourceKeys), "TextMarkerBackgroundColor"); - public static ResourceKey TextMarkerDefinitionBackgroundColor = new ComponentResourceKey(typeof(ResourceKeys), "TextMarkerDefinitionBackgroundColor"); - public static ResourceKey LinkTextForegroundBrush = new ComponentResourceKey(typeof(ResourceKeys), "LinkTextForegroundBrush"); - public static ResourceKey BracketHighlightBackgroundBrush = new ComponentResourceKey(typeof(ResourceKeys), "BracketHighlightBackgroundBrush"); - public static ResourceKey BracketHighlightBorderPen = new ComponentResourceKey(typeof(ResourceKeys), "BracketHighlightBorderPen"); + public static ResourceKey TextBackgroundBrush = new ComponentResourceKey(typeof(ResourceKeys), nameof(TextBackgroundBrush)); + public static ResourceKey TextForegroundBrush = new ComponentResourceKey(typeof(ResourceKeys), nameof(TextForegroundBrush)); + public static ResourceKey TextMarkerBackgroundColor = new ComponentResourceKey(typeof(ResourceKeys), nameof(TextMarkerBackgroundColor)); + public static ResourceKey TextMarkerDefinitionBackgroundColor = new ComponentResourceKey(typeof(ResourceKeys), nameof(TextMarkerDefinitionBackgroundColor)); + public static ResourceKey SearchResultBackgroundBrush = new ComponentResourceKey(typeof(ResourceKeys), nameof(SearchResultBackgroundBrush)); + public static ResourceKey LinkTextForegroundBrush = new ComponentResourceKey(typeof(ResourceKeys), nameof(LinkTextForegroundBrush)); + public static ResourceKey BracketHighlightBackgroundBrush = new ComponentResourceKey(typeof(ResourceKeys), nameof(BracketHighlightBackgroundBrush)); + public static ResourceKey BracketHighlightBorderPen = new ComponentResourceKey(typeof(ResourceKeys), nameof(BracketHighlightBorderPen)); + public static ResourceKey ThemeAwareButtonEffect = new ComponentResourceKey(typeof(ResourceKeys), nameof(ThemeAwareButtonEffect)); } } diff --git a/ILSpy/Themes/SyntaxColor.cs b/ILSpy/Themes/SyntaxColor.cs new file mode 100644 index 000000000..cf9a29b00 --- /dev/null +++ b/ILSpy/Themes/SyntaxColor.cs @@ -0,0 +1,32 @@ +#nullable enable + +using System.Windows; +using System.Windows.Media; + +using ICSharpCode.AvalonEdit.Highlighting; + +namespace ICSharpCode.ILSpy.Themes; + +public class SyntaxColor +{ + public Color? Foreground { get; set; } + public Color? Background { get; set; } + public FontWeight? FontWeight { get; set; } + public FontStyle? FontStyle { get; set; } + + public void ApplyTo(HighlightingColor color) + { + color.Foreground = Foreground is { } foreground ? new SimpleHighlightingBrush(foreground) : null; + color.Background = Background is { } background ? new SimpleHighlightingBrush(background) : null; + color.FontWeight = FontWeight ?? FontWeights.Normal; + color.FontStyle = FontStyle ?? FontStyles.Normal; + } + + public static void ResetColor(HighlightingColor color) + { + color.Foreground = null; + color.Background = null; + color.FontWeight = null; + color.FontStyle = null; + } +} diff --git a/ILSpy/Themes/Theme.Dark.xaml b/ILSpy/Themes/Theme.Dark.xaml new file mode 100644 index 000000000..76d3abfbb --- /dev/null +++ b/ILSpy/Themes/Theme.Dark.xaml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/Theme.Light.xaml b/ILSpy/Themes/Theme.Light.xaml new file mode 100644 index 000000000..ca08971e2 --- /dev/null +++ b/ILSpy/Themes/Theme.Light.xaml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/Theme.RSharpDark.xaml b/ILSpy/Themes/Theme.RSharpDark.xaml new file mode 100644 index 000000000..62bfddf03 --- /dev/null +++ b/ILSpy/Themes/Theme.RSharpDark.xaml @@ -0,0 +1,96 @@ + + + + + + + + + + #995A23 + + #483D8B + #800000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/Theme.RSharpLight.xaml b/ILSpy/Themes/Theme.RSharpLight.xaml new file mode 100644 index 000000000..8eb28d77c --- /dev/null +++ b/ILSpy/Themes/Theme.RSharpLight.xaml @@ -0,0 +1,96 @@ + + + + + + + + + + #F6B94D + + #87CEFA + #FFB6C1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/Theme.VSCodeDarkPlus.xaml b/ILSpy/Themes/Theme.VSCodeDarkPlus.xaml new file mode 100644 index 000000000..7a94d4fab --- /dev/null +++ b/ILSpy/Themes/Theme.VSCodeDarkPlus.xaml @@ -0,0 +1,101 @@ + + + + + + + + + + + + #264F78 + #343A40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/Theme.VSCodeLightPlus.xaml b/ILSpy/Themes/Theme.VSCodeLightPlus.xaml new file mode 100644 index 000000000..2ab0d1000 --- /dev/null +++ b/ILSpy/Themes/Theme.VSCodeLightPlus.xaml @@ -0,0 +1,101 @@ + + + + + + + + + + + + #ADD6FF + #D6EAFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Themes/ThemeManager.cs b/ILSpy/Themes/ThemeManager.cs index 08e117815..fe03b32c2 100644 --- a/ILSpy/Themes/ThemeManager.cs +++ b/ILSpy/Themes/ThemeManager.cs @@ -16,36 +16,46 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#nullable enable + using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Controls; +using ICSharpCode.AvalonEdit.Highlighting; + namespace ICSharpCode.ILSpy.Themes { - internal class ThemeManager + public class ThemeManager { - private bool _isDarkMode; - private readonly ResourceDictionary _themeDictionaryContainer = new ResourceDictionary(); - + private string? _theme; + private readonly ResourceDictionary _themeDictionaryContainer = new(); + private readonly Dictionary _syntaxColors = new(); - public static readonly ThemeManager Current = new ThemeManager(); + public static readonly ThemeManager Current = new(); private ThemeManager() { Application.Current.Resources.MergedDictionaries.Add(_themeDictionaryContainer); } - public bool IsDarkMode { - get => _isDarkMode; - set { - _isDarkMode = value; + public string DefaultTheme => "Light"; - _themeDictionaryContainer.MergedDictionaries.Clear(); + public static IReadOnlyCollection AllThemes => new[] { + "Light", + "Dark", + "VS Code Light+", + "VS Code Dark+", + "R# Light", + "R# Dark" + }; - string theme = value ? "Dark" : "Light"; - - _themeDictionaryContainer.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri($"themes/{theme}Theme.xaml", UriKind.Relative) }); - } + public string? Theme { + get => _theme; + set => UpdateTheme(value); } public Button CreateButton() @@ -64,5 +74,51 @@ namespace ICSharpCode.ILSpy.Themes { return new Style(typeof(Button), (Style)Application.Current.FindResource(ToolBar.ButtonStyleKey)); } + + public void ApplyHighlightingColors(IHighlightingDefinition highlightingDefinition) + { + // Make sure all color values are taken from the theme + foreach (var color in highlightingDefinition.NamedHighlightingColors) + SyntaxColor.ResetColor(color); + + var prefix = $"SyntaxColor.{highlightingDefinition.Name}."; + + foreach (var (key, syntaxColor) in _syntaxColors) + { + var color = highlightingDefinition.GetNamedColor(key.Substring(prefix.Length)); + if (color is not null) + syntaxColor.ApplyTo(color); + } + } + + private void UpdateTheme(string? themeName) + { + _theme = themeName ?? DefaultTheme; + if (!AllThemes.Contains(_theme)) + _theme = DefaultTheme; + + var themeFileName = _theme + .Replace("+", "Plus") + .Replace("#", "Sharp") + .Replace(" ", ""); + + _themeDictionaryContainer.MergedDictionaries.Clear(); + _themeDictionaryContainer.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri($"themes/Theme.{themeFileName}.xaml", UriKind.Relative) }); + + _syntaxColors.Clear(); + ProcessDictionary(_themeDictionaryContainer); + + void ProcessDictionary(ResourceDictionary resourceDictionary) + { + foreach (DictionaryEntry entry in resourceDictionary) + { + if (entry is { Key: string key, Value: SyntaxColor syntaxColor }) + _syntaxColors.TryAdd(key, syntaxColor); + } + + foreach (ResourceDictionary mergedDictionary in resourceDictionary.MergedDictionaries) + ProcessDictionary(mergedDictionary); + } + } } }