Browse Source

Merge pull request #3266 from tom-englert/dev/WpfRefactoring

WPF Refactoring
pull/3271/head
Siegfried Pammer 9 months ago committed by GitHub
parent
commit
6a84a81e16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      ICSharpCode.ILSpyX/AssemblyListManager.cs
  2. 4
      ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs
  3. 3
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  4. 3
      ILSpy/App.xaml.cs
  5. 13
      ILSpy/Commands/ScopeSearchToAssembly.cs
  6. 14
      ILSpy/Commands/ScopeSearchToNamespace.cs
  7. 8
      ILSpy/Controls/CultureSelectionConverter.cs
  8. 46
      ILSpy/Controls/TreeView/Converters.cs
  9. 5
      ILSpy/Controls/TreeView/SharpTreeView.xaml
  10. 6
      ILSpy/DecompilationOptions.cs
  11. 11
      ILSpy/Docking/DockWorkspace.cs
  12. 33
      ILSpy/ExtensionMethods.cs
  13. 3
      ILSpy/Languages/CSharpILMixedLanguage.cs
  14. 7
      ILSpy/Languages/CSharpLanguage.cs
  15. 3
      ILSpy/Languages/ILLanguage.cs
  16. 127
      ILSpy/MainWindow.xaml
  17. 93
      ILSpy/MainWindow.xaml.cs
  18. 3
      ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
  19. 3
      ILSpy/Metadata/MetadataTablesTreeNode.cs
  20. 11
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs
  21. 6
      ILSpy/Options/DisplaySettings.cs
  22. 2
      ILSpy/Options/DisplaySettingsPanel.xaml
  23. 14
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  24. 24
      ILSpy/Search/SearchPane.xaml
  25. 197
      ILSpy/Search/SearchPane.xaml.cs
  26. 75
      ILSpy/Search/SearchPaneModel.cs
  27. 26
      ILSpy/TextView/DecompilerTextView.cs
  28. 5
      ILSpy/TextView/DocumentationUIBuilder.cs
  29. 11
      ILSpy/Themes/WindowStyleManagerBehavior.cs
  30. 3
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  31. 5
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  32. 4
      ILSpy/TreeNodes/ILSpyTreeNode.cs
  33. 26
      ILSpy/Util/SettingsService.cs
  34. 2
      ILSpy/ViewModels/ManageAssemblyListsViewModel.cs
  35. 103
      ILSpy/ViewModels/PaneModel.cs
  36. 46
      ILSpy/ViewModels/SearchPaneModel.cs
  37. 2
      ILSpy/Views/DebugSteps.xaml.cs

1
ICSharpCode.ILSpyX/AssemblyListManager.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.ILSpyX
} }
public bool ApplyWinRTProjections { get; set; } public bool ApplyWinRTProjections { get; set; }
public bool UseDebugSymbols { get; set; } public bool UseDebugSymbols { get; set; }
public ObservableCollection<string> AssemblyLists { get; } = new ObservableCollection<string>(); public ObservableCollection<string> AssemblyLists { get; } = new ObservableCollection<string>();

4
ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpyX.Search
public AssemblySearchKind AssemblySearchKind; public AssemblySearchKind AssemblySearchKind;
public MemberSearchKind MemberSearchKind; public MemberSearchKind MemberSearchKind;
public string[] Keywords; public string[] Keywords;
public Regex RegEx; public Regex? RegEx;
public bool FullNameSearch; public bool FullNameSearch;
public bool OmitGenerics; public bool OmitGenerics;
public string InNamespace; public string InNamespace;
@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpyX.Search
public abstract class AbstractSearchStrategy public abstract class AbstractSearchStrategy
{ {
protected readonly string[] searchTerm; protected readonly string[] searchTerm;
protected readonly Regex regex; protected readonly Regex? regex;
protected readonly bool fullNameSearch; protected readonly bool fullNameSearch;
protected readonly bool omitGenerics; protected readonly bool omitGenerics;
protected readonly SearchRequest searchRequest; protected readonly SearchRequest searchRequest;

3
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -33,6 +33,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ILCompiler.Reflection.ReadyToRun; using ILCompiler.Reflection.ReadyToRun;
@ -174,7 +175,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
.GroupBy(m => m.MethodHandle) .GroupBy(m => m.MethodHandle)
.ToDictionary(g => g.Key, g => g.ToArray()); .ToDictionary(g => g.Key, g => g.ToArray());
} }
var displaySettings = MainWindow.Instance.CurrentDisplaySettings; var displaySettings = SettingsService.Instance.DisplaySettings;
bool showMetadataTokens = displaySettings.ShowMetadataTokens; bool showMetadataTokens = displaySettings.ShowMetadataTokens;
bool showMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10; bool showMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10;
#if STRESS #if STRESS

3
ILSpy/App.xaml.cs

@ -201,7 +201,8 @@ namespace ICSharpCode.ILSpy
protected override void OnStartup(StartupEventArgs e) protected override void OnStartup(StartupEventArgs e)
{ {
var output = new StringBuilder(); var output = new StringBuilder();
if (ILSpy.MainWindow.FormatExceptions(StartupExceptions.ToArray(), output))
if (StartupExceptions.FormatExceptions(output))
{ {
MessageBox.Show(output.ToString(), "Sorry we crashed!"); MessageBox.Show(output.ToString(), "Sorry we crashed!");
Environment.Exit(1); Environment.Exit(1);

13
ILSpy/Commands/ScopeSearchToAssembly.cs

@ -23,6 +23,7 @@ using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -31,11 +32,19 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToAssembly : IContextMenuEntry public class ScopeSearchToAssembly : IContextMenuEntry
{ {
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToAssembly(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context) public void Execute(TextViewContext context)
{ {
// asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true. // asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true.
string asmName = GetAssembly(context)!; string asmName = GetAssembly(context)!;
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm; string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm); string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false; bool replaced = false;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
@ -55,7 +64,7 @@ namespace ICSharpCode.ILSpy
{ {
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args); searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
} }
MainWindow.Instance.SearchPane.SearchTerm = searchTerm; searchPane.SearchTerm = searchTerm;
} }
public bool IsEnabled(TextViewContext context) public bool IsEnabled(TextViewContext context)

14
ILSpy/Commands/ScopeSearchToNamespace.cs

@ -21,6 +21,7 @@ using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -29,10 +30,18 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToNamespace : IContextMenuEntry public class ScopeSearchToNamespace : IContextMenuEntry
{ {
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToNamespace(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context) public void Execute(TextViewContext context)
{ {
string ns = GetNamespace(context); string ns = GetNamespace(context);
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm; string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm); string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false; bool replaced = false;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
@ -52,7 +61,8 @@ namespace ICSharpCode.ILSpy
{ {
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args); searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
} }
MainWindow.Instance.SearchPane.SearchTerm = searchTerm;
searchPane.SearchTerm = searchTerm;
} }
public bool IsEnabled(TextViewContext context) public bool IsEnabled(TextViewContext context)

8
ILSpy/Controls/CultureSelectionConverter.cs

@ -19,10 +19,11 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls namespace ICSharpCode.ILSpy.Controls
{ {
public class CultureSelectionConverter : IValueConverter public class CultureSelectionConverter : MarkupExtension, IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
@ -37,5 +38,10 @@ namespace ICSharpCode.ILSpy.Controls
return parameter; return parameter;
return Binding.DoNothing; return Binding.DoNothing;
} }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
} }
} }

46
ILSpy/Controls/TreeView/Converters.cs

@ -1,46 +0,0 @@
// Copyright (c) 2020 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls.TreeView
{
public class CollapsedWhenFalse : MarkupExtension, IValueConverter
{
public static CollapsedWhenFalse Instance = new CollapsedWhenFalse();
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Instance;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

5
ILSpy/Controls/TreeView/SharpTreeView.xaml

@ -1,7 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Default="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" xmlns:Default="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"> xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:toms="urn:TomsToolbox">
<Style x:Key="ExpandCollapseToggleStyle" <Style x:Key="ExpandCollapseToggleStyle"
TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}"> TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
@ -227,7 +228,7 @@
<Grid> <Grid>
<Default:LinesRenderer x:Name="linesRenderer" <Default:LinesRenderer x:Name="linesRenderer"
ClipToBounds="True" ClipToBounds="True"
Visibility="{Binding ShowLines, RelativeSource={RelativeSource AncestorType={x:Type Default:SharpTreeView}}, Converter={Default:CollapsedWhenFalse}}" /> Visibility="{Binding ShowLines, RelativeSource={RelativeSource AncestorType={x:Type Default:SharpTreeView}}, Converter={toms:BooleanToVisibilityConverter}}" />
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<FrameworkElement Name="spacer" /> <FrameworkElement Name="spacer" />
<ToggleButton Name="expander" <ToggleButton Name="expander"

6
ILSpy/DecompilationOptions.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Gets the settings for the decompiler. /// Gets the settings for the decompiler.
/// </summary> /// </summary>
public Decompiler.DecompilerSettings DecompilerSettings { get; private set; } public DecompilerSettings DecompilerSettings { get; private set; }
/// <summary> /// <summary>
/// Gets/sets an optional state of a decompiler text view. /// Gets/sets an optional state of a decompiler text view.
@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy
internal int StepLimit = int.MaxValue; internal int StepLimit = int.MaxValue;
internal bool IsDebug = false; internal bool IsDebug = false;
public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, DisplaySettingsViewModel displaySettings) public DecompilationOptions(LanguageVersion version, DecompilerSettings settings, DisplaySettings displaySettings)
{ {
if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
languageVersion = Decompiler.CSharp.LanguageVersion.Latest; languageVersion = Decompiler.CSharp.LanguageVersion.Latest;
@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy
newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings); newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings);
} }
private string GetIndentationString(DisplaySettingsViewModel displaySettings) private string GetIndentationString(DisplaySettings displaySettings)
{ {
if (displaySettings.IndentationUseTabs) if (displaySettings.IndentationUseTabs)
{ {

11
ILSpy/Docking/DockWorkspace.cs

@ -17,17 +17,12 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Navigation;
using System.Windows.Threading; using System.Windows.Threading;
using AvalonDock; using AvalonDock;
@ -36,6 +31,7 @@ using AvalonDock.Layout.Serialization;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
@ -219,7 +215,7 @@ namespace ICSharpCode.ILSpy.Docking
} }
CloseAllTabs(); CloseAllTabs();
SessionSettings.DockLayout.Reset(); SessionSettings.DockLayout.Reset();
InitializeLayout(MainWindow.Instance.DockManager); InitializeLayout(MainWindow.Instance.dockManager);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView); MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
} }
@ -268,5 +264,8 @@ namespace ICSharpCode.ILSpy.Docking
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown) public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{ {
} }
// Dummy property to make the XAML designer happy, the model is provided by the AvalonDock PaneStyleSelectors, not by the DockWorkspace, but the designer assumes the data context in the PaneStyleSelectors is the DockWorkspace.
public PaneModel Model { get; } = null;
} }
} }

