add a simple plugin system

This commit is contained in:
2023-11-14 14:20:26 +01:00
parent 1c4d7554e2
commit 9b7eb40cfc
20 changed files with 563 additions and 6 deletions

View File

@@ -0,0 +1,62 @@
using SM64RomManager.Functions;
using System.Drawing;
using System.Reflection;
using Telerik.WinControls;
using Telerik.WinControls.UI;
namespace Pilz.Plugins.Advanced
{
public static class Extensions
{
public static Icon? ToIcon(this Image image)
{
if (image is Bitmap bitmap)
return Icon.FromHandle(bitmap.GetHicon());
return null;
}
public static RadMenuItem GetAsItem(this PluginModule module, bool addDefaultHandler = true)
{
var item = new RadMenuItem
{
Text = module.Name,
SvgImage = module.Icon,
Tag = module,
Visibility = module.Visible ? ElementVisibility.Visible : ElementVisibility.Collapsed
};
if (addDefaultHandler)
item.Click += RadMenuItem_RMMethod_Click;
return item;
}
public static RadMenuItem GetAsItem(this PluginFunction function, bool addDefaultHandler = true)
{
var item = new RadMenuItem
{
Text = function.Name,
SvgImage = function.Icon,
Tag = function,
Visibility = function.Enabled ? ElementVisibility.Visible : ElementVisibility.Collapsed
};
if (addDefaultHandler)
item.Click += RadMenuItem_RMFunction_Click;
return item;
}
private static void RadMenuItem_RMMethod_Click(object? sender, EventArgs e)
{
if (sender is RadMenuItem item && item.Tag is PluginModule function)
function.ShowUI();
}
private static void RadMenuItem_RMFunction_Click(object? sender, EventArgs e)
{
if (sender is RadMenuItem item && item.Tag is PluginFunction function)
function.Execute();
}
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="UI.for.WinForms.AllControls.Net60" Version="2023.2.718" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz.Plugins\Pilz.Plugins.csproj" />
<ProjectReference Include="..\Pilz.UI.Telerik.SymbolFactory\Pilz.UI.Telerik.SymbolFactory.csproj" />
<ProjectReference Include="..\Pilz.UI.Telerik\Pilz.UI.Telerik.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telerik.WinControls;
namespace Pilz.Plugins.Advanced
{
public abstract class PluginFunction
{
public string Type { get; init; }
public string? Name { get; init; }
public RadSvgImage? Icon { get; set; }
public bool Enabled { get; set; } = true;
protected PluginFunction(string functionType)
{
Type = functionType;
}
protected PluginFunction(string functionType, string functionName) : this(functionType)
{
Name = functionName;
}
public object? Execute()
{
return Execute((PluginFunctionParameter?)null);
}
public T? Execute<T>(params object?[]? @params)
{
return Execute<T>(new PluginFunctionSimpleParamter(@params));
}
public object? Execute(params object?[]? @params)
{
return Execute(new PluginFunctionSimpleParamter(@params));
}
public T? Execute<T>(PluginFunctionSimpleParamter? @params)
{
if (Execute(@params) is T result)
return result;
return default;
}
public object? Execute(PluginFunctionParameter? @params)
{
#if !DEBUG
try
{
#endif
return ExecuteFunction(@params);
#if !DEBUG
}
catch (Exception)
{
return null;
}
#endif
}
protected abstract object? ExecuteFunction(PluginFunctionParameter? @params);
}
}

View File

@@ -0,0 +1,60 @@
namespace Pilz.Plugins.Advanced
{
public sealed class PluginFunctionController
{
public static PluginFunctionController Instance { get; private set; } = new();
private readonly List<PluginFunction> functions = new();
public IReadOnlyCollection<PluginFunction> Functions => functions.AsReadOnly();
public void RegisterFunction(PluginFunction function)
{
if (!functions.Contains(function))
functions.Add(function);
}
public void UnregisterFunction(PluginFunction function)
{
functions.Remove(function);
}
public IEnumerable<PluginFunction> GetFunctions(string functionType)
{
return functions.Where(n => n.Type == functionType);
}
public void ExecuteAll(string functionType)
{
foreach (var function in GetFunctions(functionType))
function.Execute();
}
public void ExecuteAll(string functionType, params object?[]? @params)
{
foreach (var function in GetFunctions(functionType))
function.Execute(@params);
}
public void ExecuteAll(string functionType, PluginFunctionParameter @params)
{
foreach (var function in GetFunctions(functionType))
function.Execute(@params);
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType)
{
return GetFunctions(functionType).Select(n => n.Execute());
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType, params object?[]? @params)
{
return GetFunctions(functionType).Select(n => n.Execute(@params));
}
public IEnumerable<object?> ExcuteAndGetResults(string functionType, PluginFunctionParameter @params)
{
return GetFunctions(functionType).Select(n => n.Execute(@params));
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Plugins.Advanced
{
public class PluginFunctionParameter
{
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Plugins.Advanced
{
public sealed class PluginFunctionSimpleParamter : PluginFunctionParameter
{
public object?[]? Params { get; init; }
public PluginFunctionSimpleParamter(params object?[]? @params)
{
Params = @params;
}
}
}

View File

@@ -0,0 +1,40 @@
using Pilz.UI.Telerik;
using Pilz.UI.Telerik.Dialogs;
using System.Drawing;
using System.Windows.Forms;
using Telerik.WinControls;
namespace Pilz.Plugins.Advanced
{
public abstract class PluginModule
{
public string Type { get; init; }
public string Name { get; init; }
public RadSvgImage? Icon { get; set; }
public bool Visible { get; set; } = true;
public bool RequiresRomManager { get; set; } = true;
public bool AllowEmbedding { get; set; } = true;
protected PluginModule(string moduleType, string moduleName)
{
Type = moduleType;
Name = moduleName;
}
public virtual void ShowUI()
{
if (CreateNewUI() is PluginModuleUI ui)
{
ui.BackColor = Color.Transparent;
DialogBaseForm.Show(ui, Name, Icon!.ToImage().ToIcon()!);
}
}
public PluginModuleUI CreateUI()
{
return CreateNewUI();
}
protected abstract PluginModuleUI CreateNewUI();
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Z.Collections.Extensions;
namespace Pilz.Plugins.Advanced
{
public sealed class PluginModuleController
{
public static PluginModuleController Instance { get; private set; } = new();
private readonly List<PluginModule> modules = new();
public IReadOnlyList<PluginModule> Modules => modules.AsReadOnly();
public void RegisterModule(PluginModule module)
{
if (!modules.Contains(module))
modules.Add(module);
}
public void UnregisterModule(PluginModule module)
{
modules.Remove(module);
}
}
}

View File

@@ -0,0 +1,22 @@
using Pilz.UI.Telerik.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Pilz.Plugins.Advanced
{
public class PluginModuleUI : FlyoutDialogBase, ILoadContent
{
public PluginModuleUI()
{
ActionPanelVisible = false;
}
public virtual void LoadContent()
{
}
}
}