Reintroduce Node to better model HTML
This commit is contained in:
parent
47628ee184
commit
9aee6bc5ac
|
@ -1,86 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ooui
|
namespace Ooui
|
||||||
{
|
{
|
||||||
public class Element
|
public abstract class Element : Node
|
||||||
{
|
{
|
||||||
public string Id { get; private set; } = GenerateId ();
|
string className = "";
|
||||||
|
public string ClassName {
|
||||||
public HtmlMapping Mapping { get; private set; }
|
get => className;
|
||||||
|
set => SetProperty (ref className, value);
|
||||||
readonly List<Message> messages = new List<Message> ();
|
|
||||||
readonly List<Message> stateMessages = new List<Message> ();
|
|
||||||
|
|
||||||
public Element ()
|
|
||||||
{
|
|
||||||
Mapping = HtmlMapping.Get (GetType ());
|
|
||||||
LogCreate ();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Log (Message message)
|
|
||||||
{
|
|
||||||
messages.Add (message);
|
|
||||||
|
|
||||||
switch (message.MessageType) {
|
|
||||||
case MessageType.Create:
|
|
||||||
stateMessages.Add (message);
|
|
||||||
break;
|
|
||||||
case MessageType.SetProperty:
|
|
||||||
{
|
|
||||||
var old = stateMessages.FirstOrDefault (
|
|
||||||
x => x.MessageType == MessageType.SetProperty &&
|
|
||||||
x.Member == message.Member);
|
|
||||||
if (old != null) {
|
|
||||||
stateMessages.Remove (old);
|
|
||||||
}
|
|
||||||
stateMessages.Add (message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void LogCreate ()
|
|
||||||
{
|
|
||||||
Log (new Message {
|
|
||||||
MessageType = MessageType.Create,
|
|
||||||
TargetId = Id,
|
|
||||||
Value = Mapping.TagName,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void LogSetProperty (string propertyName, object value)
|
|
||||||
{
|
|
||||||
var m = new Message {
|
|
||||||
MessageType = MessageType.SetProperty,
|
|
||||||
TargetId = Id,
|
|
||||||
Member = Mapping.GetMemberPath (propertyName),
|
|
||||||
};
|
|
||||||
m.SetValue (value);
|
|
||||||
Log (m);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool SetProperty<T> (ref T backingStore, T newValue, string propertyName = "")
|
|
||||||
{
|
|
||||||
if (!backingStore.Equals (newValue)) {
|
|
||||||
backingStore = newValue;
|
|
||||||
LogSetProperty (propertyName, newValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string IdChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
||||||
|
|
||||||
static string GenerateId ()
|
|
||||||
{
|
|
||||||
var rand = new Random();
|
|
||||||
var chars = new char[8];
|
|
||||||
for (var i = 0; i < chars.Length; i++) {
|
|
||||||
chars[i] = IdChars[rand.Next(0, IdChars.Length)];
|
|
||||||
}
|
|
||||||
return new string(chars);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,7 @@ namespace Ooui
|
||||||
{
|
{
|
||||||
Nop,
|
Nop,
|
||||||
Create,
|
Create,
|
||||||
SetProperty,
|
Set,
|
||||||
}
|
Call,
|
||||||
|
|
||||||
public enum ValueType
|
|
||||||
{
|
|
||||||
String
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ooui
|
||||||
|
{
|
||||||
|
public abstract class Node
|
||||||
|
{
|
||||||
|
public string Id { get; private set; } = GenerateId ();
|
||||||
|
|
||||||
|
public HtmlMapping Mapping { get; private set; }
|
||||||
|
|
||||||
|
readonly List<Node> children = new List<Node> ();
|
||||||
|
readonly List<Message> messages = new List<Message> ();
|
||||||
|
readonly List<Message> stateMessages = new List<Message> ();
|
||||||
|
|
||||||
|
public Node ()
|
||||||
|
{
|
||||||
|
Mapping = HtmlMapping.Get (GetType ());
|
||||||
|
LogCreate ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node AppendChild (Node newChild)
|
||||||
|
{
|
||||||
|
return InsertBefore (newChild, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node ParentNode { get; private set; }
|
||||||
|
|
||||||
|
public Node InsertBefore (Node newChild, Node referenceChild)
|
||||||
|
{
|
||||||
|
if (referenceChild == null) {
|
||||||
|
children.Add (newChild);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var index = children.IndexOf (referenceChild);
|
||||||
|
if (index < 0) {
|
||||||
|
throw new ArgumentException ("Reference must be a child of this element", nameof(referenceChild));
|
||||||
|
}
|
||||||
|
children.Insert (index, newChild);
|
||||||
|
}
|
||||||
|
newChild.ParentNode = this;
|
||||||
|
LogCall ("insertBefore", newChild, referenceChild);
|
||||||
|
return newChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node RemoveChild (Node child)
|
||||||
|
{
|
||||||
|
if (!children.Remove (child)) {
|
||||||
|
throw new ArgumentException ("Child not contained in this element", nameof(child));
|
||||||
|
}
|
||||||
|
child.ParentNode = null;
|
||||||
|
LogCall ("removeChild", child);
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Member == message.Member);
|
||||||
|
if (old != null) {
|
||||||
|
stateMessages.Remove (old);
|
||||||
|
}
|
||||||
|
stateMessages.Add (message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LogCreate ()
|
||||||
|
{
|
||||||
|
Log (new Message {
|
||||||
|
MessageType = MessageType.Create,
|
||||||
|
TargetId = Id,
|
||||||
|
Value = Mapping.TagName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LogCall (string methodName, params object[] args)
|
||||||
|
{
|
||||||
|
Log (new Message {
|
||||||
|
MessageType = MessageType.Call,
|
||||||
|
TargetId = Id,
|
||||||
|
Member = methodName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LogSet (string propertyName, object value)
|
||||||
|
{
|
||||||
|
var m = new Message {
|
||||||
|
MessageType = MessageType.Set,
|
||||||
|
TargetId = Id,
|
||||||
|
Member = Mapping.GetMemberPath (propertyName),
|
||||||
|
};
|
||||||
|
m.SetValue (value);
|
||||||
|
Log (m);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool SetProperty<T> (ref T backingStore, T newValue, string propertyName = "")
|
||||||
|
{
|
||||||
|
if (!backingStore.Equals (newValue)) {
|
||||||
|
backingStore = newValue;
|
||||||
|
LogSet (propertyName, newValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string IdChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
|
||||||
|
static string GenerateId ()
|
||||||
|
{
|
||||||
|
var rand = new Random();
|
||||||
|
var chars = new char[8];
|
||||||
|
for (var i = 0; i < chars.Length; i++) {
|
||||||
|
chars[i] = IdChars[rand.Next(0, IdChars.Length)];
|
||||||
|
}
|
||||||
|
return new string(chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue