Skip to content

Commit

Permalink
Merge pull request #1801 from icsharpcode/avalondock
Browse files Browse the repository at this point in the history
Second iteration of docking UI for ILSpy
  • Loading branch information
siegfriedpammer authored Nov 17, 2019
2 parents 62fa9d4 + 2ae9155 commit 7e34413
Show file tree
Hide file tree
Showing 46 changed files with 1,232 additions and 220 deletions.
5 changes: 4 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[submodule "ILSpy-tests"]
path = ILSpy-tests
url = https://github.com/icsharpcode/ILSpy-tests


[submodule "AvalonDock"]
path = AvalonDock
url = https://github.com/siegfriedpammer/AvalonDock
1 change: 1 addition & 0 deletions AvalonDock
Submodule AvalonDock added at e5ec95
14 changes: 9 additions & 5 deletions BuildTools/update-assemblyinfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ $masterBranches = @("master", "5.0.x");
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";

function Test-File([string]$filename) {
return [System.IO.File]::Exists( (Join-Path (Get-Location) $filename) );
return [System.IO.File]::Exists((Join-Path (Get-Location) $filename));
}

function Test-Dir([string]$name) {
return [System.IO.Directory]::Exists( (Join-Path (Get-Location) $name) );
return [System.IO.Directory]::Exists((Join-Path (Get-Location) $name));
}

function Find-Git() {
Expand All @@ -38,22 +38,26 @@ function Find-Git() {
return $false;
}

function No-Git() {
return -not (((Test-Dir ".git") -or (Test-File ".git")) -and (Find-Git));
}

function gitVersion() {
if (-not ((Test-Dir ".git") -and (Find-Git))) {
if (No-Git) {
return 0;
}
return [Int32]::Parse((git rev-list --count "$baseCommit..HEAD")) + $baseCommitRev;
}

function gitCommitHash() {
if (-not ((Test-Dir ".git") -and (Find-Git))) {
if (No-Git) {
return "0000000000000000000000000000000000000000";
}
return (git rev-list "$baseCommit..HEAD") | Select -First 1;
}

function gitBranch() {
if (-not ((Test-Dir ".git" -or Test-File ".git") -and (Find-Git))) {
if (No-Git) {
return "no-branch";
}

Expand Down
6 changes: 6 additions & 0 deletions ILSpy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PdbP
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{B51C6636-B8D1-4200-9869-08F2689DE6C2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xceed.Wpf.AvalonDock", "AvalonDock\source\Components\Xceed.Wpf.AvalonDock\Xceed.Wpf.AvalonDock.csproj", "{D87D783A-A8EE-4A36-AAED-3AB21DC98046}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,6 +81,10 @@ Global
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.Build.0 = Release|Any CPU
{D87D783A-A8EE-4A36-AAED-3AB21DC98046}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D87D783A-A8EE-4A36-AAED-3AB21DC98046}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D87D783A-A8EE-4A36-AAED-3AB21DC98046}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D87D783A-A8EE-4A36-AAED-3AB21DC98046}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
7 changes: 2 additions & 5 deletions ILSpy/AboutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,10 @@ namespace ICSharpCode.ILSpy
[ExportMainMenuCommand(Menu = nameof(Resources._Help), Header = nameof(Resources._About), MenuOrder = 99999)]
sealed class AboutPage : SimpleCommand
{
[Import]
DecompilerTextView decompilerTextView = null;

public override void Execute(object parameter)
{
MainWindow.Instance.UnselectAll();
Display(decompilerTextView);
Display(Docking.DockWorkspace.Instance.GetTextView());
}

static readonly Uri UpdateUrl = new Uri("https://ilspy.net/updates.xml");
Expand All @@ -57,7 +54,7 @@ public override void Execute(object parameter)

public static void Display(DecompilerTextView textView)
{
AvalonEditTextOutput output = new AvalonEditTextOutput() { EnableHyperlinks = true };
AvalonEditTextOutput output = new AvalonEditTextOutput() { Title = Resources.About, EnableHyperlinks = true };
output.WriteLine(Resources.ILSpyVersion + RevisionClass.FullVersion);
if(WindowsVersionHelper.HasPackageIdentity) {
output.WriteLine($"Package Name: {WindowsVersionHelper.GetPackageFamilyName()}");
Expand Down
16 changes: 8 additions & 8 deletions ILSpy/Analyzers/AnalyzeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,31 @@ public void Execute(TextViewContext context)
{
if (context.SelectedTreeNodes != null) {
foreach (IMemberTreeNode node in context.SelectedTreeNodes) {
AnalyzerTreeView.Instance.Analyze(node.Member);
MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member);
}
} else if (context.Reference != null && context.Reference.Reference is IEntity entity) {
AnalyzerTreeView.Instance.Analyze(entity);
MainWindow.Instance.AnalyzerTreeView.Analyze(entity);
}
}

public override bool CanExecute(object parameter)
{
if (AnalyzerTreeView.Instance.IsKeyboardFocusWithin) {
return AnalyzerTreeView.Instance.SelectedItems.OfType<object>().All(n => n is IMemberTreeNode);
if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) {
return MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType<object>().All(n => n is IMemberTreeNode);
} else {
return MainWindow.Instance.SelectedNodes.All(n => n is IMemberTreeNode);
}
}

public override void Execute(object parameter)
{
if (AnalyzerTreeView.Instance.IsKeyboardFocusWithin) {
foreach (IMemberTreeNode node in AnalyzerTreeView.Instance.SelectedItems.OfType<IMemberTreeNode>().ToArray()) {
AnalyzerTreeView.Instance.Analyze(node.Member);
if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) {
foreach (IMemberTreeNode node in MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType<IMemberTreeNode>().ToArray()) {
MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member);
}
} else {
foreach (IMemberTreeNode node in MainWindow.Instance.SelectedNodes) {
AnalyzerTreeView.Instance.Analyze(node.Member);
MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member);
}
}
}
Expand Down
21 changes: 4 additions & 17 deletions ILSpy/Analyzers/AnalyzerTreeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using System.Windows;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Analyzers.TreeNodes;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.TreeView;

namespace ICSharpCode.ILSpy.Analyzers
Expand All @@ -32,21 +34,7 @@ namespace ICSharpCode.ILSpy.Analyzers
/// </summary>
public class AnalyzerTreeView : SharpTreeView, IPane
{
static AnalyzerTreeView instance;

public static AnalyzerTreeView Instance
{
get
{
if (instance == null) {
App.Current.VerifyAccess();
instance = new AnalyzerTreeView();
}
return instance;
}
}

private AnalyzerTreeView()
public AnalyzerTreeView()
{
this.ShowRoot = false;
this.Root = new AnalyzerRootNode { Language = MainWindow.Instance.CurrentLanguage };
Expand All @@ -72,8 +60,7 @@ void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollect

public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInNewPane("Analyzer", this, PanePosition.Bottom);
DockWorkspace.Instance.ToolPanes.Add(AnalyzerPaneModel.Instance);
}

public void Show(AnalyzerTreeNode node)
Expand Down
2 changes: 1 addition & 1 deletion ILSpy/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ void Window_RequestNavigate(object sender, RequestNavigateEventArgs e)
}
}
}
ILSpy.MainWindow.Instance.TextView.ShowText(output);
Docking.DockWorkspace.Instance.ShowText(output);
e.Handled = true;
}
}
Expand Down
8 changes: 4 additions & 4 deletions ILSpy/Commands/DecompileAllCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override bool CanExecute(object parameter)

