Plugins - Load features by their info before enabling plugins

General - Added missing XML comments
This commit is contained in:
Robert committed 2021-03-10 20:53:37 +01:00
1 parent fa26e6b7da
commit d5d1211649
24 files changed
+241 -180

No files matched your search

@@ -29,6 +29,9 @@ namespace Artemis.Core.LayerBrushes
/// </summary>
public ListLedGroup? LedGroup { get; internal set; }
/// <summary>
/// For internal use only, is public for dependency injection but ignore pl0x
/// </summary>
[Inject]
public IRgbService? RgbService { get; set; }
@@ -38,35 +41,6 @@ namespace Artemis.Core.LayerBrushes
/// <returns>Your RGB.NET effect</returns>
public abstract IBrush GetBrush();
internal void UpdateLedGroup()
{
if (LedGroup == null)
return;
if (Layer.Parent != null)
LedGroup.ZIndex = Layer.Parent.Children.Count - Layer.Parent.Children.IndexOf(Layer);
else
LedGroup.ZIndex = 1;
List<Led> missingLeds = Layer.Leds.Where(l => !LedGroup.ContainsLed(l.RgbLed)).Select(l => l.RgbLed).ToList();
List<Led> extraLeds = LedGroup.Where(l => Layer.Leds.All(layerLed => layerLed.RgbLed != l)).ToList();
LedGroup.AddLeds(missingLeds);
LedGroup.RemoveLeds(extraLeds);
LedGroup.Brush = GetBrush();
}
internal override void Initialize()
{
if (RgbService == null)
throw new ArtemisCoreException("Cannot initialize RGB.NET layer brush because RgbService is not set");
LedGroup = new ListLedGroup(RgbService.Surface);
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
InitializeProperties();
UpdateLedGroup();
}
#region IDisposable
/// <inheritdoc />
@@ -87,6 +61,35 @@ namespace Artemis.Core.LayerBrushes
#endregion
internal void UpdateLedGroup()
{
if (LedGroup == null)
return;
if (Layer.Parent != null)
LedGroup.ZIndex = Layer.Parent.Children.Count - Layer.Parent.Children.IndexOf(Layer);
else
LedGroup.ZIndex = 1;
List<Led> missingLeds = Layer.Leds.Where(l => !LedGroup.ContainsLed(l.RgbLed)).Select(l => l.RgbLed).ToList();
List<Led> extraLeds = LedGroup.Where(l => Layer.Leds.All(layerLed => layerLed.RgbLed != l)).ToList();
LedGroup.AddLeds(missingLeds);
LedGroup.RemoveLeds(extraLeds);
LedGroup.Brush = GetBrush();
}
internal override void Initialize()
{
if (RgbService == null)
throw new ArtemisCoreException("Cannot initialize RGB.NET layer brush because RgbService is not set");
LedGroup = new ListLedGroup(RgbService.Surface);
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
InitializeProperties();
UpdateLedGroup();
}
// Not used in this effect type
internal override void InternalRender(SKCanvas canvas, SKRect bounds, SKPaint paint)
{
+25 -24
View File
@@ -16,7 +16,7 @@ namespace Artemis.Core
/// </summary>
public class Plugin : CorePropertyChanged, IDisposable
{
private readonly List<PluginFeature> _features;
private readonly List<PluginFeatureInfo> _features;
private bool _isEnabled;
@@ -26,7 +26,7 @@ namespace Artemis.Core
Directory = directory;
Entity = pluginEntity ?? new PluginEntity {Id = Guid, IsEnabled = true};
_features = new List<PluginFeature>();
_features = new List<PluginFeatureInfo>();
}
/// <summary>
@@ -61,7 +61,7 @@ namespace Artemis.Core
/// <summary>
/// Gets a read-only collection of all features this plugin provides
/// </summary>
public ReadOnlyCollection<PluginFeature> Features => _features.AsReadOnly();
public ReadOnlyCollection<PluginFeatureInfo> Features => _features.AsReadOnly();
/// <summary>
/// The assembly the plugin code lives in
@@ -107,7 +107,7 @@ namespace Artemis.Core
/// <returns>If found, the instance of the feature</returns>
public T? GetFeature<T>() where T : PluginFeature
{
return _features.FirstOrDefault(i => i is T) as T;
return _features.FirstOrDefault(i => i.Instance is T) as T;
}
/// <inheritdoc />
@@ -122,31 +122,32 @@ namespace Artemis.Core
Entity.IsEnabled = IsEnabled;
}
internal void AddFeature(PluginFeature feature)
internal void AddFeature(PluginFeatureInfo featureInfo)
{
feature.Plugin = this;
_features.Add(feature);
if (featureInfo.Plugin != this)
throw new ArtemisCoreException("Feature is not associated with this plugin");
_features.Add(featureInfo);
OnFeatureAdded(new PluginFeatureEventArgs(feature));
OnFeatureAdded(new PluginFeatureInfoEventArgs(featureInfo));
}
internal void RemoveFeature(PluginFeature feature)
internal void RemoveFeature(PluginFeatureInfo featureInfo)
{
if (feature.IsEnabled)
if (featureInfo.Instance != null && featureInfo.Instance.IsEnabled)
throw new ArtemisCoreException("Cannot remove an enabled feature from a plugin");
_features.Remove(feature);
feature.Dispose();
OnFeatureRemoved(new PluginFeatureEventArgs(feature));
_features.Remove(featureInfo);
featureInfo.Instance?.Dispose();
OnFeatureRemoved(new PluginFeatureInfoEventArgs(featureInfo));
}
internal void SetEnabled(bool enable)
{
if (IsEnabled == enable)
return;
if (!enable && Features.Any(e => e.IsEnabled))
if (!enable && Features.Any(e => e.Instance != null && e.Instance.IsEnabled))
throw new ArtemisCoreException("Cannot disable this plugin because it still has enabled features");
IsEnabled = enable;
@@ -176,8 +177,8 @@ namespace Artemis.Core
{
if (disposing)
{
foreach (PluginFeature feature in Features)
feature.Dispose();
foreach (PluginFeatureInfo feature in Features)
feature.Instance?.Dispose();
SetEnabled(false);
Kernel?.Dispose();
@@ -189,7 +190,7 @@ namespace Artemis.Core
_features.Clear();
}
}
/// <inheritdoc />
public void Dispose()
{
@@ -198,7 +199,7 @@ namespace Artemis.Core
}
#endregion
#region Events
/// <summary>
@@ -214,12 +215,12 @@ namespace Artemis.Core
/// <summary>
/// Occurs when an feature is loaded and added to the plugin
/// </summary>
public event EventHandler<PluginFeatureEventArgs>? FeatureAdded;
public event EventHandler<PluginFeatureInfoEventArgs>? FeatureAdded;
/// <summary>
/// Occurs when an feature is disabled and removed from the plugin
/// </summary>
public event EventHandler<PluginFeatureEventArgs>? FeatureRemoved;
public event EventHandler<PluginFeatureInfoEventArgs>? FeatureRemoved;
/// <summary>
/// Invokes the Enabled event
@@ -240,7 +241,7 @@ namespace Artemis.Core
/// <summary>
/// Invokes the FeatureAdded event
/// </summary>
protected virtual void OnFeatureAdded(PluginFeatureEventArgs e)
protected virtual void OnFeatureAdded(PluginFeatureInfoEventArgs e)
{
FeatureAdded?.Invoke(this, e);
}
@@ -248,7 +249,7 @@ namespace Artemis.Core
/// <summary>
/// Invokes the FeatureRemoved event
/// </summary>
protected virtual void OnFeatureRemoved(PluginFeatureEventArgs e)
protected virtual void OnFeatureRemoved(PluginFeatureInfoEventArgs e)
{
FeatureRemoved?.Invoke(this, e);
}
+48 -11
View File
@@ -1,4 +1,5 @@
using Artemis.Core.DataModelExpansions;
using System;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.DeviceProviders;
using Artemis.Core.LayerBrushes;
using Artemis.Core.LayerEffects;
@@ -16,22 +17,48 @@ namespace Artemis.Core
{
private string? _description;
private string? _icon;
private PluginFeature? _instance;
private string _name = null!;
private PluginFeature _pluginFeature = null!;
internal PluginFeatureInfo()
internal PluginFeatureInfo(Plugin plugin, Type featureType, PluginFeatureAttribute? attribute)
{
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
FeatureType = featureType ?? throw new ArgumentNullException(nameof(featureType));
Name = attribute?.Name ?? featureType.Name.Humanize(LetterCasing.Title);
Description = attribute?.Description;
Icon = attribute?.Icon;
if (Icon != null) return;
if (typeof(BaseDataModelExpansion).IsAssignableFrom(featureType))
Icon = "TableAdd";
else if (typeof(DeviceProvider).IsAssignableFrom(featureType))
Icon = "Devices";
else if (typeof(ProfileModule).IsAssignableFrom(featureType))
Icon = "VectorRectangle";
else if (typeof(Module).IsAssignableFrom(featureType))
Icon = "GearBox";
else if (typeof(LayerBrushProvider).IsAssignableFrom(featureType))
Icon = "Brush";
else if (typeof(LayerEffectProvider).IsAssignableFrom(featureType))
Icon = "AutoAwesome";
else
Icon = "Plugin";
}
internal PluginFeatureInfo(PluginFeature instance, PluginFeatureAttribute? attribute)
internal PluginFeatureInfo(Plugin plugin, PluginFeatureAttribute? attribute, PluginFeature instance)
{
if (instance == null) throw new ArgumentNullException(nameof(instance));
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
FeatureType = instance.GetType();
Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title);
Description = attribute?.Description;
Icon = attribute?.Icon;
PluginFeature = instance;
Instance = instance;
if (Icon != null) return;
Icon = PluginFeature switch
Icon = Instance switch
{
BaseDataModelExpansion => "TableAdd",
DeviceProvider => "Devices",
@@ -43,6 +70,16 @@ namespace Artemis.Core
};
}
/// <summary>
/// Gets the plugin this feature info is associated with
/// </summary>
public Plugin Plugin { get; }
/// <summary>
/// Gets the type of the feature
/// </summary>
public Type FeatureType { get; }
/// <summary>
/// The name of the plugin
/// </summary>
@@ -75,18 +112,18 @@ namespace Artemis.Core
}
/// <summary>
/// Gets the plugin this info is associated with
/// Gets the feature this info is associated with
/// </summary>
public PluginFeature PluginFeature
public PluginFeature? Instance
{
get => _pluginFeature;
internal set => SetAndNotify(ref _pluginFeature, value);
get => _instance;
internal set => SetAndNotify(ref _instance, value);
}
/// <inheritdoc />
public override string ToString()
{
return PluginFeature.Id;
return Instance?.Id ?? "Uninitialized feature";
}
}
}