From 9f34518b99b45ff6c0cf0d61bcd7fe087e2998f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20M=C3=B8llegaard=20Pedersen?= Date: Sat, 2 Jan 2021 23:56:34 +0100 Subject: [PATCH] Lua-powered buttons (#11) --- Backend/Plugins/LuaPlugin.cs | 12 +++++ CHANGELOG.md | 1 + Frontend/MainWindow.Designer.cs | 66 ++++++++++++++--------- Frontend/MainWindow.cs | 46 ++++++++++++++-- Shared/EventFactory.cs | 24 +++++++++ Shared/EventHandler.cs | 30 +++++++++++ Shared/Events/UI/UIButtonTriggered.cs | 9 ++++ Shared/Events/UI/UICommandCreateButton.cs | 9 ++++ Shared/Events/UI/UICommandDeleteButton.cs | 9 ++++ Shared/IEventFactory.cs | 3 ++ Slipstream.csproj | 3 ++ 11 files changed, 183 insertions(+), 29 deletions(-) create mode 100644 Shared/Events/UI/UIButtonTriggered.cs create mode 100644 Shared/Events/UI/UICommandCreateButton.cs create mode 100644 Shared/Events/UI/UICommandDeleteButton.cs diff --git a/Backend/Plugins/LuaPlugin.cs b/Backend/Plugins/LuaPlugin.cs index f8c78c35..bde17e74 100644 --- a/Backend/Plugins/LuaPlugin.cs +++ b/Backend/Plugins/LuaPlugin.cs @@ -66,6 +66,8 @@ private void StartLua() Lua.RegisterFunction("set_temp_state", Api, typeof(LuaApi).GetMethod("SetTempState", new[] { typeof(string), typeof(string), typeof(int) })); Lua.RegisterFunction("get_state", Api, typeof(LuaApi).GetMethod("GetState", new[] { typeof(string) })); Lua.RegisterFunction("event_to_json", Api, typeof(LuaApi).GetMethod("EventToJson", new[] { typeof(IEvent) })); + Lua.RegisterFunction("create_button", Api, typeof(LuaApi).GetMethod("CreateButton", new[] { typeof(string) })); + Lua.RegisterFunction("delete_button", Api, typeof(LuaApi).GetMethod("DeleteButton", new[] { typeof(string) })); var ScriptPath = Path.GetDirectoryName(FilePath).Replace("\\", "\\\\"); Lua.DoString($"package.path = \"{ScriptPath}\\\\?.lua;\" .. package.path;"); @@ -195,6 +197,16 @@ public string EventToJson(IEvent @event) return EventSerdeService.Serialize(@event); } + public void CreateButton(string text) + { + EventBus.PublishEvent(EventFactory.CreateUICommandCreateButton(text)); + } + + public void DeleteButton(string text) + { + EventBus.PublishEvent(EventFactory.CreateUICommandDeleteButton(text)); + } + private void HandleDelayedExecution(IDictionary functions) { string? deleteKey = null; diff --git a/CHANGELOG.md b/CHANGELOG.md index ac52337d..d8c10e9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - PluginState to InternalPluginState - CommandTwitchSendMessage to TwitchCommandSendMessage - CommandWriteToConsole to UICommandWriteToConsole + - Buttons: Make simple buttons in UI using Lua (create_button("text")) and remove them again (delete_button("text")) ## [0.2.0](https://github.com/dennis/slipstream/releases/tag/v0.2.0) (2020-12-30) [Full Changelog](https://github.com/dennis/slipstream/compare/v0.1.0...v0.2.0) diff --git a/Frontend/MainWindow.Designer.cs b/Frontend/MainWindow.Designer.cs index f58b6831..0d54de41 100644 --- a/Frontend/MainWindow.Designer.cs +++ b/Frontend/MainWindow.Designer.cs @@ -30,43 +30,32 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.panel1 = new System.Windows.Forms.Panel(); - this.LogAreaTextBox = new System.Windows.Forms.TextBox(); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.FileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ExitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.PluginsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.OpenAudioDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.OpenScriptsDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ButtonFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); + this.LogAreaTextBox = new System.Windows.Forms.TextBox(); this.LogMessageUpdateTimer = new System.Windows.Forms.Timer(this.components); - this.SettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.panel1.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // panel1 // - this.panel1.Controls.Add(this.LogAreaTextBox); this.panel1.Controls.Add(this.menuStrip1); + this.panel1.Controls.Add(this.ButtonFlowLayoutPanel); + this.panel1.Controls.Add(this.LogAreaTextBox); this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; this.panel1.Location = new System.Drawing.Point(0, 0); this.panel1.Name = "panel1"; this.panel1.Size = new System.Drawing.Size(800, 450); this.panel1.TabIndex = 0; // - // LogAreaTextBox - // - this.LogAreaTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.LogAreaTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LogAreaTextBox.Location = new System.Drawing.Point(0, 24); - this.LogAreaTextBox.Multiline = true; - this.LogAreaTextBox.Name = "LogAreaTextBox"; - this.LogAreaTextBox.ReadOnly = true; - this.LogAreaTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.LogAreaTextBox.Size = new System.Drawing.Size(800, 426); - this.LogAreaTextBox.TabIndex = 0; - this.LogAreaTextBox.WordWrap = false; - // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -88,11 +77,18 @@ private void InitializeComponent() this.FileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.FileToolStripMenuItem.Text = "&File"; // + // SettingsToolStripMenuItem + // + this.SettingsToolStripMenuItem.Name = "SettingsToolStripMenuItem"; + this.SettingsToolStripMenuItem.Size = new System.Drawing.Size(135, 22); + this.SettingsToolStripMenuItem.Text = "Settings"; + this.SettingsToolStripMenuItem.Click += new System.EventHandler(this.SettingsToolStripMenuItem_Click); + // // ExitToolStripMenuItem // this.ExitToolStripMenuItem.Name = "ExitToolStripMenuItem"; this.ExitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); - this.ExitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.ExitToolStripMenuItem.Size = new System.Drawing.Size(135, 22); this.ExitToolStripMenuItem.Text = "Exit"; this.ExitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolStripMenuItem_Click); // @@ -125,19 +121,38 @@ private void InitializeComponent() this.OpenScriptsDirectoryToolStripMenuItem.Text = "Open Scripts Directory"; this.OpenScriptsDirectoryToolStripMenuItem.Click += new System.EventHandler(this.OpenScriptsDirectoryToolStripMenuItem_Click); // + // ButtonFlowLayoutPanel + // + this.ButtonFlowLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ButtonFlowLayoutPanel.AutoScroll = true; + this.ButtonFlowLayoutPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.ButtonFlowLayoutPanel.Location = new System.Drawing.Point(3, 418); + this.ButtonFlowLayoutPanel.Name = "ButtonFlowLayoutPanel"; + this.ButtonFlowLayoutPanel.Size = new System.Drawing.Size(794, 29); + this.ButtonFlowLayoutPanel.TabIndex = 3; + // + // LogAreaTextBox + // + this.LogAreaTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.LogAreaTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.LogAreaTextBox.Location = new System.Drawing.Point(0, 27); + this.LogAreaTextBox.Multiline = true; + this.LogAreaTextBox.Name = "LogAreaTextBox"; + this.LogAreaTextBox.ReadOnly = true; + this.LogAreaTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.LogAreaTextBox.Size = new System.Drawing.Size(797, 385); + this.LogAreaTextBox.TabIndex = 2; + this.LogAreaTextBox.WordWrap = false; + // // LogMessageUpdateTimer // this.LogMessageUpdateTimer.Enabled = true; this.LogMessageUpdateTimer.Interval = 250; this.LogMessageUpdateTimer.Tick += new System.EventHandler(this.LogMessageUpdate_Tick); // - // SettingsToolStripMenuItem - // - this.SettingsToolStripMenuItem.Name = "SettingsToolStripMenuItem"; - this.SettingsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.SettingsToolStripMenuItem.Text = "Settings"; - this.SettingsToolStripMenuItem.Click += new System.EventHandler(this.SettingsToolStripMenuItem_Click); - // // MainWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -158,7 +173,6 @@ private void InitializeComponent() #endregion private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.TextBox LogAreaTextBox; private System.Windows.Forms.Timer LogMessageUpdateTimer; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem FileToolStripMenuItem; @@ -168,6 +182,8 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem OpenScriptsDirectoryToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem OpenAudioDirectoryToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SettingsToolStripMenuItem; + private System.Windows.Forms.FlowLayoutPanel ButtonFlowLayoutPanel; + private System.Windows.Forms.TextBox LogAreaTextBox; } } diff --git a/Frontend/MainWindow.cs b/Frontend/MainWindow.cs index f44c4556..c85df155 100644 --- a/Frontend/MainWindow.cs +++ b/Frontend/MainWindow.cs @@ -1,6 +1,7 @@ #nullable enable using Slipstream.Shared; +using Slipstream.Shared.Events.UI; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -18,6 +19,7 @@ public partial class MainWindow : Form private IEventBusSubscription? EventBusSubscription; private readonly BlockingCollection PendingMessages = new BlockingCollection(); private readonly IDictionary MenuPluginItems = new Dictionary(); + private readonly IDictionary LuaButtons = new Dictionary(); private readonly ApplicationConfiguration ApplicationConfiguration; private readonly string CleanTitle; @@ -84,10 +86,9 @@ private void EventListenerMain() Debug.Assert(EventBusSubscription != null); EventHandler.OnInternalPluginState += (s, e) => EventHandler_OnInternalPluginState(e.Event); - EventHandler.OnUICommandWriteToConsole += (s, e) => - { - PendingMessages.Add($"{DateTime.Now:s} {e.Event.Message}"); - }; + EventHandler.OnUICommandWriteToConsole += (s, e) => PendingMessages.Add($"{DateTime.Now:s} {e.Event.Message}"); + EventHandler.OnUICommandCreateButton += (s, e) => EventHandler_OnUICommandCreateButton(e.Event); + EventHandler.OnUICommandDeleteButton += (s, e) => EventHandler_OnUICommandDeleteButton(e.Event); // Request full state of all known plugins, so we get any that might be started before "us" EventBus.PublishEvent(EventFactory.CreateInternalCommandPluginStates()); @@ -98,6 +99,43 @@ private void EventListenerMain() } } + private void EventHandler_OnUICommandCreateButton(UICommandCreateButton @event) + { + ExecuteSecure(() => + { + if (LuaButtons.ContainsKey(@event.Text)) + return; + + var b = new Button + { + Text = @event.Text + }; + + b.Click += (s, e) => + { + var b = s as Button; + if(b != null) + EventBus.PublishEvent(EventFactory.CreateUIButtonTriggered(b.Text)); + }; + + LuaButtons.Add(@event.Text, b); + + ButtonFlowLayoutPanel.Controls.Add(b); + }); + } + + private void EventHandler_OnUICommandDeleteButton(UICommandDeleteButton @event) + { + ExecuteSecure(() => + { + if (!LuaButtons.ContainsKey(@event.Text)) + return; + + ButtonFlowLayoutPanel.Controls.Remove(LuaButtons[@event.Text]); + LuaButtons.Remove(@event.Text); + }); + } + private void EventHandler_OnInternalPluginState(Shared.Events.Internal.InternalPluginState e) { if (e.PluginStatus != "Unregistered" && !MenuPluginItems.ContainsKey(e.Id)) diff --git a/Shared/EventFactory.cs b/Shared/EventFactory.cs index a4810128..d0e59067 100644 --- a/Shared/EventFactory.cs +++ b/Shared/EventFactory.cs @@ -453,5 +453,29 @@ public UICommandWriteToConsole CreateUICommandWriteToConsole(string message) Message = message }; } + + public UICommandCreateButton CreateUICommandCreateButton(string text) + { + return new UICommandCreateButton + { + Text = text, + }; + } + + public UICommandDeleteButton CreateUICommandDeleteButton(string text) + { + return new UICommandDeleteButton + { + Text = text, + }; + } + + public UIButtonTriggered CreateUIButtonTriggered(string text) + { + return new UIButtonTriggered + { + Text = text + }; + } } } diff --git a/Shared/EventHandler.cs b/Shared/EventHandler.cs index f9120ac2..f1ab18c2 100644 --- a/Shared/EventHandler.cs +++ b/Shared/EventHandler.cs @@ -65,6 +65,15 @@ public EventHandlerArgs(T e) #region Events: UI public delegate void OnUICommandWriteToConsoleHandler(EventHandler source, EventHandlerArgs e); public event OnUICommandWriteToConsoleHandler? OnUICommandWriteToConsole; + + public delegate void OnUICommandCreateButtonHandler(EventHandler source, EventHandlerArgs e); + public event OnUICommandCreateButtonHandler? OnUICommandCreateButton; + + public delegate void OnUICommandDeleteButtonHandler(EventHandler source, EventHandlerArgs e); + public event OnUICommandDeleteButtonHandler? OnUICommandDeleteButton; + + public delegate void OnUIButtonTriggeredHandler(EventHandler source, EventHandlerArgs e); + public event OnUIButtonTriggeredHandler? OnUIButtonTriggered; #endregion #region Events: Audio @@ -257,6 +266,27 @@ public void HandleEvent(IEvent? ev) OnUICommandWriteToConsole.Invoke(this, new EventHandlerArgs(tev)); break; + case Shared.Events.UI.UICommandCreateButton tev: + if (OnUICommandCreateButton == null) + OnDefault?.Invoke(this, new EventHandlerArgs(tev)); + else + OnUICommandCreateButton.Invoke(this, new EventHandlerArgs(tev)); + break; + + case Shared.Events.UI.UICommandDeleteButton tev: + if (OnUICommandDeleteButton == null) + OnDefault?.Invoke(this, new EventHandlerArgs(tev)); + else + OnUICommandDeleteButton.Invoke(this, new EventHandlerArgs(tev)); + break; + + case Shared.Events.UI.UIButtonTriggered tev: + if (OnUIButtonTriggered == null) + OnDefault?.Invoke(this, new EventHandlerArgs(tev)); + else + OnUIButtonTriggered.Invoke(this, new EventHandlerArgs(tev)); + break; + // Setting case Shared.Events.Setting.FileMonitorSettings tev: diff --git a/Shared/Events/UI/UIButtonTriggered.cs b/Shared/Events/UI/UIButtonTriggered.cs new file mode 100644 index 00000000..5d62a17a --- /dev/null +++ b/Shared/Events/UI/UIButtonTriggered.cs @@ -0,0 +1,9 @@ +namespace Slipstream.Shared.Events.UI +{ + public class UIButtonTriggered : IEvent + { + public string EventType => "UIButtonTriggered"; + public bool ExcludeFromTxrx => false; + public string Text { get; set; } = "INVALID-NAME"; + } +} diff --git a/Shared/Events/UI/UICommandCreateButton.cs b/Shared/Events/UI/UICommandCreateButton.cs new file mode 100644 index 00000000..31c6a17e --- /dev/null +++ b/Shared/Events/UI/UICommandCreateButton.cs @@ -0,0 +1,9 @@ +namespace Slipstream.Shared.Events.UI +{ + public class UICommandCreateButton : IEvent + { + public string EventType => "UICommandCreateButton"; + public bool ExcludeFromTxrx => true; + public string Text { get; set; } = ""; + } +} diff --git a/Shared/Events/UI/UICommandDeleteButton.cs b/Shared/Events/UI/UICommandDeleteButton.cs new file mode 100644 index 00000000..196d2b44 --- /dev/null +++ b/Shared/Events/UI/UICommandDeleteButton.cs @@ -0,0 +1,9 @@ +namespace Slipstream.Shared.Events.UI +{ + public class UICommandDeleteButton : IEvent + { + public string EventType => "UICommandDeleteButton"; + public bool ExcludeFromTxrx => true; + public string Text { get; set; } = ""; + } +} diff --git a/Shared/IEventFactory.cs b/Shared/IEventFactory.cs index a472e38f..28322b4f 100644 --- a/Shared/IEventFactory.cs +++ b/Shared/IEventFactory.cs @@ -159,5 +159,8 @@ string fogLevel TwitchReceivedCommand CreateTwitchReceivedCommand(string from, string message, bool moderator, bool subscriber, bool vip, bool broadcaster); UICommandWriteToConsole CreateUICommandWriteToConsole(string message); + UICommandCreateButton CreateUICommandCreateButton(string text); + UICommandDeleteButton CreateUICommandDeleteButton(string text); + UIButtonTriggered CreateUIButtonTriggered(string text); } } diff --git a/Slipstream.csproj b/Slipstream.csproj index c3a4cc33..d0b55242 100644 --- a/Slipstream.csproj +++ b/Slipstream.csproj @@ -154,6 +154,9 @@ + + +