radical/object.lua

74 lines
2.6 KiB
Lua

local setmetatable = setmetatable
local table = table
local rawset = rawset
local rawget = rawget
local pairs = pairs
local function setup_object(args)
local data,args,private_data,signals = {},args or {},private_data or {},{}
local private_data = args.private_data or {}
function data:connect_signal(name,func)
signals[name] = signals[name] or {}
table.insert(signals[name],func)
end
function data:disconnect_signal(name,func)
for k,v in pairs(signals[name] or {}) do
if v == func then
signals[name][k] = nil
end
end
end
function data:emit_signal(name,...)
for k,v in pairs(signals[name] or {}) do
v(data,...)
end
end
function data:add_autosignal_field(name)
args.force_private = args.force_private or {}
table.insert(args.force_private,name)
end
local function return_data(tab, key)
if rawget(tab,"get_"..key) then
return rawget(tab,"get_"..key)(tab)
elseif args.autogen_getmap == true and private_data[key] ~= nil then
return private_data[key]
elseif args.other_get_callback then
local to_return = args.other_get_callback(key)
if to_return then return to_return end
end
return rawget(tab,key)
end
local function auto_signal(key)
if args.autogen_signals == true then
data:emit_signal(key.."::changed")
end
end
local function catch_changes(tab, key,value)
local setter = rawget(tab,"set_"..key)
if setter == false then
--print("This is not a setter",debug.traceback()) --In some case, it may be called "normally", having this print is only good for debug
elseif (data[key] ~= value or (args.always_handle ~= nil and args.always_handle[key] == true)) and setter then
setter(tab,value)
auto_signal(key)
elseif (args.force_private or {})[key] == true or (args.autogen_setmap and (private_data[key] ~= nil)) then
private_data[key] = value
auto_signal(key)
elseif setter == nil then
rawset(data,key,value)
end
if args.auto_signal_changed == true then
data:emit_signal("changed")
end
end
setmetatable(data, { __index = return_data, __newindex = catch_changes, __len = function() return #data + #private_data end, })
return data,private_data
end
return setmetatable({}, { __call = function(_, ...) return setup_object(...) end })