diff --git a/src/Artemis.Core/Plugins/Abstract/ModuleDataModel.cs b/src/Artemis.Core/Plugins/Abstract/ModuleDataModel.cs
index ad95bd980..d2ce723de 100644
--- a/src/Artemis.Core/Plugins/Abstract/ModuleDataModel.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ModuleDataModel.cs
@@ -1,5 +1,4 @@
using Artemis.Core.Plugins.Interfaces;
-using Stylet;
namespace Artemis.Core.Plugins.Abstract
{
diff --git a/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs b/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
index 68ec913a6..10ba6fe62 100644
--- a/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
@@ -1,5 +1,4 @@
using Artemis.Core.Plugins.Interfaces;
-using Artemis.Core.Plugins.Models;
using Stylet;
namespace Artemis.Core.Plugins.Abstract
diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
index 8b719727d..8cce411ae 100644
--- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs
@@ -17,11 +17,6 @@ namespace Artemis.Core.Plugins.Abstract
///
public abstract bool ExpandsMainDataModel { get; }
- ///
- public void EnablePlugin()
- {
- // Load and activate the last active profile
- }
///
public virtual void Update(double deltaTime)
@@ -47,9 +42,13 @@ namespace Artemis.Core.Plugins.Abstract
public abstract IScreen GetMainViewModel();
///
- public void Dispose()
- {
- }
+ public abstract void EnablePlugin();
+
+ ///
+ public abstract void DisablePlugin();
+
+ ///
+ public abstract void Dispose();
public void ChangeActiveProfile(Profile profile)
{
diff --git a/src/Artemis.Core/Plugins/Interfaces/IPlugin.cs b/src/Artemis.Core/Plugins/Interfaces/IPlugin.cs
index 238122061..c1a703cee 100644
--- a/src/Artemis.Core/Plugins/Interfaces/IPlugin.cs
+++ b/src/Artemis.Core/Plugins/Interfaces/IPlugin.cs
@@ -2,14 +2,21 @@
namespace Artemis.Core.Plugins.Interfaces
{
+ ///
///
/// This is the base plugin type, use the other interfaces such as IModule to create plugins
///
public interface IPlugin : IDisposable
{
///
- /// Called when the plugin is loaded
+ /// Called when the plugin is activated
///
void EnablePlugin();
+
+
+ ///
+ /// Called when the plugin is deactivated
+ ///
+ void DisablePlugin();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Models/PluginInfo.cs b/src/Artemis.Core/Plugins/Models/PluginInfo.cs
index 8cba360d8..d2746ca07 100644
--- a/src/Artemis.Core/Plugins/Models/PluginInfo.cs
+++ b/src/Artemis.Core/Plugins/Models/PluginInfo.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using AppDomainToolkit;
using Artemis.Core.Plugins.Interfaces;
using Newtonsoft.Json;
@@ -7,6 +8,10 @@ namespace Artemis.Core.Plugins.Models
{
public class PluginInfo
{
+ internal PluginInfo()
+ {
+ }
+
///
/// The plugins GUID
///
@@ -28,10 +33,10 @@ namespace Artemis.Core.Plugins.Models
public string Main { get; set; }
///
- /// Full path to the plugin's current folder
+ /// The plugins root directory
///
[JsonIgnore]
- public string Folder { get; set; }
+ public DirectoryInfo Directory { get; set; }
///
/// A reference to the type implementing IPlugin, available after successful load
@@ -48,6 +53,7 @@ namespace Artemis.Core.Plugins.Models
///
/// The AppDomain context of this plugin
///
+ [JsonIgnore]
internal AppDomainContext Context { get; set; }
public override string ToString()
diff --git a/src/Artemis.Core/ProfileElements/Layer.cs b/src/Artemis.Core/ProfileElements/Layer.cs
index dd519f67c..7cd3a612a 100644
--- a/src/Artemis.Core/ProfileElements/Layer.cs
+++ b/src/Artemis.Core/ProfileElements/Layer.cs
@@ -61,12 +61,10 @@ namespace Artemis.Core.ProfileElements
public void UpdateLayerType(ILayerType layerType)
{
if (LayerType != null)
- {
lock (LayerType)
{
LayerType.Dispose();
}
- }
LayerType = layerType;
}
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 48ec8119d..f4b1ebd6b 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Exceptions;
using Artemis.Core.Plugins.Interfaces;
@@ -38,7 +37,7 @@ namespace Artemis.Core.Services
throw new ArtemisCoreException("Cannot initialize the core as it is already initialized.");
// Initialize the services
- await _pluginService.LoadPlugins();
+ await Task.Run(() => _pluginService.LoadPlugins());
await _rgbService.LoadDevices();
OnInitialized();
@@ -48,7 +47,7 @@ namespace Artemis.Core.Services
{
try
{
- var modules = _pluginService.GetModules();
+ var modules = _pluginService.GetPluginsOfType();
// Update all active modules
foreach (var module in modules)
diff --git a/src/Artemis.Core/Services/Interfaces/IPluginService.cs b/src/Artemis.Core/Services/Interfaces/IPluginService.cs
index 85e6bde9d..ce31000e3 100644
--- a/src/Artemis.Core/Services/Interfaces/IPluginService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IPluginService.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Plugins.Interfaces;
using Artemis.Core.Plugins.Models;
@@ -11,46 +9,81 @@ namespace Artemis.Core.Services.Interfaces
public interface IPluginService : IArtemisService, IDisposable
{
///
- /// Indicates wether or not plugins are currently being loaded
+ /// Indicates whether or not plugins are currently being loaded
///
bool LoadingPlugins { get; }
- ///
- /// All loaded plugins
- ///
- ReadOnlyCollection Plugins { get; }
-
///
/// Loads all installed plugins. If plugins already loaded this will reload them all
///
- Task LoadPlugins();
+ void LoadPlugins();
///
- /// Occurs when a single plugin has loaded
+ /// Unloads all installed plugins.
///
- event EventHandler PluginLoaded;
+ void UnloadPlugins();
///
- /// Occurs when loading all plugins has started
+ /// Loads the plugin defined in the provided
///
- event EventHandler StartedLoadingPlugins;
+ /// The plugin info defining the plugin to load
+ void LoadPlugin(PluginInfo pluginInfo);
///
- /// Occurs when loading all plugins has finished
+ /// Unloads the plugin defined in the provided
///
- event EventHandler FinishedLoadedPlugins;
+ /// The plugin info defining the plugin to unload
+ void UnloadPlugin(PluginInfo pluginInfo);
///
- /// If found, returns an instance of the layer type matching the given GUID
+ /// Finds the plugin info related to the plugin
+ ///
+ /// The plugin you want to find the plugin info for
+ /// The plugins PluginInfo
+ PluginInfo GetPluginInfo(IPlugin plugin);
+
+ ///
+ /// Gets the plugin info of all loaded plugins
+ ///
+ /// A list containing all the plugin info
+ List GetAllPluginInfo();
+
+ ///
+ /// Finds an instance of the layer type matching the given GUID
///
/// The GUID of the layer type to find
/// An instance of the layer type
ILayerType GetLayerTypeByGuid(Guid layerTypeGuid);
///
- /// Returns all the plugins implementing
+ /// Finds all enabled instances of type
///
- ///
- IReadOnlyList GetModules();
+ /// Either or a plugin type implementing
+ /// Returns a list of plug instances of type
+ List GetPluginsOfType() where T : IPlugin;
+
+ #region Events
+
+ ///
+ /// Occurs when a plugin has loaded
+ ///
+ event EventHandler PluginLoaded;
+
+ ///
+ /// Occurs when a plugin has been unloaded
+ ///
+ event EventHandler PluginUnloaded;
+
+ ///
+ /// Occurs when a plugin has been enabled
+ ///
+ event EventHandler PluginEnabled;
+
+ ///
+ /// Occurs when a plugin has been disabled
+ ///
+ event EventHandler PluginDisabled;
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs
index d7ecb467d..aa7e9a4b9 100644
--- a/src/Artemis.Core/Services/PluginService.cs
+++ b/src/Artemis.Core/Services/PluginService.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
-using System.Threading.Tasks;
using AppDomainToolkit;
using Artemis.Core.Events;
using Artemis.Core.Exceptions;
@@ -23,7 +21,7 @@ namespace Artemis.Core.Services
private readonly List _plugins;
private IKernel _childKernel;
- public PluginService(IKernel kernel)
+ internal PluginService(IKernel kernel)
{
_kernel = kernel;
_plugins = new List();
@@ -32,19 +30,20 @@ namespace Artemis.Core.Services
Directory.CreateDirectory(Constants.DataFolder + "plugins");
}
+ ///
public bool LoadingPlugins { get; private set; }
- public ReadOnlyCollection Plugins => _plugins.AsReadOnly();
///
- public async Task LoadPlugins()
+ public void LoadPlugins()
{
if (LoadingPlugins)
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
- OnStartedLoadingPlugins();
-
- await Task.Run(() =>
+ lock (_plugins)
{
+ LoadingPlugins = true;
+
+ // Unload all currently loaded plugins first
UnloadPlugins();
// Create a child kernel and app domain that will only contain the plugins
@@ -53,6 +52,7 @@ namespace Artemis.Core.Services
// Load the plugin assemblies into the plugin context
var directory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins"));
foreach (var subDirectory in directory.EnumerateDirectories())
+ {
try
{
// Load the metadata
@@ -62,61 +62,145 @@ namespace Artemis.Core.Services
// Locate the main entry
var pluginInfo = JsonConvert.DeserializeObject(File.ReadAllText(metadataFile));
- // TODO Just temporarily until settings are in place
- pluginInfo.Enabled = true;
- var mainFile = Path.Combine(subDirectory.FullName, pluginInfo.Main);
- if (!File.Exists(mainFile))
- throw new ArtemisPluginException(pluginInfo, "Couldn't find the plugins main entry at " + mainFile);
-
- // Load the plugin, all types implementing IPlugin and register them with DI
- var setupInfo = new AppDomainSetup
- {
- ApplicationName = pluginInfo.Guid.ToString(),
- ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
- PrivateBinPath = subDirectory.FullName
- };
- pluginInfo.Context = AppDomainContext.Create(setupInfo);
-
- try
- {
- pluginInfo.Context.LoadAssemblyWithReferences(LoadMethod.LoadFrom, mainFile);
- }
- catch (Exception e)
- {
- throw new ArtemisPluginException(pluginInfo, "Failed to load the plugins assembly", e);
- }
-
- // Get the IPlugin implementation from the main assembly and if there is only one, instantiate it
- var mainAssembly = pluginInfo.Context.Domain.GetAssemblies().First(a => a.Location == mainFile);
- var pluginTypes = mainAssembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t)).ToList();
- if (pluginTypes.Count > 1)
- throw new ArtemisPluginException(pluginInfo, $"Plugin contains {pluginTypes.Count} implementations of IPlugin, only 1 allowed");
- if (pluginTypes.Count == 0)
- throw new ArtemisPluginException(pluginInfo, "Plugin contains no implementation of IPlugin");
-
- var pluginType = pluginTypes.Single();
- _childKernel.Bind().To(pluginType).InSingletonScope();
- try
- {
- pluginInfo.Instance = (IPlugin) _childKernel.Get(pluginType);
- }
- catch (Exception e)
- {
- throw new ArtemisPluginException(pluginInfo, "Failed to instantiate the plugin", e);
- }
- _plugins.Add(pluginInfo);
+ pluginInfo.Directory = subDirectory;
+ LoadPlugin(pluginInfo);
}
catch (Exception e)
{
throw new ArtemisPluginException("Failed to load plugin", e);
}
+ }
// Activate plugins after they are all loaded
foreach (var pluginInfo in _plugins.Where(p => p.Enabled))
+ {
pluginInfo.Instance.EnablePlugin();
- });
+ OnPluginEnabled(new PluginEventArgs(pluginInfo));
+ }
- OnFinishedLoadedPlugins();
+ LoadingPlugins = false;
+ }
+ }
+
+ ///
+ public void UnloadPlugins()
+ {
+ lock (_plugins)
+ {
+ // Unload all plugins
+ while (_plugins.Count > 0)
+ {
+ UnloadPlugin(_plugins[0]);
+ }
+
+ // Dispose the child kernel and therefore any leftover plugins instantiated with it
+ if (_childKernel != null)
+ {
+ _childKernel.Dispose();
+ _childKernel = null;
+ }
+
+ _plugins.Clear();
+ }
+ }
+
+ ///
+ public void LoadPlugin(PluginInfo pluginInfo)
+ {
+ lock (_plugins)
+ {
+ // Unload the plugin first if it is already loaded
+ if (_plugins.Contains(pluginInfo))
+ UnloadPlugin(pluginInfo);
+
+ // TODO Just temporarily until settings are in place
+ pluginInfo.Enabled = true;
+ var mainFile = Path.Combine(pluginInfo.Directory.FullName, pluginInfo.Main);
+ if (!File.Exists(mainFile))
+ throw new ArtemisPluginException(pluginInfo, "Couldn't find the plugins main entry at " + mainFile);
+
+ // Load the plugin, all types implementing IPlugin and register them with DI
+ var setupInfo = new AppDomainSetup
+ {
+ ApplicationName = pluginInfo.Guid.ToString(),
+ ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
+ PrivateBinPath = pluginInfo.Directory.FullName
+ };
+ pluginInfo.Context = AppDomainContext.Create(setupInfo);
+
+ try
+ {
+ pluginInfo.Context.LoadAssemblyWithReferences(LoadMethod.LoadFrom, mainFile);
+ }
+ catch (Exception e)
+ {
+ throw new ArtemisPluginException(pluginInfo, "Failed to load the plugins assembly", e);
+ }
+
+ // Get the IPlugin implementation from the main assembly and if there is only one, instantiate it
+ var mainAssembly = pluginInfo.Context.Domain.GetAssemblies().First(a => a.Location == mainFile);
+ var pluginTypes = mainAssembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t)).ToList();
+ if (pluginTypes.Count > 1)
+ throw new ArtemisPluginException(pluginInfo, $"Plugin contains {pluginTypes.Count} implementations of IPlugin, only 1 allowed");
+ if (pluginTypes.Count == 0)
+ throw new ArtemisPluginException(pluginInfo, "Plugin contains no implementation of IPlugin");
+
+ var pluginType = pluginTypes.Single();
+ try
+ {
+ pluginInfo.Instance = (IPlugin) _childKernel.Get(pluginType);
+ }
+ catch (Exception e)
+ {
+ throw new ArtemisPluginException(pluginInfo, "Failed to instantiate the plugin", e);
+ }
+
+ _plugins.Add(pluginInfo);
+ OnPluginLoaded(new PluginEventArgs(pluginInfo));
+ }
+ }
+
+ ///
+ public void UnloadPlugin(PluginInfo pluginInfo)
+ {
+ lock (_plugins)
+ {
+ try
+ {
+ pluginInfo.Instance.DisablePlugin();
+ }
+ catch (Exception)
+ {
+ // TODO: Log these
+ }
+ finally
+ {
+ OnPluginDisabled(new PluginEventArgs(pluginInfo));
+ }
+
+ _childKernel.Unbind(pluginInfo.Instance.GetType());
+
+ pluginInfo.Instance.Dispose();
+ pluginInfo.Context.Dispose();
+ _plugins.Remove(pluginInfo);
+
+ OnPluginUnloaded(new PluginEventArgs(pluginInfo));
+ }
+ }
+
+ ///
+ public PluginInfo GetPluginInfo(IPlugin plugin)
+ {
+ lock (_plugins)
+ {
+ return _plugins.FirstOrDefault(p => p.Instance == plugin);
+ }
+ }
+
+ ///
+ public List GetAllPluginInfo()
+ {
+ return new List(_plugins);
}
///
@@ -132,9 +216,13 @@ namespace Artemis.Core.Services
return layerType;
}
- public IReadOnlyList GetModules()
+ ///
+ public List GetPluginsOfType() where T : IPlugin
{
- return Plugins.Where(p => p.Instance is IModule).Select(p => (IModule) p.Instance).ToList();
+ lock (_plugins)
+ {
+ return _plugins.Where(p => p.Enabled && p.Instance is T).Select(p => (T) p.Instance).ToList();
+ }
}
public void Dispose()
@@ -142,38 +230,32 @@ namespace Artemis.Core.Services
UnloadPlugins();
}
- private void UnloadPlugins()
- {
- _plugins.Clear();
-
- if (_childKernel != null)
- {
- _childKernel.Dispose();
- _childKernel = null;
- }
- }
#region Events
public event EventHandler PluginLoaded;
- public event EventHandler StartedLoadingPlugins;
- public event EventHandler FinishedLoadedPlugins;
+ public event EventHandler PluginUnloaded;
+ public event EventHandler PluginEnabled;
+ public event EventHandler PluginDisabled;
- private void OnPluginLoaded(PluginEventArgs e)
+ protected virtual void OnPluginLoaded(PluginEventArgs e)
{
PluginLoaded?.Invoke(this, e);
}
- private void OnStartedLoadingPlugins()
+ protected virtual void OnPluginUnloaded(PluginEventArgs e)
{
- LoadingPlugins = true;
- StartedLoadingPlugins?.Invoke(this, EventArgs.Empty);
+ PluginUnloaded?.Invoke(this, e);
}
- private void OnFinishedLoadedPlugins()
+ protected virtual void OnPluginEnabled(PluginEventArgs e)
{
- LoadingPlugins = false;
- FinishedLoadedPlugins?.Invoke(this, EventArgs.Empty);
+ PluginEnabled?.Invoke(this, e);
+ }
+
+ protected virtual void OnPluginDisabled(PluginEventArgs e)
+ {
+ PluginDisabled?.Invoke(this, e);
}
#endregion
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index 45606879f..8dadac100 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -13,8 +13,8 @@ namespace Artemis.Core.Services
{
public class RgbService : IRgbService, IDisposable
{
- private readonly TimerUpdateTrigger _updateTrigger;
private readonly List _loadedDevices;
+ private readonly TimerUpdateTrigger _updateTrigger;
public RgbService()
{
@@ -68,7 +68,9 @@ namespace Artemis.Core.Services
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
}
else
+ {
OnDeviceReloaded(new DeviceEventArgs(surfaceDevice));
+ }
}
}
});
diff --git a/src/Artemis.Core/app.config b/src/Artemis.Core/app.config
index 58347c373..ec91ee1d6 100644
--- a/src/Artemis.Core/app.config
+++ b/src/Artemis.Core/app.config
@@ -28,7 +28,8 @@
-
+
@@ -52,7 +53,8 @@
-
+
@@ -68,7 +70,8 @@
-
+
@@ -84,7 +87,8 @@
-
+
@@ -92,7 +96,8 @@
-
+
diff --git a/src/Artemis.Core/packages.config b/src/Artemis.Core/packages.config
index ce487c687..6dc3ac0de 100644
--- a/src/Artemis.Core/packages.config
+++ b/src/Artemis.Core/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs
index 67aa2b011..2c792b09e 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs
+++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs
@@ -1,4 +1,5 @@
-using System.Drawing;
+using System;
+using System.Drawing;
using Artemis.Core.Plugins.Interfaces;
using Artemis.Core.ProfileElements;
using QRCoder;
@@ -17,6 +18,11 @@ namespace Artemis.Plugins.LayerTypes.Brush
var qrGenerator = new QRCodeGenerator();
}
+ public void DisablePlugin()
+ {
+ throw new NotImplementedException();
+ }
+
public void Update(Layer layer)
{
var config = layer.LayerTypeConfiguration as BrushConfiguration;
diff --git a/src/Artemis.Plugins.LayerTypes.Brush/packages.config b/src/Artemis.Plugins.LayerTypes.Brush/packages.config
index f559146e0..046348732 100644
--- a/src/Artemis.Plugins.LayerTypes.Brush/packages.config
+++ b/src/Artemis.Plugins.LayerTypes.Brush/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
index cafc22e97..afac2ad5d 100644
--- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs
+++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Drawing;
using Artemis.Core;
using Artemis.Core.Plugins.Interfaces;
@@ -70,6 +71,11 @@ namespace Artemis.Plugins.Modules.General
PopulateColors();
}
+ public void DisablePlugin()
+ {
+ throw new NotImplementedException();
+ }
+
private void UpdateLedColor(Led led, double deltaTime)
{
if (_colors.ContainsKey(led))
diff --git a/src/Artemis.Plugins.Modules.General/packages.config b/src/Artemis.Plugins.Modules.General/packages.config
index a2474caba..a7463e291 100644
--- a/src/Artemis.Plugins.Modules.General/packages.config
+++ b/src/Artemis.Plugins.Modules.General/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/src/Artemis.Storage/Migrations/StorageContextModelSnapshot.cs b/src/Artemis.Storage/Migrations/StorageContextModelSnapshot.cs
index c27d9c124..d0eb9328a 100644
--- a/src/Artemis.Storage/Migrations/StorageContextModelSnapshot.cs
+++ b/src/Artemis.Storage/Migrations/StorageContextModelSnapshot.cs
@@ -11,7 +11,7 @@ namespace Artemis.Storage.Migrations
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
-#pragma warning disable 612, 618
+ #pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
@@ -180,7 +180,7 @@ namespace Artemis.Storage.Migrations
.WithMany()
.HasForeignKey("RootFolderGuid");
});
-#pragma warning restore 612, 618
+ #pragma warning restore 612, 618
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/App.config b/src/Artemis.UI/App.config
index 39dcaca51..fcbfc6adb 100644
--- a/src/Artemis.UI/App.config
+++ b/src/Artemis.UI/App.config
@@ -31,7 +31,8 @@
-
+
@@ -55,7 +56,8 @@
-
+
@@ -71,7 +73,8 @@
-
+
@@ -87,7 +90,8 @@
-
+
@@ -95,7 +99,8 @@
-
+
diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs
index 5a4f82d85..c3c420e5b 100644
--- a/src/Artemis.UI/Bootstrapper.cs
+++ b/src/Artemis.UI/Bootstrapper.cs
@@ -22,6 +22,8 @@ namespace Artemis.UI
protected override void ConfigureIoC(IKernel kernel)
{
+ kernel.Settings.InjectNonPublic = true;
+
// Load this assembly's module
kernel.Load();
// Load the core assembly's module
diff --git a/src/Artemis.UI/Controls/Visualizers/RGBSurfaceVisualizer.cs b/src/Artemis.UI/Controls/Visualizers/RGBSurfaceVisualizer.cs
index 32c0cb364..d05fd77c1 100644
--- a/src/Artemis.UI/Controls/Visualizers/RGBSurfaceVisualizer.cs
+++ b/src/Artemis.UI/Controls/Visualizers/RGBSurfaceVisualizer.cs
@@ -70,10 +70,8 @@ namespace Artemis.UI.Controls.Visualizers
private void RGBSurfaceOnSurfaceLayoutChanged(SurfaceLayoutChangedEventArgs args)
{
if (args.DeviceAdded)
- {
foreach (var device in args.Devices)
_newDevices.Add(device);
- }
UpdateSurface();
}
diff --git a/src/Artemis.UI/Stylet/ArtemisViewManager.cs b/src/Artemis.UI/Stylet/ArtemisViewManager.cs
index fdb164b3e..75461aa26 100644
--- a/src/Artemis.UI/Stylet/ArtemisViewManager.cs
+++ b/src/Artemis.UI/Stylet/ArtemisViewManager.cs
@@ -6,7 +6,6 @@ namespace Artemis.UI.Stylet
{
public ArtemisViewManager(ViewManagerConfig config) : base(config)
{
-
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Stylet/NinjectBootstrapper.cs b/src/Artemis.UI/Stylet/NinjectBootstrapper.cs
index e04484bed..e8717f153 100644
--- a/src/Artemis.UI/Stylet/NinjectBootstrapper.cs
+++ b/src/Artemis.UI/Stylet/NinjectBootstrapper.cs
@@ -34,7 +34,7 @@ namespace Artemis.UI.Stylet
kernel.Bind().ToConstant(new ViewManager(viewManagerConfig));
kernel.Bind().ToConstant(this).InTransientScope();
- kernel.Bind().ToMethod(c => new WindowManager(c.Kernel.Get(),() => c.Kernel.Get(), c.Kernel.Get())).InSingletonScope();
+ kernel.Bind().ToMethod(c => new WindowManager(c.Kernel.Get(), () => c.Kernel.Get(), c.Kernel.Get())).InSingletonScope();
kernel.Bind().To().InSingletonScope();
kernel.Bind().To(); // Not singleton!
}
diff --git a/src/Artemis.UI/ViewModels/RootViewModel.cs b/src/Artemis.UI/ViewModels/RootViewModel.cs
index a62f43220..392cc0933 100644
--- a/src/Artemis.UI/ViewModels/RootViewModel.cs
+++ b/src/Artemis.UI/ViewModels/RootViewModel.cs
@@ -1,9 +1,9 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
+using Artemis.Core.Events;
using Artemis.Core.Plugins.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.ViewModels.Interfaces;
@@ -29,44 +29,22 @@ namespace Artemis.UI.ViewModels
// Sync up with the plugin service
Modules = new BindableCollection();
- LoadingPlugins = _pluginService.LoadingPlugins;
- _pluginService.StartedLoadingPlugins += PluginServiceOnStartedLoadingPlugins;
- _pluginService.FinishedLoadedPlugins += PluginServiceOnFinishedLoadedPlugins;
-
- if (!LoadingPlugins)
- Modules.AddRange(_pluginService.GetModules());
+ Modules.AddRange(_pluginService.GetPluginsOfType());
+ _pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
+ _pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
PropertyChanged += OnSelectedModuleChanged;
PropertyChanged += OnSelectedPageChanged;
}
-
public IObservableCollection Modules { get; set; }
-
public bool MenuOpen { get; set; }
- public bool LoadingPlugins { get; set; }
public ListBoxItem SelectedPage { get; set; }
public IModule SelectedModule { get; set; }
- private void PluginServiceOnStartedLoadingPlugins(object sender, EventArgs eventArgs)
- {
- LoadingPlugins = true;
-
- Modules.Clear();
- SelectedModule = null;
- }
-
- private void PluginServiceOnFinishedLoadedPlugins(object sender, EventArgs eventArgs)
- {
- Modules.AddRange(_pluginService.GetModules());
- SelectedModule = null;
-
- LoadingPlugins = false;
- }
-
public async Task NavigateToSelectedModule()
{
- if (SelectedModule == null || LoadingPlugins)
+ if (SelectedModule == null)
return;
// Create a view model for the given plugin info (which will be a module)
@@ -78,6 +56,31 @@ namespace Artemis.UI.ViewModels
MenuOpen = false;
}
+ private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
+ {
+ var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid);
+ if (existing != null)
+ {
+ if (SelectedModule == existing && SelectedModule != null)
+ SelectedModule = null;
+ Modules.Remove(existing);
+ }
+
+ if (e.PluginInfo.Instance is IModule module)
+ Modules.Add(module);
+ }
+
+ private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e)
+ {
+ var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid);
+ if (existing != null)
+ {
+ if (SelectedModule == existing && SelectedModule != null)
+ SelectedModule = null;
+ Modules.Remove(existing);
+ }
+ }
+
private async void OnSelectedModuleChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedModule")