@Ignatz, this is @Jmv38 event manager with some minor mods.
-- @tnlogy >> @JMV38 modifications >>@Briarfox minor Mods
-- ############## START of EVENT MANAGER ##################
-- example of usage:
-- evMngr = EventMngr() -- create the event manager
-- className = EventMngr.class() -- Binds functionality to a class
-- evMngr:bind() -- Alias for :on
-- evMngr:unbind() -- Alias for :off
-- evMngr:on("all",func) -- "all" is a special event that captures all events and passes the event
-- name as the first param
-- evMngr:on("touch",func) -- register func() to fire on "touch" event
-- evMngr:on("touch", obj.func, obj) -- register obj:func() to fire on "touch" event
-- evMngr:trigger("touch",10,50) -- fires func(10,50) and obj:func(10,50)
-- evMngr:off("touch", func) -- unregister func()
-- evMngr:off("touch", obj.func, obj) -- unregister obj:func()
-- evMngr:off("touch") -- unregister all "touch" listeners
-- evMngr:off(obj.func) -- unregister all listeners with obj.func
-- evMngr:off(obj) -- unregister events with obj listening
-- evMngr:reset() -- unregister everything
EventMngr = class()
function EventMngr:init() end
function EventMngr:on(names, fn, obj)
for name in string.gmatch(names, "%S+") do
if not self.events then self.events = {} end
if not self.events[name] then self.events[name] = {} end
local new = true -- confirm it is a new request
for i,fa in ipairs(self.events[name]) do
if fa.func == fn and fa.obj == obj then new = false end
end
if new then table.insert(self.events[name], {func = fn, obj = obj }) end
end
return self
end
function EventMngr:reset()
self.events = {}
end
function EventMngr:off(nameOrFnOrObj, fn, obj)
local name
local fn,obj = fn,obj -- manage the case when they are nil
local firstType = type(nameOrFnOrObj)
local request
if firstType == "string" then
name = nameOrFnOrObj
if fn == nil then request = "remove all instances of this event"
else request = "remove this event" end
elseif firstType == "function" then
fn = nameOrFnOrObj
request = "remove all events with this function"
else
obj = nameOrFnOrObj
request = "remove all events with this object"
end
if request == "remove all instances of this event" then
self.events[name] = nil
else
local evs = self.events -- go through all events ...
if name then evs = {evs[name]} end -- ... or through 1 event only
for k,fns in pairs(evs) do
local n = #fns
for i=0,n-1 do
local j = n-i -- go backward because of remove, ipairs not suitable
local f = fns[j]
local match
if request == "remove this event"
then match=(f.func==fn and f.obj==obj)
elseif request == "remove all events with this function"
then match=(f.func==fn)
elseif request == "remove all events with this object"
then match=(f.obj==obj)
end
if match then table.remove(fns,j) end
end
end
end
return self
end
function EventMngr:trigger(name, ...)
self.lastTrigger = name
local evs = (self.events and self.events[name]) or {}
for i,fa in ipairs(evs) do
local func,obj = fa.func, fa.obj
if obj then func(obj,...)
else func(...) end
end
--trigger all
local evs = (self.events and self.events["all"]) or {}
for i,fa in ipairs(evs) do
local func,obj = fa.func, fa.obj
if obj then func(obj,name,...)
else func(name,...) end
end
end
EventMngr.bind = EventMngr.on
EventMngr.unbind = EventMngr.off
function EventMngr.class()
local target = class()
for k, v in pairs(EventMngr) do
target[k] = v
end
return target
end
-- ############## END of EVENT MANAGER ##################
local function allCB(name ,x,y)
print(name.." event was called")
end
local function func(x,y)
print("touch at",x,y)
end
local Obj1 = EventMngr.class()
function Obj1:init()
self:on("touch",function() print("Bound to class") end)
end
-- fake class for the tests
local Obj = class()
function Obj:init(name)
self.name = name
-- evMngr:on("all",self.all,self)
end
function Obj:echo(x,y)
print(self.name .. " touch at ".. tostring(x) .. " , " .. tostring(y) )
end
function Obj:all(name)
print("Event called "..name)
end
function setup()
evMngr = EventMngr()
evMngr:bind("all",allCB)
-- test on a standalone function
print("Testing class binding")
ob1 = Obj1()
ob1:trigger("touch")
print("-------------------")
print("one touch should be triggered:")
evMngr:bind("touch",func)
evMngr:trigger("touch",10,50)
print("-------------------")
print("here nothing should happen:") print("")
evMngr:unbind("touch")
evMngr:trigger("touch",10,50)
-- test on a class member
obj1 = Obj("object 1")
obj2 = Obj("object 2")
print("-------------------")
print("2 objects should echo a touch event:")
evMngr:on("touch", obj1.echo, obj1)
evMngr:on("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
evMngr:trigger("touch1",11,51)
print("touch object 2 is off:")
evMngr:off("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
print("-------------------")
print("re-arm the 2 events:")
evMngr:on("touch", obj1.echo, obj1)
evMngr:on("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
print("echo removed :nothing should happen:") print("")
evMngr:off(obj1.echo)
evMngr:trigger("touch",10,50)
print("-------------------")
print("re-arm the 2 events:")
evMngr:on("touch", obj1.echo, obj1)
evMngr:on("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
print("object 1 removed :")
evMngr:off(obj1)
evMngr:trigger("touch",10,50)
print("-------------------")
print("re-arm the 2 events:")
evMngr:on("touch", obj1.echo, obj1)
evMngr:on("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
print("trigger removed :nothing should happen:") print("")
evMngr:off("touch")
evMngr:trigger("touch",10,50)
print("-------------------")
print("re-arm the 2 events:")
evMngr:on("touch", obj1.echo, obj1)
evMngr:on("touch", obj2.echo, obj2)
evMngr:trigger("touch",10,50)
evMngr:reset()
print("reset :nothing should happen:") print("")
evMngr:trigger("touch",10,50)
end
function draw()
background(20)
end
function touched(t)
evMngr:trigger("touch",t.x,t.y)
end