Fix bubbling events through nodes
This commit is contained in:
parent
d4bae780d3
commit
a780f97578
|
@ -33,16 +33,16 @@ namespace Ooui
|
||||||
}
|
}
|
||||||
return context2d;
|
return context2d;
|
||||||
}
|
}
|
||||||
protected override void SaveStateMessageIfNeeded (Message message)
|
protected override bool SaveStateMessageIfNeeded (Message message)
|
||||||
{
|
{
|
||||||
switch (message.MessageType) {
|
if (message.TargetId == Id) {
|
||||||
case MessageType.Call when message.Key == "getContext" && message.Value is Array a && a.Length == 1 && "2d".Equals (a.GetValue (0)):
|
switch (message.MessageType) {
|
||||||
AddStateMessage (message);
|
case MessageType.Call when message.Key == "getContext" && message.Value is Array a && a.Length == 1 && "2d".Equals (a.GetValue (0)):
|
||||||
break;
|
AddStateMessage (message);
|
||||||
default:
|
break;
|
||||||
base.SaveStateMessageIfNeeded (message);
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return base.SaveStateMessageIfNeeded (message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
const debug = true;
|
const debug = false;
|
||||||
|
|
||||||
const nodes = {};
|
const nodes = {};
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,7 @@ namespace Ooui
|
||||||
{
|
{
|
||||||
if (message == null)
|
if (message == null)
|
||||||
return;
|
return;
|
||||||
if (message.TargetId == Id)
|
SaveStateMessageIfNeeded (message);
|
||||||
SaveStateMessageIfNeeded (message);
|
|
||||||
TriggerEventFromMessage (message);
|
TriggerEventFromMessage (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,8 +148,11 @@ namespace Ooui
|
||||||
lock (stateMessages) updater (stateMessages);
|
lock (stateMessages) updater (stateMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SaveStateMessageIfNeeded (Message message)
|
protected virtual bool SaveStateMessageIfNeeded (Message message)
|
||||||
{
|
{
|
||||||
|
if (message.TargetId != Id)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (message.MessageType) {
|
switch (message.MessageType) {
|
||||||
case MessageType.Create:
|
case MessageType.Create:
|
||||||
AddStateMessage (message);
|
AddStateMessage (message);
|
||||||
|
@ -165,12 +167,15 @@ namespace Ooui
|
||||||
AddStateMessage (message);
|
AddStateMessage (message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool TriggerEventFromMessage (Message message)
|
protected virtual bool TriggerEventFromMessage (Message message)
|
||||||
{
|
{
|
||||||
if (message.TargetId != Id)
|
if (message.TargetId != Id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
List<EventHandler> handlers = null;
|
List<EventHandler> handlers = null;
|
||||||
lock (eventListeners) {
|
lock (eventListeners) {
|
||||||
List<EventHandler> hs;
|
List<EventHandler> hs;
|
||||||
|
@ -178,10 +183,11 @@ namespace Ooui
|
||||||
handlers = new List<EventHandler> (hs);
|
handlers = new List<EventHandler> (hs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (handlers == null) return true;
|
if (handlers != null) {
|
||||||
var args = EventArgs.Empty;
|
var args = EventArgs.Empty;
|
||||||
foreach (var h in handlers) {
|
foreach (var h in handlers) {
|
||||||
h.Invoke (this, args);
|
h.Invoke (this, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ namespace Ooui
|
||||||
public Input ()
|
public Input ()
|
||||||
: base ("input")
|
: base ("input")
|
||||||
{
|
{
|
||||||
|
// Subscribe to the change event so we always get up-to-date values
|
||||||
|
Changed += (s, e) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Input (InputType type)
|
public Input (InputType type)
|
||||||
|
@ -71,6 +73,15 @@ namespace Ooui
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool TriggerEventFromMessage (Message message)
|
||||||
|
{
|
||||||
|
if (message.TargetId == Id && message.MessageType == MessageType.Event && message.Key == "change") {
|
||||||
|
Value = message.Value != null ? Convert.ToString (message.Value) : "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.TriggerEventFromMessage (message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InputType
|
public enum InputType
|
||||||
|
|
|
@ -29,10 +29,11 @@ namespace Ooui
|
||||||
Value = args,
|
Value = args,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Message Event (string targetId, string eventType) => new Message {
|
public static Message Event (string targetId, string eventType, object value = null) => new Message {
|
||||||
MessageType = MessageType.Event,
|
MessageType = MessageType.Event,
|
||||||
TargetId = targetId,
|
TargetId = targetId,
|
||||||
Key = eventType,
|
Key = eventType,
|
||||||
|
Value = value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
83
Ooui/Node.cs
83
Ooui/Node.cs
|
@ -100,49 +100,64 @@ namespace Ooui
|
||||||
Send (message);
|
Send (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SaveStateMessageIfNeeded (Message message)
|
protected override bool SaveStateMessageIfNeeded (Message message)
|
||||||
{
|
{
|
||||||
switch (message.MessageType) {
|
if (message.TargetId == Id) {
|
||||||
case MessageType.Call when message.Key == "insertBefore":
|
switch (message.MessageType) {
|
||||||
AddStateMessage (message);
|
case MessageType.Call when message.Key == "insertBefore":
|
||||||
break;
|
AddStateMessage (message);
|
||||||
case MessageType.Call when message.Key == "removeChild" && message.Value is Array ma && ma.Length == 1:
|
break;
|
||||||
UpdateStateMessages (state => {
|
case MessageType.Call when message.Key == "removeChild" && message.Value is Array ma && ma.Length == 1:
|
||||||
var mchild = ma.GetValue (0);
|
UpdateStateMessages (state => {
|
||||||
Node nextChild = null;
|
var mchild = ma.GetValue (0);
|
||||||
for (var i = 0; i < state.Count; ) {
|
Node nextChild = null;
|
||||||
var x = state[i];
|
for (var i = 0; i < state.Count; ) {
|
||||||
if (x.Key == "insertBefore" && x.Value is Array xa && xa.Length == 2 && ReferenceEquals (xa.GetValue (0), mchild)) {
|
var x = state[i];
|
||||||
// Remove any inserts for this node
|
if (x.Key == "insertBefore" && x.Value is Array xa && xa.Length == 2 && ReferenceEquals (xa.GetValue (0), mchild)) {
|
||||||
nextChild = xa.GetValue (1) as Node;
|
// Remove any inserts for this node
|
||||||
state.RemoveAt (i);
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (x.Key == "insertBefore" && x.Value is Array ya && ya.Length == 2 && ReferenceEquals (ya.GetValue (1), mchild)) {
|
});
|
||||||
// Replace inserts that reference this node
|
break;
|
||||||
state[i] = Message.Call (Id, "insertBefore", ya.GetValue (0), nextChild);
|
default:
|
||||||
i++;
|
base.SaveStateMessageIfNeeded (message);
|
||||||
}
|
break;
|
||||||
else {
|
}
|
||||||
i++;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
});
|
var ch = Children;
|
||||||
break;
|
for (var i = 0; i < ch.Count; i++) {
|
||||||
default:
|
if (ch[i].SaveStateMessageIfNeeded (message))
|
||||||
base.SaveStateMessageIfNeeded (message);
|
return true;
|
||||||
break;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool TriggerEventFromMessage (Message message)
|
protected override bool TriggerEventFromMessage (Message message)
|
||||||
{
|
{
|
||||||
if (base.TriggerEventFromMessage (message))
|
if (message.TargetId == Id) {
|
||||||
return true;
|
if (base.TriggerEventFromMessage (message))
|
||||||
var ch = Children;
|
|
||||||
for (var i = 0; i < ch.Count; i++) {
|
|
||||||
if (ch[i].TriggerEventFromMessage (message))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
var ch = Children;
|
||||||
|
for (var i = 0; i < ch.Count; i++) {
|
||||||
|
if (ch[i].TriggerEventFromMessage (message))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace Ooui
|
||||||
public TextArea ()
|
public TextArea ()
|
||||||
: base ("textarea")
|
: base ("textarea")
|
||||||
{
|
{
|
||||||
|
// Subscribe to the change event so we always get up-to-date values
|
||||||
|
Changed += (s, e) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextArea (string text)
|
public TextArea (string text)
|
||||||
|
@ -42,5 +44,13 @@ namespace Ooui
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool TriggerEventFromMessage (Message message)
|
||||||
|
{
|
||||||
|
if (message.TargetId == Id && message.MessageType == MessageType.Event && message.Key == "change") {
|
||||||
|
Value = message.Value != null ? Convert.ToString (message.Value) : "";
|
||||||
|
}
|
||||||
|
return base.TriggerEventFromMessage (message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Ooui;
|
using Ooui;
|
||||||
|
|
||||||
namespace Samples
|
namespace Samples
|
||||||
{
|
{
|
||||||
public class TodoSample
|
public class TodoSample
|
||||||
{
|
{
|
||||||
Button MakeTodo ()
|
|
||||||
|
Element MakeTodo ()
|
||||||
{
|
{
|
||||||
var button = new Button ("Click me!");
|
var items = new List ();
|
||||||
button.Style.FontSize = 100;
|
var input = new Input ();
|
||||||
var count = 0;
|
var button = new Button ("Add the item");
|
||||||
button.Clicked += (s, e) => {
|
button.Clicked += (s, e) => {
|
||||||
button.Style.FontSize = (int)button.Style.FontSize + 1;
|
items.AppendChild (new ListItem {
|
||||||
count++;
|
Text = input.Value
|
||||||
button.Text = $"Clicked {count} times";
|
});
|
||||||
};
|
};
|
||||||
return button;
|
var app = new Div ();
|
||||||
|
app.AppendChild (input);
|
||||||
|
app.AppendChild (button);
|
||||||
|
app.AppendChild (items);
|
||||||
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish ()
|
public void Publish ()
|
||||||
|
|
|
@ -51,5 +51,15 @@ namespace Tests
|
||||||
p.Receive (Message.Event (b.Id, "click"));
|
p.Receive (Message.Event (b.Id, "click"));
|
||||||
Assert.IsTrue (clicked);
|
Assert.IsTrue (clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ValueBubblesDown ()
|
||||||
|
{
|
||||||
|
var p = new Div ();
|
||||||
|
var b = new Input ();
|
||||||
|
p.AppendChild (b);
|
||||||
|
p.Receive (Message.Event (b.Id, "change", "please work"));
|
||||||
|
Assert.AreEqual ("please work", b.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue