Browse Source

Merge pull request #2554 from icsharpcode/fix-ui-typesystem

Fix typesystems used in the UI
pull/2560/head
Siegfried Pammer 4 years ago committed by GitHub
parent
commit
70c17dd1c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      ILSpy/Analyzers/AnalyzerTreeView.cs
  2. 58
      ILSpy/Docking/DockWorkspace.cs
  3. 31
      ILSpy/FilterSettings.cs
  4. 22
      ILSpy/MainWindow.xaml
  5. 67
      ILSpy/MainWindow.xaml.cs
  6. 30
      ILSpy/MainWindowViewModel.cs
  7. 17
      ILSpy/Search/SearchPane.cs
  8. 2
      ILSpy/SessionSettings.cs
  9. 7
      ILSpy/TextView/DecompilerTextView.cs
  10. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  11. 14
      ILSpy/TreeNodes/EventTreeNode.cs
  12. 14
      ILSpy/TreeNodes/FieldTreeNode.cs
  13. 14
      ILSpy/TreeNodes/MethodTreeNode.cs
  14. 17
      ILSpy/TreeNodes/PropertyTreeNode.cs
  15. 14
      ILSpy/TreeNodes/TypeTreeNode.cs
  16. 10
      ILSpy/ViewModels/ManageAssemblyListsViewModel.cs
  17. 59
      ILSpy/ViewModels/TabPageModel.cs
  18. 18
      ILSpy/Views/DebugSteps.xaml.cs

18
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.Analyzers
/// </summary>
public class AnalyzerTreeView : SharpTreeView
{
FilterSettings filterSettings;
public AnalyzerTreeView()
{
this.ShowRoot = false;
@ -42,7 +44,21 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -42,7 +44,21 @@ namespace ICSharpCode.ILSpy.Analyzers
this.BorderThickness = new Thickness(0);
ContextMenuProvider.Add(this);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
filterSettings = MainWindow.Instance.SessionSettings.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
}
private void DockWorkspace_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
filterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
break;
}
}
private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

