76 lines
2.7 KiB
Lua
76 lines
2.7 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)
|
|
data:emit_signal("connection",name,#signals[name])
|
|
end
|
|
|
|
function data:disconnect_signal(name,func)
|
|
for k,v in pairs(signals[name] or {}) do
|
|
if v == func then
|
|
signals[name][k] = nil
|
|
data:emit_signal("disconnection",name,#signals[name])
|
|
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 }) |