From 7b40bfba78794e79dcc3f118b605bf238812cb17 Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Wed, 31 Aug 2016 21:04:40 -0400 Subject: [PATCH 1/6] Plugin System Part 1: -Added a plugin loader & library system -Added a base interface for any plugins -Added a Plugin MenuItem interface -Added a Plugin Menu Generator -Slightly modified the Main window to allow plugins to show -Added the load of plugins at the start of the application --- src/EVEMon.Common/EVEMon.Common.csproj | 6 + .../PluginSytem/Core/IEVEMonPluginContract.cs | 14 +++ .../PluginSytem/Core/PluginLibrary.cs | 103 ++++++++++++++++++ .../PluginSytem/Core/PluginLoader.cs | 99 +++++++++++++++++ .../Helpers/PluginMenuGenerator.cs | 57 ++++++++++ .../Interfaces/IPluginToolMenuItem.cs | 16 +++ src/EVEMon/MainWindow.Designer.cs | 27 +++-- src/EVEMon/MainWindow.cs | 8 ++ src/EVEMon/Program.cs | 5 + 9 files changed, 326 insertions(+), 9 deletions(-) create mode 100644 src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs create mode 100644 src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs create mode 100644 src/EVEMon.Common/PluginSytem/Core/PluginLoader.cs create mode 100644 src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs create mode 100644 src/EVEMon.Common/PluginSytem/Interfaces/IPluginToolMenuItem.cs diff --git a/src/EVEMon.Common/EVEMon.Common.csproj b/src/EVEMon.Common/EVEMon.Common.csproj index d56ca8126..de4ddef92 100644 --- a/src/EVEMon.Common/EVEMon.Common.csproj +++ b/src/EVEMon.Common/EVEMon.Common.csproj @@ -194,6 +194,11 @@ + + + + + @@ -1240,6 +1245,7 @@ Always + diff --git a/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs b/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs new file mode 100644 index 000000000..0dbce54b3 --- /dev/null +++ b/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs @@ -0,0 +1,14 @@ +namespace EVEMon.Common.PluginSytem +{ + /// + /// Base Plugin interface for the EVEMon plugins. + /// + public interface IEVEMonPluginContract + { + /// + /// Define the plugin name. + /// + /// Returns a value identifying the plugin by name. + string PluginName(); + } +} diff --git a/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs b/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs new file mode 100644 index 000000000..4ea214d8c --- /dev/null +++ b/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Linq; + +// TODO: +// - use 1 plugin loader for each interface type request in a dictionary + +namespace EVEMon.Common.PluginSytem +{ + /// + /// Library of plugins. Will allow to load matching assemblies to a specified interface. + /// + public class PluginLibrary + { + /// Allows to override the plugin path. + /// If changed after the plugins are used, make sure to FlushAndLoadPlugins() again. + public static string pluginPathOverride = null; + + /// Allows to override the plugin recursive folder check. + /// If changed after the plugins are used, make sure to FlushAndLoadPlugins() again. + public static bool pluginRecursiveOverride = true; + + // singleton + private static Lazy instance; + + /// Gets the instance of the library + /// The instance. + public static PluginLibrary Instance + { + get + { + if (instance == null) + { + instance = new Lazy(() => new PluginLibrary(), LazyThreadSafetyMode.ExecutionAndPublication); + } + return instance.Value; + } + } + + private PluginLibrary() + { + FlushAndLoadPlugins(); + } + + private PluginLoader pluginList; + + /// Flushs and load the plugins. Will Obliterate the old plugins loaded. Use only in rare cases. + public void FlushAndLoadPlugins() + { + string pluginPath = AppDomain.CurrentDomain.BaseDirectory; + if (!string.IsNullOrWhiteSpace(pluginPathOverride)) + { + pluginPath = pluginPathOverride; + } + pluginList = new PluginLoader(pluginPath, pluginRecursiveOverride); + } + + /// + /// Gets all plugins. + /// + /// The all plugins. + public List GetAllPlugins() + { + return pluginList.GetPlugins(); + } + + /// + /// Gets the plugins that matches an interface + /// + /// List of baseplugin (to be casted). + /// Contract type. + public List GetPluginByType (Type contractType) + { + return GetPluginByType(contractType, -1); + } + + /// + /// Gets the plugins that matches an interface + /// + /// List of baseplugin (to be casted). + /// Contract type. + /// The maximum number of hits. Default is -1 (no maximum) + public List GetPluginByType (Type contractType, int maxCount) + { + List outputList = new List(); + foreach (IEVEMonPluginContract plugin in pluginList.GetPlugins()) + { + if (plugin.GetType().GetInterface(contractType.FullName) != null) + { + outputList.Add(plugin); + } + + if ((maxCount != -1) && (outputList.Count() >= maxCount)) + { + // we have enough, return the list now + return outputList; + } + } + return outputList; + } + } +} \ No newline at end of file diff --git a/src/EVEMon.Common/PluginSytem/Core/PluginLoader.cs b/src/EVEMon.Common/PluginSytem/Core/PluginLoader.cs new file mode 100644 index 000000000..20eb59452 --- /dev/null +++ b/src/EVEMon.Common/PluginSytem/Core/PluginLoader.cs @@ -0,0 +1,99 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections.Generic; + +namespace EVEMon.Common.PluginSytem +{ + /// + /// Generic Plugin loader. + /// + public class PluginLoader where T : IEVEMonPluginContract + { + private List pluginList = new List(); + + /// + /// Constructor to fill the plugin Loader with compliant plugins + /// + /// Path. + /// If set to true recursive. + public PluginLoader(string path, bool recursive) + { + string[] dllFileNames = null; + + if (Directory.Exists(path)) + { + if (recursive) + { + dllFileNames = RecursiveFindDLLs(path).ToArray(); + } else + { + dllFileNames = Directory.GetFiles(path, "*.dll"); + } + + List assemblies = new List(dllFileNames.Length); + foreach (string dllFile in dllFileNames) + { + AssemblyName an = AssemblyName.GetAssemblyName(dllFile); + Assembly assembly = Assembly.Load(an); + assemblies.Add(assembly); + } + + Type pluginType = typeof(T); + List pluginTypes = new List(); + foreach (Assembly assembly in assemblies) + { + if (assembly != null) + { + Type[] types = assembly.GetTypes(); + + foreach (Type type in types) + { + if (type.IsInterface || type.IsAbstract) + { + continue; + } else + { + if (type.GetInterface(pluginType.FullName) != null) + { + pluginTypes.Add(type); + } + } + } + } + } + + List plugins = new List(pluginTypes.Count); + foreach (Type type in pluginTypes) + { + T plugin = (T)Activator.CreateInstance(type); + plugins.Add(plugin); + } + + pluginList = plugins; + } + } + + /// + /// Get the list of compliant plugins + /// + /// The plugins. + public List GetPlugins() + { + return pluginList; + } + + private List RecursiveFindDLLs (string path) + { + List output = new List(); + + foreach (string d in Directory.GetDirectories(path)) + { + output.AddRange(RecursiveFindDLLs(d)); + } + + output.AddRange(Directory.GetFiles(path, "*.dll")); + return output; + } + } +} \ No newline at end of file diff --git a/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs new file mode 100644 index 000000000..52663f696 --- /dev/null +++ b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Windows.Forms; + +namespace EVEMon.Common.PluginSytem.Helpers +{ + /// + /// Generator to fetch the different Plugins menu. + /// + public class PluginMenuGenerator + { + /// + /// The enumerable of the loaded plugins. + /// + public IEnumerable PluginData; + + /// + /// The amount of plugins loaded. + /// + public int PluginCount = 0; + + /// + /// Constructor for the PluginMenuGenerator. + /// + public PluginMenuGenerator() + { + LoadPluginData(); + } + + /// + /// Method to launch the loading of plugins. + /// + public void LoadPluginData() + { + List output = new List(); + PluginCount = 0; + + List pluginList = PluginLibrary.Instance.GetPluginByType(typeof(IPluginMenuItem)); + foreach (IPluginMenuItem pluginInfo in pluginList) + { + output.AddRange(pluginInfo.MenuItemList); + PluginCount++; + } + + PluginData = output.ToArray(); + } + + /// + /// Method to know if there is any plugin loaded with menu items. + /// + /// A value representing the number of loaded plugins with menu items. + public bool AnyPluginsAvailable() + { + return PluginCount > 0; + } + + } +} diff --git a/src/EVEMon.Common/PluginSytem/Interfaces/IPluginToolMenuItem.cs b/src/EVEMon.Common/PluginSytem/Interfaces/IPluginToolMenuItem.cs new file mode 100644 index 000000000..26a8dcb66 --- /dev/null +++ b/src/EVEMon.Common/PluginSytem/Interfaces/IPluginToolMenuItem.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Windows.Forms; + +namespace EVEMon.Common.PluginSytem +{ + /// + /// Plugin contract to add a MenuItem in the plugins list. + /// + public interface IPluginMenuItem : IEVEMonPluginContract + { + /// + /// Fill with the list of MenuItem that will be appended to the Main menu list. + /// + IEnumerable MenuItemList { get; } + } +} diff --git a/src/EVEMon/MainWindow.Designer.cs b/src/EVEMon/MainWindow.Designer.cs index 023c85db5..7202bdc34 100644 --- a/src/EVEMon/MainWindow.Designer.cs +++ b/src/EVEMon/MainWindow.Designer.cs @@ -95,6 +95,7 @@ private void InitializeComponent() this.secondSeparator = new System.Windows.Forms.ToolStripSeparator(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pluginsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.forumsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.userVoiceMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.twitterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -311,7 +312,8 @@ private void InitializeComponent() this.plansToolStripMenuItem, this.toolsToolStripMenuItem, this.helpToolStripMenuItem, - this.testsToolStripMenuItem}); + this.testsToolStripMenuItem, + this.pluginsToolStripMenuItem}); this.mainMenuBar.Location = new System.Drawing.Point(0, 0); this.mainMenuBar.Name = "mainMenuBar"; this.mainMenuBar.Size = new System.Drawing.Size(600, 24); @@ -547,7 +549,7 @@ private void InitializeComponent() this.secondSeparator, this.optionsToolStripMenuItem}); this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; - this.toolsToolStripMenuItem.Size = new System.Drawing.Size(47, 20); + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20); this.toolsToolStripMenuItem.Text = "&Tools"; // // apiTesterToolStripMenuItem @@ -696,11 +698,17 @@ private void InitializeComponent() this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); this.helpToolStripMenuItem.Text = "&Help"; // + // pluginsToolStripMenuItem + // + this.pluginsToolStripMenuItem.Name = "pluginsToolStripMenuItem"; + this.pluginsToolStripMenuItem.Size = new System.Drawing.Size(44, 20); + this.pluginsToolStripMenuItem.Text = "Plu&gins"; + // // forumsMenuItem // this.forumsMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("forumsMenuItem.Image"))); this.forumsMenuItem.Name = "forumsMenuItem"; - this.forumsMenuItem.Size = new System.Drawing.Size(229, 22); + this.forumsMenuItem.Size = new System.Drawing.Size(230, 22); this.forumsMenuItem.Text = "&Forums"; this.forumsMenuItem.Click += new System.EventHandler(this.forumsMenuItem_Click); // @@ -708,7 +716,7 @@ private void InitializeComponent() // this.userVoiceMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("userVoiceMenuItem.Image"))); this.userVoiceMenuItem.Name = "userVoiceMenuItem"; - this.userVoiceMenuItem.Size = new System.Drawing.Size(229, 22); + this.userVoiceMenuItem.Size = new System.Drawing.Size(230, 22); this.userVoiceMenuItem.Text = "&Suggest a Feature (UserVoice)"; this.userVoiceMenuItem.Click += new System.EventHandler(this.userVoiceMenuItem_Click); // @@ -716,7 +724,7 @@ private void InitializeComponent() // this.twitterMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("twitterMenuItem.Image"))); this.twitterMenuItem.Name = "twitterMenuItem"; - this.twitterMenuItem.Size = new System.Drawing.Size(229, 22); + this.twitterMenuItem.Size = new System.Drawing.Size(230, 22); this.twitterMenuItem.Text = "Follow us on Twitter"; this.twitterMenuItem.Click += new System.EventHandler(this.twitterMenuItem_Click); // @@ -724,20 +732,20 @@ private void InitializeComponent() // this.readTheDocsManualToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("readTheDocsManualToolStripMenuItem.Image"))); this.readTheDocsManualToolStripMenuItem.Name = "readTheDocsManualToolStripMenuItem"; - this.readTheDocsManualToolStripMenuItem.Size = new System.Drawing.Size(229, 22); + this.readTheDocsManualToolStripMenuItem.Size = new System.Drawing.Size(230, 22); this.readTheDocsManualToolStripMenuItem.Text = "Read The Docs (Manual)"; this.readTheDocsManualToolStripMenuItem.Click += new System.EventHandler(this.readTheDocsManualMenuItem_Click); // // helpAboutKnownProblemsToolStripSeparator // this.helpAboutKnownProblemsToolStripSeparator.Name = "helpAboutKnownProblemsToolStripSeparator"; - this.helpAboutKnownProblemsToolStripSeparator.Size = new System.Drawing.Size(226, 6); + this.helpAboutKnownProblemsToolStripSeparator.Size = new System.Drawing.Size(227, 6); // // aboutMenuItem // this.aboutMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("aboutMenuItem.Image"))); this.aboutMenuItem.Name = "aboutMenuItem"; - this.aboutMenuItem.Size = new System.Drawing.Size(229, 22); + this.aboutMenuItem.Size = new System.Drawing.Size(230, 22); this.aboutMenuItem.Text = "&About..."; this.aboutMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); // @@ -751,7 +759,7 @@ private void InitializeComponent() this.testTimeoutOneSecToolStripMenuItem, this.restartToolStripMenuItem}); this.testsToolStripMenuItem.Name = "testsToolStripMenuItem"; - this.testsToolStripMenuItem.Size = new System.Drawing.Size(40, 20); + this.testsToolStripMenuItem.Size = new System.Drawing.Size(41, 20); this.testsToolStripMenuItem.Text = "Te&st"; this.testsToolStripMenuItem.Visible = false; this.testsToolStripMenuItem.DropDownOpening += new System.EventHandler(this.testToolStripMenuItem_DropDownOpening); @@ -1271,6 +1279,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem pluginsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem aboutMenuItem; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem mineralWorksheetMenuItem; diff --git a/src/EVEMon/MainWindow.cs b/src/EVEMon/MainWindow.cs index 71f9f421c..2c71d38d4 100644 --- a/src/EVEMon/MainWindow.cs +++ b/src/EVEMon/MainWindow.cs @@ -48,6 +48,8 @@ using EVEMon.Updater; using EVEMon.Watchdog; using EVEMon.WindowsApi; +using EVEMon.Common.PluginSytem; +using EVEMon.Common.PluginSytem.Helpers; namespace EVEMon { @@ -118,6 +120,12 @@ public MainWindow() DisplayTestMenu(); m_startMinimized = Environment.GetCommandLineArgs().Contains("-startMinimized"); + + PluginMenuGenerator pluginMenuGenetaror = new PluginMenuGenerator(); + if (pluginMenuGenetaror.AnyPluginsAvailable()) + { + pluginsToolStripMenuItem.DropDownItems.AddRange(pluginMenuGenetaror.PluginData); + } } /// diff --git a/src/EVEMon/Program.cs b/src/EVEMon/Program.cs index e67fb64a3..09a72375c 100644 --- a/src/EVEMon/Program.cs +++ b/src/EVEMon/Program.cs @@ -12,6 +12,7 @@ using EVEMon.Common.Threading; using EVEMon.ExceptionHandling; using EVEMon.WindowsApi; +using EVEMon.Common.PluginSytem; namespace EVEMon { @@ -77,6 +78,10 @@ private static async Task StartupAsync() EveMonClient.Initialize(); Settings.Initialize(); + // Plugin system loading + PluginLibrary.pluginPathOverride = AppDomain.CurrentDomain.BaseDirectory + @"\plugins\"; + PluginLibrary.Instance.FlushAndLoadPlugins(); + // Did something requested an exit before we entered Run() ? if (s_exitRequested) return; From b723f312c19222109a89adf1828985206a94489b Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Wed, 31 Aug 2016 21:49:08 -0400 Subject: [PATCH 2/6] Plugin System Fix: -Change the plugin menu generator to use Array instead of IEnumerable --- src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs index 52663f696..cbcd63e09 100644 --- a/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs +++ b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs @@ -11,7 +11,7 @@ public class PluginMenuGenerator /// /// The enumerable of the loaded plugins. /// - public IEnumerable PluginData; + public ToolStripMenuItem[] PluginData; /// /// The amount of plugins loaded. From 8c3eae45881fca9fa60e891e1992a0e6d9055541 Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Wed, 31 Aug 2016 22:07:41 -0400 Subject: [PATCH 3/6] Plugin System Fix: -Proper comment. --- src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs index cbcd63e09..1c528e87e 100644 --- a/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs +++ b/src/EVEMon.Common/PluginSytem/Helpers/PluginMenuGenerator.cs @@ -9,7 +9,7 @@ namespace EVEMon.Common.PluginSytem.Helpers public class PluginMenuGenerator { /// - /// The enumerable of the loaded plugins. + /// The array of the loaded plugins. /// public ToolStripMenuItem[] PluginData; From ed9b10c24e9d45e59ba2ea39b4afbfd2af65c2cb Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Thu, 1 Sep 2016 13:21:04 -0400 Subject: [PATCH 4/6] Plugin System enhancement: -Converted the Plugin name from method to property. -Added a Plugin version to the basic interface for future development. --- .../PluginSytem/Core/IEVEMonPluginContract.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs b/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs index 0dbce54b3..2cabbd34e 100644 --- a/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs +++ b/src/EVEMon.Common/PluginSytem/Core/IEVEMonPluginContract.cs @@ -6,9 +6,13 @@ public interface IEVEMonPluginContract { /// - /// Define the plugin name. + /// Gets the plugin name. /// - /// Returns a value identifying the plugin by name. - string PluginName(); + string PluginName { get; } + + /// + /// Gets the plugin version information. + /// + string PluginVersion { get; } } } From beabb39a085107e05245d5e1d51b257ed159f0c1 Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Thu, 1 Sep 2016 15:52:21 -0400 Subject: [PATCH 5/6] Plugin System Enhancement: -Add a plugin viewer that is a plugin itself to view which plugins are loaded. --- EVEMon.sln | 11 ++ .../EVEMon.PluginViewer.csproj | 111 ++++++++++++++++ plugins/EVEMon.PluginViewer/PluginViewer.cs | 86 +++++++++++++ .../PluginViewerForm.Designer.cs | 115 +++++++++++++++++ .../EVEMon.PluginViewer/PluginViewerForm.cs | 60 +++++++++ .../EVEMon.PluginViewer/PluginViewerForm.resx | 120 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 18 +++ plugins/EVEMon.PluginViewer/packages.config | 7 + 8 files changed, 528 insertions(+) create mode 100644 plugins/EVEMon.PluginViewer/EVEMon.PluginViewer.csproj create mode 100644 plugins/EVEMon.PluginViewer/PluginViewer.cs create mode 100644 plugins/EVEMon.PluginViewer/PluginViewerForm.Designer.cs create mode 100644 plugins/EVEMon.PluginViewer/PluginViewerForm.cs create mode 100644 plugins/EVEMon.PluginViewer/PluginViewerForm.resx create mode 100644 plugins/EVEMon.PluginViewer/Properties/AssemblyInfo.cs create mode 100644 plugins/EVEMon.PluginViewer/packages.config diff --git a/EVEMon.sln b/EVEMon.sln index 2b6c81792..d2534bdf9 100644 --- a/EVEMon.sln +++ b/EVEMon.sln @@ -52,6 +52,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.EVEMon", "tests\Tests EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Helpers", "tests\Tests.Helpers\Tests.Helpers.csproj", "{1917E258-0979-4333-8B20-5D66E8986E1C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{894945A4-8C92-451A-9FFE-0C5402EBD68E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EVEMon.PluginViewer", "plugins\EVEMon.PluginViewer\EVEMon.PluginViewer.csproj", "{E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -133,6 +137,12 @@ Global {1917E258-0979-4333-8B20-5D66E8986E1C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1917E258-0979-4333-8B20-5D66E8986E1C}.Release|Any CPU.ActiveCfg = Release|Any CPU {1917E258-0979-4333-8B20-5D66E8986E1C}.Snapshot|Any CPU.ActiveCfg = Snapshot|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Release|Any CPU.Build.0 = Release|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Snapshot|Any CPU.ActiveCfg = Release|Any CPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2}.Snapshot|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -152,5 +162,6 @@ Global {87682BB1-CCE5-4CA4-BDE8-1A2ACF0B3CE0} = {9AB16E7E-E520-4444-8E8E-165129CC93B3} {FD639BF6-3414-4FB2-8325-61744D44F028} = {B2FD94FF-A895-4519-A97F-6DEA32F15F8E} {1917E258-0979-4333-8B20-5D66E8986E1C} = {B2FD94FF-A895-4519-A97F-6DEA32F15F8E} + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2} = {894945A4-8C92-451A-9FFE-0C5402EBD68E} EndGlobalSection EndGlobal diff --git a/plugins/EVEMon.PluginViewer/EVEMon.PluginViewer.csproj b/plugins/EVEMon.PluginViewer/EVEMon.PluginViewer.csproj new file mode 100644 index 000000000..2e98fe014 --- /dev/null +++ b/plugins/EVEMon.PluginViewer/EVEMon.PluginViewer.csproj @@ -0,0 +1,111 @@ + + + + + Debug + AnyCPU + {E11D68FA-686E-45E0-9FA2-9EC9F90ECCA2} + Library + Properties + EVEMon.PluginViewer + EVEMon.PluginViewer + v4.6.1 + 512 + + + + + + true + full + false + ..\..\src\EVEMon\bin\Debug\Plugins\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\src\EVEMon\bin\Release\Plugins\ + TRACE + prompt + 4 + + + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll + False + + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll + False + + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll + False + + + + + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll + False + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll + False + + + + + + + + + + + + + + Form + + + PluginViewerForm.cs + + + + + + PluginViewerForm.cs + + + + + + + + {c0665275-3e0b-4117-81b0-751206ed03cd} + EVEMon.Common + False + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + \ No newline at end of file diff --git a/plugins/EVEMon.PluginViewer/PluginViewer.cs b/plugins/EVEMon.PluginViewer/PluginViewer.cs new file mode 100644 index 000000000..43a1c72b6 --- /dev/null +++ b/plugins/EVEMon.PluginViewer/PluginViewer.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +using EVEMon.Common.PluginSytem; + +namespace EVEMon.PluginViewer +{ + class PluginViewer : IPluginMenuItem + { + + #region Fields + + private ToolStripMenuItem _mnuPluginViewer; + + private const string _pluginName = "Plugin Viewer"; + private const string _pluginVersion = "0.1"; + + #endregion Fields + + + #region Constructor + + public PluginViewer() + { + ToolStripMenuItem mnuPluginViewer = new ToolStripMenuItem(); + mnuPluginViewer.Name = "mnuPluginViewer"; + mnuPluginViewer.Size = new System.Drawing.Size(114, 20); + mnuPluginViewer.Text = "Plugin Viewer..."; + mnuPluginViewer.Click += new System.EventHandler(mnuPluginViewer_Click); + + _mnuPluginViewer = mnuPluginViewer; + } + + #endregion Constructor + + + #region IPLuginMenuItem implementation + + public IEnumerable MenuItemList + { + get + { + var list = new List(); + list.Add(_mnuPluginViewer); + return list; + } + } + + public string PluginName + { + get + { + return _pluginName; + } + + } + + public string PluginVersion + { + get + { + return _pluginVersion; + } + } + + #endregion IPLuginMenuItem implementation + + + #region Event Handler + + /// + /// Event handling for when the Menu item is clicked. + /// + /// the control sending. + /// event args + private void mnuPluginViewer_Click(object sender, EventArgs e) + { + PluginViewerForm viewer = new PluginViewerForm(); + viewer.ShowDialog(); + } + + #endregion Event Handler + + } +} diff --git a/plugins/EVEMon.PluginViewer/PluginViewerForm.Designer.cs b/plugins/EVEMon.PluginViewer/PluginViewerForm.Designer.cs new file mode 100644 index 000000000..2cc3db87f --- /dev/null +++ b/plugins/EVEMon.PluginViewer/PluginViewerForm.Designer.cs @@ -0,0 +1,115 @@ +namespace EVEMon.PluginViewer +{ + partial class PluginViewerForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblPluginCountHeader = new System.Windows.Forms.Label(); + this.lblPluginCount = new System.Windows.Forms.Label(); + this.btnClose = new System.Windows.Forms.Button(); + this.txtPluginInfo = new System.Windows.Forms.TextBox(); + this.lblLoadedPlugins = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // lblPluginCountHeader + // + this.lblPluginCountHeader.AutoSize = true; + this.lblPluginCountHeader.Location = new System.Drawing.Point(12, 12); + this.lblPluginCountHeader.Name = "lblPluginCountHeader"; + this.lblPluginCountHeader.Size = new System.Drawing.Size(70, 13); + this.lblPluginCountHeader.TabIndex = 0; + this.lblPluginCountHeader.Text = "Plugin Count:"; + // + // lblPluginCount + // + this.lblPluginCount.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.lblPluginCount.Location = new System.Drawing.Point(93, 11); + this.lblPluginCount.Name = "lblPluginCount"; + this.lblPluginCount.Size = new System.Drawing.Size(100, 16); + this.lblPluginCount.TabIndex = 1; + this.lblPluginCount.Text = "0"; + // + // btnClose + // + this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnClose.Location = new System.Drawing.Point(292, 346); + this.btnClose.Name = "btnClose"; + this.btnClose.Size = new System.Drawing.Size(75, 23); + this.btnClose.TabIndex = 3; + this.btnClose.Text = "&Close"; + this.btnClose.UseVisualStyleBackColor = true; + this.btnClose.Click += new System.EventHandler(this.btnClose_Click); + // + // txtPluginInfo + // + this.txtPluginInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPluginInfo.Enabled = false; + this.txtPluginInfo.Location = new System.Drawing.Point(12, 58); + this.txtPluginInfo.Multiline = true; + this.txtPluginInfo.Name = "txtPluginInfo"; + this.txtPluginInfo.Size = new System.Drawing.Size(355, 282); + this.txtPluginInfo.TabIndex = 4; + // + // lblLoadedPlugins + // + this.lblLoadedPlugins.AutoSize = true; + this.lblLoadedPlugins.Location = new System.Drawing.Point(12, 42); + this.lblLoadedPlugins.Name = "lblLoadedPlugins"; + this.lblLoadedPlugins.Size = new System.Drawing.Size(80, 13); + this.lblLoadedPlugins.TabIndex = 5; + this.lblLoadedPlugins.Text = "Loaded Plugins"; + // + // PluginViewerForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(378, 375); + this.Controls.Add(this.lblLoadedPlugins); + this.Controls.Add(this.txtPluginInfo); + this.Controls.Add(this.btnClose); + this.Controls.Add(this.lblPluginCount); + this.Controls.Add(this.lblPluginCountHeader); + this.MaximizeBox = false; + this.MinimumSize = new System.Drawing.Size(394, 413); + this.Name = "PluginViewerForm"; + this.Text = "Plugin Viewer"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label lblPluginCountHeader; + private System.Windows.Forms.Label lblPluginCount; + private System.Windows.Forms.Button btnClose; + private System.Windows.Forms.TextBox txtPluginInfo; + private System.Windows.Forms.Label lblLoadedPlugins; + } +} \ No newline at end of file diff --git a/plugins/EVEMon.PluginViewer/PluginViewerForm.cs b/plugins/EVEMon.PluginViewer/PluginViewerForm.cs new file mode 100644 index 000000000..bb12a4ac8 --- /dev/null +++ b/plugins/EVEMon.PluginViewer/PluginViewerForm.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +using EVEMon.Common.PluginSytem; + +namespace EVEMon.PluginViewer +{ + public partial class PluginViewerForm : Form + { + #region Constructor + + /// + /// Constructor for the Plugin Viewer form. + /// + public PluginViewerForm() + { + InitializeComponent(); + + LoadPluginsInfo(); + } + + #endregion Constructor + + + #region Event Handler + + /// + /// Event handler for the close button. + /// + /// control sender + /// event args + private void btnClose_Click(object sender, EventArgs e) + { + Close(); + } + + #endregion Event Handler + + #region Methods + + /// + /// Populates the Plugin info list and displays it. + /// + public void LoadPluginsInfo() + { + StringBuilder output = new StringBuilder(); + List pluginList = PluginLibrary.Instance.GetAllPlugins(); + foreach (IEVEMonPluginContract pluginInfo in pluginList) + { + output.AppendLine($"{pluginInfo.PluginName} v{pluginInfo.PluginVersion}"); + } + txtPluginInfo.Text = output.ToString(); + lblPluginCount.Text = pluginList.Count.ToString(); + } + + #endregion Methods + } +} diff --git a/plugins/EVEMon.PluginViewer/PluginViewerForm.resx b/plugins/EVEMon.PluginViewer/PluginViewerForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/plugins/EVEMon.PluginViewer/PluginViewerForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/plugins/EVEMon.PluginViewer/Properties/AssemblyInfo.cs b/plugins/EVEMon.PluginViewer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a352af794 --- /dev/null +++ b/plugins/EVEMon.PluginViewer/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// Note: Shared assembly information is specified in SharedAssemblyInfo.cs + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EVEMon.PluginViewer")] +[assembly: AssemblyProduct("EVEMon.PluginViewer")] + +// Version information for an assembly +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e11d68fa-686e-45e0-9fa2-9ec9f90ecca2")] + diff --git a/plugins/EVEMon.PluginViewer/packages.config b/plugins/EVEMon.PluginViewer/packages.config new file mode 100644 index 000000000..616de5a6c --- /dev/null +++ b/plugins/EVEMon.PluginViewer/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 2de55fcb9c2322fd47e54c4a9ae49150b98f8d0d Mon Sep 17 00:00:00 2001 From: elliena-bulmer Date: Thu, 1 Sep 2016 18:33:16 -0400 Subject: [PATCH 6/6] Plugin System enhancement: -Add proper comments to the plugin viewer files. -Added a extra 'todo' in the PluginLibrary. --- plugins/EVEMon.PluginViewer/PluginViewer.cs | 29 +++++++++++++++++-- .../EVEMon.PluginViewer/PluginViewerForm.cs | 4 +++ .../PluginSytem/Core/PluginLibrary.cs | 3 +- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/plugins/EVEMon.PluginViewer/PluginViewer.cs b/plugins/EVEMon.PluginViewer/PluginViewer.cs index 43a1c72b6..9d4459756 100644 --- a/plugins/EVEMon.PluginViewer/PluginViewer.cs +++ b/plugins/EVEMon.PluginViewer/PluginViewer.cs @@ -6,14 +6,27 @@ namespace EVEMon.PluginViewer { + /// + /// PluginViewer class used to see what plugins are loaded. + /// class PluginViewer : IPluginMenuItem { #region Fields - + + /// + /// The MenuItem to be sent to the plugin interface. + /// private ToolStripMenuItem _mnuPluginViewer; + /// + /// The Plugin name constant. + /// private const string _pluginName = "Plugin Viewer"; + + /// + /// The plugin version constant. + /// private const string _pluginVersion = "0.1"; #endregion Fields @@ -21,14 +34,17 @@ class PluginViewer : IPluginMenuItem #region Constructor + /// + /// Constructor for the PluginViewer class. + /// public PluginViewer() { + // Initialize the menuitem. ToolStripMenuItem mnuPluginViewer = new ToolStripMenuItem(); mnuPluginViewer.Name = "mnuPluginViewer"; mnuPluginViewer.Size = new System.Drawing.Size(114, 20); mnuPluginViewer.Text = "Plugin Viewer..."; mnuPluginViewer.Click += new System.EventHandler(mnuPluginViewer_Click); - _mnuPluginViewer = mnuPluginViewer; } @@ -37,6 +53,9 @@ public PluginViewer() #region IPLuginMenuItem implementation + /// + /// Gets the MenuItemList information for the plugin system. + /// public IEnumerable MenuItemList { get @@ -47,6 +66,9 @@ public IEnumerable MenuItemList } } + /// + /// Gets the plugin name for the plugin system. + /// public string PluginName { get @@ -56,6 +78,9 @@ public string PluginName } + /// + /// Gets the plugin version for the plugin system. + /// public string PluginVersion { get diff --git a/plugins/EVEMon.PluginViewer/PluginViewerForm.cs b/plugins/EVEMon.PluginViewer/PluginViewerForm.cs index bb12a4ac8..1848f0345 100644 --- a/plugins/EVEMon.PluginViewer/PluginViewerForm.cs +++ b/plugins/EVEMon.PluginViewer/PluginViewerForm.cs @@ -7,6 +7,9 @@ namespace EVEMon.PluginViewer { + /// + /// Form displaying the loaded plugins. + /// public partial class PluginViewerForm : Form { #region Constructor @@ -38,6 +41,7 @@ private void btnClose_Click(object sender, EventArgs e) #endregion Event Handler + #region Methods /// diff --git a/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs b/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs index 4ea214d8c..6c1f31743 100644 --- a/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs +++ b/src/EVEMon.Common/PluginSytem/Core/PluginLibrary.cs @@ -4,7 +4,8 @@ using System.Linq; // TODO: -// - use 1 plugin loader for each interface type request in a dictionary +// - Use 1 plugin loader for each interface type request in a dictionary. +// - Find a way to prevent loading non-EVEMon plugins that may be using the same file extension. namespace EVEMon.Common.PluginSytem {