58
ILSpy/Docking/DockWorkspace.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
@ -45,14 +46,46 @@ namespace ICSharpCode.ILSpy.Docking @@ -45,14 +46,46 @@ namespace ICSharpCode.ILSpy.Docking
public event PropertyChangedEventHandler PropertyChanged;
public static DockWorkspace Instance { get; } = new DockWorkspace();
public static DockWorkspace Instance { get; private set; }
private DockWorkspace()
internal DockWorkspace(MainWindow parent)
{
Instance = this;
this.TabPages.CollectionChanged += Documents_CollectionChanged;
parent.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
}
private void Documents_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
private void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems == null)
{
return;
}
foreach (var tab in TabPages.ToArray())
{
var state = tab.GetState();
if (state == null || state.DecompiledNodes == null)
{
continue;
}
bool found = false;
foreach (var node in state.DecompiledNodes)
{
var assemblyNode = node.Ancestors().OfType<TreeNodes.AssemblyTreeNode>().LastOrDefault();
if (assemblyNode != null && !e.OldItems.Contains(assemblyNode.LoadedAssembly))
{
found = true;
break;
}
}
if (!found && TabPages.Count > 1)
{
TabPages.Remove(tab);
}
}
}
private void Documents_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var collection = (PaneCollection<TabPageModel>)sender;
bool canClose = collection.Count > 1;
@ -94,8 +127,6 @@ namespace ICSharpCode.ILSpy.Docking @@ -94,8 +127,6 @@ namespace ICSharpCode.ILSpy.Docking
if (_activeTabPage != value)
{
_activeTabPage = value;
this.sessionSettings.FilterSettings.Language = value.Language;
this.sessionSettings.FilterSettings.LanguageVersion = value.LanguageVersion;
var state = value.GetState();
if (state != null)
{
@ -173,23 +204,6 @@ namespace ICSharpCode.ILSpy.Docking @@ -173,23 +204,6 @@ namespace ICSharpCode.ILSpy.Docking
internal void LoadSettings(SessionSettings sessionSettings)
{
this.sessionSettings = sessionSettings;
sessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
}
private void FilterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Language")
{
ActiveTabPage.Language = sessionSettings.FilterSettings.Language;
if (sessionSettings.FilterSettings.Language.HasLanguageVersions)
{
sessionSettings.FilterSettings.LanguageVersion = ActiveTabPage.LanguageVersion;
}
}
else if (e.PropertyName == "LanguageVersion")
{
ActiveTabPage.LanguageVersion = sessionSettings.FilterSettings.LanguageVersion;
}
}
internal void CloseAllTabs()

31
ILSpy/FilterSettings.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
@ -34,6 +35,13 @@ namespace ICSharpCode.ILSpy @@ -34,6 +35,13 @@ namespace ICSharpCode.ILSpy
/// </remarks>
public class FilterSettings : INotifyPropertyChanged
{
/// <summary>
/// This dictionary is necessary to remember language versions across language changes. For example,
/// the user first select C# 10, then switches to IL, then switches back to C#. After that we must be
/// able to restore the original selection (i.e., C# 10).
/// </summary>
private readonly Dictionary<Language, LanguageVersion> languageVersionHistory = new Dictionary<Language, LanguageVersion>();
public FilterSettings(XElement element)
{
this.ShowApiLevel = (ApiVisibility?)(int?)element.Element("ShowAPILevel") ?? ApiVisibility.PublicAndInternal;
@ -146,8 +154,27 @@ namespace ICSharpCode.ILSpy @@ -146,8 +154,27 @@ namespace ICSharpCode.ILSpy
set {
if (language != value)
{
if (language != null && language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
language = value;
OnPropertyChanged();
if (language.HasLanguageVersions)
{
if (languageVersionHistory.TryGetValue(value, out var version))
{
LanguageVersion = version;
}
else
{
LanguageVersion = Language.LanguageVersions.Last();
}
}
else
{
LanguageVersion = default;
}
}
}
}
@ -167,6 +194,10 @@ namespace ICSharpCode.ILSpy @@ -167,6 +194,10 @@ namespace ICSharpCode.ILSpy
if (languageVersion != value)
{
languageVersion = value;
if (language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
OnPropertyChanged();
}
}

22
ILSpy/MainWindow.xaml

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
d:DataContext="{d:DesignInstance local:MainWindowDataContext}"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}"
>
<Window.Resources>
<controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
@ -103,9 +103,9 @@ @@ -103,9 +103,9 @@
<MenuItem Header="{x:Static properties:Resources._File}" />
<!-- contents of file menu are added using MEF -->
<MenuItem Header="{x:Static properties:Resources._View}">
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.FilterSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.FilterSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.FilterSettings.ApiVisAll}" />
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisAll}" />
<Separator/>
<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}}" />
@ -156,25 +156,25 @@ @@ -156,25 +156,25 @@
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</Button>
<Separator />
<CheckBox IsChecked="{Binding SessionSettings.FilterSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.FilterSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.FilterSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<CheckBox IsChecked="{Binding Workspace.ActiveTabPage.FilterSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}" Style="{StaticResource DarkModeAwareImageStyle}"/>
</CheckBox>
<Separator />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto"
IsEnabled="{Binding ActiveTabPage.SupportsLanguageSwitching, Source={x:Static docking:DockWorkspace.Instance}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}" ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding SessionSettings.FilterSettings.Language}"/>
SelectedItem="{Binding Workspace.ActiveTabPage.FilterSettings.Language}"/>
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto" ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={StaticResource BooleanToVisibilityConverter}}"
IsEnabled="{Binding ActiveTabPage.SupportsLanguageSwitching, Source={x:Static docking:DockWorkspace.Instance}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SessionSettings.FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
SelectedItem="{Binding Workspace.ActiveTabPage.FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
<Separator />
<CheckBox IsChecked="{Binding SessionSettings.IsDarkMode}" ToolTip="{x:Static properties:Resources.DarkMode}">
<Image Source="Images/DarkMode.png" Stretch="None" Style="{StaticResource DarkModeAwareImageStyle}"/>

67
ILSpy/MainWindow.xaml.cs

@ -32,7 +32,6 @@ using System.Windows.Controls; @@ -32,7 +32,6 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Threading;
@ -55,13 +54,6 @@ using Microsoft.Win32; @@ -55,13 +54,6 @@ using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
class MainWindowDataContext
{
public DockWorkspace Workspace { get; set; }
public SessionSettings SessionSettings { get; set; }
public AssemblyListManager AssemblyListManager { get; set; }
}
/// <summary>
/// The main window of the application.
/// </summary>
@ -70,7 +62,8 @@ namespace ICSharpCode.ILSpy @@ -70,7 +62,8 @@ namespace ICSharpCode.ILSpy
bool refreshInProgress, changingActiveTab;
readonly NavigationHistory<NavigationState> history = new NavigationHistory<NavigationState>();
ILSpySettings spySettingsForMainWindow_Loaded;
internal SessionSettings sessionSettings;
SessionSettings sessionSettings;
FilterSettings filterSettings;
AssemblyList assemblyList;
AssemblyListTreeNode assemblyListTreeNode;
@ -115,8 +108,8 @@ namespace ICSharpCode.ILSpy @@ -115,8 +108,8 @@ namespace ICSharpCode.ILSpy
// Make sure Images are initialized on the UI thread.
this.Icon = Images.ILSpyIcon;
this.DataContext = new MainWindowDataContext {
Workspace = DockWorkspace.Instance,
this.DataContext = new MainWindowViewModel {
Workspace = new DockWorkspace(this),
SessionSettings = sessionSettings,
AssemblyListManager = AssemblyListManager
};
@ -130,8 +123,10 @@ namespace ICSharpCode.ILSpy @@ -130,8 +123,10 @@ namespace ICSharpCode.ILSpy
InitializeComponent();
InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
sessionSettings.PropertyChanged += SessionSettings_PropertyChanged;
filterSettings = sessionSettings.FilterSettings;
filterSettings.PropertyChanged += filterSettings_PropertyChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
InitMainMenu();
InitToolbar();
ContextMenuProvider.Add(AssemblyTreeView);
@ -139,6 +134,18 @@ namespace ICSharpCode.ILSpy @@ -139,6 +134,18 @@ namespace ICSharpCode.ILSpy
this.Loaded += MainWindow_Loaded;
}
private void DockWorkspace_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
filterSettings.PropertyChanged -= filterSettings_PropertyChanged;
filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += filterSettings_PropertyChanged;
break;
}
}
private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
@ -406,7 +413,7 @@ namespace ICSharpCode.ILSpy @@ -406,7 +413,7 @@ namespace ICSharpCode.ILSpy
{
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
sessionSettings.FilterSettings.Language = Languages.GetLanguage(args.Language);
filterSettings.Language = Languages.GetLanguage(args.Language);
return true;
}
@ -597,8 +604,7 @@ namespace ICSharpCode.ILSpy @@ -597,8 +604,7 @@ namespace ICSharpCode.ILSpy
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
DockWorkspace.Instance.TabPages.Add(new TabPageModel() {
Language = CurrentLanguage,
LanguageVersion = CurrentLanguageVersion
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.First();
@ -770,7 +776,7 @@ namespace ICSharpCode.ILSpy @@ -770,7 +776,7 @@ namespace ICSharpCode.ILSpy
assemblyList.CollectionChanged += assemblyList_Assemblies_CollectionChanged;
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.FilterSettings = filterSettings.Clone();
assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false);
AssemblyTreeView.Root = assemblyListTreeNode;
@ -824,7 +830,6 @@ namespace ICSharpCode.ILSpy @@ -824,7 +830,6 @@ namespace ICSharpCode.ILSpy
void filterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
RefreshTreeView();
RefreshTreeViewFilter();
if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion")
{
@ -838,7 +843,7 @@ namespace ICSharpCode.ILSpy @@ -838,7 +843,7 @@ namespace ICSharpCode.ILSpy
// Thus, the main window will use one mutable instance (for data-binding), and assign a new clone to the ILSpyTreeNodes whenever the main
// mutable instance changes.
if (assemblyListTreeNode != null)
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.FilterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone();
}
internal AssemblyListTreeNode AssemblyListTreeNode {
@ -867,8 +872,7 @@ namespace ICSharpCode.ILSpy @@ -867,8 +872,7 @@ namespace ICSharpCode.ILSpy
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
Language = CurrentLanguage,
LanguageVersion = CurrentLanguageVersion
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
AssemblyTreeView.SelectedItem = null;
@ -914,8 +918,7 @@ namespace ICSharpCode.ILSpy @@ -914,8 +918,7 @@ namespace ICSharpCode.ILSpy
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
Language = CurrentLanguage,
LanguageVersion = CurrentLanguageVersion
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
}
@ -1173,11 +1176,6 @@ namespace ICSharpCode.ILSpy @@ -1173,11 +1176,6 @@ namespace ICSharpCode.ILSpy
}
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
RefreshTreeView();
}
void RefreshTreeView()
{
try
{
@ -1206,7 +1204,10 @@ namespace ICSharpCode.ILSpy @@ -1206,7 +1204,10 @@ namespace ICSharpCode.ILSpy
{
state = DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState;
}
DecompileSelectedNodes(state);
if (!changingActiveTab)
{
DecompileSelectedNodes(state);
}
SelectionChanged?.Invoke(sender, e);
}
@ -1274,8 +1275,10 @@ namespace ICSharpCode.ILSpy @@ -1274,8 +1275,10 @@ namespace ICSharpCode.ILSpy
}
}
public Language CurrentLanguage => sessionSettings.FilterSettings.Language;
public LanguageVersion CurrentLanguageVersion => sessionSettings.FilterSettings.LanguageVersion;
public Language CurrentLanguage => DockWorkspace.Instance.ActiveTabPage.FilterSettings.Language;
public LanguageVersion CurrentLanguageVersion => DockWorkspace.Instance.ActiveTabPage.FilterSettings.LanguageVersion;
public bool SupportsLanguageSwitching => DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching;
public event SelectionChangedEventHandler SelectionChanged;
@ -1347,8 +1350,7 @@ namespace ICSharpCode.ILSpy @@ -1347,8 +1350,7 @@ namespace ICSharpCode.ILSpy
{
DockWorkspace.Instance.TabPages.Add(
new TabPageModel() {
Language = CurrentLanguage,
LanguageVersion = CurrentLanguageVersion
FilterSettings = filterSettings.Clone()
});
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
}
@ -1413,6 +1415,7 @@ namespace ICSharpCode.ILSpy @@ -1413,6 +1415,7 @@ namespace ICSharpCode.ILSpy
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(DockManager));
sessionSettings.FilterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone();
sessionSettings.Save();
}

30
ILSpy/MainWindowViewModel.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) 2021 Siegfried Pammer
//
// 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 ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy
{
class MainWindowViewModel
{
public DockWorkspace Workspace { get; set; }
public SessionSettings SessionSettings { get; set; }
public AssemblyListManager AssemblyListManager { get; set; }
}
}

17
ILSpy/Search/SearchPane.cs

@ -50,6 +50,7 @@ namespace ICSharpCode.ILSpy @@ -50,6 +50,7 @@ namespace ICSharpCode.ILSpy
RunningSearch currentSearch;
bool runSearchOnNextShow;
IComparer<SearchResult> resultsComparer;
FilterSettings filterSettings;
public static readonly DependencyProperty ResultsProperty =
DependencyProperty.Register("Results", typeof(ObservableCollection<SearchResult>), typeof(SearchPane),
@ -76,13 +77,27 @@ namespace ICSharpCode.ILSpy @@ -76,13 +77,27 @@ namespace ICSharpCode.ILSpy
ContextMenuProvider.Add(listBox);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
filterSettings = MainWindow.Instance.SessionSettings.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
CompositionTarget.Rendering += UpdateResults;
// This starts empty search right away, so do at the end (we're still in ctor)
searchModeComboBox.SelectedIndex = (int)MainWindow.Instance.SessionSettings.SelectedSearchMode;
}
private void DockWorkspace_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
filterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
break;
}
}
void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (IsVisible)

2
ILSpy/SessionSettings.cs

