object: Add dynamic properties support.
Similar systems already exist un luaobject, wibox and the declarative widget system. This close the gap and also bring the property based syntax to wibox and other gears.object users. While this need to be enabled explicitly for legacy reasons, it doesn't break the API. Once widespread, this implementation will replace the one found in wibox.widget.base_widget.
This commit is contained in:
parent
32eeaa9513
commit
4b21ca9184
|
@ -122,11 +122,58 @@ function object:emit_signal(name, ...)
|
|||
end
|
||||
end
|
||||
|
||||
--- Returns a new object. You can call :emit_signal(), :disconnect_signal,
|
||||
-- :connect_signal() and :add_signal() on the resulting object.
|
||||
local function new()
|
||||
local function get_miss(self, key)
|
||||
local class = rawget(self, "_class")
|
||||
|
||||
if rawget(self, "get_"..key) then
|
||||
return rawget(self, "get_"..key)(self)
|
||||
elseif class and class["get_"..key] then
|
||||
return class["get_"..key](self)
|
||||
elseif class then
|
||||
return class[key]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function set_miss(self, key, value)
|
||||
local class = rawget(self, "_class")
|
||||
|
||||
if rawget(self, "set_"..key) then
|
||||
return rawget(self, "set_"..key)(self, value)
|
||||
elseif class and class["set_"..key] then
|
||||
return class["set_"..key](self, value)
|
||||
elseif rawget(self, "_enable_auto_signals") then
|
||||
local changed = class[key] ~= value
|
||||
class[key] = value
|
||||
|
||||
if changed then
|
||||
self:emit_signal("property::"..key, value)
|
||||
end
|
||||
else
|
||||
return rawset(self, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new object. You can call `:emit_signal()`, `:disconnect_signal()`,
|
||||
-- `:connect_signal()` and `:add_signal()` on the resulting object.
|
||||
--
|
||||
-- Note that `args.enable_auto_signals` is only supported when
|
||||
-- `args.enable_properties` is true.
|
||||
--
|
||||
-- @tparam[opt={}] table args The arguments
|
||||
-- @tparam[opt=false] boolean args.enable_properties Automatically call getters and setters
|
||||
-- @tparam[opt=false] boolean args.enable_auto_signals Generate "property::xxxx" signals
|
||||
-- when an unknown property is set.
|
||||
-- @tparam[opt=nil] table args.class
|
||||
-- @treturn table A new object
|
||||
-- @function gears.object
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
local ret = {}
|
||||
|
||||
-- Automatic signals cannot work without both miss handlers.
|
||||
assert(not (args.enable_auto_signals and args.enable_properties ~= true))
|
||||
|
||||
-- Copy all our global functions to our new object
|
||||
for k, v in pairs(object) do
|
||||
if type(v) == "function" then
|
||||
|
@ -136,7 +183,27 @@ local function new()
|
|||
|
||||
ret._signals = {}
|
||||
|
||||
return ret
|
||||
local mt = {}
|
||||
|
||||
-- Look for methods in another table
|
||||
ret._class = args.class
|
||||
ret._enable_auto_signals = args.enable_auto_signals
|
||||
|
||||
-- To catch all changes, a proxy is required
|
||||
if args.enable_auto_signals then
|
||||
ret._class = ret._class and setmetatable({}, {__index = args.class}) or {}
|
||||
end
|
||||
|
||||
if args.enable_properties then
|
||||
-- Check got existing get_xxxx and set_xxxx
|
||||
mt.__index = get_miss
|
||||
mt.__newindex = set_miss
|
||||
elseif args.class then
|
||||
-- Use the class table a miss handler
|
||||
mt.__index = ret._class
|
||||
end
|
||||
|
||||
return setmetatable(ret, mt)
|
||||
end
|
||||
|
||||
function object.mt.__call(_, ...)
|
||||
|
|
Loading…
Reference in New Issue