Browse Source

Use MEF for the existing File menu items.

pull/70/head
Daniel Grunwald 14 years ago
parent
commit
d0670aae7b
  1. 2
      ILSpy/AboutPage.cs
  2. 4
      ILSpy/AssemblyList.cs
  3. 55
      ILSpy/Commands.cs
  4. 24
      ILSpy/ExportCommandAttribute.cs
  5. 2
      ILSpy/LoadedAssembly.cs
  6. 20
      ILSpy/MainWindow.xaml
  7. 62
      ILSpy/MainWindow.xaml.cs
  8. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  9. 2
      ILSpy/TreeNodes/EventTreeNode.cs
  10. 2
      ILSpy/TreeNodes/FieldTreeNode.cs
  11. 2
      ILSpy/TreeNodes/MethodTreeNode.cs
  12. 2
      ILSpy/TreeNodes/NamespaceTreeNode.cs
  13. 2
      ILSpy/TreeNodes/PropertyTreeNode.cs
  14. 2
      ILSpy/TreeNodes/TypeTreeNode.cs

2
ILSpy/AboutPage.cs

@ -21,7 +21,7 @@ using ICSharpCode.ILSpy.TextView; @@ -21,7 +21,7 @@ using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_Help", Header = "_About", Order = 99999)]
[ExportMainMenuCommand(Menu = "_Help", Header = "_About", MenuOrder = 99999)]
sealed class AboutPage : SimpleCommand
{
[Import]

4
ILSpy/AssemblyList.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// A list of assemblies.
/// </summary>
sealed class AssemblyList
public sealed class AssemblyList
{
readonly string listName;
@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy @@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Saves this assembly list to XML.
/// </summary>
public XElement SaveAsXml()
internal XElement SaveAsXml()
{
return new XElement(
"List",

55
ILSpy/Commands.cs

@ -2,11 +2,16 @@ @@ -2,11 +2,16 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Input;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "E_xit", Order = 99999, Category = "Exit")]
[ExportMainMenuCommand(Menu = "_File", Header = "E_xit", MenuOrder = 99999, MenuCategory = "Exit")]
sealed class ExitCommand : SimpleCommand
{
public override void Execute(object parameter)
@ -15,26 +20,57 @@ namespace ICSharpCode.ILSpy @@ -15,26 +20,57 @@ namespace ICSharpCode.ILSpy
}
}
[ExportToolbarCommand(ToolTip = "Back", Icon = "Images/Back.png", Category = "Navigation")]
[ExportToolbarCommand(ToolTip = "Back", ToolbarIcon = "Images/Back.png", ToolbarCategory = "Navigation", ToolbarOrder = 0)]
sealed class BrowseBackCommand : CommandWrapper {
public BrowseBackCommand() : base(NavigationCommands.BrowseBack) {}
}
[ExportToolbarCommand(ToolTip = "Forward", Icon = "Images/Forward.png", Category = "Navigation", Order = 1)]
[ExportToolbarCommand(ToolTip = "Forward", ToolbarIcon = "Images/Forward.png", ToolbarCategory = "Navigation", ToolbarOrder = 1)]
sealed class BrowseForwardCommand : CommandWrapper {
public BrowseForwardCommand() : base(NavigationCommands.BrowseForward) {}
}
[ExportToolbarCommand(ToolTip = "Open", Icon = "Images/Open.png", Category = "Open")]
[ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
sealed class OpenCommand : CommandWrapper {
public OpenCommand() : base(ApplicationCommands.Open) {}
}
[ExportToolbarCommand(ToolTip = "Reload all assemblies", Icon = "Images/Refresh.png", Category = "Open", Order = 1)]
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuCategory = "Open", MenuOrder = 1)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override void Execute(object parameter)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = MainWindow.Instance;
if (dlg.ShowDialog() == true) {
MainWindow.Instance.OpenFiles(dlg.SelectedFileNames);
}
}
}
[ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
sealed class RefreshCommand : CommandWrapper {
public RefreshCommand() : base(NavigationCommands.Refresh) {}
}
[ExportMainMenuCommand(Menu = "_File", Header = "_Save Code...", MenuIcon = "Images/SaveFile.png", MenuCategory = "Save", MenuOrder = 0)]
sealed class SaveCommand : SimpleCommand
{
public override void Execute(object parameter)
{
MainWindow mainWindow = MainWindow.Instance;
if (mainWindow.SelectedNodes.Count() == 1) {
if (mainWindow.SelectedNodes.Single().Save(mainWindow.TextView))
return;
}
mainWindow.TextView.SaveToDisk(mainWindow.CurrentLanguage,
mainWindow.SelectedNodes,
new DecompilationOptions() { FullDecompilation = true });
}
}
class CommandWrapper : ICommand
{
ICommand wrappedCommand;
@ -44,6 +80,15 @@ namespace ICSharpCode.ILSpy @@ -44,6 +80,15 @@ namespace ICSharpCode.ILSpy
this.wrappedCommand = wrappedCommand;
}
public static ICommand Unwrap(ICommand command)
{
CommandWrapper w = command as CommandWrapper;
if (w != null)
return w.wrappedCommand;
else
return command;
}
public event EventHandler CanExecuteChanged {
add { wrappedCommand.CanExecuteChanged += value; }
remove { wrappedCommand.CanExecuteChanged -= value; }

24
ILSpy/ExportCommandAttribute.cs

@ -10,11 +10,11 @@ namespace ICSharpCode.ILSpy @@ -10,11 +10,11 @@ namespace ICSharpCode.ILSpy
#region Toolbar
public interface IToolbarCommandMetadata
{
string Icon { get; }
string ToolbarIcon { get; }
string ToolTip { get; }
string Category { get; }
string ToolbarCategory { get; }
double Order { get; }
double ToolbarOrder { get; }
}
[MetadataAttribute]
@ -27,21 +27,21 @@ namespace ICSharpCode.ILSpy @@ -27,21 +27,21 @@ namespace ICSharpCode.ILSpy
}
public string ToolTip { get; set; }
public string Icon { get; set; }
public string Category { get; set; }
public double Order { get; set; }
public string ToolbarIcon { get; set; }
public string ToolbarCategory { get; set; }
public double ToolbarOrder { get; set; }
}
#endregion
#region Main Menu
public interface IMainMenuCommandMetadata
{
string Icon { get; }
string MenuIcon { get; }
string Header { get; }
string Menu { get; }
string Category { get; }
string MenuCategory { get; }
double Order { get; }
double MenuOrder { get; }
}
[MetadataAttribute]
@ -53,11 +53,11 @@ namespace ICSharpCode.ILSpy @@ -53,11 +53,11 @@ namespace ICSharpCode.ILSpy
{
}
public string Icon { get; set; }
public string MenuIcon { get; set; }
public string Header { get; set; }
public string Menu { get; set; }
public string Category { get; set; }
public double Order { get; set; }
public string MenuCategory { get; set; }
public double MenuOrder { get; set; }
}
#endregion
}

