Browse Source

Fix #1932: Add ExportToolPaneAttribute and reimplement ShowInBottomPane and ShowInTopPane.

pull/1939/head
Siegfried Pammer 5 years ago
parent
commit
ecda21f7f9
  1. 9
      ILSpy/Analyzers/AnalyzerTreeView.cs
  2. 2
      ILSpy/Commands/DecompileInNewViewCommand.cs
  3. 20
      ILSpy/Commands/ExportCommandAttribute.cs
  4. 2
      ILSpy/Commands/ShowDebugSteps.cs
  5. 6
      ILSpy/Commands/SortAssemblyListCommand.cs
  6. 93
      ILSpy/Docking/DockWorkspace.cs
  7. 2
      ILSpy/ILSpy.csproj
  8. 26
      ILSpy/IPane.cs
  9. 2
      ILSpy/Languages/ILAstLanguage.cs
  10. 17
      ILSpy/MainWindow.xaml
  11. 110
      ILSpy/MainWindow.xaml.cs
  12. 10
      ILSpy/Search/SearchPane.cs
  13. 7
      ILSpy/ViewModels/AnalyzerPaneModel.cs
  14. 6
      ILSpy/ViewModels/AssemblyListPaneModel.cs
  15. 7
      ILSpy/ViewModels/DebugStepsPaneModel.cs
  16. 32
      ILSpy/ViewModels/LegacyToolPaneModel.cs
  17. 7
      ILSpy/ViewModels/SearchPaneModel.cs
  18. 4
      ILSpy/ViewModels/ToolPaneModel.cs
  19. 14
      ILSpy/Views/DebugSteps.xaml.cs

9
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy.Analyzers
/// <summary> /// <summary>
/// Analyzer tree view. /// Analyzer tree view.
/// </summary> /// </summary>
public class AnalyzerTreeView : SharpTreeView, IPane public class AnalyzerTreeView : SharpTreeView
{ {
public AnalyzerTreeView() public AnalyzerTreeView()
{ {
@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Analyzers
public void Show() public void Show()
{ {
AnalyzerPaneModel.Instance.Show(); DockWorkspace.Instance.ShowToolPane(AnalyzerPaneModel.PaneContentId);
} }
public void Show(AnalyzerTreeNode node) public void Show(AnalyzerTreeNode node)
@ -123,11 +123,6 @@ namespace ICSharpCode.ILSpy.Analyzers
} }
} }
void IPane.Closed()
{
this.Root.Children.Clear();
}
sealed class AnalyzerRootNode : AnalyzerTreeNode sealed class AnalyzerRootNode : AnalyzerTreeNode
{ {
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies) public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)

2
ILSpy/Commands/DecompileInNewViewCommand.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy.Commands
IEnumerable<ILSpyTreeNode> GetNodes(TextViewContext context) IEnumerable<ILSpyTreeNode> GetNodes(TextViewContext context)
{ {
if (context.SelectedTreeNodes != null) { if (context.SelectedTreeNodes != null) {
if (context.TreeView != MainWindow.Instance.treeView) { if (context.TreeView != MainWindow.Instance.AssemblyTreeView) {
return context.SelectedTreeNodes.OfType<IMemberTreeNode>().Select(FindTreeNode).Where(n => n != null); return context.SelectedTreeNodes.OfType<IMemberTreeNode>().Select(FindTreeNode).Where(n => n != null);
} else { } else {
return context.SelectedTreeNodes.OfType<ILSpyTreeNode>().Where(n => n != null); return context.SelectedTreeNodes.OfType<ILSpyTreeNode>().Where(n => n != null);

20
ILSpy/Commands/ExportCommandAttribute.cs

@ -30,7 +30,6 @@ namespace ICSharpCode.ILSpy
string ToolbarCategory { get; } string ToolbarCategory { get; }
object Tag { get; } object Tag { get; }
double ToolbarOrder { get; } double ToolbarOrder { get; }
} }
[MetadataAttribute] [MetadataAttribute]
@ -85,4 +84,23 @@ namespace ICSharpCode.ILSpy
public double MenuOrder { get; set; } public double MenuOrder { get; set; }
} }
#endregion #endregion
#region Tool Panes
public interface IToolPaneMetadata
{
string ContentId { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportToolPaneAttribute : ExportAttribute, IToolPaneMetadata
{
public ExportToolPaneAttribute()
: base("ToolPane", typeof(ViewModels.ToolPaneModel))
{
}
public string ContentId { get; set; }
}
#endregion
} }

2
ILSpy/Commands/ShowDebugSteps.cs

@ -11,7 +11,7 @@ namespace ICSharpCode.ILSpy.Commands
{ {
public override void Execute(object parameter) public override void Execute(object parameter)
{ {
DebugStepsPaneModel.Instance.Show(); DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
} }
} }
} }