33
ILSpy/ExtensionMethods.cs

@ -20,12 +20,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -75,7 +77,7 @@ namespace ICSharpCode.ILSpy
public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this MetadataFile file) public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this MetadataFile file)
{ {
return LoadedAssemblyExtensions.GetLoadedAssembly(file) return LoadedAssemblyExtensions.GetLoadedAssembly(file)
.GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(MainWindow.Instance.CurrentDecompilerSettings)); .GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(SettingsService.Instance.DecompilerSettings));
} }
#region DPI independence #region DPI independence
@ -162,5 +164,34 @@ namespace ICSharpCode.ILSpy
{ {
return color?.R * 0.3 + color?.G * 0.6 + color?.B * 0.1 ?? 0.0; return color?.R * 0.3 + color?.G * 0.6 + color?.B * 0.1 ?? 0.0;
} }
internal static bool FormatExceptions(this IList<App.ExceptionData> exceptions, StringBuilder output)
{
if (exceptions.Count == 0)
return false;
bool first = true;
foreach (var item in exceptions)
{
if (first)
first = false;
else
output.AppendLine("-------------------------------------------------");
output.AppendLine("Error(s) loading plugin: " + item.PluginName);
if (item.Exception is System.Reflection.ReflectionTypeLoadException)
{
var e = (System.Reflection.ReflectionTypeLoadException)item.Exception;
foreach (var ex in e.LoaderExceptions)
{
output.AppendLine(ex.ToString());
output.AppendLine();
}
}
else
output.AppendLine(item.Exception.ToString());
}
return true;
}
} }
} }

3
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -34,6 +34,7 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Extensions; using ICSharpCode.ILSpyX.Extensions;
@ -49,7 +50,7 @@ namespace ICSharpCode.ILSpy
protected override ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options) protected override ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options)
{ {
var displaySettings = MainWindow.Instance.CurrentDisplaySettings; var displaySettings = SettingsService.Instance.DisplaySettings;
return new ReflectionDisassembler(output, return new ReflectionDisassembler(output,
new MixedMethodBodyDisassembler(output, options) { new MixedMethodBodyDisassembler(output, options) {
DetectControlStructure = detectControlStructure, DetectControlStructure = detectControlStructure,

7
ILSpy/Languages/CSharpLanguage.cs

@ -41,6 +41,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using LanguageVersion = ICSharpCode.ILSpyX.LanguageVersion; using LanguageVersion = ICSharpCode.ILSpyX.LanguageVersion;
@ -572,7 +573,7 @@ namespace ICSharpCode.ILSpy
CSharpAmbience ambience = new CSharpAmbience(); CSharpAmbience ambience = new CSharpAmbience();
// Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes. // Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes.
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList; ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList;
if (MainWindow.Instance.CurrentDecompilerSettings.LiftNullables) if (SettingsService.Instance.DecompilerSettings.LiftNullables)
{ {
ambience.ConversionFlags |= ConversionFlags.UseNullableSpecifierForValueTypes; ambience.ConversionFlags |= ConversionFlags.UseNullableSpecifierForValueTypes;
} }
@ -775,7 +776,7 @@ namespace ICSharpCode.ILSpy
public override bool ShowMember(IEntity member) public override bool ShowMember(IEntity member)
{ {
MetadataFile assembly = member.ParentModule.MetadataFile; MetadataFile assembly = member.ParentModule.MetadataFile;
return showAllMembers || !CSharpDecompiler.MemberIsHidden(assembly, member.MetadataToken, MainWindow.Instance.CurrentDecompilerSettings); return showAllMembers || !CSharpDecompiler.MemberIsHidden(assembly, member.MetadataToken, SettingsService.Instance.DecompilerSettings);
} }
public override RichText GetRichTextTooltip(IEntity entity) public override RichText GetRichTextTooltip(IEntity entity)
@ -784,7 +785,7 @@ namespace ICSharpCode.ILSpy
var output = new StringWriter(); var output = new StringWriter();
var decoratedWriter = new TextWriterTokenWriter(output); var decoratedWriter = new TextWriterTokenWriter(output);
var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter); var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter);
var settings = MainWindow.Instance.CurrentDecompilerSettings; var settings = SettingsService.Instance.DecompilerSettings;
if (!settings.LiftNullables) if (!settings.LiftNullables)
{ {
flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes; flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes;

3
ILSpy/Languages/ILLanguage.cs

@ -30,6 +30,7 @@ using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -57,7 +58,7 @@ namespace ICSharpCode.ILSpy
protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options) protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options)
{ {
var displaySettings = MainWindow.Instance.CurrentDisplaySettings; var displaySettings = SettingsService.Instance.DisplaySettings;
output.IndentationString = options.DecompilerSettings.CSharpFormattingOptions.IndentationString; output.IndentationString = options.DecompilerSettings.CSharpFormattingOptions.IndentationString;
return new ReflectionDisassembler(output, options.CancellationToken) { return new ReflectionDisassembler(output, options.CancellationToken) {
DetectControlStructure = detectControlStructure, DetectControlStructure = detectControlStructure,

127
ILSpy/MainWindow.xaml

@ -1,16 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Window <Window
x:Class="ICSharpCode.ILSpy.MainWindow" x:Class="ICSharpCode.ILSpy.MainWindow"
x:ClassModifier="public"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:local="clr-namespace:ICSharpCode.ILSpy" xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:search="clr-namespace:ICSharpCode.ILSpy.Search"
xmlns:avalondock="https://github.com/Dirkster99/AvalonDock" xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking" xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking"
xmlns:analyzers="clr-namespace:ICSharpCode.ILSpy.Analyzers"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
Title="ILSpy" Title="ILSpy"
MinWidth="250" MinWidth="250"
@ -23,21 +21,22 @@
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes" xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox" xmlns:toms="urn:TomsToolbox"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels" xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}" xmlns:treeNodes="clr-namespace:ICSharpCode.ILSpy.TreeNodes"
> xmlns:util="clr-namespace:ICSharpCode.ILSpy.Util"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
<Window.Resources> <Window.Resources>
<tv:SharpTreeView x:Key="AssemblyTreeView" <tv:SharpTreeView x:Key="AssemblyTreeView"
AutomationProperties.Name="Assemblies and Classes" AutomationProperties.Name="Assemblies and Classes"
SelectionChanged="TreeView_SelectionChanged" SelectionChanged="TreeView_SelectionChanged"
ShowRoot="False" ShowRoot="False"
AllowDropOrder="True" AllowDropOrder="True"
AllowDrop="True" AllowDrop="True"
BorderThickness="0" Visibility="Visible"> BorderThickness="0" Visibility="Visible">
<tv:SharpTreeView.ItemContainerStyle> <tv:SharpTreeView.ItemContainerStyle>
<Style TargetType="tv:SharpTreeViewItem"> <Style TargetType="tv:SharpTreeViewItem">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}"> <ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}" d:DataContext="{d:DesignInstance treeNodes:ILSpyTreeNode}">
<Border Background="Transparent"> <Border Background="Transparent">
<Border Background="{TemplateBinding Background}"> <Border Background="{TemplateBinding Background}">
<tv:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" /> <tv:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" />
@ -77,7 +76,7 @@
<ContentPresenter Content="{Binding Content}" /> <ContentPresenter Content="{Binding Content}" />
</DataTemplate> </DataTemplate>
<controls:CultureSelectionConverter x:Key="cultureSelectionConverter" /> <toms:BindingRelay x:Key="WindowBinding" DataContext="{Binding}" />
</Window.Resources> </Window.Resources>
@ -126,18 +125,19 @@
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" /> <MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" /> <MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" /> <MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
<Separator/> <Separator />
<MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}"> <MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}">
<MenuItem.ItemContainerStyle> <MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}"> <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Command" Value="{x:Static local:ILSpyCommands.SetTheme}" /> <Setter Property="Command" Value="{x:Static local:ILSpyCommands.SetTheme}" />
<Setter Property="CommandParameter" Value="{Binding}" /> <Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="IsCheckable" Value="True" /><!-- Required by AvalonDock's MenuItem style to show the checkmark --> <Setter Property="IsCheckable" Value="True" />
<!-- Required by AvalonDock's MenuItem style to show the checkmark -->
<Setter Property="IsChecked"> <Setter Property="IsChecked">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay"> <MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay">
<Binding /> <Binding />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}" Path="SessionSettings.Theme" /> <Binding Source="{StaticResource WindowBinding}" Path="DataContext.SessionSettings.Theme" />
</MultiBinding> </MultiBinding>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -145,9 +145,9 @@
</MenuItem.ItemContainerStyle> </MenuItem.ItemContainerStyle>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources.UILanguage}"> <MenuItem Header="{x:Static properties:Resources.UILanguage}">
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter={x:Null}}" /> <MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=en-US}" /> <MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=zh-Hans}" /> <MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" /> <MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" />
@ -183,39 +183,52 @@
<!-- 'Open' toolbar category is inserted here --> <!-- 'Open' toolbar category is inserted here -->
<Separator /> <Separator />
<ComboBox Name="assemblyListComboBox" Width="100" MaxDropDownHeight="Auto" <ComboBox Name="assemblyListComboBox" Width="100" MaxDropDownHeight="Auto"
ItemsSource="{Binding AssemblyListManager.AssemblyLists}" ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}" ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
SelectedItem="{Binding SessionSettings.ActiveAssemblyList}"/> ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
<Button Command="{x:Static local:ILSpyCommands.ManageAssemblyListsCommand}" ToolTip="{x:Static properties:Resources.ManageAssemblyLists}"> SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}" Style="{StaticResource DarkModeAwareImageStyle}"/> <Button Command="{x:Static local:ILSpyCommands.ManageAssemblyListsCommand}"
ToolTip="{x:Static properties:Resources.ManageAssemblyLists}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</Button> </Button>
<Separator /> <Separator />
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<Separator /> <Separator />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto" <ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}" IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}" ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}" ItemsSource="{x:Static local:Languages.AllLanguages}"
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}"/> ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto" ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}" SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto"
ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}" Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}" IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/> SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
</ToolBar> </ToolBar>
<!-- Update panel --> <!-- Update panel -->
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed"> <Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
<DockPanel KeyboardNavigation.TabNavigation="Contained"> <DockPanel KeyboardNavigation.TabNavigation="Contained">
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button> <Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center" Text="{x:Static properties:Resources.ILSpyVersionAvailable}" /> <TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center"
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick" Content="{x:Static properties:Resources.Download}"/> Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick"
Content="{x:Static properties:Resources.Download}" />
</StackPanel> </StackPanel>
</DockPanel> </DockPanel>
</Border> </Border>
@ -224,21 +237,21 @@
<StatusBarItem DockPanel.Dock="Right"> <StatusBarItem DockPanel.Dock="Right">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"
HorizontalAlignment="Right" HorizontalAlignment="Right"
x:Name="StatusLabel" x:Name="statusLabel"
ToolTip="{x:Static properties:Resources.Status}" ToolTip="{x:Static properties:Resources.Status}"
Text="{x:Static properties:Resources.StandBy}"/> Text="{x:Static properties:Resources.StandBy}" />
</StatusBarItem> </StatusBarItem>
</StatusBar> </StatusBar>
<avalondock:DockingManager x:Name="DockManager" <avalondock:DockingManager x:Name="dockManager"
DataContext="{Binding Workspace}" DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}" AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}" DocumentsSource="{Binding TabPages}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}" ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}"
AllowMixedOrientation="True"> AllowMixedOrientation="True">
<avalondock:DockingManager.DocumentHeaderTemplate> <avalondock:DockingManager.DocumentHeaderTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type viewModels:PaneModel}">
<TextBlock x:Name="headerText" Text="{Binding Title}" /> <TextBlock x:Name="headerText" Text="{Binding Title}" />
<DataTemplate.Triggers> <DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True"> <DataTrigger Binding="{Binding IsActive}" Value="True">
@ -252,11 +265,11 @@
<docking:PaneStyleSelector> <docking:PaneStyleSelector>
<docking:PaneStyleSelector.ToolPaneStyle> <docking:PaneStyleSelector.ToolPaneStyle>
<Style TargetType="{x:Type avalondock:LayoutAnchorableItem}"> <Style TargetType="{x:Type avalondock:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/> <Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}"/> <Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}" />
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/> <Setter Property="ContentId" Value="{Binding Model.ContentId}" />
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/> <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}" />
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/> <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}" />
<Setter Property="CanHide" Value="{Binding Model.IsCloseable}" /> <Setter Property="CanHide" Value="{Binding Model.IsCloseable}" />
<Setter Property="HideCommand" Value="{Binding Model.CloseCommand}" /> <Setter Property="HideCommand" Value="{Binding Model.CloseCommand}" />
<Setter Property="CanClose" Value="{Binding Model.IsCloseable}" /> <Setter Property="CanClose" Value="{Binding Model.IsCloseable}" />
@ -265,11 +278,11 @@
</docking:PaneStyleSelector.ToolPaneStyle> </docking:PaneStyleSelector.ToolPaneStyle>
<docking:PaneStyleSelector.TabPageStyle> <docking:PaneStyleSelector.TabPageStyle>
<Style TargetType="{x:Type avalondock:LayoutItem}"> <Style TargetType="{x:Type avalondock:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/> <Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}"/> <Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={toms:BooleanToVisibilityConverter VisibilityWhenBooleanIsFalse=Hidden}}" />
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/> <Setter Property="ContentId" Value="{Binding Model.ContentId}" />
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/> <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}" />
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/> <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}" />
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" /> <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
<Setter Property="CanClose" Value="{Binding Model.IsCloseable, Mode=TwoWay}" /> <Setter Property="CanClose" Value="{Binding Model.IsCloseable, Mode=TwoWay}" />
</Style> </Style>
@ -278,4 +291,4 @@
</avalondock:DockingManager.LayoutItemContainerStyleSelector> </avalondock:DockingManager.LayoutItemContainerStyleSelector>
</avalondock:DockingManager> </avalondock:DockingManager>
</DockPanel> </DockPanel>
</Window> </Window>

