diff --git a/Basalt/libraries/utils.lua b/Basalt/libraries/utils.lua index 4fc0812..f76e26a 100644 --- a/Basalt/libraries/utils.lua +++ b/Basalt/libraries/utils.lua @@ -273,28 +273,6 @@ removeTags = removeTags, 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, --- Writes text with special color tags diff --git a/Basalt/libraries/xmlParser.lua b/Basalt/libraries/xmlParser.lua new file mode 100644 index 0000000..dde7575 --- /dev/null +++ b/Basalt/libraries/xmlParser.lua @@ -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 diff --git a/Basalt/plugins/advancedBackground.lua b/Basalt/plugins/advancedBackground.lua index 022d78d..4c38f5a 100644 --- a/Basalt/plugins/advancedBackground.lua +++ b/Basalt/plugins/advancedBackground.lua @@ -1,5 +1,4 @@ -local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { VisualObject = function(base) @@ -29,12 +28,6 @@ return { return bgSymbolColor 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) base.draw(self) self:addDraw("advanced-bg", function() @@ -45,8 +38,8 @@ return { self:addForegroundBox(1, 1, w, h, bgSymbolColor) end end - end, 2) - end, + end, 2) + end } return object diff --git a/Basalt/plugins/animations.lua b/Basalt/plugins/animations.lua index ca84ab3..99fe8f0 100644 --- a/Basalt/plugins/animations.lua +++ b/Basalt/plugins/animations.lua @@ -215,8 +215,7 @@ local lerp = { easeInOutBounce=easeInOutBounce, } -local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { VisualObject = function(base, basalt) @@ -337,24 +336,7 @@ return { 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, + end } return object diff --git a/Basalt/plugins/bigfonts.lua b/Basalt/plugins/bigfonts.lua index 9d29bbb..2dd01bb 100644 --- a/Basalt/plugins/bigfonts.lua +++ b/Basalt/plugins/bigfonts.lua @@ -140,8 +140,7 @@ local function makeText(nSize, sString, nFC, nBC, bBlit) 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: -local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { Label = function(base) local fontsize = 1 @@ -196,12 +195,6 @@ return { 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) base.draw(self) self:addDraw("bigfonts", function() @@ -220,7 +213,7 @@ return { end end end) - end, + end } return object end diff --git a/Basalt/plugins/border.lua b/Basalt/plugins/border.lua index 6c00d5c..517cd86 100644 --- a/Basalt/plugins/border.lua +++ b/Basalt/plugins/border.lua @@ -1,5 +1,4 @@ -local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { VisualObject = function(base) @@ -80,23 +79,6 @@ return { 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 } diff --git a/Basalt/plugins/dynamicValues.lua b/Basalt/plugins/dynamicValues.lua index 7c58315..4e9e9c6 100644 --- a/Basalt/plugins/dynamicValues.lua +++ b/Basalt/plugins/dynamicValues.lua @@ -1,6 +1,5 @@ local utils = require("utils") local count = utils.tableCount -local xmlValue = utils.xmlValue return { VisualObject = function(base, basalt) diff --git a/Basalt/plugins/reactive.lua b/Basalt/plugins/reactive.lua new file mode 100644 index 0000000..b9d1485 --- /dev/null +++ b/Basalt/plugins/reactive.lua @@ -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 +} diff --git a/Basalt/plugins/shadow.lua b/Basalt/plugins/shadow.lua index c53c188..d807f2d 100644 --- a/Basalt/plugins/shadow.lua +++ b/Basalt/plugins/shadow.lua @@ -1,5 +1,4 @@ -local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { VisualObject = function(base) @@ -29,12 +28,6 @@ return { 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 } diff --git a/Basalt/plugins/textures.lua b/Basalt/plugins/textures.lua index 2cc40ba..2e7d953 100644 --- a/Basalt/plugins/textures.lua +++ b/Basalt/plugins/textures.lua @@ -1,6 +1,6 @@ local images = require("images") local utils = require("utils") -local xmlValue = utils.xmlValue +local XMLParser = require("xmlParser") return { VisualObject = function(base) local textureId, infinitePlay = 1, true @@ -107,14 +107,6 @@ return { end end, 1) 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 } diff --git a/Basalt/plugins/xml.lua b/Basalt/plugins/xml.lua deleted file mode 100644 index 726bcfa..0000000 --- a/Basalt/plugins/xml.lua +++ /dev/null @@ -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, - -}