mirror of
https://github.com/kikito/beholder.lua.git
synced 2024-12-16 00:34:21 +00:00
created the Node pseudo-class
This commit is contained in:
parent
c5e741e884
commit
1aa51a9ac5
84
beholder.lua
84
beholder.lua
@ -16,59 +16,80 @@ local function copy(t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- private node-exclusive functions
|
-- private node-exclusive functions
|
||||||
local function findOrCreateChildNode(node, key)
|
|
||||||
node.children[key] = node.children[key] or { callbacks = {}, children = {} }
|
local Node = {
|
||||||
return node.children[key]
|
_nodesById = setmetatable({}, {__mode="k"})
|
||||||
|
}
|
||||||
|
|
||||||
|
function Node:new()
|
||||||
|
return setmetatable( { callbacks = {}, children = {} }, { __index = Node } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function findOrCreateDescendantNode(node, keys)
|
function Node:findById(id)
|
||||||
|
return self._nodesById[id]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Node:findOrCreateChild(key)
|
||||||
|
self.children[key] = self.children[key] or Node:new()
|
||||||
|
return self.children[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Node:findOrCreateDescendant(keys)
|
||||||
|
local node = self
|
||||||
for i=1, #keys do
|
for i=1, #keys do
|
||||||
node = findOrCreateChildNode(node, keys[i])
|
node = node:findOrCreateChild(keys[i])
|
||||||
end
|
end
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
local function executeNodeCallbacks(node, params)
|
function Node:executeCallbacks(params)
|
||||||
local counter = 0
|
local counter = 0
|
||||||
for _,callback in pairs(node.callbacks) do
|
for _,callback in pairs(self.callbacks) do
|
||||||
callback(unpack(params))
|
callback(unpack(params))
|
||||||
counter = counter + 1
|
counter = counter + 1
|
||||||
end
|
end
|
||||||
return counter
|
return counter
|
||||||
end
|
end
|
||||||
|
|
||||||
local function executeAllCallbacks(node, params)
|
function Node:executeAllCallbacks(params)
|
||||||
local counter = executeNodeCallbacks(node, params)
|
local counter = self:executeCallbacks(params)
|
||||||
for _,child in pairs(node.children) do
|
for _,child in pairs(self.children) do
|
||||||
counter = counter + executeAllCallbacks(child, params)
|
counter = counter + child:executeAllCallbacks(params)
|
||||||
end
|
end
|
||||||
return counter
|
return counter
|
||||||
end
|
end
|
||||||
|
|
||||||
local function executeEventCallbacks(node, event)
|
function Node:executeEventCallbacks(event)
|
||||||
local params = copy(event)
|
local params = copy(event)
|
||||||
local counter = executeNodeCallbacks(node, params)
|
local counter = self:executeCallbacks(params)
|
||||||
|
local node = self
|
||||||
|
|
||||||
for i=1, #event do
|
for i=1, #event do
|
||||||
node = node.children[event[i]]
|
node = node.children[event[i]]
|
||||||
if not node then break end
|
if not node then break end
|
||||||
table.remove(params, 1)
|
table.remove(params, 1)
|
||||||
counter = counter + executeNodeCallbacks(node, params)
|
counter = counter + node:executeCallbacks(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
return counter
|
return counter
|
||||||
end
|
end
|
||||||
|
|
||||||
local function removeCallbackFromNode(node, id)
|
function Node:removeCallback(id)
|
||||||
if not node then return false end
|
self.callbacks[id] = nil
|
||||||
node.callbacks[id] = nil
|
Node._nodesById[id] = nil
|
||||||
return true
|
end
|
||||||
|
|
||||||
|
function Node:addCallback(callback)
|
||||||
|
local id = {}
|
||||||
|
self.callbacks[id] = callback
|
||||||
|
Node._nodesById[id] = self
|
||||||
|
return id
|
||||||
end
|
end
|
||||||
|
|
||||||
-- beholder private functions
|
-- beholder private functions
|
||||||
|
|
||||||
local function checkSelf(self, methodName)
|
local function checkSelf(self, methodName)
|
||||||
assert(type(self)=="table" and self._root and self._nodesById, "Use beholder:" .. methodName .. " instead of beholder." .. methodName)
|
assert(type(self)=="table" and self._root, "Use beholder:" .. methodName .. " instead of beholder." .. methodName)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function extractEventAndCallbackFromParams(params)
|
local function extractEventAndCallbackFromParams(params)
|
||||||
@ -78,19 +99,7 @@ local function extractEventAndCallbackFromParams(params)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function initialize(self)
|
local function initialize(self)
|
||||||
self._root = { callbacks={}, children={} }
|
self._root = Node:new()
|
||||||
self._nodesById = setmetatable({}, {__mode="k"})
|
|
||||||
end
|
|
||||||
|
|
||||||
local function findNodeById(self, id)
|
|
||||||
return self._nodesById[id]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addCallbackToNode(self, node, callback)
|
|
||||||
local id = {}
|
|
||||||
node.callbacks[id] = callback
|
|
||||||
self._nodesById[id] = node
|
|
||||||
return id
|
|
||||||
end
|
end
|
||||||
|
|
||||||
------ Public interface
|
------ Public interface
|
||||||
@ -100,22 +109,25 @@ local beholder = {}
|
|||||||
function beholder:observe(...)
|
function beholder:observe(...)
|
||||||
checkSelf(self, 'observe')
|
checkSelf(self, 'observe')
|
||||||
local event, callback = extractEventAndCallbackFromParams({...})
|
local event, callback = extractEventAndCallbackFromParams({...})
|
||||||
return addCallbackToNode(self, findOrCreateDescendantNode(self._root, event), callback)
|
return self._root:findOrCreateDescendant(event):addCallback(callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:stopObserving(id)
|
function beholder:stopObserving(id)
|
||||||
checkSelf(self, 'stopObserving')
|
checkSelf(self, 'stopObserving')
|
||||||
return removeCallbackFromNode(findNodeById(self, id), id)
|
local node = Node:findById(id)
|
||||||
|
if not node then return false end
|
||||||
|
node:removeCallback(id)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:trigger(...)
|
function beholder:trigger(...)
|
||||||
checkSelf(self, 'trigger')
|
checkSelf(self, 'trigger')
|
||||||
return falseIfZero( executeEventCallbacks(self._root, {...}) )
|
return falseIfZero( self._root:executeEventCallbacks({...}) )
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:triggerAll(...)
|
function beholder:triggerAll(...)
|
||||||
checkSelf(self, 'triggerAll')
|
checkSelf(self, 'triggerAll')
|
||||||
return falseIfZero( executeAllCallbacks(self._root, {...}) )
|
return falseIfZero( self._root:executeAllCallbacks({...}) )
|
||||||
end
|
end
|
||||||
|
|
||||||
function beholder:reset()
|
function beholder:reset()
|
||||||
|
Loading…
Reference in New Issue
Block a user