Skip to content

Commit

Permalink
Move command handling from main window to command implementations.
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-englert committed Sep 10, 2024
1 parent c592abc commit f910778
Show file tree
Hide file tree
Showing 25 changed files with 255 additions and 239 deletions.
28 changes: 21 additions & 7 deletions ILSpy/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@

using TomsToolbox.Composition;
using TomsToolbox.Wpf.Composition;
using ICSharpCode.ILSpy.Themes;
using System.Globalization;
using System.Threading;

namespace ICSharpCode.ILSpy
{
Expand Down Expand Up @@ -75,25 +78,34 @@ public App()
SingleInstance.NewInstanceDetected += SingleInstance_NewInstanceDetected;
}

SharpTreeNode.SetImagesProvider(new WpfWindowsTreeNodeImagesProvider());

InitializeComponent();

Resources.RegisterDefaultStyles();

if (!Debugger.IsAttached)
{
AppDomain.CurrentDomain.UnhandledException += ShowErrorBox;
Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException;
}

TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException;

SharpTreeNode.SetImagesProvider(new WpfWindowsTreeNodeImagesProvider());

Resources.RegisterDefaultStyles();

InitializeMef().GetAwaiter().GetResult();

// Register the export provider so that it can be accessed from WPF/XAML components.
ExportProviderLocator.Register(ExportProvider);
// Add data templates registered via MEF.
Resources.MergedDictionaries.Add(DataTemplateManager.CreateDynamicDataTemplates(ExportProvider));

var sessionSettings = SettingsService.Instance.SessionSettings;
ThemeManager.Current.Theme = sessionSettings.Theme;
if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(sessionSettings.CurrentCulture);
}

EventManager.RegisterClassHandler(typeof(Window),
Hyperlink.RequestNavigateEvent,
new RequestNavigateEventHandler(Window_RequestNavigate));
Expand All @@ -109,9 +121,11 @@ public App()
string unknownArguments = string.Join(", ", CommandLineArguments.ArgumentsParser.RemainingArguments);
MessageBox.Show(unknownArguments, "ILSpy Unknown Command Line Arguments Passed");
}

SettingsService.Instance.AssemblyListManager.CreateDefaultAssemblyLists();
}

private static void SingleInstance_NewInstanceDetected(object sender, NewInstanceEventArgs e) => ExportProvider.GetExportedValue<AssemblyListPaneModel>().HandleSingleInstanceCommandLineArguments(e.Args).HandleExceptions();
private static void SingleInstance_NewInstanceDetected(object sender, NewInstanceEventArgs e) => ExportProvider.GetExportedValue<AssemblyTreeModel>().HandleSingleInstanceCommandLineArguments(e.Args).HandleExceptions();

static Assembly ResolvePluginDependencies(AssemblyLoadContext context, AssemblyName assemblyName)
{
Expand Down Expand Up @@ -203,7 +217,7 @@ protected override void OnStartup(StartupEventArgs e)

MainWindow = new MainWindow();
MainWindow.Loaded += (sender, args) => {
ExportProvider.GetExportedValue<AssemblyListPaneModel>().Initialize();
ExportProvider.GetExportedValue<AssemblyTreeModel>().Initialize();
};
MainWindow.Show();
}
Expand Down Expand Up @@ -266,7 +280,7 @@ internal static void UnhandledException(Exception exception)

void Window_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
ExportProvider.GetExportedValue<AssemblyListPaneModel>().NavigateTo(e);
ExportProvider.GetExportedValue<AssemblyTreeModel>().NavigateTo(e);
}
}
}
2 changes: 1 addition & 1 deletion ILSpy/AssemblyTree/AssemblyListPane.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
xmlns:assemblyTree="clr-namespace:ICSharpCode.ILSpy.AssemblyTree"
xmlns:toms="urn:TomsToolbox"
mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance assemblyTree:AssemblyListPaneModel}"
d:DataContext="{d:DesignInstance assemblyTree:AssemblyTreeModel}"
AutomationProperties.Name="Assemblies and Classes"
ShowRoot="False"
AllowDropOrder="True"
Expand Down
4 changes: 2 additions & 2 deletions ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
/// <summary>
/// Interaction logic for AssemblyListPane.xaml
/// </summary>
[DataTemplate(typeof(AssemblyListPaneModel))]
[DataTemplate(typeof(AssemblyTreeModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class AssemblyListPane
{
Expand All @@ -27,7 +27,7 @@ protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)

if (e.Property == DataContextProperty)
{
if (e.NewValue is not AssemblyListPaneModel model)
if (e.NewValue is not AssemblyTreeModel model)
return;

model.SetActiveView(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using System.Reflection.Metadata;

using ICSharpCode.ILSpyX.Extensions;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.Decompiler;
Expand All @@ -60,16 +59,16 @@ namespace ICSharpCode.ILSpy.AssemblyTree
[ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class AssemblyListPaneModel : ToolPaneModel
public class AssemblyTreeModel : ToolPaneModel
{
public const string PaneContentId = "assemblyListPane";

AssemblyListPane activeView;
AssemblyListTreeNode assemblyListTreeNode;

readonly NavigationHistoryService history = NavigationHistoryService.Instance;
readonly NavigationHistory<NavigationState> history = new();

public AssemblyListPaneModel()
public AssemblyTreeModel()
{
Title = Resources.Assemblies;
ContentId = PaneContentId;
Expand Down Expand Up @@ -795,6 +794,10 @@ public void NavigateHistory(bool forward)
DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false);
}

public bool CanNavigateBack => history.CanNavigateBack;

public bool CanNavigateForward => history.CanNavigateForward;

internal void NavigateTo(RequestNavigateEventArgs e, bool recordHistory = true, bool inNewTabPage = false)
{
if (e.Uri.Scheme == "resource")
Expand Down Expand Up @@ -914,5 +917,16 @@ static void CollapseChildren(SharpTreeNode node)
child.IsExpanded = false;
}
}

public void OpenFiles(string[] fileNames, bool focusNode = true)
{
if (fileNames == null)
throw new ArgumentNullException(nameof(fileNames));

if (focusNode)
UnselectAll();

LoadAssemblies(fileNames, focusNode: focusNode);
}
}
}
26 changes: 25 additions & 1 deletion ILSpy/Commands/BrowseBackCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using System.Windows.Input;

using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;

namespace ICSharpCode.ILSpy
Expand All @@ -27,9 +28,32 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseBackCommand : CommandWrapper
{
public BrowseBackCommand()
readonly AssemblyTreeModel assemblyTreeModel;

[ImportingConstructor]
public BrowseBackCommand(AssemblyTreeModel assemblyTreeModel)
: base(NavigationCommands.BrowseBack)
{
this.assemblyTreeModel = assemblyTreeModel;
}

protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
base.OnCanExecute(sender, e);

e.Handled = true;
e.CanExecute = assemblyTreeModel.CanNavigateBack;
}

protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
base.OnExecute(sender, e);

if (assemblyTreeModel.CanNavigateBack)
{
e.Handled = true;
assemblyTreeModel.NavigateHistory(false);
}
}
}
}
27 changes: 26 additions & 1 deletion ILSpy/Commands/BrowseForwardCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using System.Windows.Input;

