Allow for reactive props from imperative code
This commit is contained in:
@@ -18,11 +18,11 @@ local Layout = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local function executeScript(script, env)
|
local executeScript = function(script, env)
|
||||||
return load(script, nil, "t", env)()
|
return load(script, nil, "t", env)()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function registerFunctionEvent(object, event, script, env)
|
local registerFunctionEvent = function(object, event, script, env)
|
||||||
event(object, function(...)
|
event(object, function(...)
|
||||||
local success, msg = pcall(load(script, nil, "t", env))
|
local success, msg = pcall(load(script, nil, "t", env))
|
||||||
if not success then
|
if not success then
|
||||||
@@ -46,6 +46,38 @@ end
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
basalt = function(basalt)
|
basalt = function(basalt)
|
||||||
|
local createObjectsFromXMLNode = function(node, env)
|
||||||
|
local layout = env[node.tag]
|
||||||
|
if (layout ~= nil) then
|
||||||
|
local props = {}
|
||||||
|
for prop, expression in pairs(node.attributes) do
|
||||||
|
props[prop] = load("return " .. expression, nil, "t", env)
|
||||||
|
end
|
||||||
|
return basalt.createObjectsFromLayout(layout, props)
|
||||||
|
end
|
||||||
|
|
||||||
|
local objectName = node.tag:gsub("^%l", string.upper)
|
||||||
|
local object = basalt:createObject(objectName, node.attributes["id"])
|
||||||
|
for attribute, expression in pairs(node.attributes) do
|
||||||
|
if (attribute:sub(1, 2) == "on") then
|
||||||
|
registerFunctionEvent(object, object[attribute], expression .. "()", env)
|
||||||
|
else
|
||||||
|
local update = function()
|
||||||
|
local value = load("return " .. expression, nil, "t", env)()
|
||||||
|
object:setProperty(attribute, value)
|
||||||
|
end
|
||||||
|
basalt.effect(update)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, child in ipairs(node.children) do
|
||||||
|
local childObjects = basalt.createObjectsFromXMLNode(child, env)
|
||||||
|
for _, childObject in ipairs(childObjects) do
|
||||||
|
object:addChild(childObject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return {object}
|
||||||
|
end
|
||||||
|
|
||||||
local object = {
|
local object = {
|
||||||
reactive = function(initialValue)
|
reactive = function(initialValue)
|
||||||
local value = initialValue
|
local value = initialValue
|
||||||
@@ -109,57 +141,26 @@ return {
|
|||||||
return Layout.fromXML(text)
|
return Layout.fromXML(text)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
createObjectsFromXMLNode = function(node, env)
|
|
||||||
local objects
|
|
||||||
local layout = env[node.tag]
|
|
||||||
if (layout ~= nil) then
|
|
||||||
local updateFns = {}
|
|
||||||
for prop, expression in pairs(node.attributes) do
|
|
||||||
updateFns[prop] = basalt.derived(function()
|
|
||||||
return load("return " .. expression, nil, "t", env)()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
local props = {}
|
|
||||||
setmetatable(props, {
|
|
||||||
__index = function(_, k)
|
|
||||||
return updateFns[k]()
|
|
||||||
end
|
|
||||||
})
|
|
||||||
objects = basalt.createObjectsFromLayout(layout, props)
|
|
||||||
else
|
|
||||||
local objectName = node.tag:gsub("^%l", string.upper)
|
|
||||||
local object = basalt:createObject(objectName, node.attributes["id"])
|
|
||||||
for attribute, expression in pairs(node.attributes) do
|
|
||||||
if (attribute:sub(1, 2) == "on") then
|
|
||||||
registerFunctionEvent(object, object[attribute], expression .. "()", env)
|
|
||||||
else
|
|
||||||
local update = function()
|
|
||||||
local value = load("return " .. expression, nil, "t", env)()
|
|
||||||
object:setProperty(attribute, value)
|
|
||||||
end
|
|
||||||
basalt.effect(update)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _, child in ipairs(node.children) do
|
|
||||||
local childObjects = basalt.createObjectsFromXMLNode(child, env)
|
|
||||||
for _, childObject in ipairs(childObjects) do
|
|
||||||
object:addChild(childObject)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
objects = {object}
|
|
||||||
end
|
|
||||||
return objects
|
|
||||||
end,
|
|
||||||
|
|
||||||
createObjectsFromLayout = function(layout, props)
|
createObjectsFromLayout = function(layout, props)
|
||||||
local env = _ENV
|
local env = _ENV
|
||||||
env.props = props
|
env.props = {}
|
||||||
|
local updateFns = {}
|
||||||
|
for prop, getFn in pairs(props) do
|
||||||
|
updateFns[prop] = basalt.derived(function()
|
||||||
|
return getFn()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
setmetatable(env.props, {
|
||||||
|
__index = function(_, k)
|
||||||
|
return updateFns[k]()
|
||||||
|
end
|
||||||
|
})
|
||||||
if (layout.script ~= nil) then
|
if (layout.script ~= nil) then
|
||||||
executeScript(layout.script, env)
|
executeScript(layout.script, env)
|
||||||
end
|
end
|
||||||
local objects = {}
|
local objects = {}
|
||||||
for _, node in ipairs(layout.nodes) do
|
for _, node in ipairs(layout.nodes) do
|
||||||
local _objects = basalt.createObjectsFromXMLNode(node, env)
|
local _objects = createObjectsFromXMLNode(node, env)
|
||||||
for _, object in ipairs(_objects) do
|
for _, object in ipairs(_objects) do
|
||||||
table.insert(objects, object)
|
table.insert(objects, object)
|
||||||
end
|
end
|
||||||
@@ -173,11 +174,17 @@ return {
|
|||||||
Container = function(base, basalt)
|
Container = function(base, basalt)
|
||||||
local object = {
|
local object = {
|
||||||
loadLayout = function(self, path, props)
|
loadLayout = function(self, path, props)
|
||||||
|
local wrappedProps = {}
|
||||||
if (props == nil) then
|
if (props == nil) then
|
||||||
props = {}
|
props = {}
|
||||||
end
|
end
|
||||||
|
for prop, value in pairs(props) do
|
||||||
|
wrappedProps[prop] = function()
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
local layout = basalt.layout(path)
|
local layout = basalt.layout(path)
|
||||||
local objects = basalt.createObjectsFromLayout(layout, props)
|
local objects = basalt.createObjectsFromLayout(layout, wrappedProps)
|
||||||
for _, object in ipairs(objects) do
|
for _, object in ipairs(objects) do
|
||||||
self:addChild(object)
|
self:addChild(object)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user