diff --git a/Pilz.Plugins.Advanced.UI.Gtk/Extensions.cs b/Pilz.Plugins.Advanced.UI.Gtk/Extensions.cs new file mode 100644 index 0000000..9839bc7 --- /dev/null +++ b/Pilz.Plugins.Advanced.UI.Gtk/Extensions.cs @@ -0,0 +1,127 @@ +using Gtk; + +namespace Pilz.Plugins.Advanced.UI.Gtk; + +public static class Extensions +{ + private class PluginFunctionEventArgs(EventArgs original, PluginFunction function) : EventArgs + { + public EventArgs Original { get; } = original; + public PluginFunction Function { get; } = function; + } + + private class PluginModuleEventArgs(EventArgs original, PluginModuleBase function) : EventArgs + { + public EventArgs Original { get; } = original; + public PluginModuleBase Function { get; } = function; + } + + public static MenuItem GetAsItem(this PluginModuleBase module) + { + return module.GetAsItem(true); + } + + public static MenuItem GetAsItem(this PluginModuleBase module, bool addDefaultHandler) + { + return module.GetAsItem(addDefaultHandler ? (sender, e) => RadMenuItem_RMMethod_Click(sender, new PluginModuleEventArgs(e, module)) : null); + } + + public static MenuItem GetAsItem(this PluginFunction function) + { + return function.GetAsItem(true); + } + + public static MenuItem GetAsItem(this PluginFunction function, bool addDefaultHandler) + { + return function.GetAsItem(addDefaultHandler ? (sender, e) => RadMenuItem_RMFunction_Click(sender, new PluginFunctionEventArgs(e, function)) : null); + } + + public static MenuItem GetAsItem(this PluginFeature module, EventHandler? clickHandler) + { + var item = new MenuItem(module.Name) + { + Visible = module.Enabled, + TooltipText = module.Description ?? module.Name + }; + + if (clickHandler is not null) + item.Activated += clickHandler; + + return item; + } + + /// + /// Inserts all items to a menu item. + /// + /// + /// + /// Will add a default click handler that executes the feature.
+ /// You usually don't set customClickHandler if you set this parameter to true. + /// Adds a custom click handler. If addDefaultHandler is true, it will only work on s.
+ /// You usually don't set addDefaultHandler to true if you set this parameter to something not null. + /// Defines a custom default position (index). + /// Defines a custom top position (index). + /// Defines a custom bottom position (index). + /// Defines if splitters should be inserted to seperate the new items by priorization. + public static IEnumerable> InsertItemsTo(this IEnumerable features, + MenuItem parentMenuItem, + bool addDefaultHandler = false, + EventHandler? customClickHandler = null, + int? customDefault = null, + int? customTop = null, + int? customBottom = null, + bool insertPrioSplitters = false) + { + var insertedItems = new List>(); + FeaturePrioritization? prevPrio = null; + + // Oder by priorization + features = features.OrderByDescending(n => n.Prioritization); + + foreach (var feature in features) + { + MenuItem item; + + if (feature is PluginFunction function) + item = function.GetAsItem(addDefaultHandler); + else if (feature is PluginModuleBase module) + item = module.GetAsItem(addDefaultHandler); + else + item = feature.GetAsItem(null); + + if (!addDefaultHandler && customClickHandler != null) + item.Activated += customClickHandler; + + if (insertPrioSplitters && (prevPrio == null || prevPrio > feature.Prioritization)) + { + insertItem(new SeparatorMenuItem()); + prevPrio = feature.Prioritization; + } + + insertItem(item); + + void insertItem(MenuItem item) + { + if (parentMenuItem.Submenu is Menu subMenu) + subMenu.Append(item); + } + + if (item.Parent != null) + insertedItems.Add(new(item, feature)); + } + + return insertedItems; + } + + private static void RadMenuItem_RMMethod_Click(object? sender, EventArgs e) + { + if (sender is MenuItem item && item.Sensitive && e is PluginFunctionEventArgs args && args.Function.Enabled) + throw new NotImplementedException(); + } + + private static void RadMenuItem_RMFunction_Click(object? sender, EventArgs e) + { + if (sender is MenuItem item && item.Sensitive && e is PluginFunctionEventArgs args && args.Function.Enabled) + args.Function.Execute(); + } +} \ No newline at end of file diff --git a/Pilz.Plugins.Advanced.UI.Gtk/Pilz.Plugins.Advanced.UI.Gtk.csproj b/Pilz.Plugins.Advanced.UI.Gtk/Pilz.Plugins.Advanced.UI.Gtk.csproj new file mode 100644 index 0000000..e9f3589 --- /dev/null +++ b/Pilz.Plugins.Advanced.UI.Gtk/Pilz.Plugins.Advanced.UI.Gtk.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + + + + 1.0.0 + + + + + + + + + + + + diff --git a/Pilz.sln b/Pilz.sln index 5e47d7b..a04d9c0 100644 --- a/Pilz.sln +++ b/Pilz.sln @@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.UI.Gtk", "Pilz.UI.Gtk\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.UI", "Pilz.UI\Pilz.UI.csproj", "{E75FBCEF-B971-4036-85D3-27D4ACA77156}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.Plugins.Advanced.UI.Gtk", "Pilz.Plugins.Advanced.UI.Gtk\Pilz.Plugins.Advanced.UI.Gtk.csproj", "{F9CA6B5C-F14F-418D-9617-6007ED75E82F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -251,6 +253,14 @@ Global {E75FBCEF-B971-4036-85D3-27D4ACA77156}.Release|Any CPU.Build.0 = Release|Any CPU {E75FBCEF-B971-4036-85D3-27D4ACA77156}.Release|x86.ActiveCfg = Release|Any CPU {E75FBCEF-B971-4036-85D3-27D4ACA77156}.Release|x86.Build.0 = Release|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Debug|x86.ActiveCfg = Debug|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Debug|x86.Build.0 = Debug|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Release|Any CPU.Build.0 = Release|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Release|x86.ActiveCfg = Release|Any CPU + {F9CA6B5C-F14F-418D-9617-6007ED75E82F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE