mirror of https://github.com/buggins/dlangui.git
DOM initial implementation
This commit is contained in:
parent
2f4799e140
commit
d090f8ad49
|
@ -246,6 +246,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="src\dlangui\core\collections.d" />
|
<Compile Include="src\dlangui\core\collections.d" />
|
||||||
|
<Compile Include="src\dlangui\core\dom.d" />
|
||||||
<Compile Include="src\dlangui\core\editable.d" />
|
<Compile Include="src\dlangui\core\editable.d" />
|
||||||
<Compile Include="src\dlangui\core\events.d" />
|
<Compile Include="src\dlangui\core\events.d" />
|
||||||
<Compile Include="src\dlangui\core\files.d" />
|
<Compile Include="src\dlangui\core\files.d" />
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="src\dlangui\core\collections.d" />
|
<Compile Include="src\dlangui\core\collections.d" />
|
||||||
<Compile Include="src\dlangui\core\config.d" />
|
<Compile Include="src\dlangui\core\config.d" />
|
||||||
|
<Compile Include="src\dlangui\core\dom.d" />
|
||||||
<Compile Include="src\dlangui\core\editable.d" />
|
<Compile Include="src\dlangui\core\editable.d" />
|
||||||
<Compile Include="src\dlangui\core\events.d" />
|
<Compile Include="src\dlangui\core\events.d" />
|
||||||
<Compile Include="src\dlangui\core\files.d" />
|
<Compile Include="src\dlangui\core\files.d" />
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="src\dlangui\package.d" />
|
<Compile Include="src\dlangui\package.d" />
|
||||||
<Compile Include="src\dlangui\core\collections.d" />
|
<Compile Include="src\dlangui\core\collections.d" />
|
||||||
|
<Compile Include="src\dlangui\core\dom.d" />
|
||||||
<Compile Include="src\dlangui\core\editable.d" />
|
<Compile Include="src\dlangui\core\editable.d" />
|
||||||
<Compile Include="src\dlangui\core\events.d" />
|
<Compile Include="src\dlangui\core\events.d" />
|
||||||
<Compile Include="src\dlangui\core\files.d" />
|
<Compile Include="src\dlangui\core\files.d" />
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<useArrayBounds>0</useArrayBounds>
|
<useArrayBounds>0</useArrayBounds>
|
||||||
<noboundscheck>0</noboundscheck>
|
<noboundscheck>0</noboundscheck>
|
||||||
<useSwitchError>0</useSwitchError>
|
<useSwitchError>0</useSwitchError>
|
||||||
<useUnitTests>0</useUnitTests>
|
<useUnitTests>1</useUnitTests>
|
||||||
<useInline>0</useInline>
|
<useInline>0</useInline>
|
||||||
<release>0</release>
|
<release>0</release>
|
||||||
<preservePaths>0</preservePaths>
|
<preservePaths>0</preservePaths>
|
||||||
|
@ -542,6 +542,7 @@
|
||||||
<Folder name="core">
|
<Folder name="core">
|
||||||
<File path="src\dlangui\core\collections.d" />
|
<File path="src\dlangui\core\collections.d" />
|
||||||
<File path="src\dlangui\core\config.d" />
|
<File path="src\dlangui\core\config.d" />
|
||||||
|
<File path="src\dlangui\core\dom.d" />
|
||||||
<File path="src\dlangui\core\editable.d" />
|
<File path="src\dlangui\core\editable.d" />
|
||||||
<File path="src\dlangui\core\events.d" />
|
<File path="src\dlangui\core\events.d" />
|
||||||
<File path="src\dlangui\core\files.d" />
|
<File path="src\dlangui\core\files.d" />
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
module dlangui.core.dom;
|
||||||
|
|
||||||
|
import dlangui.core.collections;
|
||||||
|
|
||||||
|
import std.traits;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.string;
|
||||||
|
|
||||||
|
/// Base class for DOM nodes
|
||||||
|
class Node {
|
||||||
|
private:
|
||||||
|
Node _parent;
|
||||||
|
Document _document;
|
||||||
|
public:
|
||||||
|
/// returns parent node
|
||||||
|
@property Node parent() { return _parent; }
|
||||||
|
/// returns document node
|
||||||
|
@property Document document() { return _document; }
|
||||||
|
|
||||||
|
// node properties
|
||||||
|
|
||||||
|
/// returns true if node is text
|
||||||
|
@property bool isText() { return false; }
|
||||||
|
/// returns true if node is element
|
||||||
|
@property bool isElement() { return false; }
|
||||||
|
/// returns true if node has child nodes
|
||||||
|
@property bool hasChildren() { return false; }
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
|
||||||
|
/// returns attribute count
|
||||||
|
@property int attrCount() { return 0; }
|
||||||
|
|
||||||
|
// child nodes
|
||||||
|
|
||||||
|
/// returns child node count
|
||||||
|
@property int childCount() { return 0; }
|
||||||
|
/// returns child node by index
|
||||||
|
@property Node child(int index) { return null; }
|
||||||
|
/// returns first child node
|
||||||
|
@property Node firstChild() { return null; }
|
||||||
|
/// returns last child node
|
||||||
|
@property Node lastChild() { return null; }
|
||||||
|
|
||||||
|
/// node text
|
||||||
|
@property dstring text() { return null; }
|
||||||
|
/// ditto
|
||||||
|
@property void text(dstring s) { }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Text node
|
||||||
|
class Text : Node {
|
||||||
|
private:
|
||||||
|
dstring _text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// node text
|
||||||
|
override @property dstring text() { return _text; }
|
||||||
|
/// ditto
|
||||||
|
override @property void text(dstring s) { _text = s; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Element node
|
||||||
|
class Element : Node {
|
||||||
|
private:
|
||||||
|
Collection!Node _children;
|
||||||
|
public:
|
||||||
|
// child nodes
|
||||||
|
|
||||||
|
/// returns child node count
|
||||||
|
override @property int childCount() { return cast(int)_children.length; }
|
||||||
|
/// returns child node by index
|
||||||
|
override @property Node child(int index) { return index >= 0 && index < _children.length ? _children[index] : null; }
|
||||||
|
/// returns first child node
|
||||||
|
override @property Node firstChild() { return _children.length > 0 ? _children[0] : null; }
|
||||||
|
/// returns last child node
|
||||||
|
override @property Node lastChild() { return _children.length > 0 ? _children[_children.length - 1] : null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Document node
|
||||||
|
class Document : Element {
|
||||||
|
public:
|
||||||
|
this() {
|
||||||
|
_elemIds.init!Tag();
|
||||||
|
_attrIds.init!Attr();
|
||||||
|
_nsIds.init!Ns();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
IdentMap!(elem_id) _elemIds;
|
||||||
|
IdentMap!(attr_id) _attrIds;
|
||||||
|
IdentMap!(ns_id) _nsIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// id type for interning namespaces
|
||||||
|
alias ns_id = ushort;
|
||||||
|
/// id type for interning element names
|
||||||
|
alias elem_id = uint;
|
||||||
|
/// id type for interning attribute names
|
||||||
|
alias attr_id = ushort;
|
||||||
|
|
||||||
|
/// remove trailing _ from string, e.g. "body_" -> "body"
|
||||||
|
private string removeTrailingUnderscore(string s) {
|
||||||
|
if (s.endsWith("_"))
|
||||||
|
return s[0..$-1];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// String identifier to Id map - for interning strings
|
||||||
|
struct IdentMap(ident_t) {
|
||||||
|
/// initialize with elements of enum
|
||||||
|
void init(E)() if (is(E == enum)) {
|
||||||
|
foreach(member; EnumMembers!E) {
|
||||||
|
internString(removeTrailingUnderscore(member.to!string), member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// intern string - return ID assigned for it
|
||||||
|
ident_t internString(string s, ident_t id = 0) {
|
||||||
|
if (auto p = s in _stringToId)
|
||||||
|
return *p;
|
||||||
|
ident_t res;
|
||||||
|
if (id > 0) {
|
||||||
|
if (_nextId <= id)
|
||||||
|
_nextId = cast(ident_t)(id + 1);
|
||||||
|
res = id;
|
||||||
|
} else {
|
||||||
|
res = _nextId++;
|
||||||
|
}
|
||||||
|
_idToString[res] = s;
|
||||||
|
_stringToId[s] = res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/// lookup id for string, return 0 if string is not found
|
||||||
|
ident_t opIndex(string s) {
|
||||||
|
if (auto p = s in _stringToId)
|
||||||
|
return *p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/// lookup name for id, return null if not found
|
||||||
|
string opIndex(ident_t id) {
|
||||||
|
if (auto p = id in _idToString)
|
||||||
|
return *p;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
string[ident_t] _idToString;
|
||||||
|
ident_t[string] _stringToId;
|
||||||
|
ident_t _nextId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// standard tags
|
||||||
|
enum Tag {
|
||||||
|
NONE,
|
||||||
|
body_,
|
||||||
|
pre,
|
||||||
|
div,
|
||||||
|
span
|
||||||
|
}
|
||||||
|
|
||||||
|
/// standard attributes
|
||||||
|
enum Attr {
|
||||||
|
NONE,
|
||||||
|
id,
|
||||||
|
class_,
|
||||||
|
style
|
||||||
|
}
|
||||||
|
|
||||||
|
/// standard namespaces
|
||||||
|
enum Ns {
|
||||||
|
NONE,
|
||||||
|
xmlns,
|
||||||
|
xs,
|
||||||
|
xlink,
|
||||||
|
l,
|
||||||
|
xsi
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import std.algorithm : equal;
|
||||||
|
//import std.stdio;
|
||||||
|
IdentMap!(elem_id) map;
|
||||||
|
map.init!Tag();
|
||||||
|
//writeln("running DOM unit test");
|
||||||
|
assert(map["pre"] == Tag.pre);
|
||||||
|
assert(map["body"] == Tag.body_);
|
||||||
|
assert(map[Tag.div].equal("div"));
|
||||||
|
|
||||||
|
Document doc = new Document();
|
||||||
|
destroy(doc);
|
||||||
|
}
|
Loading…
Reference in New Issue