using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;

namespace ICSharpCode.ILSpy
Expand All @@ -27,9 +28,33 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseForwardCommand : CommandWrapper
{
public BrowseForwardCommand()
private readonly AssemblyTreeModel assemblyTreeModel;

[ImportingConstructor]
public BrowseForwardCommand(AssemblyTreeModel assemblyTreeModel)
: base(NavigationCommands.BrowseForward)
{
this.assemblyTreeModel = assemblyTreeModel;
}

protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
base.OnCanExecute(sender, e);

e.Handled = true;
e.CanExecute = assemblyTreeModel.CanNavigateForward;
}

protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
base.OnExecute(sender, e);

if (assemblyTreeModel.CanNavigateForward)
{
e.Handled = true;
assemblyTreeModel.NavigateHistory(true);
}
}

}
}
19 changes: 15 additions & 4 deletions ILSpy/Commands/CommandWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.

using System;
using System.Windows;
using System.Windows.Input;

namespace ICSharpCode.ILSpy
Expand All @@ -28,15 +29,16 @@ class CommandWrapper : ICommand
public CommandWrapper(ICommand wrappedCommand)
{
this.wrappedCommand = wrappedCommand;

Application.Current.MainWindow?.CommandBindings.Add(new CommandBinding(wrappedCommand, OnExecute, OnCanExecute));
}

public static ICommand Unwrap(ICommand command)
{
CommandWrapper w = command as CommandWrapper;
if (w != null)
if (command is CommandWrapper w)
return w.wrappedCommand;
else
return command;

return command;
}

public event EventHandler CanExecuteChanged {
Expand All @@ -53,5 +55,14 @@ public bool CanExecute(object parameter)
{
return wrappedCommand.CanExecute(parameter);
}

protected virtual void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
}

protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
}
}
26 changes: 25 additions & 1 deletion ILSpy/Commands/OpenCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,42 @@
using System.ComponentModel.Composition;
using System.Windows.Input;

using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;

using Microsoft.Win32;

namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._Open), MenuIcon = "Images/Open", MenuCategory = nameof(Resources.Open), MenuOrder = 0)]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()
private readonly AssemblyTreeModel assemblyTreeModel;

[ImportingConstructor]
public OpenCommand(AssemblyTreeModel assemblyTreeModel)
: base(ApplicationCommands.Open)
{
this.assemblyTreeModel = assemblyTreeModel;
}

protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
base.OnExecute(sender, e);

e.Handled = true;
OpenFileDialog dlg = new OpenFileDialog {
Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*",
Multiselect = true,
RestoreDirectory = true
};

if (dlg.ShowDialog() == true)
{
assemblyTreeModel.OpenFiles(dlg.FileNames);
}
}
}
}
19 changes: 16 additions & 3 deletions ILSpy/Commands/OpenFromGacCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;

using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;

namespace ICSharpCode.ILSpy
Expand All @@ -27,17 +28,29 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenFromGacCommand : SimpleCommand
{
private readonly AssemblyTreeModel assemblyTreeModel;

[ImportingConstructor]
public OpenFromGacCommand(AssemblyTreeModel assemblyTreeModel)
{
this.assemblyTreeModel = assemblyTreeModel;
}

public override bool CanExecute(object parameter)
{
return AppEnvironment.IsWindows;
}

public override void Execute(object parameter)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = MainWindow.Instance;
OpenFromGacDialog dlg = new OpenFromGacDialog {
Owner = MainWindow.Instance
};

if (dlg.ShowDialog() == true)
MainWindow.Instance.OpenFiles(dlg.SelectedFileNames);
{
assemblyTreeModel.OpenFiles(dlg.SelectedFileNames);
}
}
}
}
Loading

0 comments on commit f910778

Please sign in to comment.