Remove children from state

This commit is contained in:
Frank A. Krueger 2017-06-17 23:21:49 -07:00
parent e2f6e7ed3f
commit 15578a6bac
4 changed files with 96 additions and 22 deletions

View File

@ -18,10 +18,10 @@ namespace Ooui
public event Action<Message> MessageSent; public event Action<Message> MessageSent;
public IEnumerable<Message> StateMessages { public IReadOnlyList<Message> StateMessages {
get { get {
lock (stateMessages) { lock (stateMessages) {
return new List<Message> (stateMessages); return new List<Message> (stateMessages).AsReadOnly ();
} }
} }
} }
@ -37,6 +37,8 @@ namespace Ooui
}); });
} }
public override string ToString() => $"<{TagName} id=\"{Id}\" />";
public virtual EventTarget GetElementById (string id) public virtual EventTarget GetElementById (string id)
{ {
if (id == Id) return this; if (id == Id) return this;
@ -134,37 +136,30 @@ namespace Ooui
TriggerEventFromMessage (message); TriggerEventFromMessage (message);
} }
protected void SaveStateMessage (Message message) protected void AddStateMessage (Message message)
{ {
lock (stateMessages) stateMessages.Add (message); lock (stateMessages) stateMessages.Add (message);
} }
void LockedReplaceStateMessage (Message old, Message message) protected void UpdateStateMessages (Action<List<Message>> updater)
{ {
if (old != null) { lock (stateMessages) updater (stateMessages);
stateMessages.Remove (old);
}
stateMessages.Add (message);
} }
protected virtual void SaveStateMessageIfNeeded (Message message) protected virtual void SaveStateMessageIfNeeded (Message message)
{ {
switch (message.MessageType) { switch (message.MessageType) {
case MessageType.Create: case MessageType.Create:
SaveStateMessage (message); AddStateMessage (message);
break; break;
case MessageType.Set: case MessageType.Set:
{ UpdateStateMessages (state => {
lock (stateMessages) { state.RemoveAll (x => x.MessageType == MessageType.Set && x.Key == message.Key);
var old = stateMessages.FirstOrDefault ( state.Add (message);
x => x.MessageType == MessageType.Set && });
x.Key == message.Key);
LockedReplaceStateMessage (old, message);
}
}
break; break;
case MessageType.Listen: case MessageType.Listen:
SaveStateMessage (message); AddStateMessage (message);
break; break;
} }
} }

View File

@ -103,10 +103,30 @@ namespace Ooui
protected override void SaveStateMessageIfNeeded (Message message) protected override void SaveStateMessageIfNeeded (Message message)
{ {
switch (message.MessageType) { switch (message.MessageType) {
case MessageType.Call when case MessageType.Call when message.Key == "insertBefore":
message.Key == "insertBefore" || AddStateMessage (message);
message.Key == "removeChild": break;
SaveStateMessage (message); case MessageType.Call when message.Key == "removeChild" && message.Value is Array ma && ma.Length == 1:
UpdateStateMessages (state => {
var mchild = ma.GetValue (0);
Node nextChild = null;
for (var i = 0; i < state.Count; ) {
var x = state[i];
if (x.Key == "insertBefore" && x.Value is Array xa && xa.Length == 2 && ReferenceEquals (xa.GetValue (0), mchild)) {
// Remove any inserts for this node
nextChild = xa.GetValue (1) as Node;
state.RemoveAt (i);
}
else if (x.Key == "insertBefore" && x.Value is Array ya && ya.Length == 2 && ReferenceEquals (ya.GetValue (1), mchild)) {
// Replace inserts that reference this node
state[i] = Message.Call (Id, "insertBefore", ya.GetValue (0), nextChild);
i++;
}
else {
i++;
}
}
});
break; break;
default: default:
base.SaveStateMessageIfNeeded (message); base.SaveStateMessageIfNeeded (message);

18
Tests/EventTargetTests.cs Normal file
View File

@ -0,0 +1,18 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ooui;
namespace Tests
{
[TestClass]
public class EventTargetTests
{
[TestMethod]
public void CreationState ()
{
var b = new Button ();
Assert.AreEqual (1, b.StateMessages.Count);
}
}
}

41
Tests/NodeTests.cs Normal file
View File

@ -0,0 +1,41 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ooui;
namespace Tests
{
[TestClass]
public class NodeTests
{
[TestMethod]
public void TextState ()
{
var b = new Button ();
Assert.AreEqual (1, b.StateMessages.Count);
b.Text = "Hello";
Assert.AreEqual (2, b.StateMessages.Count);
b.Text = "Bye";
Assert.AreEqual (2, b.StateMessages.Count);
}
[TestMethod]
public void InsertBeforeOfRemovedNodeStillWorks ()
{
var p = new Div ();
var c0 = new Span ();
var c1 = new Span ();
var c2 = new Span ();
p.InsertBefore (c2, null);
p.InsertBefore (c1, c2);
p.InsertBefore (c0, c1);
p.RemoveChild (c1);
var ms = p.StateMessages;
Assert.AreEqual (3, ms.Count);
var c0s = (Array)ms[2].Value;
Assert.AreEqual (2, c0s.Length);
Assert.AreEqual (c0, c0s.GetValue (0));
Assert.AreEqual (c2, c0s.GetValue (1));
}
}
}