Browse Source

Use MEF for the existing File menu items.

pull/70/head
Daniel Grunwald 15 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;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
[ExportMainMenuCommand(Menu = "_Help", Header = "_About", Order = 99999)] [ExportMainMenuCommand(Menu = "_Help", Header = "_About", MenuOrder = 99999)]
sealed class AboutPage : SimpleCommand sealed class AboutPage : SimpleCommand
{ {
[Import] [Import]

4
ILSpy/AssemblyList.cs

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

55
ILSpy/Commands.cs

@ -2,11 +2,16 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy 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 sealed class ExitCommand : SimpleCommand
{ {
public override void Execute(object parameter) public override void Execute(object parameter)
@ -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 { sealed class BrowseBackCommand : CommandWrapper {
public BrowseBackCommand() : base(NavigationCommands.BrowseBack) {} 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 { sealed class BrowseForwardCommand : CommandWrapper {
public BrowseForwardCommand() : base(NavigationCommands.BrowseForward) {} 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 { sealed class OpenCommand : CommandWrapper {
public OpenCommand() : base(ApplicationCommands.Open) {} 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 { sealed class RefreshCommand : CommandWrapper {
public RefreshCommand() : base(NavigationCommands.Refresh) {} 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 class CommandWrapper : ICommand
{ {
ICommand wrappedCommand; ICommand wrappedCommand;
@ -44,6 +80,15 @@ namespace ICSharpCode.ILSpy
this.wrappedCommand = wrappedCommand; 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 { public event EventHandler CanExecuteChanged {
add { wrappedCommand.CanExecuteChanged += value; } add { wrappedCommand.CanExecuteChanged += value; }
remove { wrappedCommand.CanExecuteChanged -= value; } remove { wrappedCommand.CanExecuteChanged -= value; }

24
ILSpy/ExportCommandAttribute.cs

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

2
ILSpy/LoadedAssembly.cs

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

20
ILSpy/MainWindow.xaml

@ -34,25 +34,7 @@
<DockPanel> <DockPanel>
<!-- Main menu --> <!-- Main menu -->
<Menu DockPanel.Dock="Top" Name="mainMenu"> <Menu DockPanel.Dock="Top" Name="mainMenu">
<MenuItem Header="_File"> <MenuItem Header="_File" /> <!-- contents of file menu are added using MEF -->
<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="_View"> <MenuItem Header="_View">
<MenuItem Header="Show _internal types and members" IsCheckable="True" IsChecked="{Binding FilterSettings.ShowInternalApi}"> <MenuItem Header="Show _internal types and members" IsCheckable="True" IsChecked="{Binding FilterSettings.ShowInternalApi}">
<MenuItem.Icon> <MenuItem.Icon>

62
ILSpy/MainWindow.xaml.cs

@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy
{ {
int navigationPos = 0; int navigationPos = 0;
int openPos = 1; 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") { if (commandGroup.Key == "Navigation") {
foreach (var command in commandGroup) { foreach (var command in commandGroup) {
toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command)); toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command));
@ -130,12 +130,12 @@ namespace ICSharpCode.ILSpy
Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command) Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command)
{ {
return new Button { return new Button {
Command = command.Value, Command = CommandWrapper.Unwrap(command.Value),
ToolTip = command.Metadata.ToolTip, ToolTip = command.Metadata.ToolTip,
Content = new Image { Content = new Image {
Width = 16, Width = 16,
Height = 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
void InitMainMenu() 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); 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) { if (topLevelMenuItem == null) {
topLevelMenuItem = new MenuItem(); topLevelMenuItem = new MenuItem();
topLevelMenuItem.Header = topLevelMenu.Key; topLevelMenuItem.Header = topLevelMenu.Key;
mainMenu.Items.Add(topLevelMenuItem); mainMenu.Items.Add(topLevelMenuItem);
} else { } else if (topLevelMenuItem.Items.Count > 0) {
topLevelMenuItem.Items.Add(new Separator()); topLevelMenuItem.Items.Add(new Separator());
} }
foreach (var entry in category) { foreach (var entry in category) {
MenuItem menuItem = new MenuItem(); MenuItem menuItem = new MenuItem();
menuItem.Header = entry.Metadata.Header; menuItem.Command = CommandWrapper.Unwrap(entry.Value);
menuItem.Command = entry.Value; if (!string.IsNullOrEmpty(entry.Metadata.Header))
if (!string.IsNullOrEmpty(entry.Metadata.Icon)) { menuItem.Header = entry.Metadata.Header;
if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) {
menuItem.Icon = new Image { menuItem.Icon = new Image {
Width = 16, Width = 16,
Height = 16, Height = 16,
Source = Images.LoadImage(entry.Value, entry.Metadata.Icon) Source = Images.LoadImage(entry.Value, entry.Metadata.MenuIcon)
}; };
} }
topLevelMenuItem.Items.Add(menuItem); topLevelMenuItem.Items.Add(menuItem);
@ -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(); treeView.UnselectAll();
SharpTreeNode lastNode = null; SharpTreeNode lastNode = null;
foreach (string file in fileNames) { foreach (string file in fileNames) {
@ -413,18 +416,9 @@ namespace ICSharpCode.ILSpy
ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName));
SelectNode(FindNodeByPath(path, true)); 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 #endregion
#region Decompile / Save #region Decompile (TreeView_SelectionChanged)
void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e) void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
if (treeView.SelectedItems.Count == 1) { if (treeView.SelectedItems.Count == 1) {
@ -432,21 +426,23 @@ namespace ICSharpCode.ILSpy
if (node != null && node.View(decompilerTextView)) if (node != null && node.View(decompilerTextView))
return; return;
} }
decompilerTextView.Decompile(sessionSettings.FilterSettings.Language, decompilerTextView.Decompile(this.CurrentLanguage, this.SelectedNodes, new DecompilationOptions());
treeView.GetTopLevelSelection().OfType<ILSpyTreeNode>(),
new DecompilationOptions());
} }
void saveCode_Click(object sender, RoutedEventArgs e) public DecompilerTextView TextView {
{ get { return decompilerTextView; }
if (treeView.SelectedItems.Count == 1) { }
ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode;
if (node != null && node.Save(decompilerTextView)) public Language CurrentLanguage {
return; 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 #endregion

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

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

2
ILSpy/TreeNodes/EventTreeNode.cs

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

2
ILSpy/TreeNodes/FieldTreeNode.cs

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

2
ILSpy/TreeNodes/MethodTreeNode.cs

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

2
ILSpy/TreeNodes/NamespaceTreeNode.cs

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

2
ILSpy/TreeNodes/PropertyTreeNode.cs

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

2
ILSpy/TreeNodes/TypeTreeNode.cs

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

Loading…
Cancel
Save