+--[[
+Compound - Container
+]]--
+Compound = class(Node)
+
+function Compound.__init__(self, ...)
+ Node.__init__(self)
+ self.children = {...}
+end
+
+function Compound.parse(self, ...)
+ local cstate, state = 0, 0
+
+ for k, child in ipairs(self.children) do
+ cstate = child:parse(...)
+ state = (not state or cstate < state) and cstate or state
+ end
+
+ return state
+end
+
+
+--[[
+Delegator - Node controller
+]]--
+Delegator = class(Node)
+function Delegator.__init__(self, ...)
+ Node.__init__(self, ...)
+ self.nodes = {}
+ self.template = "cbi/delegator"
+end
+
+function Delegator.state(self, name, node, transitor)
+ transitor = transitor or self.transistor_linear
+ local state = {node=node, name=name, transitor=transitor}
+
+ assert(instanceof(node, Node), "Invalid node")
+ assert(not self.nodes[name], "Duplicate entry")
+
+ self.nodes[name] = state
+ self:append(state)
+
+ return state
+end
+
+function Delegator.get(self, name)
+ return self.nodes[name]
+end
+
+function Delegator.transistor_linear(self, state, cstate)
+ if cstate > 0 then
+ for i, child in ipairs(self.children) do
+ if state == child then
+ return self.children[i+1]
+ end
+ end
+ else
+ return state
+ end
+end
+
+function Delegator.parse(self, ...)
+ local active = self:getactive()
+ assert(active, "Invalid state")
+
+ local cstate = active.node:parse()
+ self.active = active.transistor(self, active.node, cstate)
+
+ if not self.active then
+ return FORM_DONE
+ else
+ self.active:parse(false)
+ return FROM_PROCEED
+ end
+end
+
+function Delegator.render(self, ...)
+ self.active.node:render(...)
+end
+
+function Delegator.getactive(self)
+ return self:get(Map.formvalue(self, "cbi.delegated")
+ or (self.children[1] and self.children[1].name))
+end