stuff
This commit is contained in:
parent
06f5283709
commit
8a639f3121
2 changed files with 51 additions and 47 deletions
|
|
@ -127,33 +127,35 @@ type
|
||||||
EqResult = enum
|
EqResult = enum
|
||||||
different, similar, identical
|
different, similar, identical
|
||||||
|
|
||||||
proc equalsShallow(a, b: VNode): EqResult =
|
proc eq(a, b: VNode; shallow: bool): EqResult =
|
||||||
if a.kind != b.kind: return different
|
if a.kind != b.kind: return different
|
||||||
if a.id != b.id: return different
|
if a.id != b.id: return different
|
||||||
if a.key != b.key: return different
|
result = identical
|
||||||
|
if a.key != b.key:
|
||||||
|
kout cstring"different keys", a.key, b.key
|
||||||
|
if b.key == 0:
|
||||||
|
kout cstring"key for ", cstring($b.kind)
|
||||||
|
return different
|
||||||
if a.kind == VNodeKind.text:
|
if a.kind == VNodeKind.text:
|
||||||
if a.text != b.text: return different
|
if a.text != b.text: return different
|
||||||
elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk:
|
elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk:
|
||||||
if a.text != b.text: return different
|
if a.text != b.text: return different
|
||||||
if a.len != b.len: return different
|
if a.len != b.len: return different
|
||||||
for i in 0..<a.len:
|
for i in 0..<a.len:
|
||||||
if equalsShallow(a[i], b[i]) == different: return different
|
if eq(a[i], b[i], shallow) == different: return different
|
||||||
|
elif not shallow:
|
||||||
|
if a.len != b.len: return different
|
||||||
|
for i in 0..<a.len:
|
||||||
|
let res = eq(a[i], b[i], shallow)
|
||||||
|
if res == different: return different
|
||||||
|
elif res == similar:
|
||||||
|
# but continue, maybe something makes it 'different'!
|
||||||
|
result = similar
|
||||||
if not sameAttrs(a, b): return different
|
if not sameAttrs(a, b): return different
|
||||||
if a.class != b.class: return different
|
if a.class != b.class: return different
|
||||||
if a.style != b.style: return similar
|
if a.style != b.style: return similar
|
||||||
# Do not test event listeners here!
|
# Do not test event listeners here!
|
||||||
return identical
|
return result
|
||||||
|
|
||||||
proc equalsTree(a, b: VNode): bool =
|
|
||||||
when false:
|
|
||||||
# hashing is too fragile now with component support:
|
|
||||||
if not a.validHash:
|
|
||||||
a.calcHash()
|
|
||||||
if not b.validHash:
|
|
||||||
b.calcHash()
|
|
||||||
return a.hash == b.hash
|
|
||||||
else:
|
|
||||||
result = eq(a, b)
|
|
||||||
|
|
||||||
proc updateDirtyElements(parent, current: Node, newNode: VNode) =
|
proc updateDirtyElements(parent, current: Node, newNode: VNode) =
|
||||||
if newNode.key >= 0 and isDirty(newNode.key):
|
if newNode.key >= 0 and isDirty(newNode.key):
|
||||||
|
|
@ -170,8 +172,21 @@ proc updateDirtyElements(parent, current: Node, newNode: VNode) =
|
||||||
# leave early if we know there cannot be anything left to do:
|
# leave early if we know there cannot be anything left to do:
|
||||||
#if dirtyCount <= 0: return
|
#if dirtyCount <= 0: return
|
||||||
|
|
||||||
|
proc updateStyles(newNode, oldNode: VNode; shallow: bool) =
|
||||||
|
# we keep the oldNode, but take over the style from the new node:
|
||||||
|
if oldNode.dom != nil:
|
||||||
|
kout cstring"updateStyle deep updated dom"
|
||||||
|
if newNode.style != nil: applyStyle(oldNode.dom, newNode.style)
|
||||||
|
else: oldNode.dom.style = Style()
|
||||||
|
oldNode.style = newNode.style
|
||||||
|
if not shallow:
|
||||||
|
assert newNode.len == oldNode.len
|
||||||
|
for i in 0 ..< newNode.len:
|
||||||
|
updateStyles(newNode[i], oldNode[i], shallow)
|
||||||
|
|
||||||
proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
let res = equalsShallow(newNode, oldNode)
|
let res = eq(newNode, oldNode, shallow=true)
|
||||||
|
kout cstring($res), cstring"shallow"
|
||||||
if res == different:
|
if res == different:
|
||||||
detach(oldNode)
|
detach(oldNode)
|
||||||
let n = vnodeToDom(newNode)
|
let n = vnodeToDom(newNode)
|
||||||
|
|
@ -180,12 +195,7 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
else:
|
else:
|
||||||
parent.replaceChild(n, current)
|
parent.replaceChild(n, current)
|
||||||
else:
|
else:
|
||||||
if res == similar:
|
if res == similar: updateStyles(newNode, oldNode, true)
|
||||||
# we keep the oldNode, but take over the style from the new node:
|
|
||||||
if oldNode.dom != nil:
|
|
||||||
if newNode.style != nil: applyStyle(oldNode.dom, newNode.style)
|
|
||||||
else: oldNode.dom.style = Style()
|
|
||||||
oldNode.style = newNode.style
|
|
||||||
|
|
||||||
if newNode.kind != VNodeKind.text:
|
if newNode.kind != VNodeKind.text:
|
||||||
let newLength = newNode.len
|
let newLength = newNode.len
|
||||||
|
|
@ -204,16 +214,27 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode) =
|
||||||
current.removeChild(current.lastChild)
|
current.removeChild(current.lastChild)
|
||||||
else:
|
else:
|
||||||
var commonPrefix = 0
|
var commonPrefix = 0
|
||||||
while commonPrefix < minLength and
|
|
||||||
equalsTree(newNode[commonPrefix], oldNode[commonPrefix]):
|
template eqAndUpdate(a, b: VNode; action: untyped) =
|
||||||
inc commonPrefix
|
let r = eq(a, b, false)
|
||||||
|
kout cstring($r), cstring"eqAndUpdate"
|
||||||
|
case r
|
||||||
|
of identical: action
|
||||||
|
of different: break
|
||||||
|
of similar:
|
||||||
|
updateStyles(a, b, false)
|
||||||
|
action
|
||||||
|
|
||||||
|
while commonPrefix < minLength:
|
||||||
|
eqAndUpdate(newNode[commonPrefix], oldNode[commonPrefix]):
|
||||||
|
inc commonPrefix
|
||||||
|
|
||||||
var oldPos = oldLength - 1
|
var oldPos = oldLength - 1
|
||||||
var newPos = newLength - 1
|
var newPos = newLength - 1
|
||||||
while oldPos >= commonPrefix and newPos >= commonPrefix and
|
while oldPos >= commonPrefix and newPos >= commonPrefix:
|
||||||
equalsTree(newNode[newPos], oldNode[oldPos]):
|
eqAndUpdate(newNode[newPos], oldNode[oldPos]):
|
||||||
dec oldPos
|
dec oldPos
|
||||||
dec newPos
|
dec newPos
|
||||||
|
|
||||||
var pos = min(oldPos, newPos) + 1
|
var pos = min(oldPos, newPos) + 1
|
||||||
for i in commonPrefix..pos-1:
|
for i in commonPrefix..pos-1:
|
||||||
|
|
@ -241,6 +262,7 @@ proc dodraw() =
|
||||||
if dorender.isNil: return
|
if dorender.isNil: return
|
||||||
let newtree = dorender()
|
let newtree = dorender()
|
||||||
newtree.id = "ROOT"
|
newtree.id = "ROOT"
|
||||||
|
kout cstring"do draw!", cstring getStackTrace()
|
||||||
toFocus = nil
|
toFocus = nil
|
||||||
if currentTree == nil:
|
if currentTree == nil:
|
||||||
currentTree = newtree
|
currentTree = newtree
|
||||||
|
|
|
||||||
18
src/vdom.nim
18
src/vdom.nim
|
|
@ -133,24 +133,6 @@ proc vthunk*(name: cstring; args: varargs[VNode, vn]): VNode =
|
||||||
proc dthunk*(name: cstring; args: varargs[VNode, vn]): VNode =
|
proc dthunk*(name: cstring; args: varargs[VNode, vn]): VNode =
|
||||||
VNode(kind: VNodeKind.dthunk, text: name, key: -1, kids: @args)
|
VNode(kind: VNodeKind.dthunk, text: name, key: -1, kids: @args)
|
||||||
|
|
||||||
proc eq*(a, b: VNode): bool =
|
|
||||||
if a.kind != b.kind: return false
|
|
||||||
if a.id != b.id: return false
|
|
||||||
if a.class != b.class: return false
|
|
||||||
if a.key != b.key: return false
|
|
||||||
if a.kind != VNodeKind.text:
|
|
||||||
if a.kids.len != b.kids.len: return false
|
|
||||||
for i in 0..<a.kids.len:
|
|
||||||
if not eq(a.kids[i], b.kids[i]): return false
|
|
||||||
if a.text != b.text: return false
|
|
||||||
if a.attrs.len != b.attrs.len: return false
|
|
||||||
for i in 0..<a.attrs.len:
|
|
||||||
if a.attrs[i] != b.attrs[i]: return false
|
|
||||||
# Do not compare styles here. The idea is that nodes only
|
|
||||||
# differing in styling can be made equal easily enough:
|
|
||||||
#if a.style != b.style: return false
|
|
||||||
result = true
|
|
||||||
|
|
||||||
proc setAttr*(n: VNode; key: cstring; val: cstring = "") =
|
proc setAttr*(n: VNode; key: cstring; val: cstring = "") =
|
||||||
if n.attrs.isNil:
|
if n.attrs.isNil:
|
||||||
n.attrs = @[key, val]
|
n.attrs = @[key, val]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue