Refactors
Fix
This commit is contained in:
@@ -70,7 +70,7 @@ local XMLParser = {
|
|||||||
if #stack > 1 then
|
if #stack > 1 then
|
||||||
error("XMLParser: unclosed " .. stack[#stack].tag)
|
error("XMLParser: unclosed " .. stack[#stack].tag)
|
||||||
end
|
end
|
||||||
return top
|
return top.children
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
local XMLParser = require("xmlParser")
|
local XMLParser = require("xmlParser")
|
||||||
local utils = require("utils")
|
|
||||||
local uuid = utils.uuid
|
|
||||||
|
|
||||||
local function maybeExecuteScript(nodeTree, renderContext)
|
local Layout = {
|
||||||
for _, node in ipairs(nodeTree.children) do
|
fromXML = function(text)
|
||||||
if (node.tag == "script") then
|
local nodes = XMLParser.parseText(text)
|
||||||
return load(node.value, nil, "t", renderContext.env)()
|
local script = nil
|
||||||
|
for index, node in ipairs(nodes) do
|
||||||
|
if (node.tag == "script") then
|
||||||
|
script = node.value
|
||||||
|
table.remove(nodes, index)
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
return {
|
||||||
|
nodes = nodes,
|
||||||
|
script = script
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local function executeScript(script, env)
|
||||||
|
return load(script, nil, "t", env)()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function registerFunctionEvent(self, event, script, renderContext)
|
local function registerFunctionEvent(object, event, script, env)
|
||||||
local eventEnv = renderContext.env
|
event(object, function(...)
|
||||||
event(self, function(...)
|
local success, msg = pcall(load(script, nil, "t", env))
|
||||||
eventEnv.event = {...}
|
|
||||||
local success, msg = pcall(load(script, nil, "t", eventEnv))
|
|
||||||
if not success then
|
if not success then
|
||||||
error("XML Error: "..msg)
|
error("XML Error: "..msg)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function registerFunctionEvents(self, node, events, renderContext)
|
|
||||||
for _, event in pairs(events) do
|
|
||||||
local expression = node.attributes[event]
|
|
||||||
if (expression ~= nil) then
|
|
||||||
registerFunctionEvent(self, self[event], expression .. "()", renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local currentEffect = nil
|
local currentEffect = nil
|
||||||
|
|
||||||
local clearEffectDependencies = function(effect)
|
local clearEffectDependencies = function(effect)
|
||||||
@@ -46,12 +47,6 @@ end
|
|||||||
return {
|
return {
|
||||||
basalt = function(basalt)
|
basalt = function(basalt)
|
||||||
local object = {
|
local object = {
|
||||||
layout = function(path)
|
|
||||||
return {
|
|
||||||
path = path,
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
|
|
||||||
reactive = function(initialValue)
|
reactive = function(initialValue)
|
||||||
local value = initialValue
|
local value = initialValue
|
||||||
local observerEffects = {}
|
local observerEffects = {}
|
||||||
@@ -102,139 +97,88 @@ return {
|
|||||||
setValue(computeFn())
|
setValue(computeFn())
|
||||||
end)
|
end)
|
||||||
return getValue;
|
return getValue;
|
||||||
end
|
end,
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
VisualObject = function(base, basalt)
|
layout = function(path)
|
||||||
|
if (not fs.exists(path)) then
|
||||||
local object = {
|
error("Can't open file " .. path)
|
||||||
setValuesByXMLData = function(self, node, renderContext)
|
|
||||||
renderContext.env[self:getName()] = self
|
|
||||||
for attribute, expression in pairs(node.attributes) do
|
|
||||||
local update = function()
|
|
||||||
local value = load("return " .. expression, nil, "t", renderContext.env)()
|
|
||||||
self:setProperty(attribute, value)
|
|
||||||
end
|
|
||||||
basalt.effect(update)
|
|
||||||
end
|
end
|
||||||
registerFunctionEvents(self, node, {
|
local f = fs.open(path, "r")
|
||||||
"onClick",
|
local text = f.readAll()
|
||||||
"onClickUp",
|
f.close()
|
||||||
"onHover",
|
return Layout.fromXML(text)
|
||||||
"onScroll",
|
|
||||||
"onDrag",
|
|
||||||
"onKey",
|
|
||||||
"onKeyUp",
|
|
||||||
"onRelease",
|
|
||||||
"onChar",
|
|
||||||
"onGetFocus",
|
|
||||||
"onLoseFocus",
|
|
||||||
"onResize",
|
|
||||||
"onReposition",
|
|
||||||
"onEvent",
|
|
||||||
"onLeave"
|
|
||||||
}, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
end,
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
ChangeableObject = function(base, basalt)
|
createObjectsFromXMLNode = function(node, env)
|
||||||
local object = {
|
local objects
|
||||||
setValuesByXMLData = function(self, node, renderContext)
|
local layout = env[node.tag]
|
||||||
base.setValuesByXMLData(self, node, renderContext)
|
if (layout ~= nil) then
|
||||||
registerFunctionEvent(self, node, {
|
local updateFns = {}
|
||||||
"onChange"
|
for prop, expression in pairs(node.attributes) do
|
||||||
}, renderContext)
|
updateFns[prop] = basalt.derived(function()
|
||||||
return self
|
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 object = basalt:createObject(node.tag, 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,
|
end,
|
||||||
|
|
||||||
|
createObjectsFromLayout = function(layout, props)
|
||||||
|
local env = _ENV
|
||||||
|
env.props = props
|
||||||
|
if (layout.script ~= nil) then
|
||||||
|
executeScript(layout.script, env)
|
||||||
|
end
|
||||||
|
local objects = {}
|
||||||
|
for _, node in ipairs(layout.nodes) do
|
||||||
|
local _objects = basalt.createObjectsFromXMLNode(node, env)
|
||||||
|
for _, object in ipairs(_objects) do
|
||||||
|
table.insert(objects, object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return objects
|
||||||
|
end
|
||||||
}
|
}
|
||||||
return object
|
return object
|
||||||
end,
|
end,
|
||||||
|
|
||||||
Container = function(base, basalt)
|
Container = function(base, basalt)
|
||||||
local lastXMLReferences = {}
|
|
||||||
|
|
||||||
local function xmlDefaultValues(node, obj, renderContext)
|
|
||||||
if (obj~=nil) then
|
|
||||||
obj:setValuesByXMLData(node, renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addXMLObjectType(node, addFn, self, renderContext)
|
|
||||||
if (node ~= nil) then
|
|
||||||
if (node.attributes ~= nil) then
|
|
||||||
node = {node}
|
|
||||||
end
|
|
||||||
for _, v in pairs(node) do
|
|
||||||
local obj = addFn(self, v["@id"] or uuid())
|
|
||||||
lastXMLReferences[obj:getName()] = obj
|
|
||||||
xmlDefaultValues(v, obj, renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function insertChildLayout(self, layout, node, renderContext)
|
|
||||||
local updateFns = {}
|
|
||||||
for prop, expression in pairs(node.attributes) do
|
|
||||||
updateFns[prop] = basalt.derived(function()
|
|
||||||
return load("return " .. expression, nil, "t", renderContext.env)()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
local props = {}
|
|
||||||
setmetatable(props, {
|
|
||||||
__index = function(_, k)
|
|
||||||
return updateFns[k]()
|
|
||||||
end
|
|
||||||
})
|
|
||||||
self:loadLayout(layout.path, props)
|
|
||||||
end
|
|
||||||
|
|
||||||
local object = {
|
local object = {
|
||||||
setValuesByXMLData = function(self, node, renderContext)
|
|
||||||
lastXMLReferences = {}
|
|
||||||
base.setValuesByXMLData(self, node, renderContext)
|
|
||||||
|
|
||||||
local _OBJECTS = basalt.getObjects()
|
|
||||||
|
|
||||||
for _, child in pairs(node.children) do
|
|
||||||
local tagName = child.tag
|
|
||||||
if (tagName == "animation") then
|
|
||||||
addXMLObjectType(child, self.addAnimation, self, renderContext)
|
|
||||||
else
|
|
||||||
local layout = renderContext.env[tagName]
|
|
||||||
local objectKey = tagName:gsub("^%l", string.upper)
|
|
||||||
if (layout ~= nil) then
|
|
||||||
insertChildLayout(self, layout, child, renderContext)
|
|
||||||
elseif (_OBJECTS[objectKey] ~= nil) then
|
|
||||||
local addFn = self["add" .. objectKey]
|
|
||||||
addXMLObjectType(child, addFn, self, renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
loadLayout = function(self, path, props)
|
loadLayout = function(self, path, props)
|
||||||
if(fs.exists(path))then
|
local layout = basalt.layout(path)
|
||||||
local renderContext = {}
|
local objects = basalt.createObjectsFromLayout(layout, props)
|
||||||
renderContext.env = _ENV
|
for _, object in ipairs(objects) do
|
||||||
renderContext.env.props = props
|
self:addChild(object)
|
||||||
local f = fs.open(path, "r")
|
|
||||||
local nodeTree = XMLParser.parseText(f.readAll())
|
|
||||||
f.close()
|
|
||||||
lastXMLReferences = {}
|
|
||||||
maybeExecuteScript(nodeTree, renderContext)
|
|
||||||
self:setValuesByXMLData(nodeTree, renderContext)
|
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end,
|
end
|
||||||
|
|
||||||
getXMLElements = function(self)
|
|
||||||
return lastXMLReferences
|
|
||||||
end,
|
|
||||||
}
|
}
|
||||||
return object
|
return object
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user