1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
--------------------------------------------------------------
-- Mimic the luakit signal api functions for tables --
-- @author Fabian Streitel <karottenreibe@gmail.com> --
-- @author Mason Larobina <mason.larobina@gmail.com> --
-- @copyright 2010 Fabian Streitel, Mason Larobina --
--------------------------------------------------------------
-- Grab environment we need
local assert = assert
local io = io
local ipairs = ipairs
local setmetatable = setmetatable
local string = string
local table = table
local tostring = tostring
local type = type
local unpack = unpack
local verbose = luakit.verbose
--- Provides a signal API similar to GTK's signals.
module("lousy.signal")
-- Private signal data for objects
local data = setmetatable({}, { __mode = "k" })
local methods = {
"add_signal",
"emit_signal",
"remove_signal",
"remove_signals",
}
local function get_data(object)
local d = data[object]
assert(d, "object isn't setup for signals")
return d
end
function add_signal(object, signame, func)
local signals = get_data(object).signals
-- Check signal name
assert(type(signame) == "string", "invalid signame type: " .. type(signame))
assert(string.match(signame, "^[%w_%-:]+$"), "invalid chars in signame: " .. signame)
-- Check handler function
assert(type(func) == "function", "invalid handler function")
-- Add to signals table
if not signals[signame] then
signals[signame] = { func, }
else
table.insert(signals[signame], func)
end
end
function emit_signal(object, signame, ...)
local d = get_data(object)
local sigfuncs = d.signals[signame] or {}
if verbose then
io.stderr:write(string.format("D: lousy.signal: emit_signal: "
.. "%q on %s\n", signame, tostring(object)))
end
for _, sigfunc in ipairs(sigfuncs) do
local ret
if d.module then
ret = { sigfunc(...) }
else
ret = { sigfunc(object, ...) }
end
if ret[1] ~= nil then
return unpack(ret)
end
end
end
-- Remove a signame & function pair.
function remove_signal(object, signame, func)
local signals = get_data(object).signals
local sigfuncs = signals[signame] or {}
for i, sigfunc in ipairs(sigfuncs) do
if sigfunc == func then
table.remove(sigfuncs, i)
-- Remove empty sigfuncs table
if #sigfuncs == 0 then
signals[signame] = nil
end
return func
end
end
end
-- Remove all signal handlers with the given signame.
function remove_signals(object, signame)
local signals = get_data(object).signals
signals[signame] = nil
end
function setup(object, module)
assert(not data[object], "given object already setup for signals")
data[object] = { signals = {}, module = module }
for _, fn in ipairs(methods) do
assert(not object[fn], "signal object method conflict: " .. fn)
if module then
local func = _M[fn]
object[fn] = function (...) return func(object, ...) end
else
object[fn] = _M[fn]
end
end
return object
end
-- vim: et:sw=4:ts=8:sts=4:tw=80
|