@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpy @@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpy
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public FilterSettings FilterSettings { get; private set; }
public FilterSettings FilterSettings { get; internal set; }
public SearchMode SelectedSearchMode { get; set; }
public bool IsDarkMode {

7
ILSpy/TextView/DecompilerTextView.cs

@ -152,7 +152,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -152,7 +152,7 @@ namespace ICSharpCode.ILSpy.TextView
{
if (this.DataContext is PaneModel model)
{
model.Title = currentTitle ?? ILSpy.Properties.Resources.NewTab;
model.Title = currentTitle ?? ILSpy.Properties.Resources.Decompiling;
}
}
@ -665,8 +665,8 @@ namespace ICSharpCode.ILSpy.TextView @@ -665,8 +665,8 @@ namespace ICSharpCode.ILSpy.TextView
textOutput.Title = string.Join(", ", nodes.Select(n => n.Text));
}
ShowOutput(textOutput, highlighting);
decompiledNodes = nodes;
ShowOutput(textOutput, highlighting);
}
/// <summary>
@ -815,12 +815,12 @@ namespace ICSharpCode.ILSpy.TextView @@ -815,12 +815,12 @@ namespace ICSharpCode.ILSpy.TextView
return RunWithCancellation(
delegate (CancellationToken ct) { // creation of the background task
context.Options.CancellationToken = ct;
decompiledNodes = context.TreeNodes;
return DecompileAsync(context, outputLengthLimit);
})
.Then(
delegate (AvalonEditTextOutput textOutput) { // handling the result
ShowOutput(textOutput, context.Language.SyntaxHighlighting, context.Options.TextViewState);
decompiledNodes = context.TreeNodes;
})
.Catch<Exception>(exception => {
textEditor.SyntaxHighlighting = null;
@ -835,7 +835,6 @@ namespace ICSharpCode.ILSpy.TextView @@ -835,7 +835,6 @@ namespace ICSharpCode.ILSpy.TextView
output.WriteLine(exception.ToString());
}
ShowOutput(output);
decompiledNodes = context.TreeNodes;
});
}

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -200,7 +200,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -200,7 +200,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
void LoadChildrenForPEFile(PEFile module)
{
typeSystem = LoadedAssembly.GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(new DecompilationOptions().DecompilerSettings));
typeSystem = LoadedAssembly.GetTypeSystemOrNull();
var assembly = (MetadataModule)typeSystem.MainModule;
this.Children.Add(new Metadata.MetadataTreeNode(module, this));
Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull();