2
ILSpy/LoadedAssembly.cs

@ -14,7 +14,7 @@ namespace ICSharpCode.ILSpy @@ -14,7 +14,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Represents an assembly loaded into ILSpy.
/// </summary>
sealed class LoadedAssembly
public sealed class LoadedAssembly
{
readonly Task<AssemblyDefinition> assemblyTask;
readonly AssemblyList assemblyList;

20
ILSpy/MainWindow.xaml

@ -34,25 +34,7 @@ @@ -34,25 +34,7 @@
<DockPanel>
<!-- Main menu -->
<Menu DockPanel.Dock="Top" Name="mainMenu">
<MenuItem Header="_File">
<MenuItem Command="Open">
<MenuItem.Icon>
<Image Width="16" Height="16" Source="Images/Open.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Open from _GAC" Click="OpenFromGac_Click" />
<MenuItem Command="Refresh" Header="_Reload">
<MenuItem.Icon>
<Image Width="16" Height="16" Source="Images/Refresh.png" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="_Save Code" Click="saveCode_Click">
<MenuItem.Icon>
<Image Width="16" Height="16" Source="Images/SaveFile.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_File" /> <!-- contents of file menu are added using MEF -->
<MenuItem Header="_View">
<MenuItem Header="Show _internal types and members" IsCheckable="True" IsChecked="{Binding FilterSettings.ShowInternalApi}">
<MenuItem.Icon>

62
ILSpy/MainWindow.xaml.cs

@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy @@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy
{
int navigationPos = 0;
int openPos = 1;
foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => c.Metadata.ToolbarCategory)) {
if (commandGroup.Key == "Navigation") {
foreach (var command in commandGroup) {
toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command));
@ -130,12 +130,12 @@ namespace ICSharpCode.ILSpy @@ -130,12 +130,12 @@ namespace ICSharpCode.ILSpy
Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command)
{
return new Button {
Command = command.Value,
Command = CommandWrapper.Unwrap(command.Value),
ToolTip = command.Metadata.ToolTip,
Content = new Image {
Width = 16,
Height = 16,
Source = Images.LoadImage(command.Value, command.Metadata.Icon)
Source = Images.LoadImage(command.Value, command.Metadata.ToolbarIcon)
}
};
}
@ -147,25 +147,26 @@ namespace ICSharpCode.ILSpy @@ -147,25 +147,26 @@ namespace ICSharpCode.ILSpy
void InitMainMenu()
{
foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Menu)) {
foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => c.Metadata.Menu)) {
var topLevelMenuItem = mainMenu.Items.OfType<MenuItem>().FirstOrDefault(m => (m.Header as string) == topLevelMenu.Key);
foreach (var category in topLevelMenu.GroupBy(c => c.Metadata.Category)) {
foreach (var category in topLevelMenu.GroupBy(c => c.Metadata.MenuCategory)) {
if (topLevelMenuItem == null) {
topLevelMenuItem = new MenuItem();
topLevelMenuItem.Header = topLevelMenu.Key;
mainMenu.Items.Add(topLevelMenuItem);
} else {
} else if (topLevelMenuItem.Items.Count > 0) {
topLevelMenuItem.Items.Add(new Separator());
}
foreach (var entry in category) {
MenuItem menuItem = new MenuItem();
menuItem.Header = entry.Metadata.Header;
menuItem.Command = entry.Value;
if (!string.IsNullOrEmpty(entry.Metadata.Icon)) {
menuItem.Command = CommandWrapper.Unwrap(entry.Value);
if (!string.IsNullOrEmpty(entry.Metadata.Header))
menuItem.Header = entry.Metadata.Header;
if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) {
menuItem.Icon = new Image {
Width = 16,
Height = 16,
Source = Images.LoadImage(entry.Value, entry.Metadata.Icon)
Source = Images.LoadImage(entry.Value, entry.Metadata.MenuIcon)
};
}
topLevelMenuItem.Items.Add(menuItem);
@ -388,8 +389,10 @@ namespace ICSharpCode.ILSpy @@ -388,8 +389,10 @@ namespace ICSharpCode.ILSpy
}
}
void OpenFiles(string[] fileNames)
public void OpenFiles(string[] fileNames)
{
if (fileNames == null)
throw new ArgumentNullException("fileNames");
treeView.UnselectAll();
SharpTreeNode lastNode = null;
foreach (string file in fileNames) {
@ -413,18 +416,9 @@ namespace ICSharpCode.ILSpy @@ -413,18 +416,9 @@ namespace ICSharpCode.ILSpy
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true));
}
void OpenFromGac_Click(object sender, RoutedEventArgs e)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = this;
if (dlg.ShowDialog() == true) {
OpenFiles(dlg.SelectedFileNames);
}
}
#endregion
#region Decompile / Save
#region Decompile (TreeView_SelectionChanged)
void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (treeView.SelectedItems.Count == 1) {
@ -432,21 +426,23 @@ namespace ICSharpCode.ILSpy @@ -432,21 +426,23 @@ namespace ICSharpCode.ILSpy
if (node != null && node.View(decompilerTextView))
return;
}
decompilerTextView.Decompile(sessionSettings.FilterSettings.Language,
treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>(),
new DecompilationOptions());
decompilerTextView.Decompile(this.CurrentLanguage, this.SelectedNodes, new DecompilationOptions());
}
void saveCode_Click(object sender, RoutedEventArgs e)
{
if (treeView.SelectedItems.Count == 1) {
ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode;
if (node != null && node.Save(decompilerTextView))
return;
public DecompilerTextView TextView {
get { return decompilerTextView; }
}
public Language CurrentLanguage {
get {
return sessionSettings.FilterSettings.Language;
}
}
public IEnumerable<ILSpyTreeNode> SelectedNodes {
get {
return treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>();
}
decompilerTextView.SaveToDisk(sessionSettings.FilterSettings.Language,
treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>(),
new DecompilationOptions() { FullDecompilation = true });
}
#endregion

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// Tree node representing an assembly.
/// This class is responsible for loading both namespace and type nodes.
/// </summary>
sealed class AssemblyTreeNode : ILSpyTreeNode
public sealed class AssemblyTreeNode : ILSpyTreeNode
{
readonly LoadedAssembly assembly;
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();

2
ILSpy/TreeNodes/EventTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Represents an event in the TreeView.
/// </summary>
sealed class EventTreeNode : ILSpyTreeNode
public sealed class EventTreeNode : ILSpyTreeNode
{
readonly EventDefinition ev;

2
ILSpy/TreeNodes/FieldTreeNode.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Represents a field in the TreeView.
/// </summary>
sealed class FieldTreeNode : ILSpyTreeNode
public sealed class FieldTreeNode : ILSpyTreeNode
{
readonly FieldDefinition field;

2
ILSpy/TreeNodes/MethodTreeNode.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -29,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Tree Node representing a field, method, property, or event.
/// </summary>
sealed class MethodTreeNode : ILSpyTreeNode
public sealed class MethodTreeNode : ILSpyTreeNode
{
MethodDefinition method;

2
ILSpy/TreeNodes/NamespaceTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Namespace node. The loading of the type nodes is handled by the parent AssemblyTreeNode.
/// </summary>
sealed class NamespaceTreeNode : ILSpyTreeNode
public sealed class NamespaceTreeNode : ILSpyTreeNode
{
string name;

2
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Represents a property in the TreeView.
/// </summary>
sealed class PropertyTreeNode : ILSpyTreeNode
public sealed class PropertyTreeNode : ILSpyTreeNode
{
readonly PropertyDefinition property;
readonly bool isIndexer;

2
ILSpy/TreeNodes/TypeTreeNode.cs

@ -26,7 +26,7 @@ using Mono.Cecil; @@ -26,7 +26,7 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes
{
sealed class TypeTreeNode : ILSpyTreeNode
public sealed class TypeTreeNode : ILSpyTreeNode
{
readonly TypeDefinition type;
readonly AssemblyTreeNode parentAssemblyNode;

Loading…
Cancel
Save