diff --git a/experiments/example.nim b/experiments/example.nim index fd1e208..d48143d 100644 --- a/experiments/example.nim +++ b/experiments/example.nim @@ -1,57 +1,72 @@ -import vdom, vstyles, components, karax, karaxdsl, jdict, jstrutils, kdom +import vdom, vstyles, karax, karaxdsl, jdict, jstrutils, kdom + +type + Car = ref object of VComponent + counter: int + cntdown: int + timer: TimeOut + list: seq[cstring] + change: bool + onclick: proc (ev: Event; n: VNode) + +const ticksUntilChange = 5 + +proc car*(images: seq[cstring]): Car = + new(result) + result.list = images + result.cntdown = ticksUntilChange + + proc docount() = + dec result.cntdown + if result.cntdown == 0: + result.counter = (result.counter + 1) mod result.list.len + result.cntdown = ticksUntilChange + else: + result.timer = setTimeout(docount, 30) + result.change = true + redraw() + + result.onclick = proc (ev: Event; n: VNode) = + result.change = false + if result.timer != nil: + clearTimeout(result.timer) + result.timer = setTimeout(docount, 30) + +method changed(c: Car): bool = true var images: seq[cstring] = @[cstring"a", "b", "c", "d"] -proc carousel*(key: VKey): VNode {.component.} = - state: - var counter: int = 0 - var cntdown: int = 5 - var timer: Timeout = nil - - proc docount() = - cntdown = cntdown - 1 - if cntdown == 0: - counter = (counter + 1) mod images.len - cntdown = 5 - else: - timer = setTimeout(docount, 30) - redraw() - - proc next(ev: Event; n: VNode) = - if timer != nil: - clearTimeout(timer) - timer = setTimeout(docount, 30) - +proc carousel*(): VNode = + let c = car(images) let col = - case counter + case c.counter of 0: cstring"#4d4d4d" of 1: cstring"#ff00ff" of 2: cstring"#00ffff" of 3: cstring"#ffff00" else: cstring"red" - - result = buildHtml(tdiv(key=key)): - text images[counter] - button(onclick = next): + result = buildHtml(tdiv(nref = c)): + text images[c.counter] + button(onclick = c.onclick): text "Next" tdiv(style = style(StyleAttr.color, col)): text "This changes its color." - if cntdown != 5: - text &cntdown + if c.cntdown != ticksUntilChange: + text &c.cntdown proc createDom(): VNode = result = buildHtml(table): tr: td: - carousel(0) + carousel() td: - carousel(1) + carousel() tr: td: - carousel(2) + carousel() td: - carousel(3) + carousel() setRenderer createDom diff --git a/experiments/refs/demo.nim b/experiments/refs/demo.nim index 6ecc7db..a0db59f 100644 --- a/experiments/refs/demo.nim +++ b/experiments/refs/demo.nim @@ -2,7 +2,7 @@ include karaxprelude import future, sequtils type - CustomRef = ref object of VNodeRef + CustomRef = ref object of VComponent method onAttach(r: CustomRef) = kout(cstring"custom ref attached") @@ -13,10 +13,10 @@ method onDetach(r: CustomRef) = var modelData = @[5, 2, 4] - refA = VNodeRef() - refB = VNodeRef() + refA = VComponent() + refB = VComponent() refC = CustomRef() - refSeq = newSeq[VNodeRef]() + refSeq = newSeq[VComponent]() proc onClick(ev: Event, n: VNode) = modelData.add(0) @@ -25,11 +25,13 @@ proc showRefs() = kout(refA) kout(refB) kout(refC) - kout(refSeq.map(nref => nref.vnode)) + for i in 0 ..< refSeq.len: + kout(refSeq[i].vnode) + #kout(refSeq.map(nref => nref.vnode)) -proc secureRefSlot(i: int): VNodeRef = +proc secureRefSlot(i: int): VComponent = while refSeq.len <= i: - refSeq.add(VNodeRef()) + refSeq.add(VComponent()) result = refSeq[i] proc view(): VNode = @@ -53,4 +55,4 @@ proc view(): VNode = proc renderer(): VNode = view() -setRenderer(renderer, showRefs) +setRenderer(renderer, "ROOT", showRefs) diff --git a/src/karax.nim b/src/karax.nim index 77cebdf..56357ef 100644 --- a/src/karax.nim +++ b/src/karax.nim @@ -150,6 +150,9 @@ proc eq(a, b: VNode; deep: bool): EqResult = if a.id != b.id: return different result = identical if a.key != b.key: return different + if a.nref != nil and changed(a.nref): + kout cstring"yes, change!" + return different if a.kind == VNodeKind.text: if a.text != b.text: return different elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk: @@ -201,6 +204,7 @@ proc updateStyles(newNode, oldNode: VNode; deep: bool) = proc updateDom(newNode, oldNode: VNode) = newNode.dom = oldNode.dom + newNode.nref = oldNode.nref assert newNode.len == oldNode.len for i in 0 ..< newNode.len: updateDom(newNode[i], oldNode[i]) diff --git a/src/vdom.nim b/src/vdom.nim index 9f9c642..e478da1 100644 --- a/src/vdom.nim +++ b/src/vdom.nim @@ -101,8 +101,7 @@ macro buildLookupTables(): untyped = buildLookupTables() type - VNodeRef* = ref object of RootObj - vnode*: VNode + VComponent* = ref object of RootObj EventHandler* = proc (ev: Event; target: VNode) {.closure.} VKey* = int @@ -111,7 +110,7 @@ type kind*: VNodeKind key*: VKey id*, class*, text*: cstring - nref*: VNodeRef + nref*: VComponent kids: seq[VNode] # even index: key, odd index: value; done this way for memory efficiency: attrs: seq[cstring] @@ -122,9 +121,9 @@ type dom*: Node ## the attached real DOM node. Can be 'nil' if the virtual node ## is not part of the virtual DOM anymore. -method onAttach*(v: VNodeRef) {.base.} = discard -method onDetach*(v: VNodeRef) {.base.} = discard -method changed*(v: VNodeRef): bool {.base.} = false +method onAttach*(v: VComponent) {.base.} = discard +method onDetach*(v: VComponent) {.base.} = discard +method changed*(v: VComponent): bool {.base.} = false proc value*(n: VNode): cstring = n.text proc `value=`*(n: VNode; v: cstring) = n.text = v