14
ILSpy/TreeNodes/EventTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
@ -45,14 +46,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -45,14 +46,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
public IEvent EventDefinition { get; }
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.MetadataToken.ToSuffixString();
public override object Text => GetText(GetEventDefinition(), this.Language) + EventDefinition.MetadataToken.ToSuffixString();
private IEvent GetEventDefinition()
{
return ((MetadataModule)EventDefinition.ParentModule.PEFile
?.GetTypeSystemWithCurrentOptionsOrNull()
?.MainModule)?.GetDefinition((EventDefinitionHandle)EventDefinition.MetadataToken) ?? EventDefinition;
}
public static object GetText(IEvent ev, Language language)
{
return language.EventToString(ev, false, false, false);
}
public override object Icon => GetIcon(EventDefinition);
public override object Icon => GetIcon(GetEventDefinition());
public static ImageSource GetIcon(IEvent @event)
{
@ -76,7 +84,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -76,7 +84,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (EventDefinition.Accessibility)
switch (GetEventDefinition().Accessibility)
{
case Accessibility.Public:
case Accessibility.ProtectedOrInternal:

14
ILSpy/TreeNodes/FieldTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
@ -37,14 +38,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -37,14 +38,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.FieldDefinition = field ?? throw new ArgumentNullException(nameof(field));
}
public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.MetadataToken.ToSuffixString();
public override object Text => GetText(GetFieldDefinition(), Language) + FieldDefinition.MetadataToken.ToSuffixString();
private IField GetFieldDefinition()
{
return ((MetadataModule)FieldDefinition.ParentModule.PEFile
?.GetTypeSystemWithCurrentOptionsOrNull()
?.MainModule)?.GetDefinition((FieldDefinitionHandle)FieldDefinition.MetadataToken) ?? FieldDefinition;
}
public static object GetText(IField field, Language language)
{
return language.FieldToString(field, includeDeclaringTypeName: false, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false);
}
public override object Icon => GetIcon(FieldDefinition);
public override object Icon => GetIcon(GetFieldDefinition());
public static ImageSource GetIcon(IField field)
{
@ -77,7 +85,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -77,7 +85,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (FieldDefinition.Accessibility)
switch (GetFieldDefinition().Accessibility)
{
case Accessibility.Public:
case Accessibility.Protected:

14
ILSpy/TreeNodes/MethodTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
@ -37,14 +38,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -37,14 +38,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.MethodDefinition = method ?? throw new ArgumentNullException(nameof(method));
}
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.MetadataToken.ToSuffixString();
public override object Text => GetText(GetMethodDefinition(), Language) + MethodDefinition.MetadataToken.ToSuffixString();
private IMethod GetMethodDefinition()
{
return ((MetadataModule)MethodDefinition.ParentModule.PEFile
?.GetTypeSystemWithCurrentOptionsOrNull()
?.MainModule)?.GetDefinition((MethodDefinitionHandle)MethodDefinition.MetadataToken) ?? MethodDefinition;
}
public static object GetText(IMethod method, Language language)
{
return language.MethodToString(method, false, false, false);
}
public override object Icon => GetIcon(MethodDefinition);
public override object Icon => GetIcon(GetMethodDefinition());
public static ImageSource GetIcon(IMethod method)
{
@ -102,7 +110,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -102,7 +110,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (MethodDefinition.Accessibility)
switch (GetMethodDefinition().Accessibility)
{
case Accessibility.Public:
case Accessibility.Protected:

17
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -17,14 +17,10 @@ @@ -17,14 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Reflection;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -52,14 +48,21 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -52,14 +48,21 @@ namespace ICSharpCode.ILSpy.TreeNodes
public IProperty PropertyDefinition { get; }
public override object Text => GetText(PropertyDefinition, Language) + PropertyDefinition.MetadataToken.ToSuffixString();
public override object Text => GetText(GetPropertyDefinition(), Language) + PropertyDefinition.MetadataToken.ToSuffixString();
private IProperty GetPropertyDefinition()
{
return ((MetadataModule)PropertyDefinition.ParentModule.PEFile
?.GetTypeSystemWithCurrentOptionsOrNull()
?.MainModule)?.GetDefinition((PropertyDefinitionHandle)PropertyDefinition.MetadataToken) ?? PropertyDefinition;
}
public static object GetText(IProperty property, Language language)
{
return language.PropertyToString(property, false, false, false);
}
public override object Icon => GetIcon(PropertyDefinition);
public override object Icon => GetIcon(GetPropertyDefinition());
public static ImageSource GetIcon(IProperty property)
{
@ -84,7 +87,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -84,7 +87,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (PropertyDefinition.Accessibility)
switch (GetPropertyDefinition().Accessibility)
{
case Accessibility.Public:
case Accessibility.ProtectedOrInternal:

14
ILSpy/TreeNodes/TypeTreeNode.cs

@ -41,12 +41,20 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -41,12 +41,20 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyTreeNode ParentAssemblyNode { get; }
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false)
public override object Text => this.Language.TypeToString(GetTypeDefinition(), includeNamespace: false)
+ TypeDefinition.MetadataToken.ToSuffixString();
private ITypeDefinition GetTypeDefinition()
{
return ((MetadataModule)ParentAssemblyNode.LoadedAssembly
.GetPEFileOrNull()
?.GetTypeSystemWithCurrentOptionsOrNull()
?.MainModule).GetDefinition((SRM.TypeDefinitionHandle)TypeDefinition.MetadataToken);
}
public override bool IsPublicAPI {
get {
switch (TypeDefinition.Accessibility)
switch (GetTypeDefinition().Accessibility)
{
case Accessibility.Public:
case Accessibility.Protected:
@ -120,7 +128,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -120,7 +128,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.DecompileType(TypeDefinition, output, options);
language.DecompileType(GetTypeDefinition(), output, options);
}
public override object Icon => GetIcon(TypeDefinition);

10
ILSpy/ViewModels/ManageAssemblyListsViewModel.cs

@ -191,9 +191,9 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -191,9 +191,9 @@ namespace ICSharpCode.ILSpy.ViewModels
if (manager.AssemblyLists.Count > 0)
{
SelectedAssemblyList = manager.AssemblyLists[Math.Max(0, index - 1)];
if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList)
if (MainWindow.Instance.SessionSettings.ActiveAssemblyList == assemblyList)
{
MainWindow.Instance.sessionSettings.ActiveAssemblyList = SelectedAssemblyList;
MainWindow.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList;
}
}
}
@ -234,9 +234,9 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -234,9 +234,9 @@ namespace ICSharpCode.ILSpy.ViewModels
string assemblyList = SelectedAssemblyList;
SelectedAssemblyList = dlg.ListName;
manager.RenameList(assemblyList, dlg.ListName);
if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList)
if (MainWindow.Instance.SessionSettings.ActiveAssemblyList == assemblyList)
{
MainWindow.Instance.sessionSettings.ActiveAssemblyList = manager.AssemblyLists[manager.AssemblyLists.Count - 1];
MainWindow.Instance.SessionSettings.ActiveAssemblyList = manager.AssemblyLists[manager.AssemblyLists.Count - 1];
}
}
}
@ -372,7 +372,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -372,7 +372,7 @@ namespace ICSharpCode.ILSpy.ViewModels
private void ExecuteSelectAssemblyList()
{
MainWindow.Instance.sessionSettings.ActiveAssemblyList = SelectedAssemblyList;
MainWindow.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList;
this.parent.Close();
}
}

59
ILSpy/ViewModels/TabPageModel.cs

@ -27,61 +27,36 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -27,61 +27,36 @@ namespace ICSharpCode.ILSpy.ViewModels
{
public class TabPageModel : PaneModel
{
private readonly Dictionary<Language, LanguageVersion> languageVersionHistory = new Dictionary<Language, LanguageVersion>();
public TabPageModel()
{
this.Title = Properties.Resources.NewTab;
}
private Language language;
public Language Language {
get => language;
private FilterSettings filterSettings;
public FilterSettings FilterSettings {
get => filterSettings;
set {
if (language != value)
if (filterSettings != value)
{
if (language != null && language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
language = value;
RaisePropertyChanged(nameof(Language));
if (language.HasLanguageVersions)
{
if (languageVersionHistory.TryGetValue(value, out var version))
{
LanguageVersion = version;
}
else
{
LanguageVersion = Language.LanguageVersions.Last();
}
}
else
{
LanguageVersion = default;
}
filterSettings = value;
RaisePropertyChanged(nameof(FilterSettings));
}
}
}
private LanguageVersion languageVersion;
public Language Language {
get => filterSettings.Language;
set => filterSettings.Language = value;
}
public LanguageVersion LanguageVersion {
get => languageVersion;
set {
if (languageVersion != value)
{
languageVersion = value;
if (language.HasLanguageVersions)
{
languageVersionHistory[language] = languageVersion;
}
RaisePropertyChanged(nameof(LanguageVersion));
}
}
get => filterSettings.LanguageVersion;
set => filterSettings.LanguageVersion = value;
}
private bool supportsLanguageSwitching = true;
public bool SupportsLanguageSwitching {
get => supportsLanguageSwitching;
set {
@ -94,6 +69,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -94,6 +69,7 @@ namespace ICSharpCode.ILSpy.ViewModels
}
private object content;
public object Content {
get => content;
set {
@ -120,6 +96,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -120,6 +96,7 @@ namespace ICSharpCode.ILSpy.ViewModels
textView = new DecompilerTextView();
tabPage.Content = textView;
}
tabPage.Title = Properties.Resources.Decompiling;
return action(textView);
}
@ -130,6 +107,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -130,6 +107,7 @@ namespace ICSharpCode.ILSpy.ViewModels
textView = new DecompilerTextView();
tabPage.Content = textView;
}
tabPage.Title = Properties.Resources.Decompiling;
return action(textView);
}
@ -140,6 +118,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -140,6 +118,7 @@ namespace ICSharpCode.ILSpy.ViewModels
textView = new DecompilerTextView();
tabPage.Content = textView;
}
tabPage.Title = Properties.Resources.Decompiling;
action(textView);
}
}

18
ILSpy/Views/DebugSteps.xaml.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@ -22,13 +23,16 @@ namespace ICSharpCode.ILSpy @@ -22,13 +23,16 @@ namespace ICSharpCode.ILSpy
#if DEBUG
ILAstLanguage language;
#endif
FilterSettings filterSettings;
public DebugSteps()
{
InitializeComponent();
#if DEBUG
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
DockWorkspace.Instance.PropertyChanged += DockWorkspace_PropertyChanged;
this.filterSettings = MainWindow.Instance.SessionSettings.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged += SelectionChanged;
writingOptions.PropertyChanged += WritingOptions_PropertyChanged;
@ -41,6 +45,18 @@ namespace ICSharpCode.ILSpy @@ -41,6 +45,18 @@ namespace ICSharpCode.ILSpy
#endif
}
private void DockWorkspace_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DockWorkspace.Instance.ActiveTabPage):
filterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings;
filterSettings.PropertyChanged += FilterSettings_PropertyChanged;
break;
}
}
private void WritingOptions_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
DecompileAsync(lastSelectedStep);

Loading…
Cancel
Save