93
ILSpy/MainWindow.xaml.cs

@ -83,64 +83,44 @@ namespace ICSharpCode.ILSpy
get { return instance; } get { return instance; }
} }
internal AssemblyListManager AssemblyListManager { get; }
public SharpTreeView AssemblyTreeView { public SharpTreeView AssemblyTreeView {
get { get {
return FindResource("AssemblyTreeView") as SharpTreeView; return FindResource("AssemblyTreeView") as SharpTreeView;
} }
} }
public SearchPane SearchPane {
get {
return App.ExportProvider.GetExportedValue<SearchPane>();
}
}
public DecompilerSettings CurrentDecompilerSettings { get; internal set; }
public DisplaySettingsViewModel CurrentDisplaySettings { get; internal set; }
public DecompilationOptions CreateDecompilationOptions() public DecompilationOptions CreateDecompilationOptions()
{ {
var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress<DecompilationProgress>; var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress<DecompilationProgress>;
return new DecompilationOptions(CurrentLanguageVersion, CurrentDecompilerSettings, CurrentDisplaySettings) { Progress = decompilerView }; return new DecompilationOptions(CurrentLanguageVersion, SettingsService.Instance.DecompilerSettings, SettingsService.Instance.DisplaySettings) { Progress = decompilerView };
} }
public MainWindow() public MainWindow()
{ {
instance = this; instance = this;
var spySettings = SettingsService.Instance.SpySettings;
var sessionSettings = SettingsService.Instance.SessionSettings; var sessionSettings = SettingsService.Instance.SessionSettings;
this.CurrentDecompilerSettings = DecompilerSettingsPanel.LoadDecompilerSettings(spySettings);
this.CurrentDisplaySettings = DisplaySettingsPanel.LoadDisplaySettings(spySettings);
this.AssemblyListManager = new AssemblyListManager(spySettings) {
ApplyWinRTProjections = CurrentDecompilerSettings.ApplyWindowsRuntimeProjections,
UseDebugSymbols = CurrentDecompilerSettings.UseDebugSymbols
};
// Make sure Images are initialized on the UI thread. // Make sure Images are initialized on the UI thread.
this.Icon = Images.ILSpyIcon; this.Icon = Images.ILSpyIcon;
this.DataContext = new MainWindowViewModel { this.DataContext = new MainWindowViewModel {
Workspace = DockWorkspace.Instance, Workspace = DockWorkspace.Instance,
SessionSettings = sessionSettings, SessionSettings = sessionSettings,
AssemblyListManager = AssemblyListManager AssemblyListManager = SettingsService.Instance.AssemblyListManager
}; };
AssemblyListManager.CreateDefaultAssemblyLists(); SettingsService.Instance.AssemblyListManager.CreateDefaultAssemblyLists();
if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture)) if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
{ {
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sessionSettings.CurrentCulture); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sessionSettings.CurrentCulture);
} }
InitializeComponent(); InitializeComponent();
InitToolPanes(); InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager); DockWorkspace.Instance.InitializeLayout(dockManager);
MessageBus<SessionSettingsChangedEventArgs>.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e); MessageBus<SessionSettingsChangedEventArgs>.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e);
MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => filterSettings_PropertyChanged(sender, e); MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => LanguageSettings_PropertyChanged(sender, e);
MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += DockWorkspace_ActiveTabPageChanged; MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += DockWorkspace_ActiveTabPageChanged;
InitMainMenu(); InitMainMenu();
@ -661,8 +641,10 @@ namespace ICSharpCode.ILSpy
NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies);
if (args.Search != null) if (args.Search != null)
{ {
SearchPane.SearchTerm = args.Search; var searchPane = App.ExportProvider.GetExportedValue<SearchPaneModel>();
SearchPane.Show();
searchPane.SearchTerm = args.Search;
searchPane.Show();
} }
} }
@ -840,12 +822,12 @@ namespace ICSharpCode.ILSpy
{ {
// Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff. // Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff.
// This makes the UI come up a bit faster. // This makes the UI come up a bit faster.
this.assemblyList = AssemblyListManager.LoadList(sessionSettings.ActiveAssemblyList); this.assemblyList = SettingsService.Instance.AssemblyListManager.LoadList(sessionSettings.ActiveAssemblyList);
} }
else else
{ {
AssemblyListManager.ClearAll(); SettingsService.Instance.AssemblyListManager.ClearAll();
this.assemblyList = AssemblyListManager.CreateList(AssemblyListManager.DefaultListName); this.assemblyList = SettingsService.Instance.AssemblyListManager.CreateList(AssemblyListManager.DefaultListName);
} }
HandleCommandLineArguments(App.CommandLineArguments); HandleCommandLineArguments(App.CommandLineArguments);
@ -877,10 +859,10 @@ namespace ICSharpCode.ILSpy
DockWorkspace.Instance.ShowText(output); DockWorkspace.Instance.ShowText(output);
} }
bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output) static bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output)
{ {
var stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
var result = FormatExceptions(exceptions, stringBuilder); var result = exceptions.FormatExceptions(stringBuilder);
if (result) if (result)
{ {
output.Write(stringBuilder.ToString()); output.Write(stringBuilder.ToString());
@ -888,35 +870,6 @@ namespace ICSharpCode.ILSpy
return result; return result;
} }
internal static bool FormatExceptions(App.ExceptionData[] exceptions, StringBuilder output)
{
if (exceptions.Length == 0)
return false;
bool first = true;
foreach (var item in exceptions)
{
if (first)
first = false;
else
output.AppendLine("-------------------------------------------------");
output.AppendLine("Error(s) loading plugin: " + item.PluginName);
if (item.Exception is System.Reflection.ReflectionTypeLoadException)
{
var e = (System.Reflection.ReflectionTypeLoadException)item.Exception;
foreach (var ex in e.LoaderExceptions)
{
output.AppendLine(ex.ToString());
output.AppendLine();
}
}
else
output.AppendLine(item.Exception.ToString());
}
return true;
}
#region Update Check #region Update Check
string updateAvailableDownloadUrl; string updateAvailableDownloadUrl;
@ -974,7 +927,7 @@ namespace ICSharpCode.ILSpy
public void ShowAssemblyList(string name) public void ShowAssemblyList(string name)
{ {
AssemblyList list = this.AssemblyListManager.LoadList(name); AssemblyList list = SettingsService.Instance.AssemblyListManager.LoadList(name);
//Only load a new list when it is a different one //Only load a new list when it is a different one
if (list.ListName != CurrentAssemblyList.ListName) if (list.ListName != CurrentAssemblyList.ListName)
{ {
@ -1047,20 +1000,14 @@ namespace ICSharpCode.ILSpy
assemblyList.OpenAssembly(asm.Location); assemblyList.OpenAssembly(asm.Location);
} }
void filterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) void LanguageSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
RefreshTreeViewFilter();
if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion") if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion")
{ {
DecompileSelectedNodes(recordHistory: false); DecompileSelectedNodes(recordHistory: false);
} }
} }
public void RefreshTreeViewFilter()
{
SearchPane.UpdateFilter();
}
internal AssemblyListTreeNode AssemblyListTreeNode { internal AssemblyListTreeNode AssemblyListTreeNode {
get { return assemblyListTreeNode; } get { return assemblyListTreeNode; }
} }
@ -1388,7 +1335,7 @@ namespace ICSharpCode.ILSpy
{ {
refreshInProgress = true; refreshInProgress = true;
var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(AssemblyListManager.LoadList(assemblyList.ListName)); ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(assemblyList.ListName));
SelectNode(FindNodeByPath(path, true), inNewTabPage: false, AssemblyTreeView.IsFocused); SelectNode(FindNodeByPath(path, true), inNewTabPage: false, AssemblyTreeView.IsFocused);
} }
finally finally
@ -1635,7 +1582,7 @@ namespace ICSharpCode.ILSpy
sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds; sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(DockManager)); sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(dockManager));
sessionSettings.Save(); sessionSettings.Save();
} }
@ -1665,8 +1612,8 @@ namespace ICSharpCode.ILSpy
{ {
if (this.statusBar.Visibility == Visibility.Collapsed) if (this.statusBar.Visibility == Visibility.Collapsed)
this.statusBar.Visibility = Visibility.Visible; this.statusBar.Visibility = Visibility.Visible;
this.StatusLabel.Foreground = foreground; this.statusLabel.Foreground = foreground;
this.StatusLabel.Text = status; this.statusLabel.Text = status;
} }
public ItemCollection GetMainMenuItems() public ItemCollection GetMainMenuItems()

3
ILSpy/Metadata/DebugMetadataTablesTreeNode.cs

@ -21,6 +21,7 @@ using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy.Metadata
if (ShowTable(TableIndex.CustomDebugInformation)) if (ShowTable(TableIndex.CustomDebugInformation))
this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile)); this.Children.Add(new CustomDebugInformationTableTreeNode(metadataFile));
bool ShowTable(TableIndex table) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0; bool ShowTable(TableIndex table) => !SettingsService.Instance.DisplaySettings.HideEmptyMetadataTables || metadataFile.Metadata.GetTableRowCount(table) > 0;
} }
public override bool View(TabPageModel tabPage) public override bool View(TabPageModel tabPage)

3
ILSpy/Metadata/MetadataTablesTreeNode.cs

@ -23,6 +23,7 @@ using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata namespace ICSharpCode.ILSpy.Metadata
@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy.Metadata
} }
} }
internal static bool ShowTable(TableIndex table, MetadataReader metadata) => !MainWindow.Instance.CurrentDisplaySettings.HideEmptyMetadataTables || metadata.GetTableRowCount(table) > 0; internal static bool ShowTable(TableIndex table, MetadataReader metadata) => !SettingsService.Instance.DisplaySettings.HideEmptyMetadataTables || metadata.GetTableRowCount(table) > 0;
internal static MetadataTableTreeNode CreateTableTreeNode(TableIndex table, MetadataFile metadataFile) internal static MetadataTableTreeNode CreateTableTreeNode(TableIndex table, MetadataFile metadataFile)
{ {

11
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -19,6 +19,7 @@
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Settings; using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
@ -50,15 +51,15 @@ namespace ICSharpCode.ILSpy.Options
var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings(); var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings();
ISettingsProvider.SaveDecompilerSettings(root, newSettings); ISettingsProvider.SaveDecompilerSettings(root, newSettings);
MainWindow.Instance.CurrentDecompilerSettings = newSettings; SettingsService.Instance.DecompilerSettings = newSettings;
MainWindow.Instance.AssemblyListManager.ApplyWinRTProjections = newSettings.ApplyWindowsRuntimeProjections; SettingsService.Instance.AssemblyListManager.ApplyWinRTProjections = newSettings.ApplyWindowsRuntimeProjections;
MainWindow.Instance.AssemblyListManager.UseDebugSymbols = newSettings.UseDebugSymbols; SettingsService.Instance.AssemblyListManager.UseDebugSymbols = newSettings.UseDebugSymbols;
} }
public void LoadDefaults() public void LoadDefaults()
{ {
MainWindow.Instance.CurrentDecompilerSettings = new(); SettingsService.Instance.DecompilerSettings = new();
this.DataContext = new DecompilerSettingsViewModel(MainWindow.Instance.CurrentDecompilerSettings); this.DataContext = new DecompilerSettingsViewModel(SettingsService.Instance.DecompilerSettings);
} }
} }
} }

6
ILSpy/Options/DisplaySettingsViewModel.cs → ILSpy/Options/DisplaySettings.cs

@ -27,9 +27,9 @@ namespace ICSharpCode.ILSpy.Options
/// <summary> /// <summary>
/// Description of DisplaySettings. /// Description of DisplaySettings.
/// </summary> /// </summary>
public class DisplaySettingsViewModel : INotifyPropertyChanged public class DisplaySettings : INotifyPropertyChanged
{ {
public DisplaySettingsViewModel() public DisplaySettings()
{ {
this.theme = ThemeManager.Current.DefaultTheme; this.theme = ThemeManager.Current.DefaultTheme;
this.selectedFont = new FontFamily("Consolas"); this.selectedFont = new FontFamily("Consolas");
@ -328,7 +328,7 @@ namespace ICSharpCode.ILSpy.Options
} }
} }
public void CopyValues(DisplaySettingsViewModel s) public void CopyValues(DisplaySettings s)
{ {
this.Theme = s.Theme; this.Theme = s.Theme;
this.SelectedFont = s.selectedFont; this.SelectedFont = s.selectedFont;

2
ILSpy/Options/DisplaySettingsPanel.xaml

@ -7,7 +7,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes" xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
d:DataContext="{d:DesignInstance local:DisplaySettingsViewModel}"> d:DataContext="{d:DesignInstance local:DisplaySettings}">
<UserControl.Resources> <UserControl.Resources>
<local:FontSizeConverter x:Key="fontSizeConv" /> <local:FontSizeConverter x:Key="fontSizeConv" />
</UserControl.Resources> </UserControl.Resources>

14
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -99,10 +99,10 @@ namespace ICSharpCode.ILSpy.Options
select ff).ToArray(); select ff).ToArray();
} }
public static DisplaySettingsViewModel LoadDisplaySettings(ILSpySettings settings) public static DisplaySettings LoadDisplaySettings(ILSpySettings settings, SessionSettings sessionSettings = null)
{ {
XElement e = settings["DisplaySettings"]; XElement e = settings["DisplaySettings"];
var s = new DisplaySettingsViewModel(); var s = new DisplaySettings();
s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas"); s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas");
s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3; s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3;
s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false; s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
@ -124,14 +124,14 @@ namespace ICSharpCode.ILSpy.Options
s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false; s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false; s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false;
s.Theme = SettingsService.Instance.SessionSettings.Theme; s.Theme = (sessionSettings ?? SettingsService.Instance.SessionSettings).Theme;
return s; return s;
} }
public void Save(XElement root) public void Save(XElement root)
{ {
var s = (DisplaySettingsViewModel)this.DataContext; var s = (DisplaySettings)this.DataContext;
var section = new XElement("DisplaySettings"); var section = new XElement("DisplaySettings");
section.SetAttributeValue("Font", s.SelectedFont.Source); section.SetAttributeValue("Font", s.SelectedFont.Source);
@ -158,7 +158,7 @@ namespace ICSharpCode.ILSpy.Options
SettingsService.Instance.SessionSettings.Theme = s.Theme; SettingsService.Instance.SessionSettings.Theme = s.Theme;
var sessionSettings = SettingsService.Instance.SessionSettings.ToXml(); var sessionSettings = SettingsService.Instance.SessionSettings.ToXml();
MainWindow.Instance.CurrentDisplaySettings.CopyValues(s); SettingsService.Instance.DisplaySettings.CopyValues(s);
Update(section); Update(section);
Update(sessionSettings); Update(sessionSettings);
@ -190,8 +190,8 @@ namespace ICSharpCode.ILSpy.Options
public void LoadDefaults() public void LoadDefaults()
{ {
MainWindow.Instance.CurrentDisplaySettings.CopyValues(new DisplaySettingsViewModel()); SettingsService.Instance.DisplaySettings.CopyValues(new DisplaySettings());
this.DataContext = MainWindow.Instance.CurrentDisplaySettings; this.DataContext = SettingsService.Instance.DisplaySettings;
} }
} }

24
ILSpy/Search/SearchPane.xaml

@ -2,10 +2,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d"
xmlns:toms="urn:TomsToolbox" xmlns:toms="urn:TomsToolbox"
d:DesignHeight="300" d:DesignWidth="300"> xmlns:search="clr-namespace:ICSharpCode.ILSpy.Search"
xmlns:spyX="clr-namespace:ICSharpCode.ILSpyX.Search;assembly=ICSharpCode.ILSpyX"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance search:SearchPaneModel}"
viewModels:Pane.IsActive="{Binding IsActive}">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
@ -20,15 +24,19 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls:SearchBox x:Name="searchBox" DockPanel.Dock="Top" Grid.Column="0" Grid.Row="0" Margin="1" <controls:SearchBox x:Name="searchBox" DockPanel.Dock="Top" Grid.Column="0" Grid.Row="0" Margin="1"
PreviewKeyDown="SearchBox_PreviewKeyDown" PreviewKeyDown="SearchBox_PreviewKeyDown"
Text="{Binding SearchTerm, ElementName=self}" ToolTip="{x:Static properties:Resources.SearchPane_Search}" UpdateDelay="0:0:0.1" Text="{Binding SearchTerm, UpdateSourceTrigger=PropertyChanged}" ToolTip="{x:Static properties:Resources.SearchPane_Search}" UpdateDelay="0:0:0.1"
TextChanged="SearchBox_TextChanged"
WatermarkColor="Gray" WatermarkText="{x:Static properties:Resources.WatermarkText}" /> WatermarkColor="Gray" WatermarkText="{x:Static properties:Resources.WatermarkText}" />
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal"> <StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Label Margin="0,-1" Target="searchModeComboBox" Content="{x:Static properties:Resources._SearchFor}"/> <Label Margin="0,-1" Target="searchModeComboBox" Content="{x:Static properties:Resources._SearchFor}"/>
<ComboBox Width="100" Name="searchModeComboBox" Margin="1" <ComboBox Width="100" Name="searchModeComboBox" Margin="1"
TextSearch.TextPath="Name" TextSearch.TextPath="Name"
ItemsSource="{Binding SearchModes}"
SelectedValuePath="Mode"
SelectedValue="{Binding SessionSettings.SelectedSearchMode, Mode=TwoWay}"
SelectionChanged="SearchModeComboBox_SelectionChanged"> SelectionChanged="SearchModeComboBox_SelectionChanged">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type search:SearchModeModel}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" /> <Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />
@ -41,7 +49,7 @@
</Border> </Border>
<ProgressBar x:Name="searchProgressBar" Grid.Row="1" BorderThickness="0" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> <ProgressBar x:Name="searchProgressBar" Grid.Row="1" BorderThickness="0" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<ListView Grid.Row="2" BorderThickness="0,1,0,0" HorizontalContentAlignment="Stretch" KeyDown="ListBox_KeyDown" <ListView Grid.Row="2" BorderThickness="0,1,0,0" HorizontalContentAlignment="Stretch" KeyDown="ListBox_KeyDown"
MouseDoubleClick="ListBox_MouseDoubleClick" Name="listBox" SelectionMode="Single" controls:SortableGridViewColumn.SortMode="Automatic" MouseDoubleClick="ListBox_MouseDoubleClick" Name="listBox" SelectionMode="Single" controls:SortableGridViewColumn.SortMode="Automatic"
controls:GridViewColumnAutoSize.AutoWidth="40%;40%;20%" BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" controls:GridViewColumnAutoSize.AutoWidth="40%;40%;20%" BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
ItemsSource="{Binding Results, ElementName=self}" ItemsSource="{Binding Results, ElementName=self}"
toms:AdvancedScrollWheelBehavior.Attach="WithoutAnimation"> toms:AdvancedScrollWheelBehavior.Attach="WithoutAnimation">
@ -49,7 +57,7 @@
<GridView AllowsColumnReorder="False"> <GridView AllowsColumnReorder="False">
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Name}" SortBy="Name"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Name}" SortBy="Name">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" /> <Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" ToolTip="{Binding ToolTip}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Name}" ToolTip="{Binding ToolTip}" TextTrimming="CharacterEllipsis" />
@ -59,7 +67,7 @@
</controls:SortableGridViewColumn> </controls:SortableGridViewColumn>
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Location}" SortBy="Location"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Location}" SortBy="Location">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding LocationImage}" /> <Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding LocationImage}" />
<TextBlock Text="{Binding Location}" ToolTip="{Binding Location}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Location}" ToolTip="{Binding Location}" TextTrimming="CharacterEllipsis" />
@ -69,7 +77,7 @@
</controls:SortableGridViewColumn> </controls:SortableGridViewColumn>
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Assembly}" SortBy="Assembly"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Assembly}" SortBy="Assembly">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding AssemblyImage}" /> <Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding AssemblyImage}" />
<TextBlock Text="{Binding Assembly}" ToolTip="{Binding Assembly}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Assembly}" ToolTip="{Binding Assembly}" TextTrimming="CharacterEllipsis" />

197
ILSpy/Search/SearchPane.cs → ILSpy/Search/SearchPane.xaml.cs

@ -20,10 +20,8 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -34,13 +32,14 @@ using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Extensions; using ICSharpCode.ILSpyX.Extensions;
using ICSharpCode.ILSpyX.Search; using ICSharpCode.ILSpyX.Search;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;
using TomsToolbox.Wpf.Composition.Mef; using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.Search namespace ICSharpCode.ILSpy.Search
@ -49,48 +48,31 @@ namespace ICSharpCode.ILSpy.Search
/// Search pane /// Search pane
/// </summary> /// </summary>
[DataTemplate(typeof(SearchPaneModel))] [DataTemplate(typeof(SearchPaneModel))]
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.NonShared)]
[Export] public partial class SearchPane
public partial class SearchPane : UserControl
{ {
const int MAX_RESULTS = 1000; const int MAX_RESULTS = 1000;
const int MAX_REFRESH_TIME_MS = 10; // More means quicker forward of data, less means better responsibility const int MAX_REFRESH_TIME_MS = 10; // More means quicker forward of data, fewer means better responsibility
RunningSearch currentSearch; RunningSearch currentSearch;
bool runSearchOnNextShow; bool runSearchOnNextShow;
IComparer<SearchResult> resultsComparer; IComparer<SearchResult> resultsComparer;
public static readonly DependencyProperty ResultsProperty = public ObservableCollection<SearchResult> Results { get; } = [];
DependencyProperty.Register("Results", typeof(ObservableCollection<SearchResult>), typeof(SearchPane),
new PropertyMetadata(new ObservableCollection<SearchResult>())); string SearchTerm => searchBox.Text;
public ObservableCollection<SearchResult> Results {
get { return (ObservableCollection<SearchResult>)GetValue(ResultsProperty); }
}
public SearchPane() public SearchPane()
{ {
InitializeComponent(); InitializeComponent();
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Types and Members" });
searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.Items.Add(new { Image = Images.Method, Name = "Method" });
searchModeComboBox.Items.Add(new { Image = Images.Field, Name = "Field" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Property" });
searchModeComboBox.Items.Add(new { Image = Images.Event, Name = "Event" });
searchModeComboBox.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Metadata Token" });
searchModeComboBox.Items.Add(new { Image = Images.Resource, Name = "Resource" });
searchModeComboBox.Items.Add(new { Image = Images.Assembly, Name = "Assembly" });
searchModeComboBox.Items.Add(new { Image = Images.Namespace, Name = "Namespace" });
ContextMenuProvider.Add(listBox); ContextMenuProvider.Add(listBox);
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => MainWindow_Instance_CurrentAssemblyListChanged(sender, e); MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed();
CompositionTarget.Rendering += UpdateResults; MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => LanguageSettings_PropertyChanged();
// This starts empty search right away, so do at the end (we're still in ctor) CompositionTarget.Rendering += UpdateResults;
searchModeComboBox.SelectedIndex = (int)SettingsService.Instance.SessionSettings.SelectedSearchMode;
} }
void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) void CurrentAssemblyList_Changed()
{ {
if (IsVisible) if (IsVisible)
{ {
@ -103,7 +85,12 @@ namespace ICSharpCode.ILSpy.Search
} }
} }
internal void UpdateFilter() void LanguageSettings_PropertyChanged()
{
UpdateFilter();
}
void UpdateFilter()
{ {
if (IsVisible) if (IsVisible)
{ {
@ -116,43 +103,48 @@ namespace ICSharpCode.ILSpy.Search
} }
} }
public void Show() protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{ {
if (!IsVisible) base.OnPropertyChanged(e);
if (e.Property == IsVisibleProperty)
{ {
DockWorkspace.Instance.ToolPanes.Single(p => p.ContentId == SearchPaneModel.PaneContentId).IsVisible = true; if (e.NewValue as bool? != true)
if (runSearchOnNextShow) return;
{
runSearchOnNextShow = false; if (!runSearchOnNextShow)
StartSearch(this.SearchTerm); return;
}
runSearchOnNextShow = false;
StartSearch(this.SearchTerm);
} }
Dispatcher.BeginInvoke( else if (e.Property == Pane.IsActiveProperty)
DispatcherPriority.Background, {
new Action( if (e.NewValue as bool? != true)
delegate { return;
searchBox.Focus();
searchBox.SelectAll();
}));
}
public static readonly DependencyProperty SearchTermProperty = if (IsMouseOver && Mouse.LeftButton == MouseButtonState.Pressed && !SearchTerm.IsNullOrEmpty())
DependencyProperty.Register("SearchTerm", typeof(string), typeof(SearchPane), return;
new FrameworkPropertyMetadata(string.Empty, OnSearchTermChanged));
public string SearchTerm { FocusSearchBox();
get { return (string)GetValue(SearchTermProperty); } }
set { SetValue(SearchTermProperty, value); }
} }
static void OnSearchTermChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) void FocusSearchBox()
{ {
((SearchPane)o).StartSearch((string)e.NewValue); this.BeginInvoke(DispatcherPriority.Background, () => {
searchBox.Focus();
searchBox.SelectAll();
});
}
void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
{
StartSearch(searchBox.Text);
} }
void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
SettingsService.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex;
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);
} }
@ -180,31 +172,35 @@ namespace ICSharpCode.ILSpy.Search
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(KeyEventArgs e)
{ {
base.OnKeyDown(e); base.OnKeyDown(e);
if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
{ if (e.KeyboardDevice.Modifiers != ModifierKeys.Control)
searchModeComboBox.SelectedIndex = (int)SearchMode.Type; return;
e.Handled = true;
} switch (e.Key)
else if (e.Key == Key.M && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
{
searchModeComboBox.SelectedIndex = (int)SearchMode.Member;
e.Handled = true;
}
else if (e.Key == Key.S && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
{ {
searchModeComboBox.SelectedIndex = (int)SearchMode.Literal; case Key.T:
e.Handled = true; searchModeComboBox.SelectedValue = SearchMode.Type;
e.Handled = true;
break;
case Key.M:
searchModeComboBox.SelectedValue = SearchMode.Member;
e.Handled = true;
break;
case Key.S:
searchModeComboBox.SelectedValue = SearchMode.Literal;
e.Handled = true;
break;
} }
} }
void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e) void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e)
{ {
if (e.Key == Key.Down && listBox.HasItems) if (e.Key != Key.Down || !listBox.HasItems)
{ return;
e.Handled = true;
listBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); e.Handled = true;
listBox.SelectedIndex = 0; listBox.MoveFocus(new(FocusNavigationDirection.First));
} listBox.SelectedIndex = 0;
} }
void UpdateResults(object sender, EventArgs e) void UpdateResults(object sender, EventArgs e)
@ -220,18 +216,19 @@ namespace ICSharpCode.ILSpy.Search
++resultsAdded; ++resultsAdded;
} }
if (resultsAdded > 0 && Results.Count == MAX_RESULTS) if (resultsAdded <= 0 || Results.Count != MAX_RESULTS)
{ return;
Results.Add(new SearchResult {
Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound, Results.Add(new() {
Location = null!, Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound,
Assembly = null!, Location = null!,
Image = null!, Assembly = null!,
LocationImage = null!, Image = null!,
AssemblyImage = null!, LocationImage = null!,
}); AssemblyImage = null!,
currentSearch.Cancel(); });
}
currentSearch.Cancel();
} }
async void StartSearch(string searchTerm) async void StartSearch(string searchTerm)
@ -243,7 +240,7 @@ namespace ICSharpCode.ILSpy.Search
} }
MainWindow mainWindow = MainWindow.Instance; MainWindow mainWindow = MainWindow.Instance;
resultsComparer = mainWindow.CurrentDisplaySettings.SortResults ? resultsComparer = SettingsService.Instance.DisplaySettings.SortResults ?
SearchResult.ComparerByFitness : SearchResult.ComparerByFitness :
SearchResult.ComparerByName; SearchResult.ComparerByName;
Results.Clear(); Results.Clear();
@ -253,7 +250,7 @@ namespace ICSharpCode.ILSpy.Search
{ {
searchProgressBar.IsIndeterminate = true; searchProgressBar.IsIndeterminate = true;
startedSearch = new RunningSearch(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm, startedSearch = new(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm,
(SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage, (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage,
SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel); SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel);
currentSearch = startedSearch; currentSearch = startedSearch;
@ -262,7 +259,8 @@ namespace ICSharpCode.ILSpy.Search
} }
if (currentSearch == startedSearch) if (currentSearch == startedSearch)
{ //are we still running the same search {
//are we still running the same search
searchProgressBar.IsIndeterminate = false; searchProgressBar.IsIndeterminate = false;
} }
} }
@ -277,7 +275,7 @@ namespace ICSharpCode.ILSpy.Search
sealed class RunningSearch sealed class RunningSearch
{ {
readonly CancellationTokenSource cts = new CancellationTokenSource(); readonly CancellationTokenSource cts = new();
readonly IList<LoadedAssembly> assemblies; readonly IList<LoadedAssembly> assemblies;
readonly SearchRequest searchRequest; readonly SearchRequest searchRequest;
readonly SearchMode searchMode; readonly SearchMode searchMode;
@ -299,8 +297,8 @@ namespace ICSharpCode.ILSpy.Search
{ {
string[] parts = CommandLineTools.CommandLineToArgumentArray(input); string[] parts = CommandLineTools.CommandLineToArgumentArray(input);
SearchRequest request = new SearchRequest(); SearchRequest request = new();
List<string> keywords = new List<string>(); List<string> keywords = new();
Regex regex = null; Regex regex = null;
request.Mode = searchMode; request.Mode = searchMode;
@ -350,7 +348,6 @@ namespace ICSharpCode.ILSpy.Search
// then we do not interpret it as prefix, but as searchTerm. // then we do not interpret it as prefix, but as searchTerm.
searchTerm = part; searchTerm = part;
prefix = null; prefix = null;
prefixLength = -1;
} }
if (prefix == null || prefix.Length <= 2) if (prefix == null || prefix.Length <= 2)
@ -442,7 +439,7 @@ namespace ICSharpCode.ILSpy.Search
{ {
try try
{ {
return new Regex(s, RegexOptions.Compiled); return new(s, RegexOptions.Compiled);
} }
catch (ArgumentException) catch (ArgumentException)
{ {
@ -454,7 +451,7 @@ namespace ICSharpCode.ILSpy.Search
request.RegEx = regex; request.RegEx = regex;
request.SearchResultFactory = new SearchResultFactory(language); request.SearchResultFactory = new SearchResultFactory(language);
request.TreeNodeFactory = new TreeNodeFactory(); request.TreeNodeFactory = new TreeNodeFactory();
request.DecompilerSettings = MainWindow.Instance.CurrentDecompilerSettings; request.DecompilerSettings = SettingsService.Instance.DecompilerSettings;
return request; return request;
} }
@ -540,9 +537,11 @@ namespace ICSharpCode.ILSpy.Search
public ShowSearchCommand() public ShowSearchCommand()
: base(NavigationCommands.Search) : base(NavigationCommands.Search)
{ {
NavigationCommands.Search.InputGestures.Clear(); var gestures = NavigationCommands.Search.InputGestures;
NavigationCommands.Search.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift));
NavigationCommands.Search.InputGestures.Add(new KeyGesture(Key.E, ModifierKeys.Control)); gestures.Clear();
gestures.Add(new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift));
gestures.Add(new KeyGesture(Key.E, ModifierKeys.Control));
} }
} }
} }

75
ILSpy/Search/SearchPaneModel.cs

