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 IEnumerable<Message> StateMessages {
public IReadOnlyList<Message> StateMessages {
get {
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)
{
if (id == Id) return this;
@ -134,37 +136,30 @@ namespace Ooui
TriggerEventFromMessage (message);
}
protected void SaveStateMessage (Message message)
protected void AddStateMessage (Message message)
{
lock (stateMessages) stateMessages.Add (message);
}
void LockedReplaceStateMessage (Message old, Message message)
protected void UpdateStateMessages (Action<List<Message>> updater)
{
if (old != null) {
stateMessages.Remove (old);
}
stateMessages.Add (message);
lock (stateMessages) updater (stateMessages);
}
protected virtual void SaveStateMessageIfNeeded (Message message)
{
switch (message.MessageType) {
case MessageType.Create:
SaveStateMessage (message);
AddStateMessage (message);
break;
case MessageType.Set:
{
lock (stateMessages) {
var old = stateMessages.FirstOrDefault (
x => x.MessageType == MessageType.Set &&
x.Key == message.Key);
LockedReplaceStateMessage (old, message);
}
}
UpdateStateMessages (state => {
state.RemoveAll (x => x.MessageType == MessageType.Set && x.Key == message.Key);
state.Add (message);
});
break;
case MessageType.Listen:
SaveStateMessage (message);
AddStateMessage (message);
break;
}
}

View File

@ -103,10 +103,30 @@ namespace Ooui
protected override void SaveStateMessageIfNeeded (Message message)
{
switch (message.MessageType) {
case MessageType.Call when
message.Key == "insertBefore" ||
message.Key == "removeChild":
SaveStateMessage (message);
case MessageType.Call when message.Key == "insertBefore":
AddStateMessage (message);
break;
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;
default:
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));
}
}
}