From 44ae8c96f3244d61ab339e38c3fe82bb5e4347dd Mon Sep 17 00:00:00 2001 From: "Frank A. Krueger" Date: Wed, 14 Jun 2017 18:24:59 -0700 Subject: [PATCH] Add EventTarget --- Ooui/EventTarget.cs | 120 ++++++++++++++++++++++++++++++++++++++++++++ Ooui/Message.cs | 4 +- Ooui/Node.cs | 93 +++------------------------------- Ooui/Server.cs | 6 +-- 4 files changed, 132 insertions(+), 91 deletions(-) create mode 100644 Ooui/EventTarget.cs diff --git a/Ooui/EventTarget.cs b/Ooui/EventTarget.cs new file mode 100644 index 0000000..465da3f --- /dev/null +++ b/Ooui/EventTarget.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Ooui +{ + public abstract class EventTarget + { + 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; + + public EventTarget () + { + Mapping = Mapping.Get (GetType ()); + } + + protected bool SetProperty (ref T backingStore, T newValue, string attributeName, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") + { + if (!backingStore.Equals (newValue)) { + backingStore = newValue; + SendSet (attributeName, newValue); + return true; + } + return false; + } + + static long idCounter = 0; + static string GenerateId () + { + var id = System.Threading.Interlocked.Increment (ref idCounter); + return "n" + id; + } + + public virtual void Send (Message message) + { + SaveStateMessage (message); + MessageSent?.Invoke (message); + } + + protected void SendCreate () + { + Send (new Message { + MessageType = MessageType.Create, + TargetId = Id, + Key = Mapping.TagName, + }); + } + + protected void SendCall (string methodName, params object[] args) + { + Send (new Message { + MessageType = MessageType.Call, + TargetId = Id, + Key = methodName, + Value = args, + }); + } + + protected void SendSet (string attributeName, object value) + { + Send (new Message { + MessageType = MessageType.Set, + TargetId = Id, + Key = attributeName, + Value = value, + }); + } + + public virtual void Receive (Message message) + { + if (message == null) + return; + if (message.TargetId != Id) + return; + SaveStateMessageIfNeeded (message); + TriggerEventFromMessage (message); + } + + protected void SaveStateMessage (Message message) + { + stateMessages.Add (message); + } + + protected void ReplaceStateMessage (Message old, Message message) + { + if (old != null) { + stateMessages.Remove (old); + } + stateMessages.Add (message); + } + + protected virtual void SaveStateMessageIfNeeded (Message message) + { + switch (message.MessageType) { + case MessageType.Create: + SaveStateMessage (message); + break; + case MessageType.Set: + { + var old = stateMessages.FirstOrDefault ( + x => x.MessageType == MessageType.Set && + x.Key == message.Key); + ReplaceStateMessage (old, message); + } + break; + } + } + + protected virtual void TriggerEventFromMessage (Message message) + { + } + } +} diff --git a/Ooui/Message.cs b/Ooui/Message.cs index 1b037fb..1d52e07 100644 --- a/Ooui/Message.cs +++ b/Ooui/Message.cs @@ -35,8 +35,8 @@ namespace Ooui } return na; } - else if (v is Node n) { - return "\u2999" + n.Id; + else if (v is EventTarget t) { + return "\u2999" + t.Id; } return v; } diff --git a/Ooui/Node.cs b/Ooui/Node.cs index 6512e57..62896a0 100644 --- a/Ooui/Node.cs +++ b/Ooui/Node.cs @@ -4,21 +4,13 @@ using System.Linq; namespace Ooui { - public abstract class Node + public abstract class Node : EventTarget { - public string Id { get; private set; } = GenerateId (); - - public Mapping Mapping { get; private set; } - readonly List children = new List (); - readonly List messages = new List (); - readonly List stateMessages = new List (); - public event Action MessageLogged; - - public IEnumerable AllMessages => - messages - .Concat (from c in children from m in c.AllMessages select m) + public IEnumerable AllStateMessages => + StateMessages + .Concat (from c in children from m in c.AllStateMessages select m) .OrderBy (x => x.Id); public virtual string Text { @@ -30,8 +22,7 @@ namespace Ooui public Node () { - Mapping = Mapping.Get (GetType ()); - LogCreate (); + SendCreate (); } public Node AppendChild (Node newChild) @@ -54,7 +45,7 @@ namespace Ooui children.Insert (index, newChild); } newChild.ParentNode = this; - LogCall ("insertBefore", newChild, referenceChild); + SendCall ("insertBefore", newChild, referenceChild); return newChild; } @@ -64,7 +55,7 @@ namespace Ooui throw new ArgumentException ("Child not contained in this element", nameof(child)); } child.ParentNode = null; - LogCall ("removeChild", child); + SendCall ("removeChild", child); return child; } @@ -75,75 +66,5 @@ namespace Ooui RemoveChild (c); InsertBefore (newNode, null); } - - protected void Log (Message message) - { - messages.Add (message); - - switch (message.MessageType) { - case MessageType.Create: - stateMessages.Add (message); - break; - case MessageType.Set: - { - var old = stateMessages.FirstOrDefault ( - x => x.MessageType == MessageType.Set && - x.Key == message.Key); - if (old != null) { - stateMessages.Remove (old); - } - stateMessages.Add (message); - } - break; - } - - MessageLogged?.Invoke (message); - } - - protected void LogCreate () - { - Log (new Message { - MessageType = MessageType.Create, - TargetId = Id, - Key = Mapping.TagName, - }); - } - - protected void LogCall (string methodName, params object[] args) - { - Log (new Message { - MessageType = MessageType.Call, - TargetId = Id, - Key = methodName, - Value = args, - }); - } - - protected void LogSet (string attributeName, object value) - { - Log (new Message { - MessageType = MessageType.Set, - TargetId = Id, - Key = attributeName, - Value = value, - }); - } - - protected bool SetProperty (ref T backingStore, T newValue, string attributeName, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") - { - if (!backingStore.Equals (newValue)) { - backingStore = newValue; - LogSet (attributeName, newValue); - return true; - } - return false; - } - - static long idCounter = 0; - static string GenerateId () - { - var id = System.Threading.Interlocked.Increment (ref idCounter); - return "n" + id; - } } } diff --git a/Ooui/Server.cs b/Ooui/Server.cs index e374e5b..5a21e8b 100644 --- a/Ooui/Server.cs +++ b/Ooui/Server.cs @@ -191,12 +191,12 @@ namespace Ooui // // Send message history, start sending updates, and add it to the body // - foreach (var m in element.AllMessages) { + foreach (var m in element.AllStateMessages) { if (webSocket.State == WebSocketState.Open) { await SendMessageAsync (webSocket, m, token); } } - element.MessageLogged += onElementMessage; + element.MessageSent += onElementMessage; await SendMessageAsync (webSocket, new Message { TargetId = "document.body", MessageType = MessageType.Call, @@ -243,7 +243,7 @@ namespace Ooui Error ("Failed to process web socket", ex); } finally { - element.MessageLogged -= onElementMessage; + element.MessageSent -= onElementMessage; webSocket?.Dispose (); } }