change UI to UI.WinForms

This commit is contained in:
2025-06-16 11:50:17 +02:00
parent fa3a9da07e
commit 299867a910
116 changed files with 318 additions and 319 deletions

View File

@@ -0,0 +1,10 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
public enum ControlExecuteReason
{
None,
Init,
Dispose,
Add,
Remove,
}

View File

@@ -0,0 +1,109 @@
using System.Text.RegularExpressions;
namespace Pilz.Plugins.Advanced.UI.WinForms;
internal class ControlListener(IEnumerable<ControlListenerFeature> features, Control control, bool recursive) : IControlListener
{
protected bool isTracking;
public virtual bool Recursive => recursive;
public virtual Control Control => control;
public virtual IEnumerable<ControlListenerFeature> Features => features;
internal virtual void Track()
{
if (isTracking)
return;
Track(control);
isTracking = true;
}
protected virtual void Track(Control control)
{
control.Disposed += Control_Disposed;
control.ControlAdded += Control_ControlAdded;
control.ControlRemoved += Control_ControlRemoved;
if (!recursive)
return;
foreach (var child in control.Controls)
{
if (child is Control childControl)
Track(childControl);
}
}
protected virtual void Control_Disposed(object? sender, EventArgs e)
{
if (sender is not Control control)
return;
Execute(control, ControlExecuteReason.Dispose, null, false);
control.Disposed -= Control_Disposed;
control.ControlAdded -= Control_ControlAdded;
control.ControlRemoved -= Control_ControlRemoved;
}
protected virtual void Control_ControlAdded(object? sender, ControlEventArgs e)
{
if (sender is not Control control)
return;
if (e.Control is not null)
Track(e.Control);
Execute(control, ControlExecuteReason.Add, new ControlParameters(e.Control), false);
}
protected virtual void Control_ControlRemoved(object? sender, ControlEventArgs e)
{
if (sender is not Control control)
return;
Execute(control, ControlExecuteReason.Remove, new ControlParameters(e.Control), false);
}
protected internal virtual void Initialize(PluginFunctionParameter? parameters)
{
Execute(ControlExecuteReason.Init, parameters);
}
public virtual void Execute(PluginFunctionParameter? parameters)
{
Execute(ControlExecuteReason.None, parameters);
}
protected virtual void Execute(ControlExecuteReason reason, PluginFunctionParameter? parameter)
{
Execute(control, reason, parameter, recursive);
}
protected virtual void Execute(Control control, ControlExecuteReason reason, PluginFunctionParameter? parameter, bool recursive)
{
execute(control);
void execute(Control control)
{
if (control.Name is string name)
{
foreach (var feature in features)
{
if (feature.ControlName is null || feature.ControlNameRegEx && Regex.IsMatch(control.Name, feature.ControlName) || feature.ControlName == control.Name)
feature.Execute(control, reason, parameter);
}
}
if (!recursive)
return;
foreach (var child in control.Controls)
{
if (child is Control childControl)
execute(childControl);
}
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
internal class ControlListenerDummy(IEnumerable<ControlListenerFeature> features, Control control, bool recursive) : ControlListener(features, control, recursive)
{
protected override void Track(Control control)
{
}
protected override void Execute(Control control, ControlExecuteReason reason, PluginFunctionParameter? parameter, bool recursive)
{
}
}

View File

@@ -0,0 +1,18 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
public abstract class ControlListenerFeature : PluginFeature
{
public string? ControlName { get; set; }
public bool ControlNameRegEx { get; set; }
public ControlListenerFeature(string type, string identifier) : base(type, identifier)
{
}
public ControlListenerFeature(string type, string identifier, string? name) : base(type, identifier, name)
{
}
public abstract void Execute(Control control, ControlExecuteReason reason, PluginFunctionParameter? parameter);
}

View File

@@ -0,0 +1,6 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
public class ControlParameters(Control? control) : PluginFunctionParameter
{
public Control? Control { get; } = control;
}

View File

@@ -0,0 +1,36 @@
namespace Pilz.Plugins.Advanced.UI.WinForms.Extensions;
public static class PluginFeatureControllerExtensions
{
public static IControlListener ApplyControlManager(this PluginFeatureController @this, string featureType, Control control)
{
return @this.ApplyControlManager(featureType, control, true, true);
}
public static IControlListener ApplyControlManager(this PluginFeatureController @this, string featureType, Control control, PluginFunctionParameter? parameter)
{
return @this.ApplyControlManager(featureType, control, true, true, parameter);
}
public static IControlListener ApplyControlManager(this PluginFeatureController @this, string featureType, Control control, bool recursive, bool autoTrack)
{
return @this.ApplyControlManager(featureType, control, recursive, autoTrack, null);
}
public static IControlListener ApplyControlManager(this PluginFeatureController @this, string featureType, Control control, bool recursive, bool autoTrack, PluginFunctionParameter? parameter)
{
var features = @this.Features.Get(featureType).OfType<ControlListenerFeature>();
if (!features.Any())
return new ControlListenerDummy([], control, recursive);
var manager = new ControlListener(features, control, recursive);
if (autoTrack)
manager.Track();
manager.Initialize(parameter);
return manager;
}
}

View File

@@ -0,0 +1,32 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
[Flags]
public enum FeatureInsertMode
{
/// <summary>
/// Features will be inserted at the end of the collection.
/// </summary>
Default = 0,
/// <summary>
/// Features will be inserted at the end of the collection.
/// This is the default behavior and equals <see cref="Default"/>. Will only be used if not set <see cref="UseCustomDefault"/>.
/// </summary>
DefaultEnd = Default,
/// <summary>
/// Features will be inserted at the start of the collection.
/// Will only be used if not set <see cref="UseCustomDefault"/>.
/// </summary>
DefaultStart = 1,
/// <summary>
/// Features with prioritization <see cref="FeaturePrioritization.High"/> will be inserted at the top (or left).
/// </summary>
InsertTop = 1 << 2,
/// <summary>
/// Features with prioritization <see cref="FeaturePrioritization.Low"/> will be inserted at the bottom (or right).
/// </summary>
InsertBottom = 1 << 3,
/// <summary>
/// Features with prioritization other then <see cref="FeaturePrioritization.Default"/> will be inserted at the top or bottom.
/// </summary>
InsertTopAndBottom = InsertTop | InsertBottom,
}

View File

@@ -0,0 +1,11 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
[Flags]
public enum FeatureInsertPosition
{
None = 0,
Default = 1,
Top = 2,
Bottom = 3,
All = int.MaxValue,
}

View File

@@ -0,0 +1,6 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
public interface IControlListener
{
void Execute(PluginFunctionParameter? parameter);
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-windows</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup>
<Version>1.9.0</Version>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz.Plugins.Advanced\Pilz.Plugins.Advanced.csproj" />
<ProjectReference Include="..\Pilz.UI.WinForms\Pilz.UI.WinForms.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
using Pilz.UI.Dialogs;
using Pilz.UI.WinForms.Extensions;
namespace Pilz.Plugins.Advanced.UI.WinForms;
public abstract class PluginModule : PluginModule<PluginModuleUI>
{
protected PluginModule(string type, string identifier) : base(type, identifier)
{
}
protected PluginModule(string type, string identifier, string? name) : base(type, identifier, name)
{
}
public override void ShowUI(PluginFunctionParameter? @params)
{
if (CreateNewUI(@params) is PluginModuleUI ui)
{
ui.BackColor = Color.Transparent;
DialogBase.Show(ui, Name!, Image!.ToIcon()!);
}
}
}

View File

@@ -0,0 +1,15 @@
using Pilz.UI.WinForms;
using Pilz.UI.WinForms.Dialogs;
namespace Pilz.Plugins.Advanced.UI.WinForms;
public partial class PluginModuleUI : FlyoutBase, ILoadContent
{
public PluginModuleUI()
{
}
public virtual void LoadContent()
{
}
}

View File

@@ -0,0 +1,52 @@
namespace Pilz.Plugins.Advanced.UI.WinForms;
public abstract class PluginModule<TPluginModuleUI> : PluginModuleBase where TPluginModuleUI : Control
{
public bool Visible { get; set; } = true;
public bool AllowEmbedding { get; set; } = true;
/// <summary>
/// Wrapper for the <see cref="PluginFeature.Icon"/> property to directly use it as <see cref="System.Drawing.Image"/>.
/// </summary>
public Image? Image
{
get => base.Icon as Image;
set => base.Icon = value;
}
protected PluginModule(string type, string identifier) : base(type, identifier)
{
}
protected PluginModule(string type, string identifier, string? name) : base(type, identifier, name)
{
}
public virtual void ShowUI()
{
ShowUI(null);
}
public virtual void ShowUI(PluginFunctionParameter? @params)
{
}
public virtual TPluginModuleUI? CreateUI()
{
return CreateUI(null);
}
public virtual TPluginModuleUI? CreateUI(PluginFunctionParameter? @params)
{
object? ui = default;
if (OnPreExecute(@params, ref ui))
ui = CreateNewUI(@params);
OnPostExecute(@params, ref ui);
return ui as TPluginModuleUI;
}
protected abstract TPluginModuleUI? CreateNewUI(PluginFunctionParameter? @params);
}