From 76b9d95ddf60af56b6b083d8747e316c354c8509 Mon Sep 17 00:00:00 2001 From: "Frank A. Krueger" Date: Wed, 14 Jun 2017 23:10:58 -0700 Subject: [PATCH] Add Events --- Ooui/Button.cs | 5 ++++ Ooui/EventTarget.cs | 56 ++++++++++++++++++++++++++++++++++++++++++-- Ooui/Message.cs | 16 +++++++++++++ Tests/ButtonTests.cs | 19 +++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/Ooui/Button.cs b/Ooui/Button.cs index 45c9279..8027c6b 100644 --- a/Ooui/Button.cs +++ b/Ooui/Button.cs @@ -16,6 +16,11 @@ namespace Ooui set => SetProperty (ref val, value, "value"); } + public event EventHandler Clicked { + add => AddEventListener ("onclick", value); + remove => RemoveEventListener ("onclick", value); + } + public Button () { } diff --git a/Ooui/EventTarget.cs b/Ooui/EventTarget.cs index 465da3f..9dc5bd9 100644 --- a/Ooui/EventTarget.cs +++ b/Ooui/EventTarget.cs @@ -6,12 +6,15 @@ namespace Ooui { public abstract class EventTarget { + readonly List stateMessages = new List (); + + readonly Dictionary> eventListeners = + new Dictionary> (); + public string Id { get; private set; } = GenerateId (); public Mapping Mapping { get; private set; } - readonly List stateMessages = new List (); - public event Action MessageSent; public IEnumerable StateMessages => stateMessages; @@ -21,6 +24,36 @@ namespace Ooui Mapping = Mapping.Get (GetType ()); } + public void AddEventListener (string eventType, EventHandler handler) + { + if (eventType == null) return; + if (handler == null) return; + + var sendListen = false; + + List handlers; + if (!eventListeners.TryGetValue (eventType, out handlers)) { + handlers = new List (); + eventListeners[eventType] = handlers; + sendListen = true; + } + handlers.Add (handler); + + if (sendListen) + SendListen (eventType); + } + + public void RemoveEventListener (string eventType, EventHandler handler) + { + if (eventType == null) return; + if (handler == null) return; + + List handlers; + if (eventListeners.TryGetValue (eventType, out handlers)) { + handlers.Remove (handler); + } + } + protected bool SetProperty (ref T backingStore, T newValue, string attributeName, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") { if (!backingStore.Equals (newValue)) { @@ -73,6 +106,15 @@ namespace Ooui }); } + protected void SendListen (string eventType) + { + Send (new Message { + MessageType = MessageType.Listen, + TargetId = Id, + Key = eventType, + }); + } + public virtual void Receive (Message message) { if (message == null) @@ -110,11 +152,21 @@ namespace Ooui ReplaceStateMessage (old, message); } break; + case MessageType.Listen: + SaveStateMessage (message); + break; } } protected virtual void TriggerEventFromMessage (Message message) { + List handlers; + if (eventListeners.TryGetValue (message.Key, out handlers)) { + var args = EventArgs.Empty; + foreach (var h in handlers) { + h.Invoke (this, args); + } + } } } } diff --git a/Ooui/Message.cs b/Ooui/Message.cs index 1d52e07..8546c81 100644 --- a/Ooui/Message.cs +++ b/Ooui/Message.cs @@ -26,6 +26,18 @@ namespace Ooui set => v = FixupValue (value); } + public static Message Listen (string targetId, string eventType) => new Message { + MessageType = MessageType.Listen, + TargetId = targetId, + Key = eventType, + }; + + public static Message Event (string targetId, string eventType) => new Message { + MessageType = MessageType.Event, + TargetId = targetId, + Key = eventType, + }; + static object FixupValue (object v) { if (v is Array a) { @@ -60,5 +72,9 @@ namespace Ooui Set, [EnumMember(Value = "call")] Call, + [EnumMember(Value = "listen")] + Listen, + [EnumMember(Value = "event")] + Event, } } diff --git a/Tests/ButtonTests.cs b/Tests/ButtonTests.cs index 778d011..00cf2cf 100644 --- a/Tests/ButtonTests.cs +++ b/Tests/ButtonTests.cs @@ -21,5 +21,24 @@ namespace Tests var b = new Button ("Hello World!"); Assert.AreEqual ("Hello World!", b.Text); } + + [TestMethod] + public void Clicked () + { + var b = new Button ("Hello World!"); + var clicked = false; + var listened = false; + b.MessageSent += m => { + listened = listened || (m.MessageType == MessageType.Listen); + }; + Assert.IsFalse (listened); + b.Clicked += (s, e) => { + clicked = true; + }; + Assert.IsTrue (listened); + Assert.IsFalse (clicked); + b.Receive (Message.Event (b.Id, "onclick")); + Assert.IsTrue (clicked); + } } }