@ -0,0 +1,75 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX.Search;
namespace ICSharpCode.ILSpy.Search
{
public class SearchModeModel
{
public SearchMode Mode { get; init; }
public string Name { get; init; }
public ImageSource Image { get; init; }
}
[ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class SearchPaneModel : ToolPaneModel
{
private string searchTerm;
public const string PaneContentId = "searchPane";
public SearchPaneModel()
{
ContentId = PaneContentId;
Title = Properties.Resources.SearchPane_Search;
Icon = "Images/Search";
ShortcutKey = new(Key.F, ModifierKeys.Control | ModifierKeys.Shift);
IsCloseable = true;
}
public SearchModeModel[] SearchModes { get; } = [
new() { Mode = SearchMode.TypeAndMember, Image = Images.Library, Name = "Types and Members" },
new() { Mode = SearchMode.Type, Image = Images.Class, Name = "Type" },
new() { Mode = SearchMode.Member, Image = Images.Property, Name = "Member" },
new() { Mode = SearchMode.Method, Image = Images.Method, Name = "Method" },
new() { Mode = SearchMode.Field, Image = Images.Field, Name = "Field" },
new() { Mode = SearchMode.Property, Image = Images.Property, Name = "Property" },
new() { Mode = SearchMode.Event, Image = Images.Event, Name = "Event" },
new() { Mode = SearchMode.Literal, Image = Images.Literal, Name = "Constant" },
new() { Mode = SearchMode.Token, Image = Images.Library, Name = "Metadata Token" },
new() { Mode = SearchMode.Resource, Image = Images.Resource, Name = "Resource" },
new() { Mode = SearchMode.Assembly, Image = Images.Assembly, Name = "Assembly" },
new() { Mode = SearchMode.Namespace, Image = Images.Namespace, Name = "Namespace" }
];
public SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
public string SearchTerm {
get => searchTerm;
set => SetProperty(ref searchTerm, value);
}
}
}

26
ILSpy/TextView/DecompilerTextView.cs

@ -113,9 +113,9 @@ namespace ICSharpCode.ILSpy.TextView
textEditor.TextArea.Caret.PositionChanged += HighlightBrackets; textEditor.TextArea.Caret.PositionChanged += HighlightBrackets;
textEditor.MouseMove += TextEditorMouseMove; textEditor.MouseMove += TextEditorMouseMove;
textEditor.MouseLeave += TextEditorMouseLeave; textEditor.MouseLeave += TextEditorMouseLeave;
textEditor.SetBinding(Control.FontFamilyProperty, new Binding { Source = MainWindow.Instance.CurrentDisplaySettings, Path = new PropertyPath("SelectedFont") }); textEditor.SetBinding(Control.FontFamilyProperty, new Binding { Source = SettingsService.Instance.DisplaySettings, Path = new PropertyPath("SelectedFont") });
textEditor.SetBinding(Control.FontSizeProperty, new Binding { Source = MainWindow.Instance.CurrentDisplaySettings, Path = new PropertyPath("SelectedFontSize") }); textEditor.SetBinding(Control.FontSizeProperty, new Binding { Source = SettingsService.Instance.DisplaySettings, Path = new PropertyPath("SelectedFontSize") });
textEditor.SetBinding(TextEditor.WordWrapProperty, new Binding { Source = MainWindow.Instance.CurrentDisplaySettings, Path = new PropertyPath("EnableWordWrap") }); textEditor.SetBinding(TextEditor.WordWrapProperty, new Binding { Source = SettingsService.Instance.DisplaySettings, Path = new PropertyPath("EnableWordWrap") });
// disable Tab editing command (useless for read-only editor); allow using tab for focus navigation instead // disable Tab editing command (useless for read-only editor); allow using tab for focus navigation instead
RemoveEditCommand(EditingCommands.TabForward); RemoveEditCommand(EditingCommands.TabForward);
@ -125,7 +125,7 @@ namespace ICSharpCode.ILSpy.TextView
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
textEditor.ShowLineNumbers = true; textEditor.ShowLineNumbers = true;
MainWindow.Instance.CurrentDisplaySettings.PropertyChanged += CurrentDisplaySettings_PropertyChanged; SettingsService.Instance.DisplaySettings.PropertyChanged += CurrentDisplaySettings_PropertyChanged;
// SearchPanel // SearchPanel
SearchPanel searchPanel = SearchPanel.Install(textEditor.TextArea); SearchPanel searchPanel = SearchPanel.Install(textEditor.TextArea);
@ -181,11 +181,11 @@ namespace ICSharpCode.ILSpy.TextView
void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e) void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettingsViewModel.ShowLineNumbers)) if (e.PropertyName == nameof(DisplaySettings.ShowLineNumbers))
{ {
ShowLineMargin(); ShowLineMargin();
} }
else if (e.PropertyName == nameof(DisplaySettingsViewModel.HighlightCurrentLine)) else if (e.PropertyName == nameof(DisplaySettings.HighlightCurrentLine))
{ {
SetHighlightCurrentLine(); SetHighlightCurrentLine();
} }
@ -197,14 +197,14 @@ namespace ICSharpCode.ILSpy.TextView
{ {
if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line) if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line)
{ {
margin.Visibility = MainWindow.Instance.CurrentDisplaySettings.ShowLineNumbers ? Visibility.Visible : Visibility.Collapsed; margin.Visibility = SettingsService.Instance.DisplaySettings.ShowLineNumbers ? Visibility.Visible : Visibility.Collapsed;
} }
} }
} }
void SetHighlightCurrentLine() void SetHighlightCurrentLine()
{ {
textEditor.Options.HighlightCurrentLine = MainWindow.Instance.CurrentDisplaySettings.HighlightCurrentLine; textEditor.Options.HighlightCurrentLine = SettingsService.Instance.DisplaySettings.HighlightCurrentLine;
} }
#endregion #endregion
@ -485,7 +485,7 @@ namespace ICSharpCode.ILSpy.TextView
public FlowDocumentTooltip(FlowDocument document) public FlowDocumentTooltip(FlowDocument document)
{ {
TextOptions.SetTextFormattingMode(this, TextFormattingMode.Display); TextOptions.SetTextFormattingMode(this, TextFormattingMode.Display);
double fontSize = MainWindow.Instance.CurrentDisplaySettings.SelectedFontSize; double fontSize = SettingsService.Instance.DisplaySettings.SelectedFontSize;
viewer = new FlowDocumentScrollViewer() { viewer = new FlowDocumentScrollViewer() {
Width = document.MinPageWidth + fontSize * 5, Width = document.MinPageWidth + fontSize * 5,
MaxWidth = MainWindow.Instance.ActualWidth MaxWidth = MainWindow.Instance.ActualWidth
@ -532,7 +532,7 @@ namespace ICSharpCode.ILSpy.TextView
#region Highlight brackets #region Highlight brackets
void HighlightBrackets(object? sender, EventArgs e) void HighlightBrackets(object? sender, EventArgs e)
{ {
if (MainWindow.Instance.CurrentDisplaySettings.HighlightMatchingBraces) if (SettingsService.Instance.DisplaySettings.HighlightMatchingBraces)
{ {
var result = SettingsService.Instance.SessionSettings.LanguageSettings.Language.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset); var result = SettingsService.Instance.SessionSettings.LanguageSettings.Language.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset);
bracketHighlightRenderer.SetHighlight(result); bracketHighlightRenderer.SetHighlight(result);
@ -754,7 +754,7 @@ namespace ICSharpCode.ILSpy.TextView
{ {
if (state != null) if (state != null)
{ {
state.RestoreFoldings(textOutput.Foldings, MainWindow.Instance.CurrentDisplaySettings.ExpandMemberDefinitions); state.RestoreFoldings(textOutput.Foldings, SettingsService.Instance.DisplaySettings.ExpandMemberDefinitions);
textEditor.ScrollToVerticalOffset(state.VerticalOffset); textEditor.ScrollToVerticalOffset(state.VerticalOffset);
textEditor.ScrollToHorizontalOffset(state.HorizontalOffset); textEditor.ScrollToHorizontalOffset(state.HorizontalOffset);
} }
@ -778,7 +778,7 @@ namespace ICSharpCode.ILSpy.TextView
} }
currentAddress = textOutput.Address; currentAddress = textOutput.Address;
currentTitle = textOutput.Title; currentTitle = textOutput.Title;
expandMemberDefinitions = MainWindow.Instance.CurrentDisplaySettings.ExpandMemberDefinitions; expandMemberDefinitions = SettingsService.Instance.DisplaySettings.ExpandMemberDefinitions;
} }
#endregion #endregion
@ -1289,7 +1289,7 @@ namespace ICSharpCode.ILSpy.TextView
public void Dispose() public void Dispose()
{ {
MainWindow.Instance.CurrentDisplaySettings.PropertyChanged -= CurrentDisplaySettings_PropertyChanged; SettingsService.Instance.DisplaySettings.PropertyChanged -= CurrentDisplaySettings_PropertyChanged;
} }
#region Unfold #region Unfold

5
ILSpy/TextView/DocumentationUIBuilder.cs

@ -37,6 +37,7 @@ using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.Util;
namespace ICSharpCode.ILSpy.TextView namespace ICSharpCode.ILSpy.TextView
{ {
@ -115,7 +116,7 @@ namespace ICSharpCode.ILSpy.TextView
// Paragraph sadly does not support TextWrapping.NoWrap // Paragraph sadly does not support TextWrapping.NoWrap
var text = new TextBlock { var text = new TextBlock {
FontFamily = GetCodeFont(), FontFamily = GetCodeFont(),
FontSize = MainWindow.Instance.CurrentDisplaySettings.SelectedFontSize, FontSize = SettingsService.Instance.DisplaySettings.SelectedFontSize,
TextAlignment = TextAlignment.Left TextAlignment = TextAlignment.Left
}; };
text.Inlines.AddRange(richText.CreateRuns(document)); text.Inlines.AddRange(richText.CreateRuns(document));
@ -435,7 +436,7 @@ namespace ICSharpCode.ILSpy.TextView
FontFamily GetCodeFont() FontFamily GetCodeFont()
{ {
return MainWindow.Instance.CurrentDisplaySettings.SelectedFont; return SettingsService.Instance.DisplaySettings.SelectedFont;
} }
public void AddInline(Inline inline) public void AddInline(Inline inline)

11
ILSpy/Themes/WindowStyleManagerBehavior.cs

@ -24,6 +24,7 @@ using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.Util;
using TomsToolbox.Essentials; using TomsToolbox.Essentials;
using TomsToolbox.Wpf; using TomsToolbox.Wpf;
@ -42,7 +43,7 @@ namespace ICSharpCode.ILSpy.Themes
{ {
base.OnAttached(); base.OnAttached();
MainWindow.Instance.CurrentDisplaySettings.PropertyChanged += DisplaySettings_PropertyChanged; SettingsService.Instance.DisplaySettings.PropertyChanged += DisplaySettings_PropertyChanged;
_foreground = AssociatedObject.Track(Control.ForegroundProperty); _foreground = AssociatedObject.Track(Control.ForegroundProperty);
_background = AssociatedObject.Track(Control.BackgroundProperty); _background = AssociatedObject.Track(Control.BackgroundProperty);
@ -61,7 +62,7 @@ namespace ICSharpCode.ILSpy.Themes
_foreground.Changed -= Color_Changed; _foreground.Changed -= Color_Changed;
_background.Changed -= Color_Changed; _background.Changed -= Color_Changed;
MainWindow.Instance.CurrentDisplaySettings.PropertyChanged -= DisplaySettings_PropertyChanged; SettingsService.Instance.DisplaySettings.PropertyChanged -= DisplaySettings_PropertyChanged;
} }
private void Color_Changed(object sender, EventArgs e) private void Color_Changed(object sender, EventArgs e)
@ -73,7 +74,7 @@ namespace ICSharpCode.ILSpy.Themes
{ {
var window = AssociatedObject; var window = AssociatedObject;
if (MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar) if (SettingsService.Instance.DisplaySettings.StyleWindowTitleBar)
window.Style = (Style)window.FindResource(TomsToolbox.Wpf.Styles.ResourceKeys.WindowStyle); window.Style = (Style)window.FindResource(TomsToolbox.Wpf.Styles.ResourceKeys.WindowStyle);
} }
@ -84,9 +85,9 @@ namespace ICSharpCode.ILSpy.Themes
private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e) private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettingsViewModel.StyleWindowTitleBar)) if (e.PropertyName == nameof(DisplaySettings.StyleWindowTitleBar))
{ {
if (!MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar) if (!SettingsService.Instance.DisplaySettings.StyleWindowTitleBar)
{ {
restartNotificationThrottle.Tick(); restartNotificationThrottle.Tick();
return; return;

3
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -26,6 +26,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Themes; using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
@ -85,7 +86,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
this.Children.Add(new AssemblyReferenceReferencedTypesTreeNode(module, r)); this.Children.Add(new AssemblyReferenceReferencedTypesTreeNode(module, r));
var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(MainWindow.Instance.CurrentDecompilerSettings.AutoLoadAssemblyReferences); var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(SettingsService.Instance.DecompilerSettings.AutoLoadAssemblyReferences);
var referencedModule = resolver.Resolve(r); var referencedModule = resolver.Resolve(r);
if (referencedModule != null) if (referencedModule != null)
{ {

5
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -33,6 +33,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Controls.TreeView; using ICSharpCode.ILSpy.Controls.TreeView;
using ICSharpCode.ILSpy.Metadata; using ICSharpCode.ILSpy.Metadata;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.FileLoaders; using ICSharpCode.ILSpyX.FileLoaders;
@ -261,7 +262,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
ns.Children.Clear(); ns.Children.Clear();
} }
namespaces.Clear(); namespaces.Clear();
bool useNestedStructure = MainWindow.Instance.CurrentDisplaySettings.UseNestedNamespaceNodes; bool useNestedStructure = SettingsService.Instance.DisplaySettings.UseNestedNamespaceNodes;
foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance))
{ {
var ns = GetOrCreateNamespaceTreeNode(type.Namespace); var ns = GetOrCreateNamespaceTreeNode(type.Namespace);
@ -327,7 +328,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
ns.Children.Clear(); ns.Children.Clear();
} }
namespaces.Clear(); namespaces.Clear();
bool useNestedStructure = MainWindow.Instance.CurrentDisplaySettings.UseNestedNamespaceNodes; bool useNestedStructure = SettingsService.Instance.DisplaySettings.UseNestedNamespaceNodes;
foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance))
{ {
var ns = GetOrCreateNamespaceTreeNode(type.Namespace); var ns = GetOrCreateNamespaceTreeNode(type.Namespace);

4
ILSpy/TreeNodes/ILSpyTreeNode.cs

@ -158,11 +158,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected string GetSuffixString(EntityHandle handle) protected string GetSuffixString(EntityHandle handle)
{ {
if (!MainWindow.Instance.CurrentDisplaySettings.ShowMetadataTokens) if (!SettingsService.Instance.DisplaySettings.ShowMetadataTokens)
return string.Empty; return string.Empty;
int token = MetadataTokens.GetToken(handle); int token = MetadataTokens.GetToken(handle);
if (MainWindow.Instance.CurrentDisplaySettings.ShowMetadataTokensInBase10) if (SettingsService.Instance.DisplaySettings.ShowMetadataTokensInBase10)
return " @" + token; return " @" + token;
return " @" + token.ToString("x8"); return " @" + token.ToString("x8");
} }

26
ILSpy/Util/SettingsService.cs

@ -1,20 +1,34 @@
using ICSharpCode.ILSpyX.Settings; using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Util namespace ICSharpCode.ILSpy.Util
{ {
internal class SettingsService public class SettingsService
{ {
public static readonly SettingsService Instance = new SettingsService(); public static readonly SettingsService Instance = new();
private SettingsService() private SettingsService()
{ {
this.SpySettings = ILSpySettings.Load(); SpySettings = ILSpySettings.Load();
SessionSettings = new(SpySettings);
SessionSettings = new(this.SpySettings); DecompilerSettings = DecompilerSettingsPanel.LoadDecompilerSettings(SpySettings);
DisplaySettings = DisplaySettingsPanel.LoadDisplaySettings(SpySettings, SessionSettings);
AssemblyListManager = new(SpySettings) {
ApplyWinRTProjections = DecompilerSettings.ApplyWindowsRuntimeProjections,
UseDebugSymbols = DecompilerSettings.UseDebugSymbols
};
} }
public ILSpySettings SpySettings { get; } public ILSpySettings SpySettings { get; }
public SessionSettings SessionSettings { get; } public SessionSettings SessionSettings { get; }
public DecompilerSettings DecompilerSettings { get; set; }
public DisplaySettings DisplaySettings { get; }
public AssemblyListManager AssemblyListManager { get; }
} }
} }

2
ILSpy/ViewModels/ManageAssemblyListsViewModel.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.ViewModels
public ManageAssemblyListsViewModel(Window parent) public ManageAssemblyListsViewModel(Window parent)
{ {
this.manager = MainWindow.Instance.AssemblyListManager; this.manager = SettingsService.Instance.AssemblyListManager;
this.parent = parent; this.parent = parent;
NewCommand = new DelegateCommand(ExecuteNew); NewCommand = new DelegateCommand(ExecuteNew);

103
ILSpy/ViewModels/PaneModel.cs

@ -18,8 +18,11 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.ILSpy.Docking;
using TomsToolbox.Wpf; using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
@ -57,93 +60,81 @@ namespace ICSharpCode.ILSpy.ViewModels
} }
} }
public PaneModel() private bool isSelected;
{
this.closeCommand = new CloseCommandImpl(this);
}
private bool isSelected = false;
public bool IsSelected { public bool IsSelected {
get => isSelected; get => isSelected;
set { set => SetProperty(ref isSelected, value);
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
} }
private bool isActive = false; private bool isActive;
public bool IsActive { public bool IsActive {
get => isActive; get => isActive;
set { set => SetProperty(ref isActive, value);
if (isActive != value)
{
isActive = value;
OnPropertyChanged(nameof(IsActive));
}
}
} }
private bool isVisible; private bool isVisible;
public bool IsVisible { public bool IsVisible {
get { return isVisible; } get { return isVisible; }
set { set {
if (isVisible != value) if (SetProperty(ref isVisible, value) && !value)
{ {
isVisible = value; // When the pane is hidden, it should no longer be marked as active, else it won't raise an event when it is activated again.
OnPropertyChanged(nameof(IsVisible)); IsActive = false;
} }
} }
} }
private bool isCloseable = true; private bool isCloseable = true;
public bool IsCloseable { public bool IsCloseable {
get { return isCloseable; } get => isCloseable;
set { set => SetProperty(ref isCloseable, value);
if (isCloseable != value)
{
isCloseable = value;
OnPropertyChanged(nameof(IsCloseable));
}
}
} }
private ICommand closeCommand; public ICommand CloseCommand => new CloseCommandImpl(this);
public ICommand CloseCommand {
get { return closeCommand; }
set {
if (closeCommand != value)
{
closeCommand = value;
OnPropertyChanged(nameof(CloseCommand));
}
}
}
private string contentId; private string contentId;
public string ContentId { public string ContentId {
get => contentId; get => contentId;
set { set => SetProperty(ref contentId, value);
if (contentId != value)
{
contentId = value;
OnPropertyChanged(nameof(ContentId));
}
}
} }
private string title; private string title;
public string Title { public string Title {
get => title; get => title;
set { set => SetProperty(ref title, value);
if (title != value) }
{ }
title = value;
OnPropertyChanged(nameof(Title)); public static class Pane
} {
} // Helper properties to enable binding state properties from the model to the view.
public static readonly DependencyProperty IsActiveProperty = DependencyProperty.RegisterAttached(
"IsActive", typeof(bool), typeof(Pane), new FrameworkPropertyMetadata(default(bool)));
public static void SetIsActive(DependencyObject element, bool value)
{
element.SetValue(IsActiveProperty, value);
}
public static bool GetIsActive(DependencyObject element)
{
return (bool)element.GetValue(IsActiveProperty);
}
public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.RegisterAttached(
"IsVisible", typeof(bool), typeof(Pane), new FrameworkPropertyMetadata(default(bool)));
public static void SetIsVisible(DependencyObject element, bool value)
{
element.SetValue(IsVisibleProperty, value);
}
public static bool GetIsVisible(DependencyObject element)
{
return (bool)element.GetValue(IsVisibleProperty);
} }
} }
} }

46
ILSpy/ViewModels/SearchPaneModel.cs

@ -1,46 +0,0 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.ILSpy.ViewModels
{
[ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)]
public class SearchPaneModel : ToolPaneModel
{
public const string PaneContentId = "searchPane";
public SearchPaneModel()
{
ContentId = PaneContentId;
Title = Properties.Resources.SearchPane_Search;
Icon = "Images/Search";
ShortcutKey = new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift);
IsCloseable = true;
}
public override void Show()
{
base.Show();
MainWindow.Instance.SearchPane.Show();
}
}
}

2
ILSpy/Views/DebugSteps.xaml.cs

@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy
var window = MainWindow.Instance; var window = MainWindow.Instance;
var state = DockWorkspace.Instance.ActiveTabPage.GetState(); var state = DockWorkspace.Instance.ActiveTabPage.GetState();
DockWorkspace.Instance.ActiveTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(window.CurrentLanguage, window.SelectedNodes, DockWorkspace.Instance.ActiveTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(window.CurrentLanguage, window.SelectedNodes,
new DecompilationOptions(window.CurrentLanguageVersion, window.CurrentDecompilerSettings, window.CurrentDisplaySettings) { new DecompilationOptions(window.CurrentLanguageVersion, SettingsService.Instance.DecompilerSettings, SettingsService.Instance.DisplaySettings) {
StepLimit = step, StepLimit = step,
IsDebug = isDebug, IsDebug = isDebug,
TextViewState = state as TextView.DecompilerTextViewState TextViewState = state as TextView.DecompilerTextViewState

Loading…
Cancel
Save