6
ILSpy/Commands/SortAssemblyListCommand.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy
{ {
public override void Execute(object parameter) public override void Execute(object parameter)
{ {
using (MainWindow.Instance.treeView.LockUpdates()) using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
MainWindow.Instance.CurrentAssemblyList.Sort(this); MainWindow.Instance.CurrentAssemblyList.Sort(this);
} }
@ -45,8 +45,8 @@ namespace ICSharpCode.ILSpy
{ {
public override void Execute(object parameter) public override void Execute(object parameter)
{ {
using (MainWindow.Instance.treeView.LockUpdates()) using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
CollapseChildren(MainWindow.Instance.treeView.Root); CollapseChildren(MainWindow.Instance.AssemblyTreeView.Root);
void CollapseChildren(SharpTreeNode node) void CollapseChildren(SharpTreeNode node)
{ {

93
ILSpy/Docking/DockWorkspace.cs

@ -22,6 +22,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -34,7 +35,7 @@ using Xceed.Wpf.AvalonDock.Layout.Serialization;
namespace ICSharpCode.ILSpy.Docking namespace ICSharpCode.ILSpy.Docking
{ {
public class DockWorkspace : INotifyPropertyChanged public class DockWorkspace : INotifyPropertyChanged, ILayoutUpdateStrategy
{ {
private SessionSettings sessionSettings; private SessionSettings sessionSettings;
@ -58,21 +59,16 @@ namespace ICSharpCode.ILSpy.Docking
public PaneCollection<TabPageModel> TabPages { get; } = new PaneCollection<TabPageModel>(); public PaneCollection<TabPageModel> TabPages { get; } = new PaneCollection<TabPageModel>();
private ToolPaneModel[] toolPanes; public ObservableCollection<ToolPaneModel> ToolPanes { get; } = new ObservableCollection<ToolPaneModel>();
public IEnumerable<ToolPaneModel> ToolPanes {
get { public bool ShowToolPane(string contentId)
if (toolPanes == null) { {
toolPanes = new ToolPaneModel[] { var pane = ToolPanes.FirstOrDefault(p => p.ContentId == contentId);
AssemblyListPaneModel.Instance, if (pane != null) {
SearchPaneModel.Instance, pane.Show();
AnalyzerPaneModel.Instance, return true;
#if DEBUG
DebugStepsPaneModel.Instance,
#endif
};
}
return toolPanes;
} }
return false;
} }
public void Remove(PaneModel model) public void Remove(PaneModel model)
@ -103,6 +99,7 @@ namespace ICSharpCode.ILSpy.Docking
public void InitializeLayout(Xceed.Wpf.AvalonDock.DockingManager manager) public void InitializeLayout(Xceed.Wpf.AvalonDock.DockingManager manager)
{ {
manager.LayoutUpdateStrategy = this;
XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager); XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager);
serializer.LayoutSerializationCallback += LayoutSerializationCallback; serializer.LayoutSerializationCallback += LayoutSerializationCallback;
try { try {
@ -116,25 +113,8 @@ namespace ICSharpCode.ILSpy.Docking
{ {
switch (e.Model) { switch (e.Model) {
case LayoutAnchorable la: case LayoutAnchorable la:
switch (la.ContentId) { e.Content = ToolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
case AssemblyListPaneModel.PaneContentId: e.Cancel = e.Content == null;
e.Content = AssemblyListPaneModel.Instance;
break;
case SearchPaneModel.PaneContentId:
e.Content = SearchPaneModel.Instance;
break;
case AnalyzerPaneModel.PaneContentId:
e.Content = AnalyzerPaneModel.Instance;
break;
#if DEBUG
case DebugStepsPaneModel.PaneContentId:
e.Content = DebugStepsPaneModel.Instance;
break;
#endif
default:
e.Cancel = true;
break;
}
la.CanDockAsTabbedDocument = false; la.CanDockAsTabbedDocument = false;
if (!e.Cancel) { if (!e.Cancel) {
e.Cancel = ((ToolPaneModel)e.Content).IsVisible; e.Cancel = ((ToolPaneModel)e.Content).IsVisible;
@ -203,5 +183,50 @@ namespace ICSharpCode.ILSpy.Docking
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);
} }
static readonly PropertyInfo previousContainerProperty = typeof(LayoutContent).GetProperty("PreviousContainer", BindingFlags.NonPublic | BindingFlags.Instance);
public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer)
{
if (!(anchorableToShow.Content is LegacyToolPaneModel legacyContent))
return false;
anchorableToShow.CanDockAsTabbedDocument = false;
LayoutAnchorablePane previousContainer;
switch (legacyContent.Location) {
case LegacyToolPaneLocation.Top:
previousContainer = GetContainer<SearchPaneModel>();
previousContainer.Children.Add(anchorableToShow);
return true;
case LegacyToolPaneLocation.Bottom:
previousContainer = GetContainer<AnalyzerPaneModel>();
previousContainer.Children.Add(anchorableToShow);
return true;
default:
return false;
}
LayoutAnchorablePane GetContainer<T>()
{
var anchorable = layout.Descendents().OfType<LayoutAnchorable>().FirstOrDefault(x => x.Content is T)
?? layout.Hidden.First(x => x.Content is T);
return (LayoutAnchorablePane)previousContainerProperty.GetValue(anchorable) ?? (LayoutAnchorablePane)anchorable.Parent;
}
}
public void AfterInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableShown)
{
anchorableShown.IsActive = true;
anchorableShown.IsSelected = true;
}
public bool BeforeInsertDocument(LayoutRoot layout, LayoutDocument anchorableToShow, ILayoutContainer destinationContainer)
{
return false;
}
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{
}
} }
} }

2
ILSpy/ILSpy.csproj

@ -208,6 +208,7 @@
<Compile Include="Metadata\MetadataProtocolHandler.cs" /> <Compile Include="Metadata\MetadataProtocolHandler.cs" />
<Compile Include="Metadata\MetadataTableTreeNode.cs" /> <Compile Include="Metadata\MetadataTableTreeNode.cs" />
<Compile Include="Metadata\DebugMetadataTreeNode.cs" /> <Compile Include="Metadata\DebugMetadataTreeNode.cs" />
<Compile Include="ViewModels\LegacyToolPaneModel.cs" />
<Compile Include="ViewModels\ManageAssemblyListsViewModel.cs" /> <Compile Include="ViewModels\ManageAssemblyListsViewModel.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" /> <Compile Include="ViewModels\ViewModelBase.cs" />
<Compile Include="Views\CreateListDialog.xaml.cs"> <Compile Include="Views\CreateListDialog.xaml.cs">
@ -248,7 +249,6 @@
<Compile Include="Images\AccessOverlayIcon.cs" /> <Compile Include="Images\AccessOverlayIcon.cs" />
<Compile Include="Images\MemberIcon.cs" /> <Compile Include="Images\MemberIcon.cs" />
<Compile Include="Images\TypeIcon.cs" /> <Compile Include="Images\TypeIcon.cs" />
<Compile Include="IPane.cs" />
<Compile Include="ISmartTextOutput.cs" /> <Compile Include="ISmartTextOutput.cs" />
<Compile Include="Images\Images.cs" /> <Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILAstLanguage.cs" /> <Compile Include="Languages\ILAstLanguage.cs" />

26
ILSpy/IPane.cs

@ -1,26 +0,0 @@
// Copyright (c) 2011 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.
namespace ICSharpCode.ILSpy
{
public interface IPane
{
void Closed();
}
}

2
ILSpy/Languages/ILAstLanguage.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.ILSpy
} }
} }
(output as ISmartTextOutput)?.AddButton(Images.ViewCode, "Show Steps", delegate { (output as ISmartTextOutput)?.AddButton(Images.ViewCode, "Show Steps", delegate {
DebugStepsPaneModel.Instance.Show(); Docking.DockWorkspace.Instance.ShowToolPane(DebugStepsPaneModel.PaneContentId);
}); });
output.WriteLine(); output.WriteLine();
il.WriteTo(output, DebugSteps.Options); il.WriteTo(output, DebugSteps.Options);

17
ILSpy/MainWindow.xaml

@ -16,7 +16,6 @@
MinHeight="200" MinHeight="200"
UseLayoutRounding="True" UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display" TextOptions.TextFormattingMode="Display"
FocusManager.FocusedElement="{Binding ElementName=treeView}"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
> >
@ -24,7 +23,7 @@
<controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<docking:ActiveTabPageConverter x:Key="ActiveTabPageConverter"/> <docking:ActiveTabPageConverter x:Key="ActiveTabPageConverter"/>
<tv:SharpTreeView x:Key="TreeView" <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"
@ -33,7 +32,7 @@
BorderThickness="0,1,1,1" Visibility="Visible" /> BorderThickness="0,1,1,1" Visibility="Visible" />
<DataTemplate x:Key="AssemblyListPaneTemplate"> <DataTemplate x:Key="AssemblyListPaneTemplate">
<ContentControl Content="{StaticResource TreeView}" /> <ContentControl Content="{StaticResource AssemblyTreeView}" />
</DataTemplate> </DataTemplate>
<local:DebugSteps x:Key="DebugSteps" /> <local:DebugSteps x:Key="DebugSteps" />
@ -185,18 +184,6 @@
</DataTemplate> </DataTemplate>
</avalondock:DockingManager.DocumentHeaderTemplate> </avalondock:DockingManager.DocumentHeaderTemplate>
<avalondock:DockingManager.LayoutItemTemplateSelector>
<docking:PaneTemplateSelector>
<docking:PaneTemplateSelector.Mappings>
<docking:TemplateMapping Type="{x:Type viewmodels:AssemblyListPaneModel}" Template="{StaticResource AssemblyListPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:SearchPaneModel}" Template="{StaticResource SearchPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:DebugStepsPaneModel}" Template="{StaticResource DebugStepsPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:AnalyzerPaneModel}" Template="{StaticResource AnalyzerPaneTemplate}" />
<docking:TemplateMapping Type="{x:Type viewmodels:TabPageModel}" Template="{StaticResource DefaultContentTemplate}" />
</docking:PaneTemplateSelector.Mappings>
</docking:PaneTemplateSelector>
</avalondock:DockingManager.LayoutItemTemplateSelector>
<avalondock:DockingManager.LayoutItemContainerStyleSelector> <avalondock:DockingManager.LayoutItemContainerStyleSelector>
<docking:PaneStyleSelector> <docking:PaneStyleSelector>
<docking:PaneStyleSelector.ToolPaneStyle> <docking:PaneStyleSelector.ToolPaneStyle>

110
ILSpy/MainWindow.xaml.cs

@ -84,9 +84,9 @@ namespace ICSharpCode.ILSpy
internal AssemblyListManager AssemblyListManager { get; } internal AssemblyListManager AssemblyListManager { get; }
public SharpTreeView treeView { public SharpTreeView AssemblyTreeView {
get { get {
return FindResource("TreeView") as SharpTreeView; return FindResource("AssemblyTreeView") as SharpTreeView;
} }
} }
@ -120,13 +120,13 @@ namespace ICSharpCode.ILSpy
DockWorkspace.Instance.LoadSettings(sessionSettings); DockWorkspace.Instance.LoadSettings(sessionSettings);
InitializeComponent(); InitializeComponent();
InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager); DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged; sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
sessionSettings.PropertyChanged += SessionSettings_PropertyChanged; sessionSettings.PropertyChanged += SessionSettings_PropertyChanged;
InitMainMenu(); InitMainMenu();
InitToolbar(); InitToolbar();
ContextMenuProvider.Add(treeView); ContextMenuProvider.Add(AssemblyTreeView);
this.Loaded += MainWindow_Loaded; this.Loaded += MainWindow_Loaded;
} }
@ -231,6 +231,48 @@ namespace ICSharpCode.ILSpy
} }
#endregion #endregion
#region Tool Pane extensibility
private void InitToolPanes()
{
var toolPanes = App.ExportProvider.GetExports<ToolPaneModel, IToolPaneMetadata>("ToolPane");
var templateSelector = new PaneTemplateSelector();
templateSelector.Mappings.Add(new TemplateMapping {
Type = typeof(TabPageModel),
Template = (DataTemplate)FindResource("DefaultContentTemplate")
});
templateSelector.Mappings.Add(new TemplateMapping {
Type = typeof(LegacyToolPaneModel),
Template = (DataTemplate)FindResource("DefaultContentTemplate")
});
foreach (var toolPane in toolPanes) {
ToolPaneModel model = toolPane.Value;
templateSelector.Mappings.Add(new TemplateMapping { Type = model.GetType(), Template = model.Template });
DockWorkspace.Instance.ToolPanes.Add(model);
}
DockManager.LayoutItemTemplateSelector = templateSelector;
}
public void ShowInTopPane(string title, object content)
{
var model = DockWorkspace.Instance.ToolPanes.OfType<LegacyToolPaneModel>().FirstOrDefault(p => p.Content == content);
if (model == null) {
model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Top);
DockWorkspace.Instance.ToolPanes.Add(model);
}
model.Show();
}
public void ShowInBottomPane(string title, object content)
{
var model = DockWorkspace.Instance.ToolPanes.OfType<LegacyToolPaneModel>().FirstOrDefault(p => p.Content == content);
if (model == null) {
model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Bottom);
DockWorkspace.Instance.ToolPanes.Add(model);
}
model.Show();
}
#endregion
#region Message Hook #region Message Hook
protected override void OnSourceInitialized(EventArgs e) protected override void OnSourceInitialized(EventArgs e)
{ {
@ -337,7 +379,7 @@ namespace ICSharpCode.ILSpy
async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSpySettings spySettings, List<LoadedAssembly> relevantAssemblies) async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSpySettings spySettings, List<LoadedAssembly> relevantAssemblies)
{ {
var initialSelection = treeView.SelectedItem; var initialSelection = AssemblyTreeView.SelectedItem;
if (navigateTo != null) { if (navigateTo != null) {
bool found = false; bool found = false;
if (navigateTo.StartsWith("N:", StringComparison.Ordinal)) { if (navigateTo.StartsWith("N:", StringComparison.Ordinal)) {
@ -351,7 +393,7 @@ namespace ICSharpCode.ILSpy
NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName); NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
if (nsNode != null) { if (nsNode != null) {
found = true; found = true;
if (treeView.SelectedItem == initialSelection) { if (AssemblyTreeView.SelectedItem == initialSelection) {
SelectNode(nsNode); SelectNode(nsNode);
} }
break; break;
@ -366,12 +408,12 @@ namespace ICSharpCode.ILSpy
IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies)); IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
if (mr != null && mr.ParentModule.PEFile != null) { if (mr != null && mr.ParentModule.PEFile != null) {
found = true; found = true;
if (treeView.SelectedItem == initialSelection) { if (AssemblyTreeView.SelectedItem == initialSelection) {
JumpToReference(mr); JumpToReference(mr);
} }
} }
} }
if (!found && treeView.SelectedItem == initialSelection) { if (!found && AssemblyTreeView.SelectedItem == initialSelection) {
AvalonEditTextOutput output = new AvalonEditTextOutput(); AvalonEditTextOutput output = new AvalonEditTextOutput();
output.Write(string.Format("Cannot find '{0}' in command line specified assemblies.", navigateTo)); output.Write(string.Format("Cannot find '{0}' in command line specified assemblies.", navigateTo));
DockWorkspace.Instance.ShowText(output); DockWorkspace.Instance.ShowText(output);
@ -380,7 +422,7 @@ namespace ICSharpCode.ILSpy
// NavigateTo == null and an assembly was given on the command-line: // NavigateTo == null and an assembly was given on the command-line:
// Select the newly loaded assembly // Select the newly loaded assembly
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]); AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]);
if (asmNode != null && treeView.SelectedItem == initialSelection) { if (asmNode != null && AssemblyTreeView.SelectedItem == initialSelection) {
SelectNode(asmNode); SelectNode(asmNode);
} }
} else if (spySettings != null) { } else if (spySettings != null) {
@ -395,7 +437,7 @@ namespace ICSharpCode.ILSpy
} }
node = FindNodeByPath(activeTreeViewPath, true); node = FindNodeByPath(activeTreeViewPath, true);
} }
if (treeView.SelectedItem == initialSelection) { if (AssemblyTreeView.SelectedItem == initialSelection) {
if (node != null) { if (node != null) {
SelectNode(node); SelectNode(node);
@ -611,7 +653,7 @@ namespace ICSharpCode.ILSpy
assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone(); assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone();
assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false); assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false);
treeView.Root = assemblyListTreeNode; AssemblyTreeView.Root = assemblyListTreeNode;
if (assemblyList.ListName == AssemblyListManager.DefaultListName) if (assemblyList.ListName == AssemblyListManager.DefaultListName)
#if DEBUG #if DEBUG
@ -695,12 +737,12 @@ namespace ICSharpCode.ILSpy
LanguageVersion = CurrentLanguageVersion LanguageVersion = CurrentLanguageVersion
}); });
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
treeView.SelectedItem = null; AssemblyTreeView.SelectedItem = null;
} }
// Set both the selection and focus to ensure that keyboard navigation works as expected. // Set both the selection and focus to ensure that keyboard navigation works as expected.
treeView.FocusNode(obj); AssemblyTreeView.FocusNode(obj);
treeView.SelectedItem = obj; AssemblyTreeView.SelectedItem = obj;
} else { } else {
MessageBox.Show("Navigation failed because the target is hidden or a compiler-generated class.\n" + MessageBox.Show("Navigation failed because the target is hidden or a compiler-generated class.\n" +
"Please disable all filters that might hide the item (i.e. activate " + "Please disable all filters that might hide the item (i.e. activate " +
@ -722,8 +764,8 @@ namespace ICSharpCode.ILSpy
DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last();
} }
treeView.FocusNode(nodes.First()); AssemblyTreeView.FocusNode(nodes.First());
treeView.SetSelectedNodes(nodes); AssemblyTreeView.SetSelectedNodes(nodes);
} }
} }
@ -734,7 +776,7 @@ namespace ICSharpCode.ILSpy
{ {
if (path == null) if (path == null)
return null; return null;
SharpTreeNode node = treeView.Root; SharpTreeNode node = AssemblyTreeView.Root;
SharpTreeNode bestMatch = node; SharpTreeNode bestMatch = node;
foreach (var element in path) { foreach (var element in path) {
if (node == null) if (node == null)
@ -887,7 +929,7 @@ namespace ICSharpCode.ILSpy
throw new ArgumentNullException(nameof(fileNames)); throw new ArgumentNullException(nameof(fileNames));
if (focusNode) if (focusNode)
treeView.UnselectAll(); AssemblyTreeView.UnselectAll();
LoadAssemblies(fileNames, focusNode: focusNode); LoadAssemblies(fileNames, focusNode: focusNode);
} }
@ -913,7 +955,7 @@ namespace ICSharpCode.ILSpy
else { else {
var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm); var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm);
if (node != null && focusNode) { if (node != null && focusNode) {
treeView.SelectedItems.Add(node); AssemblyTreeView.SelectedItems.Add(node);
lastNode = node; lastNode = node;
} }
} }
@ -931,7 +973,7 @@ namespace ICSharpCode.ILSpy
else { else {
var node = assemblyListTreeNode.FindAssemblyNode(asm); var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null && focusNode) { if (node != null && focusNode) {
treeView.SelectedItems.Add(node); AssemblyTreeView.SelectedItems.Add(node);
lastNode = node; lastNode = node;
} }
} }
@ -940,7 +982,7 @@ namespace ICSharpCode.ILSpy
} }
if (lastNode != null && focusNode) if (lastNode != null && focusNode)
treeView.FocusNode(lastNode); AssemblyTreeView.FocusNode(lastNode);
} }
} }
@ -953,7 +995,7 @@ namespace ICSharpCode.ILSpy
{ {
try { try {
refreshInProgress = true; refreshInProgress = true;
var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode); var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
ShowAssemblyList(AssemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); ShowAssemblyList(AssemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true)); SelectNode(FindNodeByPath(path, true));
} finally { } finally {
@ -963,7 +1005,7 @@ namespace ICSharpCode.ILSpy
void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e) void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{ {
SearchPaneModel.Instance.Show(); DockWorkspace.Instance.ShowToolPane(SearchPaneModel.PaneContentId);
} }
#endregion #endregion
@ -983,20 +1025,20 @@ namespace ICSharpCode.ILSpy
if (ignoreDecompilationRequests) if (ignoreDecompilationRequests)
return; return;
if (treeView.SelectedItems.Count == 0 && refreshInProgress) if (AssemblyTreeView.SelectedItems.Count == 0 && refreshInProgress)
return; return;
if (recordHistory) { if (recordHistory) {
var currentState = DockWorkspace.Instance.ActiveTabPage.GetState(); var currentState = DockWorkspace.Instance.ActiveTabPage.GetState();
if (currentState != null) if (currentState != null)
history.UpdateCurrent(new NavigationState(currentState)); history.UpdateCurrent(new NavigationState(currentState));
history.Record(new NavigationState(treeView.SelectedItems.OfType<SharpTreeNode>())); history.Record(new NavigationState(AssemblyTreeView.SelectedItems.OfType<SharpTreeNode>()));
} }
DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true; DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true;
if (treeView.SelectedItems.Count == 1) { if (AssemblyTreeView.SelectedItems.Count == 1) {
ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode; ILSpyTreeNode node = AssemblyTreeView.SelectedItem as ILSpyTreeNode;
if (node != null && node.View(DockWorkspace.Instance.ActiveTabPage)) if (node != null && node.View(DockWorkspace.Instance.ActiveTabPage))
return; return;
} }
@ -1035,7 +1077,7 @@ namespace ICSharpCode.ILSpy
public IEnumerable<ILSpyTreeNode> SelectedNodes { public IEnumerable<ILSpyTreeNode> SelectedNodes {
get { get {
return treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>(); return AssemblyTreeView.GetTopLevelSelection().OfType<ILSpyTreeNode>();
} }
} }
#endregion #endregion
@ -1077,12 +1119,12 @@ namespace ICSharpCode.ILSpy
var newState = forward ? history.GoForward() : history.GoBack(); var newState = forward ? history.GoForward() : history.GoBack();
ignoreDecompilationRequests = true; ignoreDecompilationRequests = true;
treeView.SelectedItems.Clear(); AssemblyTreeView.SelectedItems.Clear();
foreach (var node in newState.TreeNodes) { foreach (var node in newState.TreeNodes) {
treeView.SelectedItems.Add(node); AssemblyTreeView.SelectedItems.Add(node);
} }
if (newState.TreeNodes.Any()) if (newState.TreeNodes.Any())
treeView.FocusNode(newState.TreeNodes.First()); AssemblyTreeView.FocusNode(newState.TreeNodes.First());
ignoreDecompilationRequests = false; ignoreDecompilationRequests = false;
DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false); DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false);
} }
@ -1142,8 +1184,8 @@ namespace ICSharpCode.ILSpy
{ {
base.OnClosing(e); base.OnClosing(e);
sessionSettings.ActiveAssemblyList = assemblyList.ListName; sessionSettings.ActiveAssemblyList = assemblyList.ListName;
sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(treeView.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();
@ -1167,7 +1209,7 @@ namespace ICSharpCode.ILSpy
public void UnselectAll() public void UnselectAll()
{ {
treeView.UnselectAll(); AssemblyTreeView.UnselectAll();
} }
public void SetStatus(string status, Brush foreground) public void SetStatus(string status, Brush foreground)

10
ILSpy/Search/SearchPane.cs

@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@ -40,7 +41,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Search pane /// Search pane
/// </summary> /// </summary>
public partial class SearchPane : UserControl, IPane 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, less means better responsibility
@ -105,7 +106,7 @@ namespace ICSharpCode.ILSpy
public void Show() public void Show()
{ {
if (!IsVisible) { if (!IsVisible) {
SearchPaneModel.Instance.IsVisible = true; DockWorkspace.Instance.ToolPanes.Single(p => p.ContentId == SearchPaneModel.PaneContentId).IsVisible = true;
if (runSearchOnNextShow) { if (runSearchOnNextShow) {
runSearchOnNextShow = false; runSearchOnNextShow = false;
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);
@ -140,11 +141,6 @@ namespace ICSharpCode.ILSpy
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);
} }
void IPane.Closed()
{
this.SearchTerm = string.Empty;
}
void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{ {
JumpToSelectedItem(); JumpToSelectedItem();

7
ILSpy/ViewModels/AnalyzerPaneModel.cs

@ -16,18 +16,21 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
{ {
[ExportToolPane(ContentId = PaneContentId)]
public class AnalyzerPaneModel : ToolPaneModel public class AnalyzerPaneModel : ToolPaneModel
{ {
public const string PaneContentId = "analyzerPane"; public const string PaneContentId = "analyzerPane";
public static AnalyzerPaneModel Instance { get; } = new AnalyzerPaneModel();
private AnalyzerPaneModel() private AnalyzerPaneModel()
{ {
ContentId = PaneContentId; ContentId = PaneContentId;
Title = Properties.Resources.Analyze; Title = Properties.Resources.Analyze;
} }
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("AnalyzerPaneTemplate");
} }
} }

6
ILSpy/ViewModels/AssemblyListPaneModel.cs

@ -16,21 +16,23 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Windows;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
{ {
[ExportToolPane(ContentId = PaneContentId)]
public class AssemblyListPaneModel : ToolPaneModel public class AssemblyListPaneModel : ToolPaneModel
{ {
public const string PaneContentId = "assemblyListPane"; public const string PaneContentId = "assemblyListPane";
public static AssemblyListPaneModel Instance { get; } = new AssemblyListPaneModel();
private AssemblyListPaneModel() private AssemblyListPaneModel()
{ {
Title = Resources.Assemblies; Title = Resources.Assemblies;
ContentId = PaneContentId; ContentId = PaneContentId;
IsCloseable = false; IsCloseable = false;
} }
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("AssemblyListPaneTemplate");
} }
} }

7
ILSpy/ViewModels/DebugStepsPaneModel.cs

@ -16,18 +16,21 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
{ {
[ExportToolPane(ContentId = PaneContentId)]
public class DebugStepsPaneModel : ToolPaneModel public class DebugStepsPaneModel : ToolPaneModel
{ {
public const string PaneContentId = "debugStepsPane"; public const string PaneContentId = "debugStepsPane";
public static DebugStepsPaneModel Instance { get; } = new DebugStepsPaneModel();
private DebugStepsPaneModel() private DebugStepsPaneModel()
{ {
ContentId = PaneContentId; ContentId = PaneContentId;
Title = Properties.Resources.DebugSteps; Title = Properties.Resources.DebugSteps;
} }
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("DebugStepsPaneTemplate");
} }
} }

32
ILSpy/ViewModels/LegacyToolPaneModel.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels
{
internal enum LegacyToolPaneLocation
{
Top,
Bottom
}
internal class LegacyToolPaneModel : ToolPaneModel
{
public LegacyToolPaneModel(string title, object content, LegacyToolPaneLocation location)
{
this.Title = title;
this.Content = content;
this.IsCloseable = true;
this.Location = location;
}
public object Content { get; }
public override DataTemplate Template => throw new NotSupportedException();
public LegacyToolPaneLocation Location { get; }
}
}

7
ILSpy/ViewModels/SearchPaneModel.cs

@ -16,14 +16,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
{ {
[ExportToolPane(ContentId = PaneContentId)]
public class SearchPaneModel : ToolPaneModel public class SearchPaneModel : ToolPaneModel
{ {
public const string PaneContentId = "searchPane"; public const string PaneContentId = "searchPane";
public static SearchPaneModel Instance { get; } = new SearchPaneModel();
private SearchPaneModel() private SearchPaneModel()
{ {
ContentId = PaneContentId; ContentId = PaneContentId;
@ -36,5 +37,7 @@ namespace ICSharpCode.ILSpy.ViewModels
base.Show(); base.Show();
MainWindow.Instance.SearchPane.Show(); MainWindow.Instance.SearchPane.Show();
} }
public override DataTemplate Template => (DataTemplate)MainWindow.Instance.FindResource("SearchPaneTemplate");
} }
} }

4
ILSpy/ViewModels/ToolPaneModel.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Windows;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
{ {
public abstract class ToolPaneModel : PaneModel public abstract class ToolPaneModel : PaneModel
@ -25,5 +27,7 @@ namespace ICSharpCode.ILSpy.ViewModels
this.IsActive = true; this.IsActive = true;
this.IsVisible = true; this.IsVisible = true;
} }
public abstract DataTemplate Template { get; }
} }
} }

14
ILSpy/Views/DebugSteps.xaml.cs

@ -9,7 +9,7 @@ using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
public partial class DebugSteps : UserControl, IPane public partial class DebugSteps : UserControl
{ {
static readonly ILAstWritingOptions writingOptions = new ILAstWritingOptions { static readonly ILAstWritingOptions writingOptions = new ILAstWritingOptions {
UseFieldSugar = true, UseFieldSugar = true,
@ -79,18 +79,6 @@ namespace ICSharpCode.ILSpy
#endif #endif
} }
void IPane.Closed()
{
#if DEBUG
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged -= SelectionChanged;
writingOptions.PropertyChanged -= WritingOptions_PropertyChanged;
if (language != null) {
language.StepperUpdated -= ILAstStepperUpdated;
}
#endif
}
private void ShowStateAfter_Click(object sender, RoutedEventArgs e) private void ShowStateAfter_Click(object sender, RoutedEventArgs e)
{ {
Stepper.Node n = (Stepper.Node)tree.SelectedItem; Stepper.Node n = (Stepper.Node)tree.SelectedItem;

Loading…
Cancel
Save