mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Plugins - Separated plugins and implementations as different principles
This commit is contained in:
parent
c0d0e421c7
commit
1e0dc1894d
@ -34,10 +34,10 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly PluginInfo CorePluginInfo = new PluginInfo
|
public static readonly PluginInfo CorePluginInfo = new PluginInfo
|
||||||
{
|
{
|
||||||
Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core", Enabled = true
|
Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core", IsEnabled = true
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static readonly CorePlugin CorePlugin = new CorePlugin {PluginInfo = CorePluginInfo};
|
internal static readonly CorePluginImplementation CorePluginImplementation = new CorePluginImplementation {PluginInfo = CorePluginInfo};
|
||||||
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {PluginInfo = CorePluginInfo};
|
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {PluginInfo = CorePluginInfo};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal EventPredicateWrapperDataModel()
|
internal EventPredicateWrapperDataModel()
|
||||||
{
|
{
|
||||||
PluginInfo = Constants.CorePluginInfo;
|
Implementation = Constants.CorePluginInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal ListPredicateWrapperDataModel()
|
internal ListPredicateWrapperDataModel()
|
||||||
{
|
{
|
||||||
PluginInfo = Constants.CorePluginInfo;
|
Implementation = Constants.CorePluginInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
|
|||||||
@ -93,7 +93,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data model GUID of the <see cref="Target" /> if it is a <see cref="DataModel" />
|
/// Gets the data model GUID of the <see cref="Target" /> if it is a <see cref="DataModel" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid? DataModelGuid => Target?.PluginInfo.Guid;
|
public Guid? DataModelGuid => Target?.Implementation.Guid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the point-separated path associated with this <see cref="DataModelPath" />
|
/// Gets the point-separated path associated with this <see cref="DataModelPath" />
|
||||||
@ -295,7 +295,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
|
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
|
||||||
{
|
{
|
||||||
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
|
if (e.Registration.DataModel.Implementation.Guid != Entity.DataModelGuid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Target = e.Registration.DataModel;
|
Target = e.Registration.DataModel;
|
||||||
@ -304,7 +304,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void DataModelStoreOnDataModelRemoved(object? sender, DataModelStoreEvent e)
|
private void DataModelStoreOnDataModelRemoved(object? sender, DataModelStoreEvent e)
|
||||||
{
|
{
|
||||||
if (e.Registration.DataModel.PluginInfo.Guid != Entity.DataModelGuid)
|
if (e.Registration.DataModel.Implementation.Guid != Entity.DataModelGuid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Target = null;
|
Target = null;
|
||||||
|
|||||||
@ -662,7 +662,7 @@ namespace Artemis.Core
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
LayerBrushReference current = General.BrushReference.CurrentValue;
|
LayerBrushReference current = General.BrushReference.CurrentValue;
|
||||||
if (e.Registration.Plugin.PluginInfo.Guid == current.BrushPluginGuid &&
|
if (e.Registration.PluginImplementation.PluginInfo.Guid == current.BrushPluginGuid &&
|
||||||
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
||||||
ActivateLayerBrush();
|
ActivateLayerBrush();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -254,7 +254,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
// If effects provided by the plugin are on the element, replace them with placeholders
|
// If effects provided by the plugin are on the element, replace them with placeholders
|
||||||
List<BaseLayerEffect> pluginEffects = _layerEffects.Where(ef => ef.Descriptor.LayerEffectProvider != null &&
|
List<BaseLayerEffect> pluginEffects = _layerEffects.Where(ef => ef.Descriptor.LayerEffectProvider != null &&
|
||||||
ef.PluginInfo.Guid == e.Registration.Plugin.PluginInfo.Guid).ToList();
|
ef.PluginInfo.Guid == e.Registration.PluginImplementation.PluginInfo.Guid).ToList();
|
||||||
foreach (BaseLayerEffect pluginEffect in pluginEffects)
|
foreach (BaseLayerEffect pluginEffect in pluginEffects)
|
||||||
{
|
{
|
||||||
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
|
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
|
||||||
@ -268,7 +268,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void LayerEffectStoreOnLayerEffectAdded(object sender, LayerEffectStoreEvent e)
|
private void LayerEffectStoreOnLayerEffectAdded(object sender, LayerEffectStoreEvent e)
|
||||||
{
|
{
|
||||||
if (RenderElementEntity.LayerEffects.Any(ef => ef.PluginGuid == e.Registration.Plugin.PluginInfo.Guid))
|
if (RenderElementEntity.LayerEffects.Any(ef => ef.PluginGuid == e.Registration.PluginImplementation.PluginInfo.Guid))
|
||||||
ActivateEffects();
|
ActivateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,10 +14,10 @@ namespace Artemis.Core
|
|||||||
private SKPath _renderPath;
|
private SKPath _renderPath;
|
||||||
private SKRect _renderRectangle;
|
private SKRect _renderRectangle;
|
||||||
|
|
||||||
internal ArtemisDevice(IRGBDevice rgbDevice, Plugin plugin, ArtemisSurface surface)
|
internal ArtemisDevice(IRGBDevice rgbDevice, PluginImplementation pluginImplementation, ArtemisSurface surface)
|
||||||
{
|
{
|
||||||
RgbDevice = rgbDevice;
|
RgbDevice = rgbDevice;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
Surface = surface;
|
Surface = surface;
|
||||||
DeviceEntity = new DeviceEntity();
|
DeviceEntity = new DeviceEntity();
|
||||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||||
@ -30,10 +30,10 @@ namespace Artemis.Core
|
|||||||
CalculateRenderProperties();
|
CalculateRenderProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ArtemisDevice(IRGBDevice rgbDevice, Plugin plugin, ArtemisSurface surface, DeviceEntity deviceEntity)
|
internal ArtemisDevice(IRGBDevice rgbDevice, PluginImplementation pluginImplementation, ArtemisSurface surface, DeviceEntity deviceEntity)
|
||||||
{
|
{
|
||||||
RgbDevice = rgbDevice;
|
RgbDevice = rgbDevice;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
Surface = surface;
|
Surface = surface;
|
||||||
DeviceEntity = deviceEntity;
|
DeviceEntity = deviceEntity;
|
||||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||||
@ -52,7 +52,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IRGBDevice RgbDevice { get; }
|
public IRGBDevice RgbDevice { get; }
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
public ArtemisSurface Surface { get; }
|
public ArtemisSurface Surface { get; }
|
||||||
public DeviceEntity DeviceEntity { get; }
|
public DeviceEntity DeviceEntity { get; }
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace Artemis.Core.Ninject
|
|||||||
protected override ISettingsService CreateInstance(IContext context)
|
protected override ISettingsService CreateInstance(IContext context)
|
||||||
{
|
{
|
||||||
IRequest parentRequest = context.Request.ParentRequest;
|
IRequest parentRequest = context.Request.ParentRequest;
|
||||||
if (parentRequest == null || typeof(Plugin).IsAssignableFrom(parentRequest.Service))
|
if (parentRequest == null || typeof(PluginImplementation).IsAssignableFrom(parentRequest.Service))
|
||||||
throw new ArtemisPluginException($"SettingsService can not be injected into a plugin. Inject {nameof(PluginSettings)} instead.");
|
throw new ArtemisPluginException($"SettingsService can not be injected into a plugin. Inject {nameof(PluginSettings)} instead.");
|
||||||
|
|
||||||
return _instance;
|
return _instance;
|
||||||
|
|||||||
@ -14,10 +14,10 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
|
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin info this data model belongs to
|
/// Gets the plugin implementation this data model belongs to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
public PluginInfo PluginInfo { get; internal set; }
|
public DataModelPluginImplementation Implementation { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the <see cref="DataModelPropertyAttribute" /> describing this data model
|
/// Gets the <see cref="DataModelPropertyAttribute" /> describing this data model
|
||||||
@ -43,9 +43,9 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ReadOnlyCollection<PropertyInfo> GetHiddenProperties()
|
public ReadOnlyCollection<PropertyInfo> GetHiddenProperties()
|
||||||
{
|
{
|
||||||
if (PluginInfo.Instance is ProfileModule profileModule)
|
if (Implementation is ProfileModule profileModule)
|
||||||
return profileModule.HiddenProperties;
|
return profileModule.HiddenProperties;
|
||||||
if (PluginInfo.Instance is BaseDataModelExpansion dataModelExpansion)
|
if (Implementation is BaseDataModelExpansion dataModelExpansion)
|
||||||
return dataModelExpansion.HiddenProperties;
|
return dataModelExpansion.HiddenProperties;
|
||||||
|
|
||||||
return new List<PropertyInfo>().AsReadOnly();
|
return new List<PropertyInfo>().AsReadOnly();
|
||||||
@ -81,7 +81,7 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
throw new ArtemisCoreException($"Cannot add a dynamic data model with key '{key}' " +
|
throw new ArtemisCoreException($"Cannot add a dynamic data model with key '{key}' " +
|
||||||
"because the key is already in use by a static property on this data model.");
|
"because the key is already in use by a static property on this data model.");
|
||||||
|
|
||||||
dynamicDataModel.PluginInfo = PluginInfo;
|
dynamicDataModel.Implementation = Implementation;
|
||||||
dynamicDataModel.DataModelDescription = new DataModelPropertyAttribute
|
dynamicDataModel.DataModelDescription = new DataModelPropertyAttribute
|
||||||
{
|
{
|
||||||
Name = string.IsNullOrWhiteSpace(name) ? key.Humanize() : name,
|
Name = string.IsNullOrWhiteSpace(name) ? key.Humanize() : name,
|
||||||
|
|||||||
@ -42,18 +42,18 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalEnablePlugin()
|
internal override void InternalEnable()
|
||||||
{
|
{
|
||||||
DataModel = Activator.CreateInstance<T>();
|
DataModel = Activator.CreateInstance<T>();
|
||||||
DataModel.PluginInfo = PluginInfo;
|
DataModel.Implementation = PluginInfo;
|
||||||
DataModel.DataModelDescription = GetDataModelDescription();
|
DataModel.DataModelDescription = GetDataModelDescription();
|
||||||
base.InternalEnablePlugin();
|
base.InternalEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalDisablePlugin()
|
internal override void InternalDisable()
|
||||||
{
|
{
|
||||||
DataModel = null;
|
DataModel = null;
|
||||||
base.InternalDisablePlugin();
|
base.InternalDisable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,7 +8,7 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
/// For internal use only, to implement your own layer property type, extend <see cref="DataModelExpansion{T}" />
|
/// For internal use only, to implement your own layer property type, extend <see cref="DataModelExpansion{T}" />
|
||||||
/// instead.
|
/// instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseDataModelExpansion : Plugin
|
public abstract class BaseDataModelExpansion : DataModelPluginImplementation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c>
|
/// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c>
|
||||||
|
|||||||
47
src/Artemis.Core/Plugins/DataModelPluginImplementation.cs
Normal file
47
src/Artemis.Core/Plugins/DataModelPluginImplementation.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an implementation of a certain type provided by a plugin with support for data models
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DataModelPluginImplementation : PluginImplementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
||||||
|
/// provided
|
||||||
|
/// <paramref name="interval" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="interval">The interval at which the update should occur</param>
|
||||||
|
/// <param name="action">
|
||||||
|
/// The action to call every time the interval has passed. The delta time parameter represents the
|
||||||
|
/// time passed since the last update in seconds
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The resulting plugin update registration which can be used to stop the update</returns>
|
||||||
|
public TimedUpdateRegistration AddTimedUpdate(TimeSpan interval, Action<double> action)
|
||||||
|
{
|
||||||
|
if (action == null)
|
||||||
|
throw new ArgumentNullException(nameof(action));
|
||||||
|
return new TimedUpdateRegistration(PluginInfo, interval, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
||||||
|
/// provided
|
||||||
|
/// <paramref name="interval" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="interval">The interval at which the update should occur</param>
|
||||||
|
/// <param name="asyncAction">
|
||||||
|
/// The async action to call every time the interval has passed. The delta time parameter
|
||||||
|
/// represents the time passed since the last update in seconds
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The resulting plugin update registration</returns>
|
||||||
|
public TimedUpdateRegistration AddTimedUpdate(TimeSpan interval, Func<double, Task> asyncAction)
|
||||||
|
{
|
||||||
|
if (asyncAction == null)
|
||||||
|
throw new ArgumentNullException(nameof(asyncAction));
|
||||||
|
return new TimedUpdateRegistration(PluginInfo, interval, asyncAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ namespace Artemis.Core.DeviceProviders
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to implement and register your own device provider
|
/// Allows you to implement and register your own device provider
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DeviceProvider : Plugin
|
public abstract class DeviceProvider : PluginImplementation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="DeviceProvider" /> class
|
/// Creates a new instance of the <see cref="DeviceProvider" /> class
|
||||||
@ -34,7 +34,7 @@ namespace Artemis.Core.DeviceProviders
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void DisablePlugin()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
// Does not happen with device providers, they require Artemis to restart
|
// Does not happen with device providers, they require Artemis to restart
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to create one or more <see cref="LayerBrush{T}" />s usable by profile layers.
|
/// Allows you to create one or more <see cref="LayerBrush{T}" />s usable by profile layers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class LayerBrushProvider : Plugin
|
public abstract class LayerBrushProvider : PluginImplementation
|
||||||
{
|
{
|
||||||
private readonly List<LayerBrushDescriptor> _layerBrushDescriptors;
|
private readonly List<LayerBrushDescriptor> _layerBrushDescriptors;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
protected LayerBrushProvider()
|
protected LayerBrushProvider()
|
||||||
{
|
{
|
||||||
_layerBrushDescriptors = new List<LayerBrushDescriptor>();
|
_layerBrushDescriptors = new List<LayerBrushDescriptor>();
|
||||||
PluginDisabled += OnPluginDisabled;
|
Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -38,7 +38,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// </param>
|
/// </param>
|
||||||
protected void RegisterLayerBrushDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerBrush
|
protected void RegisterLayerBrushDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerBrush
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!IsEnabled)
|
||||||
throw new ArtemisPluginException(PluginInfo, "Can only add a layer brush descriptor when the plugin is enabled");
|
throw new ArtemisPluginException(PluginInfo, "Can only add a layer brush descriptor when the plugin is enabled");
|
||||||
|
|
||||||
LayerBrushDescriptor descriptor = new LayerBrushDescriptor(displayName, description, icon, typeof(T), this);
|
LayerBrushDescriptor descriptor = new LayerBrushDescriptor(displayName, description, icon, typeof(T), this);
|
||||||
@ -46,7 +46,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
LayerBrushStore.Add(descriptor);
|
LayerBrushStore.Add(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// The store will clean up the registrations by itself, the plugin just needs to clear its own list
|
// The store will clean up the registrations by itself, the plugin just needs to clear its own list
|
||||||
_layerBrushDescriptors.Clear();
|
_layerBrushDescriptors.Clear();
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace Artemis.Core.LayerEffects
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to register one or more <see cref="LayerEffect{T}" />s usable by profile layers.
|
/// Allows you to register one or more <see cref="LayerEffect{T}" />s usable by profile layers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class LayerEffectProvider : Plugin
|
public abstract class LayerEffectProvider : PluginImplementation
|
||||||
{
|
{
|
||||||
private readonly List<LayerEffectDescriptor> _layerEffectDescriptors;
|
private readonly List<LayerEffectDescriptor> _layerEffectDescriptors;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ namespace Artemis.Core.LayerEffects
|
|||||||
protected LayerEffectProvider()
|
protected LayerEffectProvider()
|
||||||
{
|
{
|
||||||
_layerEffectDescriptors = new List<LayerEffectDescriptor>();
|
_layerEffectDescriptors = new List<LayerEffectDescriptor>();
|
||||||
PluginDisabled += OnPluginDisabled;
|
Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -38,7 +38,7 @@ namespace Artemis.Core.LayerEffects
|
|||||||
/// </param>
|
/// </param>
|
||||||
protected void RegisterLayerEffectDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerEffect
|
protected void RegisterLayerEffectDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerEffect
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!IsEnabled)
|
||||||
throw new ArtemisPluginException(PluginInfo, "Can only add a layer effect descriptor when the plugin is enabled");
|
throw new ArtemisPluginException(PluginInfo, "Can only add a layer effect descriptor when the plugin is enabled");
|
||||||
|
|
||||||
LayerEffectDescriptor descriptor = new LayerEffectDescriptor(displayName, description, icon, typeof(T), this);
|
LayerEffectDescriptor descriptor = new LayerEffectDescriptor(displayName, description, icon, typeof(T), this);
|
||||||
@ -46,7 +46,7 @@ namespace Artemis.Core.LayerEffects
|
|||||||
LayerEffectStore.Add(descriptor);
|
LayerEffectStore.Add(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// The store will clean up the registrations by itself, the plugin just needs to clear its own list
|
// The store will clean up the registrations by itself, the plugin just needs to clear its own list
|
||||||
_layerEffectDescriptors.Clear();
|
_layerEffectDescriptors.Clear();
|
||||||
|
|||||||
@ -45,18 +45,18 @@ namespace Artemis.Core.Modules
|
|||||||
return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description};
|
return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalEnablePlugin()
|
internal override void InternalEnable()
|
||||||
{
|
{
|
||||||
DataModel = Activator.CreateInstance<T>();
|
DataModel = Activator.CreateInstance<T>();
|
||||||
DataModel.PluginInfo = PluginInfo;
|
DataModel.Implementation = PluginInfo;
|
||||||
DataModel.DataModelDescription = GetDataModelDescription();
|
DataModel.DataModelDescription = GetDataModelDescription();
|
||||||
base.InternalEnablePlugin();
|
base.InternalEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalDisablePlugin()
|
internal override void InternalDisable()
|
||||||
{
|
{
|
||||||
DataModel = null;
|
DataModel = null;
|
||||||
base.InternalDisablePlugin();
|
base.InternalDisable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ namespace Artemis.Core.Modules
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to add support for new games/applications
|
/// Allows you to add support for new games/applications
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Module : Plugin
|
public abstract class Module : DataModelPluginImplementation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The modules display name that's shown in the menu
|
/// The modules display name that's shown in the menu
|
||||||
|
|||||||
@ -71,18 +71,18 @@ namespace Artemis.Core.Modules
|
|||||||
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalEnablePlugin()
|
internal override void InternalEnable()
|
||||||
{
|
{
|
||||||
DataModel = Activator.CreateInstance<T>();
|
DataModel = Activator.CreateInstance<T>();
|
||||||
DataModel.PluginInfo = PluginInfo;
|
DataModel.Implementation = PluginInfo;
|
||||||
DataModel.DataModelDescription = GetDataModelDescription();
|
DataModel.DataModelDescription = GetDataModelDescription();
|
||||||
base.InternalEnablePlugin();
|
base.InternalEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void InternalDisablePlugin()
|
internal override void InternalDisable()
|
||||||
{
|
{
|
||||||
Deactivate(true);
|
Deactivate(true);
|
||||||
base.InternalDisablePlugin();
|
base.InternalDisable();
|
||||||
DataModel = null;
|
DataModel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,178 +1,18 @@
|
|||||||
using System;
|
namespace Artemis.Core
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the base plugin type, use the other interfaces such as Module to create plugins
|
/// Represents a plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Plugin : IDisposable
|
public abstract class Plugin
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin info related to this plugin
|
/// Gets the plugin info related to this plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PluginInfo PluginInfo { get; internal set; }
|
public PluginInfo Info { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether the plugin is enabled
|
|
||||||
/// </summary>
|
|
||||||
public bool Enabled { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
|
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PluginConfigurationDialog ConfigurationDialog { get; protected set; }
|
public PluginConfigurationDialog ConfigurationDialog { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the plugin is activated
|
|
||||||
/// </summary>
|
|
||||||
public abstract void EnablePlugin();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when the plugin is deactivated or when Artemis shuts down
|
|
||||||
/// </summary>
|
|
||||||
public abstract void DisablePlugin();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
|
||||||
/// provided
|
|
||||||
/// <paramref name="interval" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="interval">The interval at which the update should occur</param>
|
|
||||||
/// <param name="action">
|
|
||||||
/// The action to call every time the interval has passed. The delta time parameter represents the
|
|
||||||
/// time passed since the last update in seconds
|
|
||||||
/// </param>
|
|
||||||
/// <returns>The resulting plugin update registration which can be used to stop the update</returns>
|
|
||||||
public PluginUpdateRegistration AddTimedUpdate(TimeSpan interval, Action<double> action)
|
|
||||||
{
|
|
||||||
if (action == null)
|
|
||||||
throw new ArgumentNullException(nameof(action));
|
|
||||||
return new PluginUpdateRegistration(PluginInfo, interval, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
|
||||||
/// provided
|
|
||||||
/// <paramref name="interval" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="interval">The interval at which the update should occur</param>
|
|
||||||
/// <param name="asyncAction">
|
|
||||||
/// The async action to call every time the interval has passed. The delta time parameter
|
|
||||||
/// represents the time passed since the last update in seconds
|
|
||||||
/// </param>
|
|
||||||
/// <returns>The resulting plugin update registration</returns>
|
|
||||||
public PluginUpdateRegistration AddTimedUpdate(TimeSpan interval, Func<double, Task> asyncAction)
|
|
||||||
{
|
|
||||||
if (asyncAction == null)
|
|
||||||
throw new ArgumentNullException(nameof(asyncAction));
|
|
||||||
return new PluginUpdateRegistration(PluginInfo, interval, asyncAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void SetEnabled(bool enable, bool isAutoEnable = false)
|
|
||||||
{
|
|
||||||
if (enable && !Enabled)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (isAutoEnable && PluginInfo.GetLockFileCreated())
|
|
||||||
{
|
|
||||||
// Don't wrap existing lock exceptions, simply rethrow them
|
|
||||||
if (PluginInfo.LoadException is ArtemisPluginLockException)
|
|
||||||
throw PluginInfo.LoadException;
|
|
||||||
|
|
||||||
throw new ArtemisPluginLockException(PluginInfo.LoadException);
|
|
||||||
}
|
|
||||||
|
|
||||||
Enabled = true;
|
|
||||||
PluginInfo.Enabled = true;
|
|
||||||
PluginInfo.CreateLockFile();
|
|
||||||
|
|
||||||
// Allow up to 15 seconds for plugins to activate.
|
|
||||||
// This means plugins that need more time should do their long running tasks in a background thread, which is intentional
|
|
||||||
// Little meh: Running this from a different thread could cause deadlocks
|
|
||||||
Task enableTask = Task.Run(InternalEnablePlugin);
|
|
||||||
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
|
||||||
throw new ArtemisPluginException(PluginInfo, "Plugin load timeout");
|
|
||||||
|
|
||||||
PluginInfo.LoadException = null;
|
|
||||||
OnPluginEnabled();
|
|
||||||
}
|
|
||||||
// If enable failed, put it back in a disabled state
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
PluginInfo.Enabled = false;
|
|
||||||
PluginInfo.LoadException = e;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!(PluginInfo.LoadException is ArtemisPluginLockException))
|
|
||||||
PluginInfo.DeleteLockFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!enable && Enabled)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
PluginInfo.Enabled = false;
|
|
||||||
|
|
||||||
// Even if disable failed, still leave it in a disabled state to avoid more issues
|
|
||||||
InternalDisablePlugin();
|
|
||||||
OnPluginDisabled();
|
|
||||||
}
|
|
||||||
// A failed load is still enabled in plugin info (to avoid disabling it permanently after a fail)
|
|
||||||
// update even that when manually disabling
|
|
||||||
else if (!enable && !Enabled)
|
|
||||||
{
|
|
||||||
PluginInfo.Enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void InternalEnablePlugin()
|
|
||||||
{
|
|
||||||
EnablePlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void InternalDisablePlugin()
|
|
||||||
{
|
|
||||||
DisablePlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
DisablePlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when the plugin is enabled
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler PluginEnabled;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when the plugin is disabled
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler PluginDisabled;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Triggers the PluginEnabled event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnPluginEnabled()
|
|
||||||
{
|
|
||||||
PluginEnabled?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Triggers the PluginDisabled event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnPluginDisabled()
|
|
||||||
{
|
|
||||||
PluginDisabled?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The layer brush this dialog belongs to
|
/// The layer brush this dialog belongs to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal Plugin Plugin { get; set; }
|
internal PluginImplementation PluginImplementation { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of view model the tab contains
|
/// The type of view model the tab contains
|
||||||
|
|||||||
@ -10,25 +10,25 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class
|
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin"></param>
|
/// <param name="pluginImplementation"></param>
|
||||||
protected PluginConfigurationViewModel(Plugin plugin)
|
protected PluginConfigurationViewModel(PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class with a validator
|
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class with a validator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin"></param>
|
/// <param name="pluginImplementation"></param>
|
||||||
/// <param name="validator"></param>
|
/// <param name="validator"></param>
|
||||||
protected PluginConfigurationViewModel(Plugin plugin, IModelValidator validator) : base(validator)
|
protected PluginConfigurationViewModel(PluginImplementation pluginImplementation, IModelValidator validator) : base(validator)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin this configuration view model is associated with
|
/// Gets the plugin this configuration view model is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
142
src/Artemis.Core/Plugins/PluginImplementation.cs
Normal file
142
src/Artemis.Core/Plugins/PluginImplementation.cs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an implementation of a certain type provided by a plugin
|
||||||
|
/// </summary>
|
||||||
|
public abstract class PluginImplementation : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin that provides this implementation
|
||||||
|
/// </summary>
|
||||||
|
public Plugin Plugin { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin info related to this plugin
|
||||||
|
/// </summary>
|
||||||
|
public PluginInfo PluginInfo { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the plugin is enabled
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEnabled { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the implementation is activated
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Enable();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the implementation is deactivated or when Artemis shuts down
|
||||||
|
/// </summary>
|
||||||
|
public abstract void Disable();
|
||||||
|
|
||||||
|
internal void SetEnabled(bool enable, bool isAutoEnable = false)
|
||||||
|
{
|
||||||
|
if (enable && !IsEnabled)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (isAutoEnable && PluginInfo.GetLockFileCreated())
|
||||||
|
{
|
||||||
|
// Don't wrap existing lock exceptions, simply rethrow them
|
||||||
|
if (PluginInfo.LoadException is ArtemisPluginLockException)
|
||||||
|
throw PluginInfo.LoadException;
|
||||||
|
|
||||||
|
throw new ArtemisPluginLockException(PluginInfo.LoadException);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsEnabled = true;
|
||||||
|
PluginInfo.IsEnabled = true;
|
||||||
|
PluginInfo.CreateLockFile();
|
||||||
|
|
||||||
|
// Allow up to 15 seconds for plugins to activate.
|
||||||
|
// This means plugins that need more time should do their long running tasks in a background thread, which is intentional
|
||||||
|
// Little meh: Running this from a different thread could cause deadlocks
|
||||||
|
Task enableTask = Task.Run(InternalEnable);
|
||||||
|
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
||||||
|
throw new ArtemisPluginException(PluginInfo, "Plugin load timeout");
|
||||||
|
|
||||||
|
PluginInfo.LoadException = null;
|
||||||
|
OnEnabled();
|
||||||
|
}
|
||||||
|
// If enable failed, put it back in a disabled state
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
IsEnabled = false;
|
||||||
|
PluginInfo.IsEnabled = false;
|
||||||
|
PluginInfo.LoadException = e;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!(PluginInfo.LoadException is ArtemisPluginLockException))
|
||||||
|
PluginInfo.DeleteLockFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!enable && IsEnabled)
|
||||||
|
{
|
||||||
|
IsEnabled = false;
|
||||||
|
PluginInfo.IsEnabled = false;
|
||||||
|
|
||||||
|
// Even if disable failed, still leave it in a disabled state to avoid more issues
|
||||||
|
InternalDisable();
|
||||||
|
OnDisabled();
|
||||||
|
}
|
||||||
|
// A failed load is still enabled in plugin info (to avoid disabling it permanently after a fail)
|
||||||
|
// update even that when manually disabling
|
||||||
|
else if (!enable && !IsEnabled)
|
||||||
|
{
|
||||||
|
PluginInfo.IsEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal virtual void InternalEnable()
|
||||||
|
{
|
||||||
|
Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal virtual void InternalDisable()
|
||||||
|
{
|
||||||
|
Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the implementation is enabled
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? Enabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the implementation is disabled
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? Disabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers the PluginEnabled event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnEnabled()
|
||||||
|
{
|
||||||
|
Enabled?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers the PluginDisabled event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnDisabled()
|
||||||
|
{
|
||||||
|
Disabled?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,6 @@ using Artemis.Storage.Entities.Plugins;
|
|||||||
using McMaster.NETCore.Plugins;
|
using McMaster.NETCore.Plugins;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Ninject.Extensions.ChildKernel;
|
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -18,10 +17,10 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
private string _description;
|
private string _description;
|
||||||
private DirectoryInfo _directory;
|
private DirectoryInfo _directory;
|
||||||
private bool _enabled;
|
|
||||||
private Guid _guid;
|
private Guid _guid;
|
||||||
private string _icon;
|
private string _icon;
|
||||||
private Plugin _instance;
|
private Plugin _instance;
|
||||||
|
private bool _isEnabled;
|
||||||
private Exception _loadException;
|
private Exception _loadException;
|
||||||
private string _main;
|
private string _main;
|
||||||
private string _name;
|
private string _name;
|
||||||
@ -103,7 +102,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to the type implementing Plugin, available after successful load
|
/// Gets the plugin this info is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Instance
|
public Plugin Instance
|
||||||
{
|
{
|
||||||
@ -114,10 +113,10 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the user enabled the plugin or not
|
/// Indicates whether the user enabled the plugin or not
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Enabled
|
public bool IsEnabled
|
||||||
{
|
{
|
||||||
get => _enabled;
|
get => _isEnabled;
|
||||||
internal set => SetAndNotify(ref _enabled, value);
|
internal set => SetAndNotify(ref _isEnabled, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -129,21 +128,21 @@ namespace Artemis.Core
|
|||||||
internal set => SetAndNotify(ref _loadException, value);
|
internal set => SetAndNotify(ref _loadException, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The PluginLoader backing this plugin
|
|
||||||
/// </summary>
|
|
||||||
internal PluginLoader PluginLoader { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The assembly the plugin code lives in
|
/// The assembly the plugin code lives in
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Assembly Assembly { get; internal set; }
|
public Assembly Assembly { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Ninject kernel of the plugin
|
/// The Ninject kernel of the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IKernel Kernel { get; internal set; }
|
public IKernel Kernel { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The PluginLoader backing this plugin
|
||||||
|
/// </summary>
|
||||||
|
internal PluginLoader PluginLoader { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity representing the plugin
|
/// The entity representing the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -155,10 +154,15 @@ namespace Artemis.Core
|
|||||||
return $"{Name} v{Version} - {Guid}";
|
return $"{Name} v{Version} - {Guid}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string? ResolveRelativePath(string path)
|
||||||
|
{
|
||||||
|
return path == null ? null : Path.Combine(Directory.FullName, path);
|
||||||
|
}
|
||||||
|
|
||||||
internal void ApplyToEntity()
|
internal void ApplyToEntity()
|
||||||
{
|
{
|
||||||
PluginEntity.Id = Guid;
|
PluginEntity.Id = Guid;
|
||||||
PluginEntity.IsEnabled = Enabled;
|
PluginEntity.IsEnabled = IsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CreateLockFile()
|
internal void CreateLockFile()
|
||||||
@ -176,10 +180,5 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
return File.Exists(Path.Combine(Directory.FullName, "artemis.lock"));
|
return File.Exists(Path.Combine(Directory.FullName, "artemis.lock"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? ResolveRelativePath(string path)
|
|
||||||
{
|
|
||||||
return path == null ? null : Path.Combine(Directory.FullName, path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,32 +8,32 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a registration for a timed plugin update
|
/// Represents a registration for a timed plugin update
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginUpdateRegistration
|
public class TimedUpdateRegistration
|
||||||
{
|
{
|
||||||
private DateTime _lastEvent;
|
private DateTime _lastEvent;
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
|
|
||||||
internal PluginUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Action<double> action)
|
internal TimedUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Action<double> action)
|
||||||
{
|
{
|
||||||
PluginInfo = pluginInfo;
|
PluginInfo = pluginInfo;
|
||||||
Interval = interval;
|
Interval = interval;
|
||||||
Action = action;
|
Action = action;
|
||||||
|
|
||||||
PluginInfo.Instance.PluginEnabled += InstanceOnPluginEnabled;
|
PluginInfo.Instance.Enabled += InstanceOnEnabled;
|
||||||
PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||||
if (PluginInfo.Instance.Enabled)
|
if (PluginInfo.Instance.IsEnabled)
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal PluginUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Func<double, Task> asyncAction)
|
internal TimedUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Func<double, Task> asyncAction)
|
||||||
{
|
{
|
||||||
PluginInfo = pluginInfo;
|
PluginInfo = pluginInfo;
|
||||||
Interval = interval;
|
Interval = interval;
|
||||||
AsyncAction = asyncAction;
|
AsyncAction = asyncAction;
|
||||||
|
|
||||||
PluginInfo.Instance.PluginEnabled += InstanceOnPluginEnabled;
|
PluginInfo.Instance.Enabled += InstanceOnEnabled;
|
||||||
PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||||
if (PluginInfo.Instance.Enabled)
|
if (PluginInfo.Instance.IsEnabled)
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (!PluginInfo.Instance.Enabled)
|
if (!PluginInfo.Instance.IsEnabled)
|
||||||
throw new ArtemisPluginException("Cannot start a timed update for a disabled plugin");
|
throw new ArtemisPluginException("Cannot start a timed update for a disabled plugin");
|
||||||
|
|
||||||
if (_timer != null)
|
if (_timer != null)
|
||||||
@ -99,7 +99,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
|
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!PluginInfo.Instance.Enabled)
|
if (!PluginInfo.Instance.IsEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (this)
|
lock (this)
|
||||||
@ -121,12 +121,12 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstanceOnPluginEnabled(object sender, EventArgs e)
|
private void InstanceOnEnabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstanceOnPluginDisabled(object sender, EventArgs e)
|
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
@ -133,8 +133,8 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
private void UpdatePluginCache()
|
private void UpdatePluginCache()
|
||||||
{
|
{
|
||||||
_modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.Enabled).ToList();
|
_modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||||
_dataModelExpansions = _pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.Enabled).ToList();
|
_dataModelExpansions = _pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureJsonConvert()
|
private void ConfigureJsonConvert()
|
||||||
@ -162,7 +162,7 @@ namespace Artemis.Core.Services
|
|||||||
lock (_dataModelExpansions)
|
lock (_dataModelExpansions)
|
||||||
{
|
{
|
||||||
// Update all active modules, check Enabled status because it may go false before before the _dataModelExpansions list is updated
|
// Update all active modules, check Enabled status because it may go false before before the _dataModelExpansions list is updated
|
||||||
foreach (BaseDataModelExpansion dataModelExpansion in _dataModelExpansions.Where(e => e.Enabled))
|
foreach (BaseDataModelExpansion dataModelExpansion in _dataModelExpansions.Where(e => e.IsEnabled))
|
||||||
dataModelExpansion.Update(args.DeltaTime);
|
dataModelExpansion.Update(args.DeltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,22 +46,22 @@ namespace Artemis.Core.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables the provided plugin
|
/// Enables the provided plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin"></param>
|
/// <param name="pluginImplementation"></param>
|
||||||
/// <param name="isAutoEnable">If true, fails if there is a lock file present</param>
|
/// <param name="isAutoEnable">If true, fails if there is a lock file present</param>
|
||||||
void EnablePlugin(Plugin plugin, bool isAutoEnable = false);
|
void EnablePlugin(PluginImplementation pluginImplementation, bool isAutoEnable = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disables the provided plugin
|
/// Disables the provided plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin"></param>
|
/// <param name="pluginImplementation"></param>
|
||||||
void DisablePlugin(Plugin plugin);
|
void DisablePlugin(PluginImplementation pluginImplementation);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the plugin info related to the plugin
|
/// Finds the plugin info related to the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin">The plugin you want to find the plugin info for</param>
|
/// <param name="pluginImplementation">The plugin you want to find the plugin info for</param>
|
||||||
/// <returns>The plugins PluginInfo</returns>
|
/// <returns>The plugins PluginInfo</returns>
|
||||||
PluginInfo GetPluginInfo(Plugin plugin);
|
PluginInfo GetPluginInfo(PluginImplementation pluginImplementation);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin info of all loaded plugins
|
/// Gets the plugin info of all loaded plugins
|
||||||
@ -70,31 +70,31 @@ namespace Artemis.Core.Services
|
|||||||
List<PluginInfo> GetAllPluginInfo();
|
List<PluginInfo> GetAllPluginInfo();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds all enabled <see cref="Plugin" /> instances of <typeparamref name="T" />
|
/// Finds all enabled <see cref="PluginImplementation" /> instances of <typeparamref name="T" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Either <see cref="Plugin" /> or a plugin type implementing <see cref="Plugin" /></typeparam>
|
/// <typeparam name="T">Either <see cref="PluginImplementation" /> or a plugin type implementing <see cref="PluginImplementation" /></typeparam>
|
||||||
/// <returns>Returns a list of plugin instances of <typeparamref name="T" /></returns>
|
/// <returns>Returns a list of plugin instances of <typeparamref name="T" /></returns>
|
||||||
List<T> GetPluginsOfType<T>() where T : Plugin;
|
List<T> GetPluginsOfType<T>() where T : PluginImplementation;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin that provided the specified assembly
|
/// Gets the plugin that provided the specified assembly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assembly"></param>
|
/// <param name="assembly"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Plugin GetPluginByAssembly(Assembly assembly);
|
PluginImplementation GetPluginByAssembly(Assembly assembly);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin that defined the specified device
|
/// Gets the plugin that defined the specified device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device"></param>
|
/// <param name="device"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Plugin GetPluginByDevice(IRGBDevice device);
|
PluginImplementation GetPluginByDevice(IRGBDevice device);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the plugin info of the current call stack
|
/// Returns the plugin info of the current call stack
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>If the current call stack contains a plugin, the plugin. Otherwise null</returns>
|
/// <returns>If the current call stack contains a plugin, the plugin. Otherwise null</returns>
|
||||||
Plugin GetCallingPlugin();
|
PluginImplementation GetCallingPlugin();
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
|
|||||||
@ -103,7 +103,7 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
lock (module)
|
lock (module)
|
||||||
{
|
{
|
||||||
bool shouldBeActivated = module.EvaluateActivationRequirements() && module.Enabled;
|
bool shouldBeActivated = module.EvaluateActivationRequirements() && module.IsEnabled;
|
||||||
if (shouldBeActivated && !module.IsActivated)
|
if (shouldBeActivated && !module.IsActivated)
|
||||||
tasks.Add(ActivateModule(module));
|
tasks.Add(ActivateModule(module));
|
||||||
else if (!shouldBeActivated && module.IsActivated)
|
else if (!shouldBeActivated && module.IsActivated)
|
||||||
|
|||||||
@ -136,7 +136,7 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Activate plugins after they are all loaded
|
// Activate plugins after they are all loaded
|
||||||
foreach (PluginInfo pluginInfo in _plugins.Where(p => p.Enabled))
|
foreach (PluginInfo pluginInfo in _plugins.Where(p => p.IsEnabled))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -180,7 +180,7 @@ namespace Artemis.Core.Services
|
|||||||
pluginEntity = new PluginEntity {Id = pluginInfo.Guid, IsEnabled = true};
|
pluginEntity = new PluginEntity {Id = pluginInfo.Guid, IsEnabled = true};
|
||||||
|
|
||||||
pluginInfo.PluginEntity = pluginEntity;
|
pluginInfo.PluginEntity = pluginEntity;
|
||||||
pluginInfo.Enabled = pluginEntity.IsEnabled;
|
pluginInfo.IsEnabled = pluginEntity.IsEnabled;
|
||||||
|
|
||||||
string mainFile = Path.Combine(pluginInfo.Directory.FullName, pluginInfo.Main);
|
string mainFile = Path.Combine(pluginInfo.Directory.FullName, pluginInfo.Main);
|
||||||
if (!File.Exists(mainFile))
|
if (!File.Exists(mainFile))
|
||||||
@ -206,7 +206,7 @@ namespace Artemis.Core.Services
|
|||||||
List<Type> pluginTypes;
|
List<Type> pluginTypes;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pluginTypes = pluginInfo.Assembly.GetTypes().Where(t => typeof(Plugin).IsAssignableFrom(t)).ToList();
|
pluginTypes = pluginInfo.Assembly.GetTypes().Where(t => typeof(PluginImplementation).IsAssignableFrom(t)).ToList();
|
||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException e)
|
catch (ReflectionTypeLoadException e)
|
||||||
{
|
{
|
||||||
@ -226,7 +226,7 @@ namespace Artemis.Core.Services
|
|||||||
};
|
};
|
||||||
pluginInfo.Kernel = new ChildKernel(_kernel);
|
pluginInfo.Kernel = new ChildKernel(_kernel);
|
||||||
pluginInfo.Kernel.Load(new PluginModule(pluginInfo));
|
pluginInfo.Kernel.Load(new PluginModule(pluginInfo));
|
||||||
pluginInfo.Instance = (Plugin) pluginInfo.Kernel.Get(pluginType, constraint: null, parameters: parameters);
|
pluginInfo.Instance = (PluginImplementation) pluginInfo.Kernel.Get(pluginType, constraint: null, parameters: parameters);
|
||||||
pluginInfo.Instance.PluginInfo = pluginInfo;
|
pluginInfo.Instance.PluginInfo = pluginInfo;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -266,29 +266,29 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnablePlugin(Plugin plugin, bool isAutoEnable = false)
|
public void EnablePlugin(PluginImplementation pluginImplementation, bool isAutoEnable = false)
|
||||||
{
|
{
|
||||||
_logger.Debug("Enabling plugin {pluginInfo}", plugin.PluginInfo);
|
_logger.Debug("Enabling plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||||
OnPluginEnabling(new PluginEventArgs(plugin.PluginInfo));
|
OnPluginEnabling(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||||
|
|
||||||
lock (_plugins)
|
lock (_plugins)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// A device provider may be queued for disable on next restart, this undoes that
|
// A device provider may be queued for disable on next restart, this undoes that
|
||||||
if (plugin is DeviceProvider && plugin.Enabled && !plugin.PluginInfo.Enabled)
|
if (pluginImplementation is DeviceProvider && pluginImplementation.IsEnabled && !pluginImplementation.PluginInfo.IsEnabled)
|
||||||
{
|
{
|
||||||
plugin.PluginInfo.Enabled = true;
|
pluginImplementation.PluginInfo.IsEnabled = true;
|
||||||
plugin.PluginInfo.ApplyToEntity();
|
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||||
_pluginRepository.SavePlugin(plugin.PluginInfo.PluginEntity);
|
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.SetEnabled(true, isAutoEnable);
|
pluginImplementation.SetEnabled(true, isAutoEnable);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Warning(new ArtemisPluginException(plugin.PluginInfo, "Exception during SetEnabled(true)", e), "Failed to enable plugin");
|
_logger.Warning(new ArtemisPluginException(pluginImplementation.PluginInfo, "Exception during SetEnabled(true)", e), "Failed to enable plugin");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -296,48 +296,48 @@ namespace Artemis.Core.Services
|
|||||||
// On an auto-enable, ensure PluginInfo.Enabled is true even if enable failed, that way a failure on auto-enable does
|
// On an auto-enable, ensure PluginInfo.Enabled is true even if enable failed, that way a failure on auto-enable does
|
||||||
// not affect the user's settings
|
// not affect the user's settings
|
||||||
if (isAutoEnable)
|
if (isAutoEnable)
|
||||||
plugin.PluginInfo.Enabled = true;
|
pluginImplementation.PluginInfo.IsEnabled = true;
|
||||||
|
|
||||||
plugin.PluginInfo.ApplyToEntity();
|
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||||
_pluginRepository.SavePlugin(plugin.PluginInfo.PluginEntity);
|
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||||
|
|
||||||
if (plugin.PluginInfo.Enabled)
|
if (pluginImplementation.PluginInfo.IsEnabled)
|
||||||
_logger.Debug("Successfully enabled plugin {pluginInfo}", plugin.PluginInfo);
|
_logger.Debug("Successfully enabled plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPluginEnabled(new PluginEventArgs(plugin.PluginInfo));
|
OnPluginEnabled(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisablePlugin(Plugin plugin)
|
public void DisablePlugin(PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
lock (_plugins)
|
lock (_plugins)
|
||||||
{
|
{
|
||||||
_logger.Debug("Disabling plugin {pluginInfo}", plugin.PluginInfo);
|
_logger.Debug("Disabling plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||||
|
|
||||||
// Device providers cannot be disabled at runtime simply queue a disable for next restart
|
// Device providers cannot be disabled at runtime simply queue a disable for next restart
|
||||||
if (plugin is DeviceProvider)
|
if (pluginImplementation is DeviceProvider)
|
||||||
{
|
{
|
||||||
// Don't call SetEnabled(false) but simply update enabled state and save it
|
// Don't call SetEnabled(false) but simply update enabled state and save it
|
||||||
plugin.PluginInfo.Enabled = false;
|
pluginImplementation.PluginInfo.IsEnabled = false;
|
||||||
plugin.PluginInfo.ApplyToEntity();
|
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||||
_pluginRepository.SavePlugin(plugin.PluginInfo.PluginEntity);
|
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.SetEnabled(false);
|
pluginImplementation.SetEnabled(false);
|
||||||
plugin.PluginInfo.ApplyToEntity();
|
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||||
_pluginRepository.SavePlugin(plugin.PluginInfo.PluginEntity);
|
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||||
|
|
||||||
_logger.Debug("Successfully disabled plugin {pluginInfo}", plugin.PluginInfo);
|
_logger.Debug("Successfully disabled plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPluginDisabled(new PluginEventArgs(plugin.PluginInfo));
|
OnPluginDisabled(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginInfo GetPluginInfo(Plugin plugin)
|
public PluginInfo GetPluginInfo(PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
return _plugins.FirstOrDefault(p => p.Instance == plugin);
|
return _plugins.FirstOrDefault(p => p.Instance == pluginImplementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PluginInfo> GetAllPluginInfo()
|
public List<PluginInfo> GetAllPluginInfo()
|
||||||
@ -345,22 +345,22 @@ namespace Artemis.Core.Services
|
|||||||
return new List<PluginInfo>(_plugins);
|
return new List<PluginInfo>(_plugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> GetPluginsOfType<T>() where T : Plugin
|
public List<T> GetPluginsOfType<T>() where T : PluginImplementation
|
||||||
{
|
{
|
||||||
return _plugins.Where(p => p.Enabled && p.Instance is T).Select(p => (T) p.Instance).ToList();
|
return _plugins.Where(p => p.IsEnabled && p.Instance is T).Select(p => (T) p.Instance).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin GetPluginByAssembly(Assembly assembly)
|
public PluginImplementation GetPluginByAssembly(Assembly assembly)
|
||||||
{
|
{
|
||||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly)?.Instance;
|
return _plugins.FirstOrDefault(p => p.Assembly == assembly)?.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin GetPluginByDevice(IRGBDevice rgbDevice)
|
public PluginImplementation GetPluginByDevice(IRGBDevice rgbDevice)
|
||||||
{
|
{
|
||||||
return GetPluginsOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices != null && d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
return GetPluginsOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices != null && d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin GetCallingPlugin()
|
public PluginImplementation GetCallingPlugin()
|
||||||
{
|
{
|
||||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||||
@ -368,9 +368,9 @@ namespace Artemis.Core.Services
|
|||||||
foreach (StackFrame stackFrame in stackFrames)
|
foreach (StackFrame stackFrame in stackFrames)
|
||||||
{
|
{
|
||||||
Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
|
Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
|
||||||
Plugin plugin = GetPluginByAssembly(assembly);
|
PluginImplementation pluginImplementation = GetPluginByAssembly(assembly);
|
||||||
if (plugin != null)
|
if (pluginImplementation != null)
|
||||||
return plugin;
|
return pluginImplementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -11,9 +11,9 @@ namespace Artemis.Core.Services
|
|||||||
public DataModelService(IPluginService pluginService)
|
public DataModelService(IPluginService pluginService)
|
||||||
{
|
{
|
||||||
// Add data models of already loaded plugins
|
// Add data models of already loaded plugins
|
||||||
foreach (Module module in pluginService.GetPluginsOfType<Module>().Where(p => p.Enabled))
|
foreach (Module module in pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled))
|
||||||
AddModuleDataModel(module);
|
AddModuleDataModel(module);
|
||||||
foreach (BaseDataModelExpansion dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.Enabled))
|
foreach (BaseDataModelExpansion dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled))
|
||||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||||
|
|
||||||
// Add data models of new plugins when they get enabled
|
// Add data models of new plugins when they get enabled
|
||||||
@ -44,9 +44,9 @@ namespace Artemis.Core.Services
|
|||||||
return (T) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
|
return (T) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModel GetPluginDataModel(Plugin plugin)
|
public DataModel GetPluginDataModel(PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
return DataModelStore.Get(plugin.PluginInfo.Guid)?.DataModel;
|
return DataModelStore.Get(pluginImplementation.PluginInfo.Guid)?.DataModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModel GetPluginDataModel(Guid pluginGuid)
|
public DataModel GetPluginDataModel(Guid pluginGuid)
|
||||||
|
|||||||
@ -34,8 +34,8 @@ namespace Artemis.Core.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// If found, returns the data model of the provided plugin
|
/// If found, returns the data model of the provided plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin">The plugin to find the data model of</param>
|
/// <param name="pluginImplementation">The plugin to find the data model of</param>
|
||||||
DataModel GetPluginDataModel(Plugin plugin);
|
DataModel GetPluginDataModel(PluginImplementation pluginImplementation);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If found, returns the data model of the provided plugin GUID
|
/// If found, returns the data model of the provided plugin GUID
|
||||||
|
|||||||
@ -44,8 +44,8 @@ namespace Artemis.Core.Services
|
|||||||
// Add all current devices
|
// Add all current devices
|
||||||
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
||||||
{
|
{
|
||||||
Plugin plugin = _pluginService.GetPluginByDevice(rgbDevice);
|
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||||
configuration.Devices.Add(new ArtemisDevice(rgbDevice, plugin, configuration));
|
configuration.Devices.Add(new ArtemisDevice(rgbDevice, pluginImplementation, configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (_surfaceConfigurations)
|
lock (_surfaceConfigurations)
|
||||||
@ -136,8 +136,8 @@ namespace Artemis.Core.Services
|
|||||||
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
||||||
if (device != null)
|
if (device != null)
|
||||||
{
|
{
|
||||||
Plugin plugin = _pluginService.GetPluginByDevice(device);
|
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(device);
|
||||||
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, plugin, surfaceConfiguration, position));
|
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, pluginImplementation, surfaceConfiguration, position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,8 +178,8 @@ namespace Artemis.Core.Services
|
|||||||
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
||||||
if (existingDeviceConfig != null)
|
if (existingDeviceConfig != null)
|
||||||
{
|
{
|
||||||
Plugin plugin = _pluginService.GetPluginByDevice(rgbDevice);
|
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||||
device = new ArtemisDevice(rgbDevice, plugin, surface, existingDeviceConfig);
|
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface, existingDeviceConfig);
|
||||||
}
|
}
|
||||||
// Fall back on creating a new device
|
// Fall back on creating a new device
|
||||||
else
|
else
|
||||||
@ -189,8 +189,8 @@ namespace Artemis.Core.Services
|
|||||||
rgbDevice.DeviceInfo,
|
rgbDevice.DeviceInfo,
|
||||||
deviceIdentifier
|
deviceIdentifier
|
||||||
);
|
);
|
||||||
Plugin plugin = _pluginService.GetPluginByDevice(rgbDevice);
|
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||||
device = new ArtemisDevice(rgbDevice, plugin, surface);
|
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
surface.Devices.Add(device);
|
surface.Devices.Add(device);
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(r => r.Plugin.PluginInfo.Guid == pluginGuid && r.ConditionOperator.GetType().Name == type);
|
return Registrations.FirstOrDefault(r => r.PluginImplementation.PluginInfo.Guid == pluginGuid && r.ConditionOperator.GetType().Name == type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(r => r.Plugin.PluginInfo.Guid == pluginGuid && r.DataBindingModifierType.GetType().Name == type);
|
return Registrations.FirstOrDefault(r => r.PluginImplementation.PluginInfo.Guid == pluginGuid && r.DataBindingModifierType.GetType().Name == type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
|||||||
if (Registrations.Any(r => r.DataModel == dataModel))
|
if (Registrations.Any(r => r.DataModel == dataModel))
|
||||||
throw new ArtemisCoreException($"Data model store already contains data model '{dataModel.DataModelDescription}'");
|
throw new ArtemisCoreException($"Data model store already contains data model '{dataModel.DataModelDescription}'");
|
||||||
|
|
||||||
registration = new DataModelRegistration(dataModel, dataModel.PluginInfo.Instance) {IsInStore = true};
|
registration = new DataModelRegistration(dataModel, dataModel.Implementation.Instance) {IsInStore = true};
|
||||||
Registrations.Add(registration);
|
Registrations.Add(registration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(d => d.Plugin.PluginInfo.Guid == pluginGuid);
|
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(d => d.Plugin.PluginInfo.Guid == pluginGuid &&
|
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid &&
|
||||||
d.LayerBrushDescriptor.LayerBrushType.Name == typeName);
|
d.LayerBrushDescriptor.LayerBrushType.Name == typeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
return Registrations.FirstOrDefault(d => d.Plugin.PluginInfo.Guid == pluginGuid && d.LayerEffectDescriptor.LayerEffectType.Name == typeName);
|
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid && d.LayerEffectDescriptor.LayerEffectType.Name == typeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,12 +7,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ConditionOperatorRegistration
|
public class ConditionOperatorRegistration
|
||||||
{
|
{
|
||||||
internal ConditionOperatorRegistration(BaseConditionOperator conditionOperator, Plugin plugin)
|
internal ConditionOperatorRegistration(BaseConditionOperator conditionOperator, PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
ConditionOperator = conditionOperator;
|
ConditionOperator = conditionOperator;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
|
|
||||||
Plugin.PluginDisabled += PluginOnPluginDisabled;
|
PluginImplementation.Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -23,16 +23,16 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the condition operator is associated with
|
/// Gets the plugin the condition operator is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInStore { get; internal set; }
|
public bool IsInStore { get; internal set; }
|
||||||
|
|
||||||
private void PluginOnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Plugin.PluginDisabled -= PluginOnPluginDisabled;
|
PluginImplementation.Disabled -= OnDisabled;
|
||||||
if (IsInStore)
|
if (IsInStore)
|
||||||
ConditionOperatorStore.Remove(this);
|
ConditionOperatorStore.Remove(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataBindingModifierTypeRegistration
|
public class DataBindingModifierTypeRegistration
|
||||||
{
|
{
|
||||||
internal DataBindingModifierTypeRegistration(BaseDataBindingModifierType dataBindingModifierType, Plugin plugin)
|
internal DataBindingModifierTypeRegistration(BaseDataBindingModifierType dataBindingModifierType, PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
DataBindingModifierType = dataBindingModifierType;
|
DataBindingModifierType = dataBindingModifierType;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
|
|
||||||
Plugin.PluginDisabled += PluginOnPluginDisabled;
|
PluginImplementation.Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -23,16 +23,16 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the data binding modifier is associated with
|
/// Gets the plugin the data binding modifier is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInStore { get; internal set; }
|
public bool IsInStore { get; internal set; }
|
||||||
|
|
||||||
private void PluginOnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Plugin.PluginDisabled -= PluginOnPluginDisabled;
|
PluginImplementation.Disabled -= OnDisabled;
|
||||||
if (IsInStore)
|
if (IsInStore)
|
||||||
DataBindingModifierTypeStore.Remove(this);
|
DataBindingModifierTypeStore.Remove(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataModelRegistration
|
public class DataModelRegistration
|
||||||
{
|
{
|
||||||
internal DataModelRegistration(DataModel dataModel, Plugin plugin)
|
internal DataModelRegistration(DataModel dataModel, PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
DataModel = dataModel;
|
DataModel = dataModel;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
|
|
||||||
Plugin.PluginDisabled += PluginOnPluginDisabled;
|
PluginImplementation.Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -24,16 +24,16 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the data model is associated with
|
/// Gets the plugin the data model is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInStore { get; internal set; }
|
public bool IsInStore { get; internal set; }
|
||||||
|
|
||||||
private void PluginOnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Plugin.PluginDisabled -= PluginOnPluginDisabled;
|
PluginImplementation.Disabled -= OnDisabled;
|
||||||
if (IsInStore)
|
if (IsInStore)
|
||||||
DataModelStore.Remove(this);
|
DataModelStore.Remove(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LayerBrushRegistration
|
public class LayerBrushRegistration
|
||||||
{
|
{
|
||||||
internal LayerBrushRegistration(LayerBrushDescriptor descriptor, Plugin plugin)
|
internal LayerBrushRegistration(LayerBrushDescriptor descriptor, PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
LayerBrushDescriptor = descriptor;
|
LayerBrushDescriptor = descriptor;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
|
|
||||||
Plugin.PluginDisabled += PluginOnPluginDisabled;
|
PluginImplementation.Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -24,16 +24,16 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the layer brush is associated with
|
/// Gets the plugin the layer brush is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInStore { get; internal set; }
|
public bool IsInStore { get; internal set; }
|
||||||
|
|
||||||
private void PluginOnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Plugin.PluginDisabled -= PluginOnPluginDisabled;
|
PluginImplementation.Disabled -= OnDisabled;
|
||||||
if (IsInStore)
|
if (IsInStore)
|
||||||
LayerBrushStore.Remove(this);
|
LayerBrushStore.Remove(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LayerEffectRegistration
|
public class LayerEffectRegistration
|
||||||
{
|
{
|
||||||
internal LayerEffectRegistration(LayerEffectDescriptor descriptor, Plugin plugin)
|
internal LayerEffectRegistration(LayerEffectDescriptor descriptor, PluginImplementation pluginImplementation)
|
||||||
{
|
{
|
||||||
LayerEffectDescriptor = descriptor;
|
LayerEffectDescriptor = descriptor;
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
|
|
||||||
Plugin.PluginDisabled += PluginOnPluginDisabled;
|
PluginImplementation.Disabled += OnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -24,16 +24,16 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the layer effect is associated with
|
/// Gets the plugin the layer effect is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public PluginImplementation PluginImplementation { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInStore { get; internal set; }
|
public bool IsInStore { get; internal set; }
|
||||||
|
|
||||||
private void PluginOnPluginDisabled(object sender, EventArgs e)
|
private void OnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Plugin.PluginDisabled -= PluginOnPluginDisabled;
|
PluginImplementation.Disabled -= OnDisabled;
|
||||||
if (IsInStore)
|
if (IsInStore)
|
||||||
LayerEffectStore.Remove(this);
|
LayerEffectStore.Remove(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,19 +5,19 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty plugin used by <see cref="Constants.CorePluginInfo"/>
|
/// An empty plugin used by <see cref="Constants.CorePluginInfo"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class CorePlugin : Plugin
|
internal class CorePluginImplementation : PluginImplementation
|
||||||
{
|
{
|
||||||
public CorePlugin()
|
public CorePluginImplementation()
|
||||||
{
|
{
|
||||||
Constants.CorePluginInfo.Instance = this;
|
Constants.CorePluginInfo.Instance = this;
|
||||||
Enabled = true;
|
IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void EnablePlugin()
|
public override void Enable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisablePlugin()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,14 +26,14 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
public EffectPlaceholderPlugin()
|
public EffectPlaceholderPlugin()
|
||||||
{
|
{
|
||||||
Enabled = true;
|
IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void EnablePlugin()
|
public override void Enable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisablePlugin()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,12 +67,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal class DummyModule : ProfileModule
|
internal class DummyModule : ProfileModule
|
||||||
{
|
{
|
||||||
public override void EnablePlugin()
|
public override void Enable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisablePlugin()
|
public override void Disable()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace Artemis.UI.Shared
|
|||||||
ViewModelType = viewModelType;
|
ViewModelType = viewModelType;
|
||||||
|
|
||||||
if (PluginInfo != Constants.CorePluginInfo)
|
if (PluginInfo != Constants.CorePluginInfo)
|
||||||
PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegistrationType RegistrationType { get; }
|
public RegistrationType RegistrationType { get; }
|
||||||
@ -35,10 +35,10 @@ namespace Artemis.UI.Shared
|
|||||||
internal void Unsubscribe()
|
internal void Unsubscribe()
|
||||||
{
|
{
|
||||||
if (PluginInfo != Constants.CorePluginInfo)
|
if (PluginInfo != Constants.CorePluginInfo)
|
||||||
PluginInfo.Instance.PluginDisabled -= InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled -= InstanceOnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstanceOnPluginDisabled(object sender, EventArgs e)
|
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (RegistrationType == RegistrationType.Input)
|
if (RegistrationType == RegistrationType.Input)
|
||||||
_dataModelUIService.RemoveDataModelInput(this);
|
_dataModelUIService.RemoveDataModelInput(this);
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace Artemis.UI.Shared
|
|||||||
ViewModelType = viewModelType;
|
ViewModelType = viewModelType;
|
||||||
|
|
||||||
if (PluginInfo != Constants.CorePluginInfo)
|
if (PluginInfo != Constants.CorePluginInfo)
|
||||||
PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginInfo PluginInfo { get; }
|
public PluginInfo PluginInfo { get; }
|
||||||
@ -26,10 +26,10 @@ namespace Artemis.UI.Shared
|
|||||||
internal void Unsubscribe()
|
internal void Unsubscribe()
|
||||||
{
|
{
|
||||||
if (PluginInfo != Constants.CorePluginInfo)
|
if (PluginInfo != Constants.CorePluginInfo)
|
||||||
PluginInfo.Instance.PluginDisabled -= InstanceOnPluginDisabled;
|
PluginInfo.Instance.Disabled -= InstanceOnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstanceOnPluginDisabled(object sender, EventArgs e)
|
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// Profile editor service will call Unsubscribe
|
// Profile editor service will call Unsubscribe
|
||||||
_profileEditorService.RemovePropertyInput(this);
|
_profileEditorService.RemovePropertyInput(this);
|
||||||
|
|||||||
@ -42,24 +42,24 @@ namespace Artemis.UI.Shared.Services
|
|||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin, bool includeMainDataModel)
|
public DataModelPropertiesViewModel GetPluginDataModelVisualization(PluginImplementation pluginImplementation, bool includeMainDataModel)
|
||||||
{
|
{
|
||||||
if (includeMainDataModel)
|
if (includeMainDataModel)
|
||||||
{
|
{
|
||||||
DataModelPropertiesViewModel mainDataModel = GetMainDataModelVisualization();
|
DataModelPropertiesViewModel mainDataModel = GetMainDataModelVisualization();
|
||||||
|
|
||||||
// If the main data model already includes the plugin data model we're done
|
// If the main data model already includes the plugin data model we're done
|
||||||
if (mainDataModel.Children.Any(c => c.DataModel.PluginInfo.Instance == plugin))
|
if (mainDataModel.Children.Any(c => c.DataModel.Implementation.Instance == pluginImplementation))
|
||||||
return mainDataModel;
|
return mainDataModel;
|
||||||
// Otherwise get just the plugin data model and add it
|
// Otherwise get just the plugin data model and add it
|
||||||
DataModelPropertiesViewModel pluginDataModel = GetPluginDataModelVisualization(plugin, false);
|
DataModelPropertiesViewModel pluginDataModel = GetPluginDataModelVisualization(pluginImplementation, false);
|
||||||
if (pluginDataModel != null)
|
if (pluginDataModel != null)
|
||||||
mainDataModel.Children.Add(pluginDataModel);
|
mainDataModel.Children.Add(pluginDataModel);
|
||||||
|
|
||||||
return mainDataModel;
|
return mainDataModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataModel dataModel = _dataModelService.GetPluginDataModel(plugin);
|
DataModel dataModel = _dataModelService.GetPluginDataModel(pluginImplementation);
|
||||||
if (dataModel == null)
|
if (dataModel == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|||||||
@ -109,11 +109,11 @@ namespace Artemis.UI.Shared.Services
|
|||||||
|
|
||||||
private async Task<object> ShowDialogAt<T>(string identifier, IParameter[] parameters) where T : DialogViewModelBase
|
private async Task<object> ShowDialogAt<T>(string identifier, IParameter[] parameters) where T : DialogViewModelBase
|
||||||
{
|
{
|
||||||
Plugin callingPlugin = _pluginService.GetCallingPlugin();
|
PluginImplementation callingPluginImplementation = _pluginService.GetCallingPlugin();
|
||||||
if (parameters == null) throw new ArgumentNullException(nameof(parameters));
|
if (parameters == null) throw new ArgumentNullException(nameof(parameters));
|
||||||
|
|
||||||
if (callingPlugin != null)
|
if (callingPluginImplementation != null)
|
||||||
return await ShowDialog(identifier, callingPlugin.PluginInfo.Kernel.Get<T>(parameters));
|
return await ShowDialog(identifier, callingPluginImplementation.PluginInfo.Kernel.Get<T>(parameters));
|
||||||
return await ShowDialog(identifier, _kernel.Get<T>(parameters));
|
return await ShowDialog(identifier, _kernel.Get<T>(parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelEditors { get; }
|
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelEditors { get; }
|
||||||
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelDisplays { get; }
|
IReadOnlyCollection<DataModelVisualizationRegistration> RegisteredDataModelDisplays { get; }
|
||||||
DataModelPropertiesViewModel GetMainDataModelVisualization();
|
DataModelPropertiesViewModel GetMainDataModelVisualization();
|
||||||
DataModelPropertiesViewModel GetPluginDataModelVisualization(Plugin plugin, bool includeMainDataModel);
|
DataModelPropertiesViewModel GetPluginDataModelVisualization(PluginImplementation pluginImplementation, bool includeMainDataModel);
|
||||||
|
|
||||||
DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes) where T : DataModelInputViewModel;
|
DataModelVisualizationRegistration RegisterDataModelInput<T>(PluginInfo pluginInfo, IReadOnlyCollection<Type> compatibleConversionTypes) where T : DataModelInputViewModel;
|
||||||
DataModelVisualizationRegistration RegisterDataModelDisplay<T>(PluginInfo pluginInfo) where T : DataModelDisplayViewModel;
|
DataModelVisualizationRegistration RegisterDataModelDisplay<T>(PluginInfo pluginInfo) where T : DataModelDisplayViewModel;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
|
|
||||||
public interface ISettingsVmFactory : IVmFactory
|
public interface ISettingsVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
PluginSettingsViewModel CreatePluginSettingsViewModel(Plugin plugin);
|
PluginSettingsViewModel CreatePluginSettingsViewModel(PluginImplementation pluginImplementation);
|
||||||
DeviceSettingsViewModel CreateDeviceSettingsViewModel(ArtemisDevice device);
|
DeviceSettingsViewModel CreateDeviceSettingsViewModel(ArtemisDevice device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ namespace Artemis.UI.Screens.Settings.Debug
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Device.Plugin.PluginInfo.Directory.FullName);
|
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Device.PluginImplementation.PluginInfo.Directory.FullName);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -117,7 +117,7 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
|
|
||||||
private void PopulateModules()
|
private void PopulateModules()
|
||||||
{
|
{
|
||||||
Modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.Enabled).ToList();
|
Modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Device.Plugin.PluginInfo.Directory.FullName);
|
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Device.PluginImplementation.PluginInfo.Directory.FullName);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -30,18 +30,18 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
||||||
private readonly IWindowManager _windowManager;
|
private readonly IWindowManager _windowManager;
|
||||||
private bool _enabling;
|
private bool _enabling;
|
||||||
private Plugin _plugin;
|
private PluginImplementation _pluginImplementation;
|
||||||
private PluginInfo _pluginInfo;
|
private PluginInfo _pluginInfo;
|
||||||
|
|
||||||
public PluginSettingsViewModel(Plugin plugin,
|
public PluginSettingsViewModel(PluginImplementation pluginImplementation,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IWindowManager windowManager,
|
IWindowManager windowManager,
|
||||||
IDialogService dialogService,
|
IDialogService dialogService,
|
||||||
IPluginService pluginService,
|
IPluginService pluginService,
|
||||||
ISnackbarMessageQueue snackbarMessageQueue)
|
ISnackbarMessageQueue snackbarMessageQueue)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
PluginImplementation = pluginImplementation;
|
||||||
PluginInfo = plugin.PluginInfo;
|
PluginInfo = pluginImplementation.PluginInfo;
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_windowManager = windowManager;
|
_windowManager = windowManager;
|
||||||
@ -50,10 +50,10 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
_snackbarMessageQueue = snackbarMessageQueue;
|
_snackbarMessageQueue = snackbarMessageQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin Plugin
|
public PluginImplementation PluginImplementation
|
||||||
{
|
{
|
||||||
get => _plugin;
|
get => _pluginImplementation;
|
||||||
set => SetAndNotify(ref _plugin, value);
|
set => SetAndNotify(ref _pluginImplementation, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginInfo PluginInfo
|
public PluginInfo PluginInfo
|
||||||
@ -69,20 +69,20 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PackIconKind Icon => GetIconKind();
|
public PackIconKind Icon => GetIconKind();
|
||||||
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
public string Type => PluginImplementation.GetType().BaseType?.Name ?? PluginImplementation.GetType().Name;
|
||||||
public bool CanOpenSettings => IsEnabled && Plugin.ConfigurationDialog != null;
|
public bool CanOpenSettings => IsEnabled && PluginImplementation.ConfigurationDialog != null;
|
||||||
public bool DisplayLoadFailed => !Enabling && PluginInfo.LoadException != null;
|
public bool DisplayLoadFailed => !Enabling && PluginInfo.LoadException != null;
|
||||||
public bool RequiresRestart => Plugin.Enabled && !PluginInfo.Enabled;
|
public bool RequiresRestart => PluginImplementation.IsEnabled && !PluginInfo.IsEnabled;
|
||||||
|
|
||||||
public bool IsEnabled
|
public bool IsEnabled
|
||||||
{
|
{
|
||||||
get => Plugin.PluginInfo.Enabled;
|
get => PluginImplementation.PluginInfo.IsEnabled;
|
||||||
set => Task.Run(() => UpdateEnabled(value));
|
set => Task.Run(() => UpdateEnabled(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenSettings()
|
public void OpenSettings()
|
||||||
{
|
{
|
||||||
PluginConfigurationDialog configurationViewModel = Plugin.ConfigurationDialog;
|
PluginConfigurationDialog configurationViewModel = PluginImplementation.ConfigurationDialog;
|
||||||
if (configurationViewModel == null)
|
if (configurationViewModel == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -93,8 +93,8 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
if (constructors.Length != 1)
|
if (constructors.Length != 1)
|
||||||
throw new ArtemisUIException("Plugin configuration dialogs must have exactly one constructor");
|
throw new ArtemisUIException("Plugin configuration dialogs must have exactly one constructor");
|
||||||
|
|
||||||
ParameterInfo pluginParameter = constructors.First().GetParameters().First(p => typeof(Plugin).IsAssignableFrom(p.ParameterType));
|
ParameterInfo pluginParameter = constructors.First().GetParameters().First(p => typeof(PluginImplementation).IsAssignableFrom(p.ParameterType));
|
||||||
ConstructorArgument plugin = new ConstructorArgument(pluginParameter.Name, Plugin);
|
ConstructorArgument plugin = new ConstructorArgument(pluginParameter.Name, PluginImplementation);
|
||||||
PluginConfigurationViewModel viewModel = (PluginConfigurationViewModel) PluginInfo.Kernel.Get(configurationViewModel.Type, plugin);
|
PluginConfigurationViewModel viewModel = (PluginConfigurationViewModel) PluginInfo.Kernel.Get(configurationViewModel.Type, plugin);
|
||||||
_windowManager.ShowDialog(new PluginSettingsWindowViewModel(viewModel, Icon));
|
_windowManager.ShowDialog(new PluginSettingsWindowViewModel(viewModel, Icon));
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
|
|
||||||
public async Task Restart()
|
public async Task Restart()
|
||||||
{
|
{
|
||||||
_logger.Debug("Restarting for device provider disable {pluginInfo}", Plugin.PluginInfo);
|
_logger.Debug("Restarting for device provider disable {pluginInfo}", PluginImplementation.PluginInfo);
|
||||||
|
|
||||||
// Give the logger a chance to write, might not always be enough but oh well
|
// Give the logger a chance to write, might not always be enough but oh well
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
@ -143,7 +143,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
return iconEnum;
|
return iconEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Plugin)
|
switch (PluginImplementation)
|
||||||
{
|
{
|
||||||
case BaseDataModelExpansion _:
|
case BaseDataModelExpansion _:
|
||||||
return PackIconKind.TableAdd;
|
return PackIconKind.TableAdd;
|
||||||
@ -170,7 +170,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enable && Plugin is DeviceProvider)
|
if (!enable && PluginImplementation is DeviceProvider)
|
||||||
{
|
{
|
||||||
await DisableDeviceProvider();
|
await DisableDeviceProvider();
|
||||||
return;
|
return;
|
||||||
@ -183,7 +183,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_pluginService.EnablePlugin(Plugin);
|
_pluginService.EnablePlugin(PluginImplementation);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -195,7 +195,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_pluginService.DisablePlugin(Plugin);
|
_pluginService.DisablePlugin(PluginImplementation);
|
||||||
|
|
||||||
NotifyOfPropertyChange(nameof(IsEnabled));
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||||
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
||||||
@ -208,9 +208,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
bool restart = false;
|
bool restart = false;
|
||||||
|
|
||||||
// If any plugin already requires a restart, don't ask the user again
|
// If any plugin already requires a restart, don't ask the user again
|
||||||
bool restartQueued = _pluginService.GetAllPluginInfo().Any(p => p.Instance != null && !p.Enabled && p.Instance.Enabled);
|
bool restartQueued = _pluginService.GetAllPluginInfo().Any(p => p.Instance != null && !p.IsEnabled && p.Instance.IsEnabled);
|
||||||
// If the plugin isn't enabled (load failed), it can be disabled without a restart
|
// If the plugin isn't enabled (load failed), it can be disabled without a restart
|
||||||
if (!restartQueued && Plugin.Enabled)
|
if (!restartQueued && PluginImplementation.IsEnabled)
|
||||||
{
|
{
|
||||||
restart = await _dialogService.ShowConfirmDialog(
|
restart = await _dialogService.ShowConfirmDialog(
|
||||||
"Disable device provider",
|
"Disable device provider",
|
||||||
@ -220,10 +220,10 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pluginService.DisablePlugin(Plugin);
|
_pluginService.DisablePlugin(PluginImplementation);
|
||||||
if (restart)
|
if (restart)
|
||||||
{
|
{
|
||||||
_logger.Debug("Restarting for device provider disable {pluginInfo}", Plugin.PluginInfo);
|
_logger.Debug("Restarting for device provider disable {pluginInfo}", PluginImplementation.PluginInfo);
|
||||||
|
|
||||||
// Give the logger a chance to write, might not always be enough but oh well
|
// Give the logger a chance to write, might not always be enough but oh well
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
Identifier="PluginSettingsDialog"
|
Identifier="PluginSettingsDialog"
|
||||||
DialogTheme="Inherit">
|
DialogTheme="Inherit">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<controls:AppBar Type="Dense" Title="{Binding ActiveItem.Plugin.PluginInfo.Name}" DockPanel.Dock="Top" Margin="-18 0 0 0" ShowShadow="False">
|
<controls:AppBar Type="Dense" Title="{Binding ActiveItem.PluginImplementation.PluginInfo.Name}" DockPanel.Dock="Top" Margin="-18 0 0 0" ShowShadow="False">
|
||||||
<controls:AppBar.AppIcon>
|
<controls:AppBar.AppIcon>
|
||||||
<materialDesign:PackIcon Kind="{Binding Icon}" Width="20" Height="28" />
|
<materialDesign:PackIcon Kind="{Binding Icon}" Width="20" Height="28" />
|
||||||
</controls:AppBar.AppIcon>
|
</controls:AppBar.AppIcon>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user