From 56c77544082ad164883a22a7dd8f3cb2950e7bb7 Mon Sep 17 00:00:00 2001 From: FlorianDahn Date: Fri, 23 Aug 2019 14:02:24 +0200 Subject: [PATCH] - Added ToggleButton as an easy switch control (i.e. for settings page) - added control id, for easier separating of controls in one form - added automatic event selection for specific controls, to not raise an event for other controls who has invoked it - changed Action method - added example --- .../Tests/Controls/ToggleButtons.cs | 49 ++++++ TelegramBaseTest/Tests/Start.cs | 12 ++ TelegramBotBase/Base/ControlBase.cs | 12 +- TelegramBotBase/Base/FormBase.cs | 13 +- TelegramBotBase/Controls/CalendarPicker.cs | 2 +- TelegramBotBase/Controls/ToggleButton.cs | 145 ++++++++++++++++++ TelegramBotBase/Controls/TreeView.cs | 8 +- TelegramBotBase/Form/ButtonBase.cs | 5 +- TelegramBotBase/Form/ButtonForm.cs | 11 +- 9 files changed, 246 insertions(+), 11 deletions(-) create mode 100644 TelegramBaseTest/Tests/Controls/ToggleButtons.cs create mode 100644 TelegramBotBase/Controls/ToggleButton.cs diff --git a/TelegramBaseTest/Tests/Controls/ToggleButtons.cs b/TelegramBaseTest/Tests/Controls/ToggleButtons.cs new file mode 100644 index 0000000..4b634c6 --- /dev/null +++ b/TelegramBaseTest/Tests/Controls/ToggleButtons.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Controls; +using TelegramBotBase.Form; + +namespace TelegramBaseTest.Tests.Controls +{ + public class ToggleButtons : AutoCleanForm + { + public ToggleButtons() + { + this.DeleteMode = TelegramBotBase.Enums.eDeleteMode.OnLeavingForm; + + this.Init += ToggleButtons_Init; + } + + private async Task ToggleButtons_Init(object sender, TelegramBotBase.Base.InitEventArgs e) + { + + var tb = new ToggleButton(); + tb.Checked = true; + tb.Toggled += Tb_Toggled; + + this.AddControl(tb); + + tb = new ToggleButton(); + tb.Checked = false; + tb.Toggled += Tb_Toggled; + + this.AddControl(tb); + + tb = new ToggleButton(); + tb.Checked = true; + tb.Toggled += Tb_Toggled; + + this.AddControl(tb); + + } + + private void Tb_Toggled(object sender, EventArgs e) + { + var tb = sender as ToggleButton; + Console.WriteLine(tb.ID.ToString() + " was pressed, and toggled to " + (tb.Checked ? "Checked" : "Unchecked")); + } + } +} diff --git a/TelegramBaseTest/Tests/Start.cs b/TelegramBaseTest/Tests/Start.cs index 75349da..e85550c 100644 --- a/TelegramBaseTest/Tests/Start.cs +++ b/TelegramBaseTest/Tests/Start.cs @@ -113,6 +113,16 @@ namespace TelegramBaseTest.Tests await this.NavigateTo(tree); + break; + + case "togglebuttons": + + message.Handled = true; + + var tb = new Controls.ToggleButtons(); + + await this.NavigateTo(tb); + break; } @@ -138,6 +148,8 @@ namespace TelegramBaseTest.Tests btn.AddButtonRow(new ButtonBase("#10 TreeView", new CallbackData("a", "treeview").Serialize())); + btn.AddButtonRow(new ButtonBase("#11 ToggleButtons", new CallbackData("a", "togglebuttons").Serialize())); + await this.Device.Send("Choose your test:", btn); } diff --git a/TelegramBotBase/Base/ControlBase.cs b/TelegramBotBase/Base/ControlBase.cs index 83e07c4..fa905e0 100644 --- a/TelegramBotBase/Base/ControlBase.cs +++ b/TelegramBotBase/Base/ControlBase.cs @@ -15,18 +15,28 @@ namespace TelegramBotBase.Base public int ID { get; set; } + public String ControlID + { + get + { + return "#c" + this.ID.ToString(); + } + } + /// /// Defines if the control should be rendered and invoked with actions /// public bool Enabled { get; set; } = true; - public virtual async Task Action(MessageResult result) + public virtual async Task Action(MessageResult result, String value = null) { } + + public virtual async Task Render(MessageResult result) { diff --git a/TelegramBotBase/Base/FormBase.cs b/TelegramBotBase/Base/FormBase.cs index 56399af..df7eea4 100644 --- a/TelegramBotBase/Base/FormBase.cs +++ b/TelegramBotBase/Base/FormBase.cs @@ -55,7 +55,7 @@ namespace TelegramBotBase.Form return; var handler = this.Events[__evInit].GetInvocationList().Cast>(); - foreach(var h in handler) + foreach (var h in handler) { await Async.InvokeAllAsync(h, this, e); } @@ -169,6 +169,17 @@ namespace TelegramBotBase.Form /// public async Task ActionControls(MessageResult message) { + //Looking for the control by id, if not listened, raise event for all + if (message.RawData.StartsWith("#c")) + { + var c = this.Controls.FirstOrDefault(a => a.ControlID == message.RawData.Split('_')[0]); + if (c != null) + { + await c.Action(message, message.RawData.Split('_')[1]); + return; + } + } + foreach (var b in this.Controls) { if (!b.Enabled) diff --git a/TelegramBotBase/Controls/CalendarPicker.cs b/TelegramBotBase/Controls/CalendarPicker.cs index 027e4df..5e51c63 100644 --- a/TelegramBotBase/Controls/CalendarPicker.cs +++ b/TelegramBotBase/Controls/CalendarPicker.cs @@ -49,7 +49,7 @@ namespace TelegramBotBase.Controls - public override async Task Action(MessageResult result) + public override async Task Action(MessageResult result, String value = null) { await result.ConfirmAction(); diff --git a/TelegramBotBase/Controls/ToggleButton.cs b/TelegramBotBase/Controls/ToggleButton.cs new file mode 100644 index 0000000..4adcd3f --- /dev/null +++ b/TelegramBotBase/Controls/ToggleButton.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Base; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Controls +{ + public class ToggleButton : ControlBase + { + + public String UncheckedIcon { get; set; } = "⚪"; + + public String CheckedIcon { get; set; } = "⚫"; + + public String CheckedString { get; set; } = "On"; + + public String UncheckedString { get; set; } = "Off"; + + public String Title { get; set; } = "Toggle"; + + public int? MessageId { get; set; } + + public bool Checked { get; set; } + + private bool RenderNecessary = true; + + private static readonly object __evToggled = new object(); + + private readonly EventHandlerList Events = new EventHandlerList(); + + + public ToggleButton() + { + + + } + + public ToggleButton(String CheckedString, String UncheckedString) + { + this.CheckedString = CheckedString; + this.UncheckedString = UncheckedString; + } + + public event EventHandler Toggled + { + add + { + this.Events.AddHandler(__evToggled, value); + } + remove + { + this.Events.RemoveHandler(__evToggled, value); + } + } + + public void OnToggled(EventArgs e) + { + (this.Events[__evToggled] as EventHandler)?.Invoke(this, e); + } + + public override async Task Action(MessageResult result, String value = null) + { + + if (result.Handled) + return; + + await result.ConfirmAction(); + + switch (value ?? "unknown") + { + case "on": + + if (this.Checked) + return; + + RenderNecessary = true; + + this.Checked = true; + + OnToggled(new EventArgs()); + + break; + + case "off": + + if (!this.Checked) + return; + + RenderNecessary = true; + + this.Checked = false; + + OnToggled(new EventArgs()); + + break; + + default: + + RenderNecessary = false; + + break; + + } + + result.Handled = true; + + } + + public override async Task Render(MessageResult result) + { + if (!RenderNecessary) + return; + + var bf = new ButtonForm(this); + + ButtonBase bOn = new ButtonBase((this.Checked ? CheckedIcon : UncheckedIcon) + " " + CheckedString, "on"); + + ButtonBase bOff = new ButtonBase((!this.Checked ? CheckedIcon : UncheckedIcon) + " " + UncheckedString, "off"); + + bf.AddButtonRow(bOn, bOff); + + if (this.MessageId != null) + { + var m = await this.Device.Edit(this.MessageId.Value, this.Title, bf); + } + else + { + var m = await this.Device.Send(this.Title, bf, disableNotification: true); + if (m != null) + { + this.MessageId = m.MessageId; + } + } + + this.RenderNecessary = false; + + + } + + } +} diff --git a/TelegramBotBase/Controls/TreeView.cs b/TelegramBotBase/Controls/TreeView.cs index 250b842..cdb7d3c 100644 --- a/TelegramBotBase/Controls/TreeView.cs +++ b/TelegramBotBase/Controls/TreeView.cs @@ -29,16 +29,16 @@ namespace TelegramBotBase.Controls } - public override async Task Action(MessageResult result) + public override async Task Action(MessageResult result, String value = null) { await result.ConfirmAction(); if (result.Handled) return; - var value = result.RawData; + var val = result.RawData; - switch (value) + switch (val) { case "up": case "parent": @@ -50,7 +50,7 @@ namespace TelegramBotBase.Controls break; default: - var n = (this.VisibleNode != null ? this.VisibleNode.FindNodeByValue(value) : this.Nodes.FirstOrDefault(a => a.Value == value)); + var n = (this.VisibleNode != null ? this.VisibleNode.FindNodeByValue(val) : this.Nodes.FirstOrDefault(a => a.Value == val)); if (n != null) { diff --git a/TelegramBotBase/Form/ButtonBase.cs b/TelegramBotBase/Form/ButtonBase.cs index 6f6ed8d..67d193a 100644 --- a/TelegramBotBase/Form/ButtonBase.cs +++ b/TelegramBotBase/Form/ButtonBase.cs @@ -31,11 +31,12 @@ namespace TelegramBotBase.Form } - public InlineKeyboardButton ToInlineButton() + public InlineKeyboardButton ToInlineButton(ButtonForm form) { + String id = (form.DependencyControl != null ? form.DependencyControl.ControlID + "_" : ""); if (this.Url == null) { - return InlineKeyboardButton.WithCallbackData(this.Text, this.Value); + return InlineKeyboardButton.WithCallbackData(this.Text, id + this.Value); } var ikb = new InlineKeyboardButton(); diff --git a/TelegramBotBase/Form/ButtonForm.cs b/TelegramBotBase/Form/ButtonForm.cs index a52f5bf..7fe1df7 100644 --- a/TelegramBotBase/Form/ButtonForm.cs +++ b/TelegramBotBase/Form/ButtonForm.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Telegram.Bot.Types.ReplyMarkups; +using TelegramBotBase.Base; namespace TelegramBotBase.Form { @@ -17,12 +18,18 @@ namespace TelegramBotBase.Form public IReplyMarkup Markup { get; set; } + public ControlBase DependencyControl { get; set; } public ButtonForm() { } + public ButtonForm(ControlBase control) + { + this.DependencyControl = control; + } + public void AddButtonRow(IEnumerable row) { Buttons.Add(row.ToList()); @@ -62,7 +69,7 @@ namespace TelegramBotBase.Form { var sp = SplitTo(buttons, buttonsPerRow); - foreach(var bl in sp) + foreach (var bl in sp) { AddButtonRow(bl); } @@ -70,7 +77,7 @@ namespace TelegramBotBase.Form public InlineKeyboardButton[][] ToArray() { - var ikb = this.Buttons.Select(a => a.Select(b => b.ToInlineButton()).ToArray()).ToArray(); + var ikb = this.Buttons.Select(a => a.Select(b => b.ToInlineButton(this)).ToArray()).ToArray(); return ikb; }