Refactor XML parser #82
@@ -273,28 +273,6 @@ removeTags = removeTags,
|
|||||||
|
|
||||||
wrapText = wrapText,
|
wrapText = wrapText,
|
||||||
|
|
||||||
xmlValue = function(name, tab)
|
|
||||||
local var
|
|
||||||
if(type(tab)~="table")then return end
|
|
||||||
if(tab[name]~=nil)then
|
|
||||||
if(type(tab[name])=="table")then
|
|
||||||
if(tab[name].value~=nil)then
|
|
||||||
var = tab[name]:value()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(var==nil)then var = tab["@"..name] end
|
|
||||||
|
|
||||||
if(var=="true")then
|
|
||||||
var = true
|
|
||||||
elseif(var=="false")then
|
|
||||||
var = false
|
|
||||||
elseif(tonumber(var)~=nil)then
|
|
||||||
var = tonumber(var)
|
|
||||||
end
|
|
||||||
return var
|
|
||||||
end,
|
|
||||||
|
|
||||||
convertRichText = convertRichText,
|
convertRichText = convertRichText,
|
||||||
|
|
||||||
--- Writes text with special color tags
|
--- Writes text with special color tags
|
||||||
|
|||||||
77
Basalt/libraries/xmlParser.lua
Normal file
77
Basalt/libraries/xmlParser.lua
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
local XMLNode = {
|
||||||
|
new = function(tag)
|
||||||
|
return {
|
||||||
|
tag = tag,
|
||||||
|
value = nil,
|
||||||
|
attributes = {},
|
||||||
|
children = {},
|
||||||
|
|
||||||
|
addChild = function(self, child)
|
||||||
|
table.insert(self.children, child)
|
||||||
|
end,
|
||||||
|
|
||||||
|
addAttribute = function(self, tag, value)
|
||||||
|
self.attributes[tag] = value
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local parseAttributes = function(node, s)
|
||||||
|
-- Parse "" style string attributes
|
||||||
|
local _, _ = string.gsub(s, "(%w+)=([\"'])(.-)%2", function(attribute, _, value)
|
||||||
|
node:addAttribute(attribute, "\"" .. value .. "\"")
|
||||||
|
end)
|
||||||
|
-- Parse {} style computed attributes
|
||||||
|
local _, _ = string.gsub(s, "(%w+)={(.-)}", function(attribute, expression)
|
||||||
|
node:addAttribute(attribute, expression)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local XMLParser = {
|
||||||
|
parseText = function(xmlText)
|
||||||
|
local stack = {}
|
||||||
|
local top = XMLNode.new()
|
||||||
|
table.insert(stack, top)
|
||||||
|
local ni, c, label, xarg, empty
|
||||||
|
local i, j = 1, 1
|
||||||
|
while true do
|
||||||
|
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
|
||||||
|
if not ni then break end
|
||||||
|
local text = string.sub(xmlText, i, ni - 1);
|
||||||
|
if not string.find(text, "^%s*$") then
|
||||||
|
local lVal = (top.value or "") .. text
|
||||||
|
stack[#stack].value = lVal
|
||||||
|
end
|
||||||
|
if empty == "/" then -- empty element tag
|
||||||
|
local lNode = XMLNode.new(label)
|
||||||
|
parseAttributes(lNode, xarg)
|
||||||
|
top:addChild(lNode)
|
||||||
|
elseif c == "" then -- start tag
|
||||||
|
local lNode = XMLNode.new(label)
|
||||||
|
parseAttributes(lNode, xarg)
|
||||||
|
table.insert(stack, lNode)
|
||||||
|
top = lNode
|
||||||
|
else -- end tag
|
||||||
|
local toclose = table.remove(stack) -- remove top
|
||||||
|
|
||||||
|
top = stack[#stack]
|
||||||
|
if #stack < 1 then
|
||||||
|
error("XMLParser: nothing to close with " .. label)
|
||||||
|
end
|
||||||
|
if toclose.tag ~= label then
|
||||||
|
error("XMLParser: trying to close " .. toclose.tag .. " with " .. label)
|
||||||
|
end
|
||||||
|
top:addChild(toclose)
|
||||||
|
end
|
||||||
|
i = j + 1
|
||||||
|
end
|
||||||
|
local text = string.sub(xmlText, i);
|
||||||
|
if #stack > 1 then
|
||||||
|
error("XMLParser: unclosed " .. stack[#stack].tag)
|
||||||
|
end
|
||||||
|
return top
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
return XMLParser
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
local utils = require("utils")
|
local XMLParser = require("xmlParser")
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base)
|
VisualObject = function(base)
|
||||||
@@ -29,12 +28,6 @@ return {
|
|||||||
return bgSymbolColor
|
return bgSymbolColor
|
||||||
end,
|
end,
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data, scripts)
|
|
||||||
if(xmlValue("background-symbol", data)~=nil)then self:setBackgroundSymbol(xmlValue("background-symbol", data), xmlValue("background-symbol-color", data)) end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
draw = function(self)
|
draw = function(self)
|
||||||
base.draw(self)
|
base.draw(self)
|
||||||
self:addDraw("advanced-bg", function()
|
self:addDraw("advanced-bg", function()
|
||||||
@@ -45,8 +38,8 @@ return {
|
|||||||
self:addForegroundBox(1, 1, w, h, bgSymbolColor)
|
self:addForegroundBox(1, 1, w, h, bgSymbolColor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end, 2)
|
end, 2)
|
||||||
end,
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
return object
|
return object
|
||||||
|
|||||||
@@ -215,8 +215,7 @@ local lerp = {
|
|||||||
easeInOutBounce=easeInOutBounce,
|
easeInOutBounce=easeInOutBounce,
|
||||||
}
|
}
|
||||||
|
|
||||||
local utils = require("utils")
|
local XMLParser = require("xmlParser")
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base, basalt)
|
VisualObject = function(base, basalt)
|
||||||
@@ -337,24 +336,7 @@ return {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data, scripts)
|
|
||||||
local animX, animY, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateX", data), xmlValue("animateY", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
|
|
||||||
local animW, animH, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateW", data), xmlValue("animateH", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
|
|
||||||
local animXOffset, animYOffset, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateXOffset", data), xmlValue("animateYOffset", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
|
|
||||||
if(animX~=nil and animY~=nil)then
|
|
||||||
self:animatePosition(animX, animY, animateDuration, animeteTimeOffset, animateMode)
|
|
||||||
end
|
|
||||||
if(animW~=nil and animH~=nil)then
|
|
||||||
self:animateSize(animW, animH, animateDuration, animeteTimeOffset, animateMode)
|
|
||||||
end
|
|
||||||
if(animXOffset~=nil and animYOffset~=nil)then
|
|
||||||
self:animateOffset(animXOffset, animYOffset, animateDuration, animeteTimeOffset, animateMode)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return object
|
return object
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ local function makeText(nSize, sString, nFC, nBC, bBlit)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- The following code is related to basalt and has nothing to do with bigfonts, it creates a plugin which will be added to labels:
|
-- The following code is related to basalt and has nothing to do with bigfonts, it creates a plugin which will be added to labels:
|
||||||
local utils = require("utils")
|
local XMLParser = require("xmlParser")
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
return {
|
return {
|
||||||
Label = function(base)
|
Label = function(base)
|
||||||
local fontsize = 1
|
local fontsize = 1
|
||||||
@@ -196,12 +195,6 @@ return {
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data, scripts)
|
|
||||||
if(xmlValue("fontSize", data)~=nil)then self:setFontSize(xmlValue("fontSize", data)) end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
draw = function(self)
|
draw = function(self)
|
||||||
base.draw(self)
|
base.draw(self)
|
||||||
self:addDraw("bigfonts", function()
|
self:addDraw("bigfonts", function()
|
||||||
@@ -220,7 +213,7 @@ return {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end,
|
end
|
||||||
}
|
}
|
||||||
return object
|
return object
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
local utils = require("utils")
|
local XMLParser = require("xmlParser")
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base)
|
VisualObject = function(base)
|
||||||
@@ -80,23 +79,6 @@ return {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end,
|
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data)
|
|
||||||
local borders = {}
|
|
||||||
if(xmlValue("border", data)~=nil)then
|
|
||||||
borders["top"] = colors[xmlValue("border", data)]
|
|
||||||
borders["bottom"] = colors[xmlValue("border", data)]
|
|
||||||
borders["left"] = colors[xmlValue("border", data)]
|
|
||||||
borders["right"] = colors[xmlValue("border", data)]
|
|
||||||
end
|
|
||||||
if(xmlValue("borderTop", data)~=nil)then borders["top"] = colors[xmlValue("borderTop", data)] end
|
|
||||||
if(xmlValue("borderBottom", data)~=nil)then borders["bottom"] = colors[xmlValue("borderBottom", data)] end
|
|
||||||
if(xmlValue("borderLeft", data)~=nil)then borders["left"] = colors[xmlValue("borderLeft", data)] end
|
|
||||||
if(xmlValue("borderRight", data)~=nil)then borders["right"] = colors[xmlValue("borderRight", data)] end
|
|
||||||
self:setBorder(borders["top"], borders["bottom"], borders["left"], borders["right"])
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
local utils = require("utils")
|
local utils = require("utils")
|
||||||
local count = utils.tableCount
|
local count = utils.tableCount
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base, basalt)
|
VisualObject = function(base, basalt)
|
||||||
|
|||||||
241
Basalt/plugins/reactive.lua
Normal file
241
Basalt/plugins/reactive.lua
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
local XMLParser = require("xmlParser")
|
||||||
|
local utils = require("utils")
|
||||||
|
local uuid = utils.uuid
|
||||||
|
|
||||||
|
local function maybeExecuteScript(nodeTree, renderContext)
|
||||||
|
for _, node in ipairs(nodeTree.children) do
|
||||||
|
if (node.tag == "script") then
|
||||||
|
return load(node.value, nil, "t", renderContext.env)()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function registerFunctionEvent(self, event, script, renderContext)
|
||||||
|
local eventEnv = renderContext.env
|
||||||
|
event(self, function(...)
|
||||||
|
eventEnv.event = {...}
|
||||||
|
local success, msg = pcall(load(script, nil, "t", eventEnv))
|
||||||
|
if not success then
|
||||||
|
error("XML Error: "..msg)
|
||||||
|
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 clearEffectDependencies = function(effect)
|
||||||
|
for _, dependency in ipairs(effect.dependencies) do
|
||||||
|
for index, backlink in ipairs(dependency) do
|
||||||
|
if (backlink == effect) then
|
||||||
|
table.remove(dependency, index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
effect.dependencies = {};
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
basalt = function(basalt)
|
||||||
|
local object = {
|
||||||
|
layout = function(path)
|
||||||
|
return {
|
||||||
|
path = path,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
|
||||||
|
reactive = function(initialValue)
|
||||||
|
local value = initialValue
|
||||||
|
local observerEffects = {}
|
||||||
|
local get = function()
|
||||||
|
if (currentEffect ~= nil) then
|
||||||
|
table.insert(observerEffects, currentEffect)
|
||||||
|
table.insert(currentEffect.dependencies, observerEffects)
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
local set = function(newValue)
|
||||||
|
value = newValue
|
||||||
|
local observerEffectsCopy = {}
|
||||||
|
for index, effect in ipairs(observerEffects) do
|
||||||
|
observerEffectsCopy[index] = effect
|
||||||
|
end
|
||||||
|
for _, effect in ipairs(observerEffectsCopy) do
|
||||||
|
effect.execute()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return get, set
|
||||||
|
end,
|
||||||
|
|
||||||
|
untracked = function(getter)
|
||||||
|
local parentEffect = currentEffect
|
||||||
|
currentEffect = nil
|
||||||
|
local value = getter()
|
||||||
|
currentEffect = parentEffect
|
||||||
|
return value
|
||||||
|
end,
|
||||||
|
|
||||||
|
effect = function(effectFn)
|
||||||
|
local effect = {dependencies = {}}
|
||||||
|
local execute = function()
|
||||||
|
clearEffectDependencies(effect)
|
||||||
|
local parentEffect = currentEffect
|
||||||
|
currentEffect = effect
|
||||||
|
effectFn()
|
||||||
|
currentEffect = parentEffect
|
||||||
|
end
|
||||||
|
effect.execute = execute
|
||||||
|
effect.execute()
|
||||||
|
end,
|
||||||
|
|
||||||
|
derived = function(computeFn)
|
||||||
|
local getValue, setValue = basalt.reactive();
|
||||||
|
basalt.effect(function()
|
||||||
|
setValue(computeFn())
|
||||||
|
end)
|
||||||
|
return getValue;
|
||||||
|
end
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
end,
|
||||||
|
|
||||||
|
VisualObject = function(base, basalt)
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
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
|
||||||
|
registerFunctionEvents(self, node, {
|
||||||
|
"onClick",
|
||||||
|
"onClickUp",
|
||||||
|
"onHover",
|
||||||
|
"onScroll",
|
||||||
|
"onDrag",
|
||||||
|
"onKey",
|
||||||
|
"onKeyUp",
|
||||||
|
"onRelease",
|
||||||
|
"onChar",
|
||||||
|
"onGetFocus",
|
||||||
|
"onLoseFocus",
|
||||||
|
"onResize",
|
||||||
|
"onReposition",
|
||||||
|
"onEvent",
|
||||||
|
"onLeave"
|
||||||
|
}, renderContext)
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
end,
|
||||||
|
|
||||||
|
ChangeableObject = function(base, basalt)
|
||||||
|
local object = {
|
||||||
|
setValuesByXMLData = function(self, node, renderContext)
|
||||||
|
base.setValuesByXMLData(self, node, renderContext)
|
||||||
|
registerFunctionEvent(self, node, {
|
||||||
|
"onChange"
|
||||||
|
}, renderContext)
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
end,
|
||||||
|
|
||||||
|
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 = {
|
||||||
|
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)
|
||||||
|
if(fs.exists(path))then
|
||||||
|
local renderContext = {}
|
||||||
|
renderContext.env = _ENV
|
||||||
|
renderContext.env.props = props
|
||||||
|
local f = fs.open(path, "r")
|
||||||
|
local nodeTree = XMLParser.parseText(f.readAll())
|
||||||
|
f.close()
|
||||||
|
lastXMLReferences = {}
|
||||||
|
maybeExecuteScript(nodeTree, renderContext)
|
||||||
|
self:setValuesByXMLData(nodeTree, renderContext)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
|
||||||
|
getXMLElements = function(self)
|
||||||
|
return lastXMLReferences
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
local utils = require("utils")
|
local XMLParser = require("xmlParser")
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base)
|
VisualObject = function(base)
|
||||||
@@ -29,12 +28,6 @@ return {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end,
|
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data, scripts)
|
|
||||||
if(xmlValue("shadow", data)~=nil)then self:setShadow(xmlValue("shadow", data)) end
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local images = require("images")
|
local images = require("images")
|
||||||
local utils = require("utils")
|
local utils = require("utils")
|
||||||
local xmlValue = utils.xmlValue
|
local XMLParser = require("xmlParser")
|
||||||
return {
|
return {
|
||||||
VisualObject = function(base)
|
VisualObject = function(base)
|
||||||
local textureId, infinitePlay = 1, true
|
local textureId, infinitePlay = 1, true
|
||||||
@@ -107,14 +107,6 @@ return {
|
|||||||
end
|
end
|
||||||
end, 1)
|
end, 1)
|
||||||
self:setDrawState("texture-base", false)
|
self:setDrawState("texture-base", false)
|
||||||
end,
|
|
||||||
|
|
||||||
setValuesByXMLData = function(self, data, scripts)
|
|
||||||
base.setValuesByXMLData(self, data, scripts)
|
|
||||||
if(xmlValue("texture", data)~=nil)then self:addTexture(xmlValue("texture", data), xmlValue("animate", data)) end
|
|
||||||
if(xmlValue("textureMode", data)~=nil)then self:setTextureMode(xmlValue("textureMode", data)) end
|
|
||||||
if(xmlValue("infinitePlay", data)~=nil)then self:setInfinitePlay(xmlValue("infinitePlay", data)) end
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,562 +0,0 @@
|
|||||||
local utils = require("utils")
|
|
||||||
local uuid = utils.uuid
|
|
||||||
local xmlValue = utils.xmlValue
|
|
||||||
|
|
||||||
local function newNode(name)
|
|
||||||
local node = {}
|
|
||||||
node.___value = nil
|
|
||||||
node.___name = name
|
|
||||||
node.___children = {}
|
|
||||||
node.___props = {}
|
|
||||||
node.___reactiveProps = {}
|
|
||||||
|
|
||||||
function node:value() return self.___value end
|
|
||||||
function node:setValue(val) self.___value = val end
|
|
||||||
function node:name() return self.___name end
|
|
||||||
function node:setName(name) self.___name = name end
|
|
||||||
function node:children() return self.___children end
|
|
||||||
function node:numChildren() return #self.___children end
|
|
||||||
function node:addChild(child)
|
|
||||||
if self[child:name()] ~= nil then
|
|
||||||
if type(self[child:name()].name) == "function" then
|
|
||||||
local tempTable = {}
|
|
||||||
table.insert(tempTable, self[child:name()])
|
|
||||||
self[child:name()] = tempTable
|
|
||||||
end
|
|
||||||
table.insert(self[child:name()], child)
|
|
||||||
else
|
|
||||||
self[child:name()] = child
|
|
||||||
end
|
|
||||||
table.insert(self.___children, child)
|
|
||||||
end
|
|
||||||
|
|
||||||
function node:properties() return self.___props end
|
|
||||||
function node:numProperties() return #self.___props end
|
|
||||||
function node:addProperty(name, value)
|
|
||||||
local lName = "@" .. name
|
|
||||||
if self[lName] ~= nil then
|
|
||||||
if type(self[lName]) == "string" then
|
|
||||||
local tempTable = {}
|
|
||||||
table.insert(tempTable, self[lName])
|
|
||||||
self[lName] = tempTable
|
|
||||||
end
|
|
||||||
table.insert(self[lName], value)
|
|
||||||
else
|
|
||||||
self[lName] = value
|
|
||||||
end
|
|
||||||
table.insert(self.___props, { name = name, value = self[lName] })
|
|
||||||
end
|
|
||||||
|
|
||||||
function node:reactiveProperties() return self.___reactiveProps end
|
|
||||||
function node:addReactiveProperty(name, value)
|
|
||||||
self.___reactiveProps[name] = value
|
|
||||||
end
|
|
||||||
|
|
||||||
return node
|
|
||||||
end
|
|
||||||
|
|
||||||
local XmlParser = {}
|
|
||||||
|
|
||||||
function XmlParser:ToXmlString(value)
|
|
||||||
value = string.gsub(value, "&", "&"); -- '&' -> "&"
|
|
||||||
value = string.gsub(value, "<", "<"); -- '<' -> "<"
|
|
||||||
value = string.gsub(value, ">", ">"); -- '>' -> ">"
|
|
||||||
value = string.gsub(value, "\"", """); -- '"' -> """
|
|
||||||
value = string.gsub(value, "([^%w%&%;%p%\t% ])",
|
|
||||||
function(c)
|
|
||||||
return string.format("&#x%X;", string.byte(c))
|
|
||||||
end);
|
|
||||||
return value;
|
|
||||||
end
|
|
||||||
|
|
||||||
function XmlParser:FromXmlString(value)
|
|
||||||
value = string.gsub(value, "&#x([%x]+)%;",
|
|
||||||
function(h)
|
|
||||||
return string.char(tonumber(h, 16))
|
|
||||||
end);
|
|
||||||
value = string.gsub(value, "&#([0-9]+)%;",
|
|
||||||
function(h)
|
|
||||||
return string.char(tonumber(h, 10))
|
|
||||||
end);
|
|
||||||
value = string.gsub(value, """, "\"");
|
|
||||||
value = string.gsub(value, "'", "'");
|
|
||||||
value = string.gsub(value, ">", ">");
|
|
||||||
value = string.gsub(value, "<", "<");
|
|
||||||
value = string.gsub(value, "&", "&");
|
|
||||||
return value;
|
|
||||||
end
|
|
||||||
|
|
||||||
function XmlParser:ParseProps(node, s)
|
|
||||||
string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a)
|
|
||||||
node:addProperty(w, self:FromXmlString(a))
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function XmlParser:ParseReactiveProps(node, s)
|
|
||||||
string.gsub(s, "(%w+)={(.-)}", function(w, a)
|
|
||||||
node:addReactiveProperty(w, a)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function XmlParser:ParseXmlText(xmlText)
|
|
||||||
local stack = {}
|
|
||||||
local top = newNode()
|
|
||||||
table.insert(stack, top)
|
|
||||||
local ni, c, label, xarg, empty
|
|
||||||
local i, j = 1, 1
|
|
||||||
while true do
|
|
||||||
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
|
|
||||||
if not ni then break end
|
|
||||||
local text = string.sub(xmlText, i, ni - 1);
|
|
||||||
if not string.find(text, "^%s*$") then
|
|
||||||
local lVal = (top:value() or "") .. self:FromXmlString(text)
|
|
||||||
stack[#stack]:setValue(lVal)
|
|
||||||
end
|
|
||||||
if empty == "/" then -- empty element tag
|
|
||||||
local lNode = newNode(label)
|
|
||||||
self:ParseProps(lNode, xarg)
|
|
||||||
self:ParseReactiveProps(lNode, xarg)
|
|
||||||
top:addChild(lNode)
|
|
||||||
elseif c == "" then -- start tag
|
|
||||||
local lNode = newNode(label)
|
|
||||||
self:ParseProps(lNode, xarg)
|
|
||||||
self:ParseReactiveProps(lNode, xarg)
|
|
||||||
table.insert(stack, lNode)
|
|
||||||
top = lNode
|
|
||||||
else -- end tag
|
|
||||||
local toclose = table.remove(stack) -- remove top
|
|
||||||
|
|
||||||
top = stack[#stack]
|
|
||||||
if #stack < 1 then
|
|
||||||
error("XmlParser: nothing to close with " .. label)
|
|
||||||
end
|
|
||||||
if toclose:name() ~= label then
|
|
||||||
error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
|
|
||||||
end
|
|
||||||
top:addChild(toclose)
|
|
||||||
end
|
|
||||||
i = j + 1
|
|
||||||
end
|
|
||||||
local text = string.sub(xmlText, i);
|
|
||||||
if #stack > 1 then
|
|
||||||
error("XmlParser: unclosed " .. stack[#stack]:name())
|
|
||||||
end
|
|
||||||
return top
|
|
||||||
end
|
|
||||||
|
|
||||||
local function maybeExecuteScript(data, renderContext)
|
|
||||||
local script = xmlValue('script', data)
|
|
||||||
if (script ~= nil) then
|
|
||||||
load(script, nil, "t", renderContext.env)()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function registerFunctionEvent(self, data, event, renderContext)
|
|
||||||
local eventEnv = renderContext.env
|
|
||||||
if(data:sub(1,1)=="$")then
|
|
||||||
local data = data:sub(2)
|
|
||||||
event(self, self:getBasalt().getVariable(data))
|
|
||||||
else
|
|
||||||
event(self, function(...)
|
|
||||||
eventEnv.event = {...}
|
|
||||||
local success, msg = pcall(load(data, nil, "t", eventEnv))
|
|
||||||
if not success then
|
|
||||||
error("XML Error: "..msg)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function registerFunctionEvents(self, data, events, renderContext)
|
|
||||||
for _, event in pairs(events) do
|
|
||||||
local expression = data:reactiveProperties()[event]
|
|
||||||
if (expression ~= nil) then
|
|
||||||
registerFunctionEvent(self, expression .. "()", self[event], renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local currentEffect = nil
|
|
||||||
|
|
||||||
local clearEffectDependencies = function(effect)
|
|
||||||
for _, dependency in ipairs(effect.dependencies) do
|
|
||||||
for index, backlink in ipairs(dependency) do
|
|
||||||
if (backlink == effect) then
|
|
||||||
table.remove(dependency, index)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
effect.dependencies = {};
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
basalt = function(basalt)
|
|
||||||
local object = {
|
|
||||||
layout = function(path)
|
|
||||||
return {
|
|
||||||
path = path,
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
|
|
||||||
reactive = function(initialValue)
|
|
||||||
local value = initialValue
|
|
||||||
local observerEffects = {}
|
|
||||||
local get = function()
|
|
||||||
if (currentEffect ~= nil) then
|
|
||||||
table.insert(observerEffects, currentEffect)
|
|
||||||
table.insert(currentEffect.dependencies, observerEffects)
|
|
||||||
end
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
local set = function(newValue)
|
|
||||||
value = newValue
|
|
||||||
local observerEffectsCopy = {}
|
|
||||||
for index, effect in ipairs(observerEffects) do
|
|
||||||
observerEffectsCopy[index] = effect
|
|
||||||
end
|
|
||||||
for _, effect in ipairs(observerEffectsCopy) do
|
|
||||||
effect.execute()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return get, set
|
|
||||||
end,
|
|
||||||
|
|
||||||
untracked = function(getter)
|
|
||||||
local parentEffect = currentEffect
|
|
||||||
currentEffect = nil
|
|
||||||
local value = getter()
|
|
||||||
currentEffect = parentEffect
|
|
||||||
return value
|
|
||||||
end,
|
|
||||||
|
|
||||||
effect = function(effectFn)
|
|
||||||
local effect = {dependencies = {}}
|
|
||||||
local execute = function()
|
|
||||||
clearEffectDependencies(effect)
|
|
||||||
local parentEffect = currentEffect
|
|
||||||
currentEffect = effect
|
|
||||||
effectFn()
|
|
||||||
currentEffect = parentEffect
|
|
||||||
end
|
|
||||||
effect.execute = execute
|
|
||||||
effect.execute()
|
|
||||||
end,
|
|
||||||
|
|
||||||
derived = function(computeFn)
|
|
||||||
local getValue, setValue = basalt.reactive();
|
|
||||||
basalt.effect(function()
|
|
||||||
setValue(computeFn())
|
|
||||||
end)
|
|
||||||
return getValue;
|
|
||||||
end
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
VisualObject = function(base, basalt)
|
|
||||||
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
renderContext.env[self:getName()] = self
|
|
||||||
for prop, expression in pairs(data:reactiveProperties()) do
|
|
||||||
local update = function()
|
|
||||||
local value = load("return " .. expression, nil, "t", renderContext.env)()
|
|
||||||
self:setProperty(prop, value)
|
|
||||||
end
|
|
||||||
basalt.effect(update)
|
|
||||||
end
|
|
||||||
for _, prop in ipairs(data:properties()) do
|
|
||||||
self:setProperty(prop.name, prop.value)
|
|
||||||
end
|
|
||||||
registerFunctionEvents(self, data, {
|
|
||||||
"onClick",
|
|
||||||
"onClickUp",
|
|
||||||
"onHover",
|
|
||||||
"onScroll",
|
|
||||||
"onDrag",
|
|
||||||
"onKey",
|
|
||||||
"onKeyUp",
|
|
||||||
"onRelease",
|
|
||||||
"onChar",
|
|
||||||
"onGetFocus",
|
|
||||||
"onLoseFocus",
|
|
||||||
"onResize",
|
|
||||||
"onReposition",
|
|
||||||
"onEvent",
|
|
||||||
"onLeave"
|
|
||||||
}, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
ChangeableObject = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
registerFunctionEvent(self, data, {
|
|
||||||
"onChange"
|
|
||||||
}, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Container = function(base, basalt)
|
|
||||||
local lastXMLReferences = {}
|
|
||||||
|
|
||||||
local function xmlDefaultValues(data, obj, renderContext)
|
|
||||||
if (obj~=nil) then
|
|
||||||
obj:setValuesByXMLData(data, renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function addXMLObjectType(node, addFn, self, renderContext)
|
|
||||||
if (node ~= nil) then
|
|
||||||
if (node.properties ~= 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 props = {}
|
|
||||||
for _, prop in ipairs(node:properties()) do
|
|
||||||
props[prop.name] = prop.value
|
|
||||||
end
|
|
||||||
local updateFns = {}
|
|
||||||
for prop, expression in pairs(node:reactiveProperties()) do
|
|
||||||
updateFns[prop] = basalt.derived(function()
|
|
||||||
return load("return " .. expression, nil, "t", renderContext.env)()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
setmetatable(props, {
|
|
||||||
__index = function(_, k)
|
|
||||||
return updateFns[k]()
|
|
||||||
end
|
|
||||||
})
|
|
||||||
self:loadLayout(layout.path, props)
|
|
||||||
end
|
|
||||||
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
lastXMLReferences = {}
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
|
|
||||||
local children = data:children()
|
|
||||||
local _OBJECTS = basalt.getObjects()
|
|
||||||
|
|
||||||
for _, childNode in pairs(children) do
|
|
||||||
local tagName = childNode.___name
|
|
||||||
if (tagName ~= "animation") then
|
|
||||||
local layout = renderContext.env[tagName]
|
|
||||||
local objectKey = tagName:gsub("^%l", string.upper)
|
|
||||||
if (layout ~= nil) then
|
|
||||||
insertChildLayout(self, layout, childNode, renderContext)
|
|
||||||
elseif (_OBJECTS[objectKey] ~= nil) then
|
|
||||||
local addFn = self["add" .. objectKey]
|
|
||||||
addXMLObjectType(childNode, addFn, self, renderContext)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
addXMLObjectType(data["animation"], self.addAnimation, self, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
loadLayout = function(self, path, props)
|
|
||||||
if(fs.exists(path))then
|
|
||||||
local renderContext = {}
|
|
||||||
renderContext.env = _ENV
|
|
||||||
renderContext.env.props = props
|
|
||||||
local f = fs.open(path, "r")
|
|
||||||
local data = XmlParser:ParseXmlText(f.readAll())
|
|
||||||
f.close()
|
|
||||||
lastXMLReferences = {}
|
|
||||||
maybeExecuteScript(data, renderContext)
|
|
||||||
self:setValuesByXMLData(data, renderContext)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
getXMLElements = function(self)
|
|
||||||
return lastXMLReferences
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Textfield = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
if(data["lines"]~=nil)then
|
|
||||||
local l = data["lines"]["line"]
|
|
||||||
if(l.properties~=nil)then l = {l} end
|
|
||||||
for _,v in pairs(l)do
|
|
||||||
self:addLine(v:value())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(data["keywords"]~=nil)then
|
|
||||||
for k,v in pairs(data["keywords"])do
|
|
||||||
if(colors[k]~=nil)then
|
|
||||||
local entry = v
|
|
||||||
if(entry.properties~=nil)then entry = {entry} end
|
|
||||||
local tab = {}
|
|
||||||
for a,b in pairs(entry)do
|
|
||||||
local keywordList = b["keyword"]
|
|
||||||
if(b["keyword"].properties~=nil)then keywordList = {b["keyword"]} end
|
|
||||||
for c,d in pairs(keywordList)do
|
|
||||||
table.insert(tab, d:value())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self:addKeywords(colors[k], tab)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(data["rules"]~=nil)then
|
|
||||||
if(data["rules"]["rule"]~=nil)then
|
|
||||||
local tab = data["rules"]["rule"]
|
|
||||||
if(data["rules"]["rule"].properties~=nil)then tab = {data["rules"]["rule"]} end
|
|
||||||
for k,v in pairs(tab)do
|
|
||||||
|
|
||||||
if(xmlValue("pattern", v)~=nil)then
|
|
||||||
self:addRule(xmlValue("pattern", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Thread = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
local script = xmlValue("start", data)~=nil
|
|
||||||
if(script~=nil)then
|
|
||||||
local f = load(script, nil, "t", renderContext.env)
|
|
||||||
self:start(f)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Timer = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
registerFunctionEvents(self, data, {
|
|
||||||
"onCall"
|
|
||||||
}, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
List = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
if(data["item"]~=nil)then
|
|
||||||
local tab = data["item"]
|
|
||||||
if(tab.properties~=nil)then tab = {tab} end
|
|
||||||
for _,v in pairs(tab)do
|
|
||||||
if(self:getType()~="Radio")then
|
|
||||||
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Dropdown = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Radio = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
if(data["item"]~=nil)then
|
|
||||||
local tab = data["item"]
|
|
||||||
if(tab.properties~=nil)then tab = {tab} end
|
|
||||||
for _,v in pairs(tab)do
|
|
||||||
self:addItem(xmlValue("text", v), xmlValue("x", v), xmlValue("y", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Graph = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
if(data["item"]~=nil)then
|
|
||||||
local tab = data["item"]
|
|
||||||
if(tab.properties~=nil)then tab = {tab} end
|
|
||||||
for _,_ in pairs(tab)do
|
|
||||||
self:addDataPoint(xmlValue("value"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
Treeview = function(base, basalt)
|
|
||||||
local object = {
|
|
||||||
setValuesByXMLData = function(self, data, renderContext)
|
|
||||||
base.setValuesByXMLData(self, data, renderContext)
|
|
||||||
local function addNode(node, data)
|
|
||||||
if(data["node"]~=nil)then
|
|
||||||
local tab = data["node"]
|
|
||||||
if(tab.properties~=nil)then tab = {tab} end
|
|
||||||
for _,v in pairs(tab)do
|
|
||||||
local n = node:addNode(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
|
|
||||||
addNode(n, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(data["node"]~=nil)then
|
|
||||||
local tab = data["node"]
|
|
||||||
if(tab.properties~=nil)then tab = {tab} end
|
|
||||||
for _,v in pairs(tab)do
|
|
||||||
local n = self:addNode(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
|
|
||||||
addNode(n, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
end,
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user