From aaaf350bc022dd7201b85e2b709ae9e6742fb1c1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 13 Apr 2011 17:20:51 +0200 Subject: [PATCH] Add context menu command and option page to the test plugin. --- ILSpy/ILSpySettings.cs | 2 +- TestPlugin/ContextMenuCommand.cs | 41 +++++++++++++ TestPlugin/CustomOptionPage.xaml | 8 +++ TestPlugin/CustomOptionPage.xaml.cs | 94 +++++++++++++++++++++++++++++ TestPlugin/Readme.txt | 46 +++++++++++++- TestPlugin/TestPlugin.csproj | 12 ++++ 6 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 TestPlugin/ContextMenuCommand.cs create mode 100644 TestPlugin/CustomOptionPage.xaml create mode 100644 TestPlugin/CustomOptionPage.xaml.cs diff --git a/ILSpy/ILSpySettings.cs b/ILSpy/ILSpySettings.cs index 787168abf..7d0fd19cb 100644 --- a/ILSpy/ILSpySettings.cs +++ b/ILSpy/ILSpySettings.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy this.root = root; } - public XElement this[string section] { + public XElement this[XName section] { get { return root.Element(section) ?? new XElement(section); } diff --git a/TestPlugin/ContextMenuCommand.cs b/TestPlugin/ContextMenuCommand.cs new file mode 100644 index 000000000..dc0f4c576 --- /dev/null +++ b/TestPlugin/ContextMenuCommand.cs @@ -0,0 +1,41 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.ILSpy; +using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.TreeView; +using Microsoft.Win32; +using Mono.Cecil; + +namespace TestPlugin +{ + [ExportContextMenuEntry(Header = "_Save Assembly")] + public class SaveAssembly : IContextMenuEntry + { + public bool IsVisible(SharpTreeNode[] selectedNodes) + { + return selectedNodes.All(n => n is AssemblyTreeNode); + } + + public bool IsEnabled(SharpTreeNode[] selectedNodes) + { + return selectedNodes.Length == 1; + } + + public void Execute(SharpTreeNode[] selectedNodes) + { + AssemblyTreeNode node = (AssemblyTreeNode)selectedNodes[0]; + AssemblyDefinition asm = node.LoadedAssembly.AssemblyDefinition as AssemblyDefinition; + if (asm != null) { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.FileName = node.LoadedAssembly.FileName; + dlg.Filter = "Assembly|*.dll;*.exe"; + if (dlg.ShowDialog(MainWindow.Instance) == true) { + asm.MainModule.Write(dlg.FileName); + } + } + } + } +} diff --git a/TestPlugin/CustomOptionPage.xaml b/TestPlugin/CustomOptionPage.xaml new file mode 100644 index 000000000..2aa86fcc1 --- /dev/null +++ b/TestPlugin/CustomOptionPage.xaml @@ -0,0 +1,8 @@ + + + Useless option 1 + + + \ No newline at end of file diff --git a/TestPlugin/CustomOptionPage.xaml.cs b/TestPlugin/CustomOptionPage.xaml.cs new file mode 100644 index 000000000..3a54453fd --- /dev/null +++ b/TestPlugin/CustomOptionPage.xaml.cs @@ -0,0 +1,94 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Xml.Linq; +using ICSharpCode.ILSpy; + +namespace TestPlugin +{ + [ExportOptionPage("TestPlugin")] + partial class CustomOptionPage : UserControl, IOptionPage + { + static readonly XNamespace ns = "http://www.ilspy.net/testplugin"; + + public CustomOptionPage() + { + InitializeComponent(); + } + + public void Load(ILSpySettings settings) + { + // For loading options, use ILSpySetting's indexer. + // If the specified section does exist, the indexer will return a new empty element. + XElement e = settings[ns + "CustomOptions"]; + // Now load the options from the XML document: + Options s = new Options(); + s.UselessOption1 = (bool?)e.Attribute("useless1") ?? s.UselessOption1; + s.UselessOption2 = (double?)e.Attribute("useless2") ?? s.UselessOption2; + this.DataContext = s; + } + + public void Save(XElement root) + { + Options s = (Options)this.DataContext; + // Save the options back into XML: + XElement section = new XElement(ns + "CustomOptions"); + section.SetAttributeValue("useless1", s.UselessOption1); + section.SetAttributeValue("useless2", s.UselessOption2); + + // Replace the existing section in the settings file, or add a new section, + // if required. + XElement existingElement = root.Element(ns + "CustomOptions"); + if (existingElement != null) + existingElement.ReplaceWith(section); + else + root.Add(section); + } + } + + class Options : INotifyPropertyChanged + { + bool uselessOption1; + + public bool UselessOption1 { + get { return uselessOption1; } + set { + if (uselessOption1 != value) { + uselessOption1 = value; + OnPropertyChanged("UselessOption1"); + } + } + } + + double uselessOption2; + + public double UselessOption2 { + get { return uselessOption2; } + set { + if (uselessOption2 != value) { + uselessOption2 = value; + OnPropertyChanged("UselessOption2"); + } + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} \ No newline at end of file diff --git a/TestPlugin/Readme.txt b/TestPlugin/Readme.txt index f2d42a0a4..ab910e57a 100644 --- a/TestPlugin/Readme.txt +++ b/TestPlugin/Readme.txt @@ -20,6 +20,50 @@ Adding another language: Adding an entry to the main menu: - [ExportMainMenuCommand(Menu = "_File", Header = "_Clear List", MenuCategory = "Open", MenuOrder = 1.5)] + [ExportMainMenuCommand(Menu = "_File", MenuIcon = "Clear.png", Header = "_Clear List", MenuCategory = "Open", MenuOrder = 1.5)] public class UnloadAllAssembliesCommand : SimpleCommand + + Menu: menu into which the item is added + MenuIcon: optional, icon to use for the menu item. Must be embedded as "Resource" (WPF-style resource) in the same assembly as the command type. + Header: text on the menu item + MenuCategory: optional, used for grouping related menu items together. A separator is added between different groups. + MenuOrder: controls the order in which the items appear (items are sorted by this value) + + The command class must implement WPF's ICommand interface. + +--- + +Adding an entry to the tool bar: + [ExportToolbarCommand(ToolTip = "Clears the current assembly list", ToolbarIcon = "Clear.png", ToolbarCategory = "Open", ToolbarOrder = 1.5)] + public class UnloadAllAssembliesCommand : SimpleCommand + + ToolTip: the tool tip + ToolbarIcon: The icon. Must be embedded as "Resource" (WPF-style resource) in the same assembly as the command type. + ToolbarCategory: optional, used for grouping related toolbar items together. A separator is added between different groups. + ToolbarOrder: controls the order in which the items appear (items are sorted by this value) + + The command class must implement WPF's ICommand interface. + +--- + +Adding an entry to the context menu: + + [ExportContextMenuEntry(Header = "_Save Assembly")] + public class SaveAssembly : IContextMenuEntry + + Icon: optional, icon to use for the menu item. Must be embedded as "Resource" (WPF-style resource) in the same assembly as the command type. + Header: text on the menu item + Category: optional, used for grouping related menu items together. A separator is added between different groups. + Order: controls the order in which the items appear (items are sorted by this value) + + Context menu entries must implement IContextMenuEntry, which defines 3 methods: + bool IsVisible, bool IsEnabled, and void Execute. + +--- + +Adding an option page: + + [ExportOptionPage("TestPlugin")] + partial class CustomOptionPage : UserControl, IOptionPage + diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj index 4299e5c4b..1dd33ea0e 100644 --- a/TestPlugin/TestPlugin.csproj +++ b/TestPlugin/TestPlugin.csproj @@ -68,7 +68,12 @@ + + + CustomOptionPage.xaml + Code + @@ -93,6 +98,13 @@ {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory + + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1} + ICSharpCode.TreeView + + + + \ No newline at end of file