public override void Execute(object parameter)
{
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) {
if (!asm.HasLoadError) {
Expand All @@ -64,7 +64,7 @@ public override void Execute(object parameter)
}
});
return output;
}, ct)).Then(output => MainWindow.Instance.TextView.ShowText(output)).HandleExceptions();
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}
}

Expand All @@ -77,7 +77,7 @@ public override void Execute(object parameter)
var language = MainWindow.Instance.CurrentLanguage;
var nodes = MainWindow.Instance.SelectedNodes.ToArray();
var options = new DecompilationOptions();
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
options.CancellationToken = ct;
Stopwatch w = Stopwatch.StartNew();
for (int i = 0; i < numRuns; ++i) {
Expand All @@ -90,7 +90,7 @@ public override void Execute(object parameter)
double msPerRun = w.Elapsed.TotalMilliseconds / numRuns;
output.Write($"Average time: {msPerRun.ToString("f1")}ms\n");
return output;
}, ct)).Then(output => MainWindow.Instance.TextView.ShowText(output)).HandleExceptions();
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}
}
}
Expand Down
37 changes: 25 additions & 12 deletions ILSpy/Commands/DecompileInNewViewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,50 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;

namespace ICSharpCode.ILSpy.Commands
{
// [ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
[ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
internal sealed class DecompileInNewViewCommand : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return true;
return context.SelectedTreeNodes != null || context.Reference?.Reference is IEntity;
}

public bool IsEnabled(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return true;
return context.SelectedTreeNodes != null || context.Reference?.Reference is IEntity;
}

public async void Execute(TextViewContext context)
public void Execute(TextViewContext context)
{
if (context.SelectedTreeNodes != null) {
var nodes = context.SelectedTreeNodes.Cast<ILSpyTreeNode>().ToArray();
DecompileNodes(nodes);
} else if (context.Reference?.Reference is IEntity entity) {
var node = MainWindow.Instance.FindTreeNode(entity);
if (node != null) {
DecompileNodes(node);
}
}
}

private static void DecompileNodes(params ILSpyTreeNode[] nodes)
{
var dtv = new DecompilerTextView();
var nodes = context.SelectedTreeNodes.Cast<ILSpyTreeNode>().ToArray();
var title = string.Join(", ", nodes.Select(x => x.ToString()));
MainWindow.Instance.ShowInNewPane(title, dtv, PanePosition.Document);
await dtv.DecompileAsync(MainWindow.Instance.CurrentLanguage, nodes, new DecompilationOptions());
DockWorkspace.Instance.Documents.Add(new ViewModels.DecompiledDocumentModel(title, title) { Language = MainWindow.Instance.CurrentLanguage, LanguageVersion = MainWindow.Instance.CurrentLanguageVersion });
DockWorkspace.Instance.ActiveDocument = DockWorkspace.Instance.Documents.Last();
MainWindow.Instance.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, (Action)delegate {
DockWorkspace.Instance.GetTextView().DecompileAsync(MainWindow.Instance.CurrentLanguage, nodes, new DecompilationOptions());
});
}
}
}
4 changes: 2 additions & 2 deletions ILSpy/Commands/DisassembleAllCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public override bool CanExecute(object parameter)

public override void Execute(object parameter)
{
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) {
if (!asm.HasLoadError) {
Expand All @@ -61,7 +61,7 @@ public override void Execute(object parameter)
}
});
return output;
}, ct)).Then(output => MainWindow.Instance.TextView.ShowText(output)).HandleExceptions();
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions ILSpy/Commands/GeneratePdbContextMenuEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ internal static void GeneratePdbForAssembly(LoadedAssembly assembly)
if (dlg.ShowDialog() != true) return;
DecompilationOptions options = new DecompilationOptions();
string fileName = dlg.FileName;
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Stopwatch stopwatch = Stopwatch.StartNew();
using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) {
Expand All @@ -83,7 +83,7 @@ internal static void GeneratePdbForAssembly(LoadedAssembly assembly)
output.AddButton(null, "Open Explorer", delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); });
output.WriteLine();
return output;
}, ct)).Then(output => MainWindow.Instance.TextView.ShowText(output)).HandleExceptions();
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}
}

Expand Down
4 changes: 2 additions & 2 deletions ILSpy/Commands/Pdb2XmlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ internal static void Execute(IEnumerable<AssemblyTreeNode> nodes)
{
var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");
var options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.IncludeMethodSpans | PdbToXmlOptions.IncludeTokens;
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
var writer = new TextOutputWriter(output);
foreach (var node in nodes) {
Expand All @@ -60,7 +60,7 @@ internal static void Execute(IEnumerable<AssemblyTreeNode> nodes)
PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options);
}
return output;
}, ct)).Then(output => MainWindow.Instance.TextView.ShowNodes(output, null, highlighting)).HandleExceptions();
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowNodes(output, null, highlighting)).HandleExceptions();
}
}

Expand Down
2 changes: 1 addition & 1 deletion ILSpy/Commands/SaveCodeContextMenuEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static bool CanExecute(IReadOnlyList<SharpTreeNode> selectedNodes)
public static void Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
{
var currentLanguage = MainWindow.Instance.CurrentLanguage;
var textView = MainWindow.Instance.TextView;
var textView = Docking.DockWorkspace.Instance.GetTextView();
if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection) {
// if there's only one treenode selected
// we will invoke the custom Save logic
Expand Down
4 changes: 3 additions & 1 deletion ILSpy/Commands/ShowDebugSteps.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#if DEBUG

using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.ViewModels;

namespace ICSharpCode.ILSpy.Commands
{
Expand All @@ -9,7 +11,7 @@ class ShowDebugSteps : SimpleCommand
{
public override void Execute(object parameter)
{
DebugSteps.Show();
DockWorkspace.Instance.ToolPanes.Add(DebugStepsPaneModel.Instance);
}
}
}
Expand Down
Loading

0 comments on commit 7e34413

Please sign in to comment.