From b940ef7154db37d4c2f57b4fa9fb298f74344546 Mon Sep 17 00:00:00 2001 From: Robert Jelic <36573031+NoryiE@users.noreply.github.com> Date: Sun, 17 Jul 2022 19:20:02 +0200 Subject: [PATCH] added new features -remade animation -added xml support -finished dynamic values -added new object: graphic -added themes for frames -textfield got some basic improvements to create coding editors --- Basalt/Frame.lua | 340 ++++++++++++++++---- Basalt/Object.lua | 232 +++++++------- Basalt/libraries/Lerp.lua | 33 +- Basalt/libraries/basaltDraw.lua | 15 + Basalt/libraries/dynamicValues.lua | 67 ++++ Basalt/libraries/geometricPoints.lua | 197 ++++++++++++ Basalt/libraries/layout.lua | 147 +++++++++ Basalt/libraries/utils.lua | 151 ++------- Basalt/loadObjects.lua | 9 +- Basalt/main.lua | 72 +++-- Basalt/objects/Animation.lua | 402 ++++++++++++++++-------- Basalt/objects/Button.lua | 26 +- Basalt/objects/Checkbox.lua | 27 +- Basalt/objects/Dropdown.lua | 41 ++- Basalt/objects/Graphic.lua | 450 ++++++++++++++++++++++++++- Basalt/objects/Image.lua | 19 +- Basalt/objects/Input.lua | 48 ++- Basalt/objects/Label.lua | 48 ++- Basalt/objects/List.lua | 58 ++-- Basalt/objects/Menubar.lua | 57 +++- Basalt/objects/Pane.lua | 9 +- Basalt/objects/Program.lua | 30 +- Basalt/objects/Progressbar.lua | 57 ++-- Basalt/objects/Radio.lua | 38 ++- Basalt/objects/Scrollbar.lua | 61 ++-- Basalt/objects/Slider.lua | 69 ++-- Basalt/objects/Switch.lua | 28 +- Basalt/objects/Textfield.lua | 218 +++++++++++-- Basalt/objects/Thread.lua | 16 + Basalt/objects/Timer.lua | 17 + Basalt/theme.lua | 55 +++- docs/objects/Animation.md | 145 ++++++++- docs/objects/Installer.md | 73 ----- 33 files changed, 2487 insertions(+), 768 deletions(-) create mode 100644 Basalt/libraries/dynamicValues.lua create mode 100644 Basalt/libraries/geometricPoints.lua delete mode 100644 docs/objects/Installer.md diff --git a/Basalt/Frame.lua b/Basalt/Frame.lua index a47eeae..e8ef02f 100644 --- a/Basalt/Frame.lua +++ b/Basalt/Frame.lua @@ -2,11 +2,13 @@ local Object = require("Object") local _OBJECTS = require("loadObjects") local BasaltDraw = require("basaltDraw") -local theme = require("theme") local utils = require("utils") +local layout = require("layout") +local uuid = utils.uuid local rpairs = utils.rpairs +local xmlValue = utils.getValueFromXML -local sub = string.sub +local sub,min,max = string.sub,math.min,math.max return function(name, parent, pTerm, basalt) -- Frame @@ -15,6 +17,8 @@ return function(name, parent, pTerm, basalt) local objects = {} local objZIndex = {} local object = {} + local variables = {} + local theme = {} local termObject = pTerm or term.current() local monSide = "" @@ -22,6 +26,13 @@ return function(name, parent, pTerm, basalt) local monitorAttached = false local dragXOffset = 0 local dragYOffset = 0 + local isScrollable = false + local minScroll = 0 + local maxScroll = 10 + local mirrorActive = false + local mirrorAttached = false + local mirrorSide = "" + local importantScroll = false base:setZIndex(10) @@ -34,22 +45,80 @@ return function(name, parent, pTerm, basalt) local xOffset, yOffset = 0, 0 + local lastXMLReferences = {} + + local function xmlDefaultValues(data, obj) + if(obj~=nil)then + obj:setValuesByXMLData(data) + end + end + + local function addXMLObjectType(tab, f, self) + if(tab~=nil)then + if(tab.properties~=nil)then tab = {tab} end + + for k,v in pairs(tab)do + local obj = f(self, v["@id"] or uuid()) + table.insert(lastXMLReferences, obj) + xmlDefaultValues(v, obj) + end + end + end + + local function duplicateTerm(term1, term2) + local both = {} + setmetatable(both, { + __index = function(_, k) + if (type(term1[k]) == "function") then + return function(...) + pcall(term1[k], ...) + return term2[k](...) + end + else + return term1[k] + end + end, + __call = function(_, f, ...) + pcall(term2[f], ...) + return term1[f](...) + end, + __newindex = function(_, k, v) + term1[k] = v + term2[k] = v + end + }) + return both + end + if (parent ~= nil) then base.parent = parent base.width, base.height = parent:getSize() - base.bgColor = theme.FrameBG - base.fgColor = theme.FrameFG + base.bgColor = parent:getTheme("FrameBG") + base.fgColor = parent:getTheme("FrameText") + print(parent:getTheme("FrameBG")) else base.width, base.height = termObject.getSize() - base.bgColor = theme.basaltBG - base.fgColor = theme.basaltFG + base.bgColor = basalt.getTheme("BasaltBG") + base.fgColor = basalt.getTheme("BasaltText") end local function getObject(name) for _, value in pairs(objects) do for _, b in pairs(value) do - if (b.name == name) then - return value + if (b:getName() == name) then + return b + end + end + end + end + local function getDeepObject(name) + local o = getObject(name) + if(o~=nil)then return o end + for _, value in pairs(objects) do + for _, b in pairs(value) do + if (b:getType() == "Frame") then + local oF = b:getDeepObject(name) + if(oF~=nil)then return oF end end end end @@ -80,6 +149,9 @@ return function(name, parent, pTerm, basalt) objects[zIndex] = {} end obj.parent = object + if(obj.init~=nil)then + obj:init() + end table.insert(objects[zIndex], obj) return obj end @@ -120,8 +192,12 @@ return function(name, parent, pTerm, basalt) return self end; - setSize = function(self, w, h) - base.setSize(self, w, h) + getVariable = function(self, name) + return basalt.getVariable(name) + end, + + setSize = function(self, w, h, rel) + base.setSize(self, w, h, rel) for _, index in pairs(objZIndex) do if (objects[index] ~= nil) then for _, value in pairs(objects[index]) do @@ -134,6 +210,29 @@ return function(name, parent, pTerm, basalt) return self end; + setTheme = function(self, _theme) + theme = _theme + return self + end, + + getTheme = function(self, name) + return theme[name] or (self.parent~=nil and self.parent:getTheme(name) or basalt.getTheme(name)) + end, + + setPosition = function(self, x, y, rel) + base.setPosition(self, x, y, rel) + for _, index in pairs(objZIndex) do + if (objects[index] ~= nil) then + for _, value in pairs(objects[index]) do + if (value.eventHandler ~= nil) then + value:sendEvent("basalt_reposition", value, self) + end + end + end + end + return self + end; + getBasaltInstance = function(self) return basalt end, @@ -185,6 +284,26 @@ return function(name, parent, pTerm, basalt) return self; end; + setScrollable = function(self, scrollable) + isScrollable = scrollable and true or false + return self + end, + + setImportantScroll = function(self, imp) + importantScroll = imp and true or false + return self + end, + + setMaxScroll = function(self, max) + maxScroll = max or maxScroll + return self + end, + + setMinScroll = function(self, min) + minScroll = min or minScroll + return self + end, + show = function(self) base.show(self) if(self.parent==nil)then @@ -214,7 +333,61 @@ return function(name, parent, pTerm, basalt) end return self end; + + addLayout = function(self, file) + if(file~=nil)then + if(fs.exists(file))then + local f = fs.open(file, "r") + local data = layout:ParseXmlText(f.readAll()) + f.close() + lastXMLReferences = {} + self:setValuesByXMLData(data) + end + end + return self + end, + + getLastLayout = function(self) + return lastXMLReferences + end, + + addLayoutFromString = function(self, str) + if(str~=nil)then + local data = layout:ParseXmlText(str) + self:setValuesByXMLData(data) + end + return self + end, + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + + if(xmlValue("moveable", data)~=nil)then if(xmlValue("moveable", data))then self:setMoveable(true) end end + if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) end end + if(xmlValue("monitor", data)~=nil)then self:setMonitor(xmlValue("monitor", data)):show() end + if(xmlValue("mirror", data)~=nil)then self:setMirror(xmlValue("mirror", data)) end + if(xmlValue("bar", data)~=nil)then if(xmlValue("bar", data))then self:showBar(true) else self:showBar(false) end end + if(xmlValue("barText", data)~=nil)then self.barText = xmlValue("barText", data) end + if(xmlValue("barBG", data)~=nil)then self.barBackground = colors[xmlValue("barBG", data)] end + if(xmlValue("barFG", data)~=nil)then self.barTextcolor = colors[xmlValue("barFG", data)] end + if(xmlValue("barAlign", data)~=nil)then self.barTextAlign = xmlValue("barAlign", data) end + if(xmlValue("layout", data)~=nil)then self:addLayout(xmlValue("layout", data)) end + if(xmlValue("xOffset", data)~=nil)then self:setOffset(xmlValue("xOffset", data), yOffset) end + if(xmlValue("yOffset", data)~=nil)then self:setOffset(yOffset, xmlValue("yOffset", data)) end + if(xmlValue("maxScroll", data)~=nil)then self:setMaxScroll(xmlValue("maxScroll", data)) end + if(xmlValue("minScroll", data)~=nil)then self:setMaxScroll(xmlValue("minScroll", data)) end + if(xmlValue("importantScroll", data)~=nil)then self:setImportantScroll(xmlValue("importantScroll", data)) end + + + for k,v in pairs(_OBJECTS)do + if(k~="Animation")then + addXMLObjectType(data[string.lower(k)], self["add"..k], self) + end + end + addXMLObjectType(data["animation"], self.addAnimation, self) + addXMLObjectType(data["frame"], self.addFrame, self) + return self + end, showBar = function(self, showIt) self.barActive = showIt or not self.barActive @@ -236,12 +409,31 @@ return function(name, parent, pTerm, basalt) return self end; + setMirror = function(self, side) + mirrorSide = side + if(mirror~=nil)then + basaltDraw.setMirror(mirror) + end + mirrorActive = true + return self + end, + + removeMirror = function(self) + mirror = nil + mirrorActive = false + basaltDraw.setMirror(nil) + return self + end, + setMonitor = function(self, side) if(side~=nil)and(side~=false)then if(peripheral.getType(side)=="monitor")then termObject = peripheral.wrap(side) monitorAttached = true end + if(self.parent~=nil)then + self.parent:removeObject(self) + end isMonitor = true else termObject = parentTerminal @@ -326,16 +518,28 @@ return function(name, parent, pTerm, basalt) if(peripheral.getType(monSide)=="monitor")then monitorAttached = true termObject = peripheral.wrap(monSide) - basaltDraw = basaltDraw(termObject) + basaltDraw = BasaltDraw(termObject) end end if(event == "peripheral_detach")and(p1==monSide)then monitorAttached = false end end + if(mirrorActive)then + if(peripheral.getType(mirrorSide)=="monitor")then + mirrorAttached = true + basaltDraw.setMirror(peripheral.wrap(mirrorSide)) + end + if(event == "peripheral_detach")and(p1==mirrorSide)then + monitorAttached = false + end + if(event=="monitor_touch")then + self:mouseHandler(event, p1, p2, p3, p4) + end + end if (event == "terminate") then - termObject.clear() termObject.setCursorPos(1, 1) + termObject.clear() basalt.stop() end end; @@ -369,6 +573,13 @@ return function(name, parent, pTerm, basalt) if (base.mouseHandler(self, event, button, x, y)) then local fx, fy = self:getAbsolutePosition(self:getAnchorPosition()) fx = fx + xOffset;fy = fy + yOffset; + if(isScrollable)and(importantScroll)then + if(event=="mouse_scroll")then + if(button>0)or(button<0)then + yOffset = max(min(yOffset-button, -minScroll),-maxScroll) + end + end + end for _, index in pairs(objZIndex) do if (objects[index] ~= nil) then for _, value in rpairs(objects[index]) do @@ -382,12 +593,19 @@ return function(name, parent, pTerm, basalt) end if (self.isMoveable) then local fx, fy = self:getAbsolutePosition(self:getAnchorPosition()) - if (x >= fx) and (x <= fx + self.width - 1) and (y == fy) and (event == "mouse_click") then + if (x >= fx) and (x <= fx + self:getWidth() - 1) and (y == fy) and (event == "mouse_click") then self.drag = true dragXOffset = fx - x dragYOffset = yOff and 1 or 0 end end + if(isScrollable)and(not importantScroll)then + if(event=="mouse_scroll")then + if(button>0)or(button<0)then + yOffset = max(min(yOffset-button, -minScroll),-maxScroll) + end + end + end if (basalt.getFocusedObject() ~= nil) then basalt.getFocusedObject():loseFocusHandler() basalt.setFocusedObject(nil) @@ -398,86 +616,80 @@ return function(name, parent, pTerm, basalt) end; setText = function(self, x, y, text) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - if (y >= 1) and (y <= self.height) then + local obx, oby = self:getAnchorPosition() + if (y >= 1) and (y <= self:getHeight()) then if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:setText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) + self.parent:setText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) else - basaltDraw.setText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) -- math.max(self.width - x + 1,1) now, before: self.width - x + 1 + basaltDraw.setText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) end end end; setBG = function(self, x, y, bgCol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - if (y >= 1) and (y <= self.height) then + local obx, oby = self:getAnchorPosition() + if (y >= 1) and (y <= self:getHeight()) then if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:setBG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) + self.parent:setBG(max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) else - basaltDraw.setBG(math.max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) + basaltDraw.setBG(max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) end end end; setFG = function(self, x, y, fgCol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - if (y >= 1) and (y <= self.height) then + local obx, oby = self:getAnchorPosition() + if (y >= 1) and (y <= self:getHeight()) then if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:setFG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) + self.parent:setFG(max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) else - basaltDraw.setFG(math.max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) + basaltDraw.setFG(max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1))) end end end; writeText = function(self, x, y, text, bgCol, fgCol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - if (y >= 1) and (y <= self.height) then + local obx, oby = self:getAnchorPosition() + if (y >= 1) and (y <= self:getHeight()) then if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:writeText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), self.width - x + 1), bgCol, fgCol) + self.parent:writeText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), self:getWidth() - x + 1), bgCol, fgCol) else - basaltDraw.writeText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)), bgCol, fgCol) + basaltDraw.writeText(max(x + (obx - 1), obx), oby + y - 1, sub(text, max(1 - x + 1, 1), max(self:getWidth() - x + 1,1)), bgCol, fgCol) end end end; drawBackgroundBox = function(self, x, y, width, height, bgCol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height)) - width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width)) + local obx, oby = self:getAnchorPosition() + + height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height)) + width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width)) if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:drawBackgroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, bgCol) + self.parent:drawBackgroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, bgCol) else - basaltDraw.drawBackgroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, bgCol) + basaltDraw.drawBackgroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, bgCol) end end; drawTextBox = function(self, x, y, width, height, symbol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height)) - width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width)) + local obx, oby = self:getAnchorPosition() + height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height)) + width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width)) if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:drawTextBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, symbol:sub(1, 1)) + self.parent:drawTextBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, sub(symbol,1,1)) else - basaltDraw.drawTextBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, symbol:sub(1, 1)) + basaltDraw.drawTextBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, sub(symbol,1,1)) end end; drawForegroundBox = function(self, x, y, width, height, fgCol) - local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height)) - width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width)) + local obx, oby = self:getAnchorPosition() + height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height)) + width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width)) if (self.parent ~= nil) then - local parentX, parentY = self.parent:getAnchorPosition() - self.parent:drawForegroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, fgCol) + self.parent:drawForegroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, fgCol) else - basaltDraw.drawForegroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, fgCol) + basaltDraw.drawForegroundBox(max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, fgCol) end end; @@ -487,37 +699,38 @@ return function(name, parent, pTerm, basalt) if (base.draw(self)) then local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local anchx, anchy = self:getAnchorPosition() + local w,h = self:getSize() if (self.parent ~= nil) then if(self.bgColor~=false)then - self.parent:drawBackgroundBox(anchx, anchy, self.width, self.height, self.bgColor) - self.parent:drawTextBox(anchx, anchy, self.width, self.height, " ") + self.parent:drawBackgroundBox(anchx, anchy, w, h, self.bgColor) + self.parent:drawTextBox(anchx, anchy, w, h, " ") end - if(self.bgColor~=false)then self.parent:drawForegroundBox(anchx, anchy, self.width, self.height, self.fgColor) end + if(self.bgColor~=false)then self.parent:drawForegroundBox(anchx, anchy, w, h, self.fgColor) end else if(self.bgColor~=false)then - basaltDraw.drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) - basaltDraw.drawTextBox(obx, oby, self.width, self.height, " ") + basaltDraw.drawBackgroundBox(anchx, anchy, w, h, self.bgColor) + basaltDraw.drawTextBox(anchx, anchy, w, h, " ") end - if(self.fgColor~=false)then basaltDraw.drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end + if(self.fgColor~=false)then basaltDraw.drawForegroundBox(anchx, anchy, w, h, self.fgColor) end end termObject.setCursorBlink(false) if (self.barActive) then if (self.parent ~= nil) then - self.parent:writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor) + self.parent:writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, w, self.barTextAlign), self.barBackground, self.barTextcolor) else - basaltDraw.writeText(obx, oby, utils.getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor) + basaltDraw.writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, w, self.barTextAlign), self.barBackground, self.barTextcolor) end if(self:getBorder("left"))then if (self.parent ~= nil) then self.parent:drawBackgroundBox(anchx-1, anchy, 1, 1, self.barBackground) if(self.bgColor~=false)then - self.parent:drawBackgroundBox(anchx-1, anchy+1, 1, self.height-1, self.bgColor) + self.parent:drawBackgroundBox(anchx-1, anchy+1, 1, h-1, self.bgColor) end end end if(self:getBorder("top"))then if (self.parent ~= nil) then - self.parent:drawBackgroundBox(anchx-1, anchy-1, self.width+1, 1, self.barBackground) + self.parent:drawBackgroundBox(anchx-1, anchy-1, w+1, 1, self.barBackground) end end end @@ -562,6 +775,9 @@ return function(name, parent, pTerm, basalt) getObject = function(self, obj) return getObject(obj) end; + getDeepObject = function(self, name) + return getDeepObject(name) + end, addFrame = function(self, name) local obj = basalt.newFrame(name, self, nil, basalt) @@ -570,7 +786,7 @@ return function(name, parent, pTerm, basalt) } for k,v in pairs(_OBJECTS)do object["add"..k] = function(self, name) - return addObject(v(name, self)) + return addObject(v(name or uuid(), self)) end end setmetatable(object, base) diff --git a/Basalt/Object.lua b/Basalt/Object.lua index 7e0d9b5..4e6d326 100644 --- a/Basalt/Object.lua +++ b/Basalt/Object.lua @@ -1,16 +1,19 @@ local basaltEvent = require("basaltEvent") -local split = require("utils").splitString -local numberFromString = require("utils").numberFromString +local dynValue = require("dynamicValues") +local utils = require("utils") +local split = utils.splitString +local numberFromString = utils.numberFromString +local xmlValue = utils.getValueFromXML return function(name) -- Base object local objectType = "Object" -- not changeable local object = {} - local value local zIndex = 1 + local value local anchor = "topLeft" local ignOffset = false - local isVisible = false + local isVisible = true local shadow = false local borderLeft = false @@ -25,45 +28,6 @@ return function(name) local eventSystem = basaltEvent() - local dynamicValue = {} - local dynamicValueResult = {} - - local function replacePercentage(str, parentValue) - local _fullStr = str - for v in _fullStr:gmatch("%d+%%") do - local pValue = v:gsub("%%", "") - print(str) - str = str:gsub(v.."%", parentValue / 100 * math.max(math.min(tonumber(pValue),100),0)) - end - return str - end - - local function fToNumber(str, fTable) - for k,v in pairs(fTable)do - if(type(v)=="function")then - local nmb = v() - for _ in str:gmatch("f"..k)do - str = string.gsub(str, "f"..k, nmb) - end - end - end - str = str:gsub("f%d+", "") - return str - end - - local calcDynamicValue = function(newDValue) - local val = dynamicValue[newDValue][1] - if(val~=nil)then - if(type(val)=="string")then - if(dynamicValue[newDValue][3]~=nil)then - dynamicValueResult[newDValue] = numberFromString(replacePercentage(fToNumber(val, dynamicValue[newDValue][3]), dynamicValue[newDValue][2]() or 1)) - else - dynamicValueResult[newDValue] = numberFromString(replacePercentage(val, dynamicValue[newDValue][2]() or 1)) - end - end - end - end - object = { x = 1, y = 1, @@ -86,6 +50,45 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + local baseFrame = self:getBaseFrame() + if(xmlValue("x", data)~=nil)then self:setPosition(xmlValue("x", data), self:getY()) end + if(xmlValue("y", data)~=nil)then self:setPosition(self:getX(), xmlValue("y", data)) end + if(xmlValue("width", data)~=nil)then self:setSize(xmlValue("width", data), self:getHeight()) end + if(xmlValue("height", data)~=nil)then self:setSize(self:getWidth(), xmlValue("height", data)) end + if(xmlValue("bg", data)~=nil)then self:setBackground(colors[xmlValue("bg", data)]) end + if(xmlValue("fg", data)~=nil)then self:setForeground(colors[xmlValue("fg", data)]) end + if(xmlValue("value", data)~=nil)then self:setValue(colors[xmlValue("value", data)]) end + if(xmlValue("visible", data)~=nil)then if(xmlValue("visible", data))then self:show() else self:hide() end end + if(xmlValue("zIndex", data)~=nil)then self:setZIndex(xmlValue("zIndex", data)) end + if(xmlValue("anchor", data)~=nil)then self:setAnchor(xmlValue("anchor", data)) end + if(xmlValue("shadow", data)~=nil)then if(xmlValue("shadow", data))then self:showShadow(true) end end + if(xmlValue("shadowColor", data)~=nil)then self:setShadow(colors[xmlValue("shadowColor", data)]) end + if(xmlValue("border", data)~=nil)then if(xmlValue("border", data))then borderLeft,borderTop,borderRight,borderBottom = true,true,true,true end end + if(xmlValue("borderLeft", data)~=nil)then if(xmlValue("borderLeft", data))then borderLeft = true else borderLeft = false end end + if(xmlValue("borderTop", data)~=nil)then if(xmlValue("borderTop", data))then borderTop = true else borderTop = false end end + if(xmlValue("borderRight", data)~=nil)then if(xmlValue("borderRight", data))then borderRight = true else borderRight = false end end + if(xmlValue("borderBottom", data)~=nil)then if(xmlValue("borderBottom", data))then borderBottom = true else borderBottom = false end end + if(xmlValue("borderColor", data)~=nil)then self:setBorder(colors[xmlValue("borderColor", data)]) end + if(xmlValue("ignoreOffset", data)~=nil)then if(xmlValue("ignoreOffset", data))then self:ignoreOffset(true) end end + if(xmlValue("onClick", data)~=nil)then self:onClick(baseFrame:getVariable(xmlValue("onClick", data))) end + if(xmlValue("onClickUp", data)~=nil)then self:onClickUp(baseFrame:getVariable(xmlValue("onClickUp", data))) end + if(xmlValue("onScroll", data)~=nil)then self:onScroll(baseFrame:getVariable(xmlValue("onScroll", data))) end + if(xmlValue("onDrag", data)~=nil)then self:onDrag(baseFrame:getVariable(xmlValue("onDrag", data))) end + if(xmlValue("onKey", data)~=nil)then self:onKey(baseFrame:getVariable(xmlValue("onKey", data))) end + if(xmlValue("onKeyUp", data)~=nil)then self:onKeyUp(baseFrame:getVariable(xmlValue("onKeyUp", data))) end + if(xmlValue("onChange", data)~=nil)then self:onChange(baseFrame:getVariable(xmlValue("onChange", data))) end + if(xmlValue("onResize", data)~=nil)then self:onResize(baseFrame:getVariable(xmlValue("onResize", data))) end + if(xmlValue("onReposition", data)~=nil)then self:onReposition(baseFrame:getVariable(xmlValue("onReposition", data))) end + if(xmlValue("onEvent", data)~=nil)then self:onEvent(baseFrame:getVariable(xmlValue("onEvent", data))) end + if(xmlValue("onGetFocus", data)~=nil)then self:onGetFocus(baseFrame:getVariable(xmlValue("onGetFocus", data))) end + if(xmlValue("onLoseFocus", data)~=nil)then self:onLoseFocus(baseFrame:getVariable(xmlValue("onLoseFocus", data))) end + if(xmlValue("onBackgroundKey", data)~=nil)then self:onBackgroundKey(baseFrame:getVariable(xmlValue("onBackgroundKey", data))) end + if(xmlValue("onBackgroundKeyUp", data)~=nil)then self:onBackgroundKeyUp(baseFrame:getVariable(xmlValue("onBackgroundKeyUp", data))) end + + return self + end, + isVisible = function(self) return isVisible end; @@ -170,38 +173,43 @@ return function(name) end; setPosition = function(self, xPos, yPos, rel) - if (rel) then - self.x, self.y = math.floor(self.x + xPos), math.floor(self.y + yPos) - else - self.x, self.y = math.floor(xPos), math.floor(yPos) - end - - if(type(xPos)=="number")then - self.x = rel and self.x+xPos or xPos + self.x = rel and self:getX()+xPos or xPos end if(type(yPos)=="number")then - self.y = rel and self.y+yPos or yPos + self.y = rel and self:getY()+yPos or yPos end - if(type(xPos)=="string")or(type(xPos)=="table")then - dynamicValue.x = {xPos, function() return self:getParent():getX() end} + if(type(xPos)=="string")then + self.x = dynValue(xPos, function() return self:getParent():getWidth() end) end - if(type(yPos)=="string")or(type(yPos)=="table")then - dynamicValue.y = {yPos, function() return self:getParent():getY() end} + if(type(xPos)=="table")then + local str = xPos[1] + table.remove(xPos, 1) + local fList = xPos + self.x = dynValue(str, function() return self:getParent():getWidth() end, fList) end - self:recalculateDynamicValue() + if(type(yPos)=="string")then + self.y = dynValue(yPos, function() return self:getParent():getHeight() end) + end + if(type(yPos)=="table")then + local str = yPos[1] + table.remove(yPos, 1) + local fList = yPos + self.y = dynValue(str, function() return self:getParent():getHeight() end, fList) + end + self:calculateDynamicValues() eventSystem:sendEvent("basalt_reposition", self) visualsChanged = true return self end; getX = function(self) - return dynamicValue.x or self.x - end, + return type(self.x)=="number" and self.x or self.x:get() + end; getY = function(self) - return dynamicValue.y or self.y - end, + return type(self.y)=="number" and self.y or self.y:get() + end; getPosition = function(self) return self:getX(), self:getY() @@ -225,39 +233,49 @@ return function(name) self.height = rel and self.height+height or height end if(type(width)=="string")then - dynamicValue.width = {width, function() return self:getParent():getWidth() end} + self.width = dynValue(width, function() return self:getParent():getWidth() end) end if(type(width)=="table")then - dynamicValue.width = {width[1], function() return self:getParent():getWidth() end} + local str = width[1] table.remove(width, 1) - dynamicValue.width[3] = width + local fList = width + self.width = dynValue(str, function() return self:getParent():getWidth() end, fList) end if(type(height)=="string")then - dynamicValue.height = {height, function() return self:getParent():getHeight() end} + self.height = dynValue(height, function() return self:getParent():getHeight() end) end if(type(height)=="table")then - dynamicValue.height = {height[1], function() return self:getParent():getHeight() end} + local str = height[1] table.remove(height, 1) - dynamicValue.height[3] = height + local fList = height + self.height = dynValue(str, function() return self:getParent():getHeight() end, fList) end - self:recalculateDynamicValue() + self:calculateDynamicValues() eventSystem:sendEvent("basalt_resize", self) visualsChanged = true return self end; getHeight = function(self) - return dynamicValueResult["height"] or self.height + return type(self.height)=="number" and self.height or self.height:get() end; getWidth = function(self) - return dynamicValueResult["width"] or self.width + return type(self.width)=="number" and self.width or self.width:get() end; getSize = function(self) return self:getWidth(), self:getHeight() end; + calculateDynamicValues = function(self) + if(type(self.width)=="table")then self.width:calculate() end + if(type(self.height)=="table")then self.height:calculate() end + if(type(self.x)=="table")then self.x:calculate() end + if(type(self.y)=="table")then self.y:calculate() end + return self + end, + setBackground = function(self, color) self.bgColor = color visualsChanged = true @@ -311,7 +329,7 @@ return function(name) end; setBorder = function(self, color) - shadowColor = color + borderColor = color return self end; @@ -390,7 +408,7 @@ return function(name) end if (self.parent ~= nil) then - local fx, fy = self.parent:getAbsolutePosition(self.parent:getAnchorPosition()) + local fx, fy = self.parent:getAbsolutePosition() x = fx + x - 1 y = fy + y - 1 end @@ -399,33 +417,35 @@ return function(name) getAnchorPosition = function(self, x, y, ignOff) if (x == nil) then - x = self.x + x = self:getX() end if (y == nil) then - y = self.y - end - if (anchor == "top") then - x = math.floor(self.parent.width/2) + x - 1 - elseif(anchor == "topRight") then - x = self.parent.width + x - 1 - elseif(anchor == "right") then - x = self.parent.width + x - 1 - y = math.floor(self.parent.height/2) + y - 1 - elseif(anchor == "bottomRight") then - x = self.parent.width + x - 1 - y = self.parent.height + y - 1 - elseif(anchor == "bottom") then - x = math.floor(self.parent.width/2) + x - 1 - y = self.parent.height + y - 1 - elseif(anchor == "bottomLeft") then - y = self.parent.height + y - 1 - elseif(anchor == "left") then - y = math.floor(self.parent.height/2) + y - 1 - elseif(anchor == "center") then - x = math.floor(self.parent.width/2) + x - 1 - y = math.floor(self.parent.height/2) + y - 1 + y = self:getY() end if(self.parent~=nil)then + local pw,ph = self.parent:getSize() + if (anchor == "top") then + x = math.floor(pw/2) + x - 1 + elseif(anchor == "topRight") then + x = pw + x - 1 + elseif(anchor == "right") then + x = pw + x - 1 + y = math.floor(ph/2) + y - 1 + elseif(anchor == "bottomRight") then + x = pw + x - 1 + y = ph + y - 1 + elseif(anchor == "bottom") then + x = math.floor(pw/2) + x - 1 + y = ph + y - 1 + elseif(anchor == "bottomLeft") then + y = ph + y - 1 + elseif(anchor == "left") then + y = math.floor(ph/2) + y - 1 + elseif(anchor == "center") then + x = math.floor(pw/2) + x - 1 + y = math.floor(ph/2) + y - 1 + end + local xO, yO = self.parent:getOffset() if not(ignOffset or ignOff) then return x+xO, y+yO @@ -523,19 +543,7 @@ return function(name) return self end; - recalculateDynamicValue = function(self, special) - if(special==nil)then - for k in pairs(dynamicValue)do - calcDynamicValue(k) - end - else - calcDynamicValue(special) - end - return self - end, - onResize = function(self, ...) - self:recalculateValues() for _,v in pairs(table.pack(...))do if(type(v)=="function")then self:registerEvent("basalt_resize", v) @@ -544,6 +552,15 @@ return function(name) return self end; + onReposition = function(self, ...) + for _,v in pairs(table.pack(...))do + if(type(v)=="function")then + self:registerEvent("basalt_reposition", v) + end + end + return self + end; + onKeyUp = function(self, ...) for _,v in pairs(table.pack(...))do if(type(v)=="function")then @@ -613,6 +630,7 @@ return function(name) local objX, objY = self:getAbsolutePosition(self:getAnchorPosition()) local w, h = self:getSize() local yOff = false + if(objY-1 == y)and(self:getBorder("top"))then y = y+1 yOff = true diff --git a/Basalt/libraries/Lerp.lua b/Basalt/libraries/Lerp.lua index 2f58315..eaaeee5 100644 --- a/Basalt/libraries/Lerp.lua +++ b/Basalt/libraries/Lerp.lua @@ -1,14 +1,27 @@ +local lerp = function(s, e, pct) + return s + (e - s) * pct +end + +local flip = function (x) + return 1 - x +end + +local easeIn = function (t) + return t * t * t +end + +local easeOut = function(t) + return flip(easeIn(flip(t))) +end + return { - lerp = function(s, e, pct) - return s + (e - s) * pct - end, + lerp = lerp, + flip = flip, + easeIn = easeIn, + easeOut = easeOut, - flip = function (x) - return 1 - x - end, - - easeIn = function (t) - return t * t - end, + easeInOut = function(t) + return lerp(easeIn(t), easeOut(t), t) + end } \ No newline at end of file diff --git a/Basalt/libraries/basaltDraw.lua b/Basalt/libraries/basaltDraw.lua index 554dbf9..9054793 100644 --- a/Basalt/libraries/basaltDraw.lua +++ b/Basalt/libraries/basaltDraw.lua @@ -3,6 +3,7 @@ local sub,rep = string.sub,string.rep return function(drawTerm) local terminal = drawTerm or term.current() + local mirrorTerm local width, height = terminal.getSize() local cacheT = {} local cacheBG = {} @@ -125,6 +126,9 @@ return function(drawTerm) end local drawHelper = { + setMirror = function(mirror) + mirrorTerm = mirror + end, setBG = function(x, y, colorStr) setBG(x, y, colorStr) end; @@ -167,13 +171,24 @@ return function(drawTerm) isBlinking = terminal.getCursorBlink() end terminal.setCursorBlink(false) + if(mirrorTerm~=nil)then terminal.setCursorBlink(false) end for n = 1, height do terminal.setCursorPos(1, n) terminal.blit(cacheT[n], cacheFG[n], cacheBG[n]) + if(mirrorTerm~=nil)then + mirrorTerm.setCursorPos(1, n) + mirrorTerm.blit(cacheT[n], cacheFG[n], cacheBG[n]) + end end terminal.setBackgroundColor(colors.black) terminal.setCursorBlink(isBlinking) terminal.setCursorPos(xC, yC) + if(mirrorTerm~=nil)then + mirrorTerm.setBackgroundColor(colors.black) + mirrorTerm.setCursorBlink(isBlinking) + mirrorTerm.setCursorPos(xC, yC) + end + end; setTerm = function(newTerm) diff --git a/Basalt/libraries/dynamicValues.lua b/Basalt/libraries/dynamicValues.lua new file mode 100644 index 0000000..9604706 --- /dev/null +++ b/Basalt/libraries/dynamicValues.lua @@ -0,0 +1,67 @@ +return function(value, parentF, ...) + local cache + local fList = ... + if(...~=nil)then + if(type(...)~="table")then + fList = table.pack(...) + end + end + + local function numberFromString(str) + return load("return " .. str)() + end + + local function replacePercentage(str, parentValue) + local _fullStr = str + for v in _fullStr:gmatch("%d+%%") do + local pValue = v:gsub("%%", "") + str = str:gsub(v.."%", parentValue / 100 * math.max(math.min(tonumber(pValue),100),0)) + end + return str + end + + local function fToNumber(str) + for k,v in pairs(fList)do + if(type(v)=="function")then + for _ in str:gmatch("f"..k)do + str = string.gsub(str, "f"..k, v()) + end + end + end + return str + end + + local function calculateValue() + if(value~=nil)then + if(type(value)=="string")then + if(fList~=nil and #fList>0)then + cache = math.floor(numberFromString(replacePercentage(fToNumber(value), parentF() or 1))+0.5) + else + cache = math.floor(numberFromString(replacePercentage(value, parentF() or 1))) + end + end + end + return cache + end + + local public = { + getType = function(self) + return "DynamicValue" + end, + + get = function(self) + return cache or calculateValue() + end, + + calculate = function(self) + calculateValue() + return self + end, + + setParent = function(self, p) + parentF = p + return self + end + } + return public +end \ No newline at end of file diff --git a/Basalt/libraries/geometricPoints.lua b/Basalt/libraries/geometricPoints.lua new file mode 100644 index 0000000..01800a2 --- /dev/null +++ b/Basalt/libraries/geometricPoints.lua @@ -0,0 +1,197 @@ +local function line(x1,y1,x2,y2) + local points = {} + if x1 == x2 and y1 == y2 then return {x=x1,y=x2} end + local minX = math.min(x1, x2) + local maxX, minY, maxY + if minX == x1 then minY,maxX,maxY = y1,x2,y2 + else minY,maxX,maxY = y2,x1,y1 end + local xDiff,yDiff = maxX - minX,maxY - minY + if xDiff > math.abs(yDiff) then + local y = minY + local dy = yDiff / xDiff + for x = minX, maxX do + table.insert(points,{x=x,y=math.floor(y + 0.5)}) + y = y + dy + end + else + local x,dx = minX,xDiff / yDiff + if maxY >= minY then + for y = minY, maxY do + table.insert(points,{x=math.floor(x + 0.5),y=y}) + x = x + dx + end + else + for y = minY, maxY, -1 do + table.insert(points,{x=math.floor(x + 0.5),y=y}) + x = x - dx + end + end + end + return points +end + +local function filledCircle(xC, yC, r) + local points = {} + for x=-r, r+1 do + local dy = math.floor(math.sqrt(r*r - x*x)) + for y=-dy, dy+1 do + table.insert(points, {x=xC+x, y=yC+y}) + end + end + return points +end + +local function ellipse(xC, yC, r1, r2, filled) + local rx,ry = math.ceil(math.floor(r1-0.5)/2),math.ceil(math.floor(r2-0.5)/2) + local x,y=0,ry + local d1 = ((ry * ry) - (rx * rx * ry) + (0.25 * rx * rx)) + local dx = 2*ry^2*x + local dy = 2*rx^2*y + local points = {} + while dx < dy do + table.insert(points,{x=x+xC,y=y+yC}) + table.insert(points,{x=-x+xC,y=y+yC}) + table.insert(points,{x=x+xC,y=-y+yC}) + table.insert(points,{x=-x+xC,y=-y+yC}) + if filled then + for y=-y+yC+1,y+yC-1 do + table.insert(points,{x=x+xC,y=y}) + table.insert(points,{x=-x+xC,y=y}) + end + end + if d1 < 0 then + x = x + 1 + dx = dx + 2*ry^2 + d1 = d1 + dx + ry^2 + else + x,y = x+1,y-1 + dx = dx + 2*ry^2 + dy = dy - 2*rx^2 + d1 = d1 + dx - dy + ry^2 + end + end + local d2 = (((ry * ry) * ((x + 0.5) * (x + 0.5))) + ((rx * rx) * ((y - 1) * (y - 1))) - (rx * rx * ry * ry)) + while y >= 0 do + table.insert(points,{x=x+xC,y=y+yC}) + table.insert(points,{x=-x+xC,y=y+yC}) + table.insert(points,{x=x+xC,y=-y+yC}) + table.insert(points,{x=-x+xC,y=-y+yC}) + if filled then + for y=-y+yC,y+yC do + table.insert(points,{x=x+xC,y=y}) + table.insert(points,{x=-x+xC,y=y}) + end + end + if d2 > 0 then + y = y - 1 + dy = dy - 2*rx^2 + d2 = d2 + rx^2 - dy + else + y = y - 1 + x = x + 1 + dy = dy - 2*rx^2 + dx = dx + 2*ry^2 + d2 = d2 + dx - dy + rx^2 + end + end + return points +end + +local function circle(xC, yC, r, filled) + return ellipse(xC, yC, r, r, filled) +end + +return { +circle = function(x, y, radius, filled) + return circle(x, y, radius, filled) +end, + +rectangle = function(x1, y1, x2, y2, filled) + local points = {} + if(filled)then + for y=y1,y2 do + for x=x1,x2 do + table.insert(points, {x=x,y=y}) + end + end + else + for y=y1,y2 do + for x=x1,x2 do + if(x==x1)or(x==x2)or(y==y1)or(y==y2)then + table.insert(points, {x=x,y=y}) + end + end + end + end + return points +end, + +triangle = function(x1, y1, x2, y2, x3, y3, filled) + local function drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3) + local m1 = (x3 - x1) / (y3 - y1) + local m2 = (x3 - x2) / (y3 - y2) + local yStart = math.ceil(y1 - 0.5) + local yEnd = math.ceil(y3 - 0.5)-1 + for y = yStart, yEnd do + local px1 = m1 * (y + 0.5 - y1) + x1 + local px2 = m2 * (y + 0.5 - y2) + x2 + local xStart = math.ceil(px1 - 0.5) + local xEnd = math.ceil(px2 - 0.5) + for x=xStart,xEnd do + table.insert(points,{x=x,y=y}) + end + end + end + + local function drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3) + local m1 = (x2 - x1) / (y2 - y1) + local m2 = (x3 - x1) / (y3 - y1) + local yStart = math.ceil(y1-0.5) + local yEnd = math.ceil(y3-0.5)-1 + for y = yStart, yEnd do + local px1 = m1 * (y + 0.5 - y1) + x1 + local px2 = m2 * (y + 0.5 - y1) + x1 + local xStart = math.ceil(px1 - 0.5) + local xEnd = math.ceil(px2 - 0.5) + for x=xStart,xEnd do + table.insert(points,{x=x,y=y}) + end + end + end + local points = {} + if(filled)then + if y2 < y1 then x1,y1,x2,y2 = x2,y2,x1,y1 end + if y3 < y2 then x2,y2,x3,y3 = x3,y3,x2,y2 end + if y2 < y2 then x1,y1,x2,y2 = x2,y2,x1,y1 end + if y1 == y2 then + if x2 < x1 then x1,y1,x2,y2 = x2,y2,x1,y1 end + drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3) + elseif y2 == y3 then + if x3 < x2 then x3,y3,x2,y2 = x2,y2,x3,y3 end + drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3) + else + local alphaSplit = (y2-y1)/(y3-y1) + local x = x1 + ((x3 - x1) * alphaSplit) + local y = y1 + ((y3 - y1) * alphaSplit) + if x2 < x then + drawFlatBottomTriangle(points,x1,y1,x2,y2,x, y) + drawFlatTopTriangle(points,x2,y2,x,y,x3,y3) + else + drawFlatBottomTriangle(points,x1,y1,x,y,x1,y1) + drawFlatTopTriangle(points,x,y,x2,y2,x3,y3) + end + end + else + points = line(x1,y1,x2,y2) + for k,v in pairs(line(x2,y2,x3,y3))do table.insert(points, v) end + for k,v in pairs(line(x3,y3,x1,y1))do table.insert(points, v) end + end + return points +end, + +line = line, + +ellipse = function(xCenter, yCenter, radius1, radius2, filled) + return ellipse(xCenter, yCenter, radius1, radius2, filled) +end +} \ No newline at end of file diff --git a/Basalt/libraries/layout.lua b/Basalt/libraries/layout.lua index e69de29..ee29437 100644 --- a/Basalt/libraries/layout.lua +++ b/Basalt/libraries/layout.lua @@ -0,0 +1,147 @@ +local function newNode(name) + local node = {} + node.___value = nil + node.___name = name + node.___children = {} + node.___props = {} + + 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[name] }) + 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:ParseArgs(node, s) + string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a) + node:addProperty(w, self:FromXmlString(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:ParseArgs(lNode, xarg) + top:addChild(lNode) + elseif c == "" then -- start tag + local lNode = newNode(label) + self:ParseArgs(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 + +function XmlParser:loadFile(xmlFilename, base) + if not base then + base = system.ResourceDirectory + end + + local path = system.pathForFile(xmlFilename, base) + local hFile, err = io.open(path, "r"); + + if hFile and not err then + local xmlText = hFile:read("*a"); -- read file content + io.close(hFile); + return self:ParseXmlText(xmlText), nil; + else + print(err) + return nil + end +end + +return XmlParser \ No newline at end of file diff --git a/Basalt/libraries/utils.lua b/Basalt/libraries/utils.lua index 195b254..06c4657 100644 --- a/Basalt/libraries/utils.lua +++ b/Basalt/libraries/utils.lua @@ -48,130 +48,41 @@ splitString = function(str, sep) return t end, +getValueFromXML = 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, + numberFromString = function(str) - print(str) return load("return " .. str)() end, --- shrink system is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/ -shrink = function(bLittleData, bgColor) - local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 }, - { 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } } - - local colourNum, exponents, colourChar = {}, {}, {} - for i = 0, 15 do - exponents[2 ^ i] = i +uuid = function() + local random = math.random + local function uuid() + local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + return string.gsub(template, '[xy]', function (c) + local v = (c == 'x') and random(0, 0xf) or random(8, 0xb) + return string.format('%x', v) + end) end - do - local hex = "0123456789abcdef" - for i = 1, 16 do - colourNum[hex:sub(i, i)] = i - 1 - colourNum[i - 1] = hex:sub(i, i) - colourChar[hex:sub(i, i)] = 2 ^ (i - 1) - colourChar[2 ^ (i - 1)] = hex:sub(i, i) - - local thisRel = relations[i - 1] - for i = 1, #thisRel do - thisRel[i] = 2 ^ thisRel[i] - end - end - end - - local function getBestColourMatch(usage) - local lastCol = relations[exponents[usage[#usage][1]]] - if(lastCol~=nil)then - for j = 1, #lastCol do - local thisRelation = lastCol[j] - for i = 1, #usage - 1 do - if usage[i][1] == thisRelation then - return i - end - end - end - end - return 1 - end - - local function colsToChar(pattern, totals) - if not totals then - local newPattern = {} - totals = {} - for i = 1, 6 do - local thisVal = pattern[i] - local thisTot = totals[thisVal] - totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal - end - pattern = newPattern - end - - local usage = {} - for key, value in pairs(totals) do - usage[#usage + 1] = { key, value } - end - - if #usage > 1 then - -- Reduce the chunk to two colours: - while #usage > 2 do - table.sort(usage, function(a, b) - return a[2] > b[2] - end) - local matchToInd, usageLen = getBestColourMatch(usage), #usage - local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1] - for i = 1, 6 do - if pattern[i] == matchFrom then - pattern[i] = matchTo - usage[matchToInd][2] = usage[matchToInd][2] + 1 - end - end - usage[usageLen] = nil - end - - -- Convert to character. Adapted from oli414's function: - -- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/ - local data = 128 - for i = 1, #pattern - 1 do - if pattern[i] ~= pattern[6] then - data = data + 2 ^ (i - 1) - end - end - return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]] - else - -- Solid colour character: - return "\128", colourChar[pattern[1]], colourChar[pattern[1]] - end - end - - local results, width, height, bgCol = { {}, {}, {} }, 0, #bLittleData + #bLittleData % 3, bgColor or colors.black - for i = 1, #bLittleData do - if #bLittleData[i] > width then - width = #bLittleData[i] - end - end - - for y = 0, height - 1, 3 do - local cRow, tRow, bRow, counter = {}, {}, {}, 1 - - for x = 0, width - 1, 2 do - -- Grab a 2x3 chunk: - local pattern, totals = {}, {} - - for yy = 1, 3 do - for xx = 1, 2 do - pattern[#pattern + 1] = (bLittleData[y + yy] and bLittleData[y + yy][x + xx]) and (bLittleData[y + yy][x + xx] == 0 and bgCol or bLittleData[y + yy][x + xx]) or bgCol - totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1 - end - end - - cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals) - counter = counter + 1 - end - - results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow) - end - - results.width, results.height = #results[1][1], #results[1] - - return results + return uuid() end, - } \ No newline at end of file diff --git a/Basalt/loadObjects.lua b/Basalt/loadObjects.lua index bbbd155..bb600dd 100644 --- a/Basalt/loadObjects.lua +++ b/Basalt/loadObjects.lua @@ -5,7 +5,14 @@ if(packaged)then end return _OBJECTS end -for _,v in pairs(fs.list(fs.combine("Basalt", "objects")))do + +local args = table.pack(...) +local dir = fs.getDir(args[2] or "Basalt") +if(dir==nil)then + error("Unable to find directory "..args[2].." please report this bug to our discord.") +end + +for _,v in pairs(fs.list(fs.combine(dir, "objects")))do if(v~="example.lua")then local name = v:gsub(".lua", "") _OBJECTS[name] = require(name) diff --git a/Basalt/main.lua b/Basalt/main.lua index 82cdcdf..7d3d554 100644 --- a/Basalt/main.lua +++ b/Basalt/main.lua @@ -1,28 +1,50 @@ local basaltEvent = require("basaltEvent")() local Frame = require("Frame") +local theme = require("theme") +local uuid = require("utils").uuid local baseTerm = term.current() -local version = 3 +local version = 4 local debugger = true local projectDirectory = fs.getDir(table.pack(...)[2] or "") -local activeKey, frames, monFrames = {}, {}, {} +local activeKey, frames, monFrames, variables = {}, {}, {}, {} local mainFrame, activeFrame, focusedObject, updaterActive if not term.isColor or not term.isColor() then - error('Basalt requires an advanced (golden) comptuer to run.', 0) + error('Basalt requires an advanced (golden) computer to run.', 0) end local function stop() updaterActive = false end +local setVariable = function(name, var) + variables[name] = var +end + +local getVariable = function(name) + return variables[name] +end + +local setTheme = function(_theme) + theme = _theme +end + +local getTheme = function(name) + return theme[name] +end + local bInstance = { getMainFrame = function() return mainFrame end, + setVariable = setVariable, + getVariable = getVariable, + getTheme = getTheme, + setMainFrame = function(mFrame) mainFrame = mFrame end, @@ -64,13 +86,15 @@ local bInstance = { } local function drawFrames() - if(mainFrame~=nil)then - mainFrame:draw() - mainFrame:drawUpdate() - end - for _,v in pairs(monFrames)do - v:draw() - v:drawUpdate() + if(updaterActive)then + if(mainFrame~=nil)then + mainFrame:draw() + mainFrame:drawUpdate() + end + for _,v in pairs(monFrames)do + v:draw() + v:drawUpdate() + end end end @@ -89,18 +113,19 @@ local function basaltUpdateEvent(event, p1, p2, p3, p4) elseif (event == "mouse_scroll") then mainFrame:mouseHandler(event, p1, p2, p3, p4) activeFrame = mainFrame - end - end - if (event == "monitor_touch") then - if(monFrames[p1]~=nil)then - monFrames[p1]:mouseHandler(event, p1, p2, p3, p4) - activeFrame = monFrames[p1] + elseif (event == "monitor_touch") then + if(monFrames[p1]~=nil)then + monFrames[p1]:mouseHandler(event, p1, p2, p3, p4) + activeFrame = monFrames[p1] + end end end if(event == "key") or (event == "char") then - activeFrame:keyHandler(event, p1) - activeFrame:backgroundKeyHandler(event, p1) + if(activeFrame~=nil)then + activeFrame:keyHandler(event, p1) + activeFrame:backgroundKeyHandler(event, p1) + end end if(event == "key")then @@ -119,10 +144,15 @@ end local basalt = {} basalt = { + setTheme = setTheme, + getTheme = getTheme, getVersion = function() return version end, + setVariable = setVariable, + getVariable = getVariable, + setBaseTerm = function(_baseTerm) baseTerm = _baseTerm end, @@ -179,6 +209,7 @@ basalt = { end, createFrame = function(name) + name = name or uuid() for _, v in pairs(frames) do if (v.name == name) then return nil @@ -186,6 +217,9 @@ basalt = { end local newFrame = Frame(name,nil,nil,bInstance) table.insert(frames, newFrame) + if(mainFrame==nil)and(newFrame:getName()~="basaltDebuggingFrame")then + newFrame:show() + end return newFrame end, @@ -222,7 +256,7 @@ basalt = { } basalt.debugFrame = basalt.createFrame("basaltDebuggingFrame"):showBar():setBackground(colors.lightGray):setBar("Debug", colors.black, colors.gray) -basalt.debugFrame:addButton("back"):setAnchor("topRight"):setSize(1, 1):setText("\22"):onClick(function() basalt.oldFrame:show() end):setBackground(colors.red):show() +basalt.debugFrame:addButton("back"):setAnchor("topRight"):setSize(1, 1):setText("\22"):onClick(function() if(basalt.oldFrame~=nil)then basalt.oldFrame:show() end end):setBackground(colors.red):show() basalt.debugList = basalt.debugFrame:addList("debugList"):setSize(basalt.debugFrame.width - 2, basalt.debugFrame.height - 3):setPosition(2, 3):setScrollable(true):show() basalt.debugLabel = basalt.debugFrame:addLabel("debugLabel"):onClick(function() basalt.oldFrame = mainFrame basalt.debugFrame:show() end):setBackground(colors.black):setForeground(colors.white):setAnchor("bottomLeft"):ignoreOffset():setZIndex(20):show() diff --git a/Basalt/objects/Animation.lua b/Basalt/objects/Animation.lua index 0006ef0..70bf9cb 100644 --- a/Basalt/objects/Animation.lua +++ b/Basalt/objects/Animation.lua @@ -1,4 +1,36 @@ -local lerp = require("Lerp") + +local xmlValue = require("utils").getValueFromXML +local basaltEvent = require("basaltEvent") + +local floor = math.floor + +local lerp = function(s, e, pct) + return s + (e - s) * pct +end + +local flip = function (x) + return 1 - x +end + +local easeIn = function (t) + return t * t * t +end + +local easeOut = function(t) + return flip(easeIn(flip(t))) +end + +local easeInOut = function(t) + return lerp(easeIn(t), easeOut(t), t) +end + +local lerp = { + lerp = lerp, + flip=flip, + easeIn=easeIn, + easeOut=easeOut, + easeInOut=easeInOut, +} return function(name) local object = {} @@ -7,39 +39,209 @@ return function(name) local timerObj local animations = {} + local animationTime = 0 local index = 1 local infinitePlay = false + local eventSystem = basaltEvent() + local nextWaitTimer = 0 local lastFunc + local loop=false local _OBJ - local function onPlay() + local function call(tab) + for k,v in pairs(tab)do + v(object, animations[index].t, index) + end + end + + local function onPlay(self) if (animations[index] ~= nil) then - animations[index].f(object, index) + call(animations[index].f) + animationTime = animations[index].t end index = index + 1 if(animations[index]==nil)then if(infinitePlay)then index = 1 + animationTime = 0 else + self:animationDoneHandler() return end end if (animations[index].t > 0) then - timerObj = os.startTimer(animations[index].t) + timerObj = os.startTimer(animations[index].t - animationTime) else - onPlay() + onPlay(self) end end + local function addAnimationPart(time, f) + for n=1,#animations do + if(animations[n].t==time)then + table.insert(animations[n].f, f) + return + end + end + for n=1,#animations do + if(animations[n].t>time)then + if(animations[n-1]~=nil)then + if(animations[n-1].t0)then + self:changeFG(duration, timer or 0, table.unpack(t)) + end + end + if(data["backgroundColor"]~=nil)then + local duration = xmlValue("duration", data["backgroundColor"]) + local timer = xmlValue("time", data["backgroundColor"]) + local t = {} + local tab = data["backgroundColor"]["color"] + if(tab~=nil)then + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + table.insert(t, colors[v:value()]) + end + end + if(duration~=nil)and(#t>0)then + self:changeBG(duration, timer or 0, table.unpack(t)) + end + end + if(data["text"]~=nil)then + local duration = xmlValue("duration", data["text"]) + local timer = xmlValue("time", data["text"]) + local t = {} + local tab = data["text"]["text"] + if(tab~=nil)then + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + table.insert(t, v:value()) + end + end + if(duration~=nil)and(#t>0)then + self:changeText(duration, timer or 0, table.unpack(t)) + end + end + if(xmlValue("onDone", data)~=nil)then + local value = xmlValue("onDone", data) + if(value:sub(1,1)=="#")then + value = xmlValue("onDone", data):sub(2,value:len()) + local o = self:getBaseFrame():getDeepObject(value) + if(o~=nil)then + self:onAnimationDone(function()o:internalObjetCall()end) + end + else + local f = self:getBaseFrame():getVariable(value) + if(f~=nil)then + self:onAnimationDone(f) + end + end + end + if(xmlValue("autoRemove", data)~=nil)then + if(xmlValue("autoRemove", data)~=false)then + self:onAnimationDone(function() self.parent:removeObject(self) end) + end + else + self:onAnimationDone(function() self.parent:removeObject(self) end) + end + + if(xmlValue("play", data)~=nil)then if(xmlValue("play", data))then self:play(loop) end end + return self + end, + getZIndex = function(self) return 1 end; @@ -48,138 +250,68 @@ return function(name) return self.name end; - add = function(self, func, wait) - lastFunc = func - table.insert(animations, { f = func, t = wait or nextWaitTimer }) - return self - end; - setObject = function(self, obj) _OBJ = obj return self end; - move = function(self, x, y, time, frames, obj) - if(obj~=nil)then - _OBJ = obj - end - if(_OBJ.setPosition==nil)or(_OBJ.getPosition==nil)then return self end - local oX,oY = _OBJ:getPosition() - if(oX==x)and(oY==y)then return self end - - local xAdd = oX<=x and (x-oX)/frames or (oX-x)/frames - local yAdd = oY<=y and (y-oY)/frames or (oY-y)/frames - local xInverted,yInverted = oX>x and true or false, oY>y and true or false - - for n=1, math.floor(frames) do - local f - if(n==frames)then - f = function() - _OBJ:setPosition(x, y) - end - else - f = function() - _OBJ:setPosition(math.floor(xInverted and oX+(-xAdd*n) or oX+xAdd*n), math.floor(yInverted and oY+(-yAdd*n) or oY+yAdd*n)) - end - end - table.insert(animations, { f = f, t = time/frames}) - end + move = function(self, x, y, duration, timer, obj) + _OBJ = obj or _OBJ + predefinedLerp(x,y,duration,timer or 0,_OBJ.getPosition,_OBJ.setPosition) return self - end; - - moveLerp = function(self, x, y, time, obj) - end, - offset = function(self, x, y, time, frames, obj) - if(obj~=nil)then - _OBJ = obj - end - if(_OBJ.setOffset==nil)or(_OBJ.getOffset==nil)then return self end - local oX,oY = _OBJ:getOffset() - oX = math.abs(oX) - oY = math.abs(oY) - - if(oX==x)and(oY==y)then return self end + offset = function(self, x, y, duration, timer, obj) + _OBJ = obj or _OBJ + predefinedLerp(x,y,duration,timer or 0,_OBJ.getOffset,_OBJ.setOffset) + return self + end, - local xAdd = oX<=x and (x-oX)/frames or (oX-x)/frames - local yAdd = oY<=y and (y-oY)/frames or (oY-y)/frames - local xInverted,yInverted = oX>x and true or false, oY>y and true or false + size = function(self, w, h, duration, timer, obj) + _OBJ = obj or _OBJ + predefinedLerp(w,h,duration,timer or 0,_OBJ.getSize,_OBJ.setSize) + return self + end, - for n=1, math.floor(frames) do - local f - if(n==frames)then - f = function() - _OBJ:setOffset(x, y) - end - else - f = function() - _OBJ:setOffset(math.floor(xInverted and oX+(-xAdd*n) or oX+xAdd*n), math.floor(yInverted and oY+(-yAdd*n) or oY+yAdd*n)) - end - end - table.insert(animations, { f = f, t = time/frames}) + changeText = function(self, duration, timer, ...) + local text = {...} + timer = timer or 0 + _OBJ = obj or _OBJ + for n=1,#text do + addAnimationPart(timer+n*(duration/#text), function() + _OBJ.setText(_OBJ, text[n]) + end) end return self - end; + end, - textColoring = function(self, time, ...) - local colors = table.pack(...) - for n=1, #colors do - table.insert(animations, { f = function() - _OBJ:setForeground(colors[n]) - end, t = time/#colors}) + changeBG = function(self, duration, timer, ...) + local colors = {...} + timer = timer or 0 + _OBJ = obj or _OBJ + for n=1,#colors do + addAnimationPart(timer+n*(duration/#colors), function() + _OBJ.setBackground(_OBJ, colors[n]) + end) end return self - end; + end, - backgroundColoring = function(self, time, ...) - local colors = table.pack(...) - for n=1, #colors do - table.insert(animations, { f = function() - _OBJ:setBackground(colors[n]) - end, t = time/#colors}) + changeFG = function(self, duration, timer, ...) + local colors = {...} + timer = timer or 0 + _OBJ = obj or _OBJ + for n=1,#colors do + addAnimationPart(timer+n*(duration/#colors), function() + _OBJ.setForeground(_OBJ, colors[n]) + end) end return self - end; + end, - setText = function(self, time, text) - if(_OBJ.setText~=nil)then - for n=1, text:len() do - table.insert(animations, { f = function() - _OBJ:setText(text:sub(1,n)) - end, t = time/text:len()}) - end - end - return self - end; - - changeText = function(self, time, ...) - if(_OBJ.setText~=nil)then - local text = table.pack(...) - for n=1, #text do - table.insert(animations, { f = function() - _OBJ:setText(text[n]) - end, t = time/#text}) - end - end - return self - end; - - coloring = function(self, time, ...) - local colors = table.pack(...) - for n=1, #colors do - if(type(colors[n]=="table"))then - table.insert(animations, { f = function() - if(colors[n][1]~=nil)then - _OBJ:setBackground(colors[n][1]) - end - if(colors[n][2]~=nil)then - _OBJ:setForeground(colors[n][2]) - end - end, t = time/#colors}) - - end - end + add = function(self, func, wait) + lastFunc = func + addAnimationPart((wait or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), func) return self end; @@ -189,44 +321,68 @@ return function(name) end; rep = function(self, reps) - for n = 1, reps do - table.insert(animations, { f = lastFunc, t = nextWaitTimer }) + if(lastFunc~=nil)then + for n = 1, reps or 1 do + addAnimationPart((wait or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), lastFunc) + end end return self end; + onAnimationDone = function(self, f) + eventSystem:registerEvent("animation_done", f) + return self + end, + + animationDoneHandler = function(self) + eventSystem:sendEvent("animation_done", self) + end; + clear = function(self) animations = {} lastFunc = nil nextWaitTimer = 0 index = 1 + animationTime = 0 infinitePlay = false return self end; play = function(self, infinite) + self:cancel() infinitePlay = infinite and true or false index = 1 + animationTime = 0 if (animations[index] ~= nil) then if (animations[index].t > 0) then timerObj = os.startTimer(animations[index].t) else onPlay() end + else + self:animationDoneHandler() end return self end; cancel = function(self) - os.cancelTimer(timerObj) - infinitePlay = false + if(timerObj~=nil)then + os.cancelTimer(timerObj) + infinitePlay = false + end return self end; + internalObjetCall = function(self) + self:play(loop) + end, + eventHandler = function(self, event, tObj) if (event == "timer") and (tObj == timerObj) then if (animations[index] ~= nil) then - onPlay() + onPlay(self) + else + self:animationDoneHandler() end end end; diff --git a/Basalt/objects/Button.lua b/Basalt/objects/Button.lua index c2fd581..5c030d9 100644 --- a/Basalt/objects/Button.lua +++ b/Basalt/objects/Button.lua @@ -1,22 +1,24 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML return function(name) -- Button local base = Object(name) local objectType = "Button" - - base:setValue("Button") - base:setZIndex(5) - base.width = 8 - base.bgColor = theme.ButtonBG - base.fgColor = theme.ButtonFG - local textHorizontalAlign = "center" local textVerticalAlign = "center" + base:setZIndex(5) + base:setValue("Button") + base.width = 12 + base.height = 3 + local object = { + init = function(self) + self.bgColor = self.parent:getTheme("ButtonBG") + self.fgColor = self.parent:getTheme("ButtonText") + end, getType = function(self) return objectType end; @@ -33,6 +35,14 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end + if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end + if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end + return self + end, + draw = function(self) if (base.draw(self)) then if (self.parent ~= nil) then diff --git a/Basalt/objects/Checkbox.lua b/Basalt/objects/Checkbox.lua index 9956309..15335b3 100644 --- a/Basalt/objects/Checkbox.lua +++ b/Basalt/objects/Checkbox.lua @@ -1,6 +1,6 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML return function(name) -- Checkbox @@ -11,12 +11,15 @@ return function(name) base:setValue(false) base.width = 1 base.height = 1 - base.bgColor = theme.CheckboxBG - base.fgColor = theme.CheckboxFG local object = { symbol = "\42", + init = function(self) + self.bgColor = self.parent:getTheme("CheckboxBG") + self.fgColor = self.parent:getTheme("CheckboxText") + end, + getType = function(self) return objectType end; @@ -35,19 +38,25 @@ return function(name) return false end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("checked", data)~=nil)then if(xmlValue("checked", data))then self:setValue(true) else self:setValue(false) end end + return self + end, + draw = function(self) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - local verticalAlign = utils.getTextVerticalAlign(self.height, "center") - - if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end - for n = 1, self.height do + local w,h = self:getSize() + local verticalAlign = utils.getTextVerticalAlign(h, "center") + if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end + for n = 1, h do if (n == verticalAlign) then if (self:getValue() == true) then - self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self.symbol, self.width, "center"), self.bgColor, self.fgColor) + self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self.symbol, w, "center"), self.bgColor, self.fgColor) else - self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", self.width, "center"), self.bgColor, self.fgColor) + self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", w, "center"), self.bgColor, self.fgColor) end end end diff --git a/Basalt/objects/Dropdown.lua b/Basalt/objects/Dropdown.lua index 30778cf..3c288d6 100644 --- a/Basalt/objects/Dropdown.lua +++ b/Basalt/objects/Dropdown.lua @@ -1,19 +1,17 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = require("utils").getValueFromXML return function(name) local base = Object(name) local objectType = "Dropdown" base.width = 12 base.height = 1 - base.bgColor = theme.dropdownBG - base.fgColor = theme.dropdownFG base:setZIndex(6) local list = {} - local itemSelectedBG = theme.selectionBG - local itemSelectedFG = theme.selectionFG + local itemSelectedBG + local itemSelectedFG local selectionColorActive = true local align = "left" local yOffset = 0 @@ -28,13 +26,35 @@ return function(name) getType = function(self) return objectType end; + init = function(self) + self.bgColor = self.parent:getTheme("DropdownBG") + self.fgColor = self.parent:getTheme("DropdownText") + itemSelectedBG = self.parent:getTheme("SelectionBG") + itemSelectedFG = self.parent:getTheme("SelectionText") + end, - setIndexOffset = function(self, yOff) + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end + if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end + if(xmlValue("dropdownWidth", data)~=nil)then dropdownW = xmlValue("dropdownWidth", data) end + if(xmlValue("dropdownHeight", data)~=nil)then dropdownH = xmlValue("dropdownHeight", data) end + if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end + if(data["item"]~=nil)then + local tab = data["item"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)]) + end + end + end, + + setOffset = function(self, yOff) yOffset = yOff return self end; - getIndexOffset = function(self) + getOffset = function(self) return yOffset end; @@ -126,7 +146,7 @@ return function(name) yOffset = #list - dropdownH end else - yOffset = list - 1 + yOffset = math.min(#list - 1, 0) end end return true @@ -143,10 +163,11 @@ return function(name) draw = function(self) if (base.draw(self)) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if (self.parent ~= nil) then - if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end + if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local val = self:getValue() - local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), self.width, align):sub(1, self.width - 1) .. (isOpened and openedSymbol or closedSymbol) + local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), w, align):sub(1, w - 1) .. (isOpened and openedSymbol or closedSymbol) self.parent:writeText(obx, oby, text, self.bgColor, self.fgColor) if (isOpened) then diff --git a/Basalt/objects/Graphic.lua b/Basalt/objects/Graphic.lua index 4395297..52be81d 100644 --- a/Basalt/objects/Graphic.lua +++ b/Basalt/objects/Graphic.lua @@ -1,6 +1,9 @@ local Object = require("Object") -local geometric = require("geometric") +local geometric = require("geometricPoints") local tHex = require("tHex") +local xmlValue = require("utils").getValueFromXML + +local sub,len,max,min = string.sub,string.len,math.max,math.min return function(name) -- Graphic @@ -8,40 +11,455 @@ return function(name) local objectType = "Graphic" base:setZIndex(2) + local graphicObjects = {} local graphic = {} - local graphicCache = {} + local shrinkedGraphic = {} + local isGraphicShrinked = false + local xOffset, yOffset = 0, 0 + local dragable = false + local xMouse,yMouse + local w, h = 40, 15 + local canvasSizeChanged = false + + local tColourLookup = {} + for n=1,16 do + tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1) + end + + local function stringToTable(str) + local t = {} + for i = 1, #str do + t[i] = str:sub(i, i) + end + return t + end + + local function setBG(x, y, width, height, colorStr) + if (y >= 1) and (y <= height) then + if (x + len(colorStr) > 0) and (x <= width) then + local oldCache = graphic[y] + local newCache + local nEnd = x + #colorStr - 1 + + if (x < 1) then + colorStr = sub(colorStr, 1 - x + 1, width - x + 1) + elseif (nEnd > width) then + colorStr = sub(colorStr, 1, width - x + 1) + end + + if (x > 1) then + newCache = sub(oldCache, 1, x - 1) .. colorStr + else + newCache = colorStr + end + if nEnd < width then + newCache = newCache .. sub(oldCache, nEnd + 1, width) + end + graphic[y] = newCache + end + end + end + + local function redrawCanvasSize() + local w,h = w,h + if(isGraphicShrinked)then w = w*2 h = h*3 end + for y=1,h do + if(graphic[y]~=nil)then + if(w>graphic[y]:len())then + graphic[y] = graphic[y]..(tHex[base.bgColor]):rep(w-graphic[y]:len()) + else + graphic[y] = graphic[y]:sub(1,w) + end + else + graphic[y] = (tHex[base.bgColor]):rep(w) + end + end + end + redrawCanvasSize() + + + local function shrink() + local function parseLine( tImageArg, sLine ) + local tLine = {} + for x=1,sLine:len() do + tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0 + end + table.insert( tImageArg, tLine ) + end + function parseImage( sRawData ) + if type( sRawData ) ~= "string" then + error( "bad argument #1 (expected string, got " .. type( sRawData ) .. ")" ) + end + local tImage = {} + for sLine in ( sRawData .. "\n" ):gmatch( "(.-)\n" ) do + parseLine( tImage, sLine ) + end + return tImage + end + + local rawImg = "" + for y=1,#graphic do + if(y==#graphic)then + rawImg = rawImg..graphic[y] + else + rawImg = rawImg..graphic[y].."\n" + end + end + local img = parseImage(rawImg) + -- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/ + local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 }, + { 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } } + + local colourNum, exponents, colourChar = {}, {}, {} + for i = 0, 15 do + exponents[2 ^ i] = i + end + do + local hex = "0123456789abcdef" + for i = 1, 16 do + colourNum[hex:sub(i, i)] = i - 1 + colourNum[i - 1] = hex:sub(i, i) + colourChar[hex:sub(i, i)] = 2 ^ (i - 1) + colourChar[2 ^ (i - 1)] = hex:sub(i, i) + + local thisRel = relations[i - 1] + for i = 1, #thisRel do + thisRel[i] = 2 ^ thisRel[i] + end + end + end + + local function getBestColourMatch(usage) + local lastCol = relations[exponents[usage[#usage][1]]] + + for j = 1, #lastCol do + local thisRelation = lastCol[j] + for i = 1, #usage - 1 do + if usage[i][1] == thisRelation then + return i + end + end + end + + return 1 + end + + local function colsToChar(pattern, totals) + if not totals then + local newPattern = {} + totals = {} + for i = 1, 6 do + local thisVal = pattern[i] + local thisTot = totals[thisVal] + totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal + end + pattern = newPattern + end + + local usage = {} + for key, value in pairs(totals) do + usage[#usage + 1] = { key, value } + end + + if #usage > 1 then + -- Reduce the chunk to two colours: + while #usage > 2 do + table.sort(usage, function(a, b) + return a[2] > b[2] + end) + local matchToInd, usageLen = getBestColourMatch(usage), #usage + local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1] + for i = 1, 6 do + if pattern[i] == matchFrom then + pattern[i] = matchTo + usage[matchToInd][2] = usage[matchToInd][2] + 1 + end + end + usage[usageLen] = nil + end + + -- Convert to character. Adapted from oli414's function: + -- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/ + local data = 128 + for i = 1, #pattern - 1 do + if pattern[i] ~= pattern[6] then + data = data + 2 ^ (i - 1) + end + end + return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]] + else + -- Solid colour character: + return "\128", colourChar[pattern[1]], colourChar[pattern[1]] + end + end + + local results, width, height, bgCol = { {}, {}, {} }, 0, #img + #img % 3, base.bgColor or colors.black + for i = 1, #img do + if #img[i] > width then + width = #img[i] + end + end + + for y = 0, height - 1, 3 do + local cRow, tRow, bRow, counter = {}, {}, {}, 1 + + for x = 0, width - 1, 2 do + -- Grab a 2x3 chunk: + local pattern, totals = {}, {} + + for yy = 1, 3 do + for xx = 1, 2 do + pattern[#pattern + 1] = (img[y + yy] and img[y + yy][x + xx]) and (img[y + yy][x + xx] == 0 and bgCol or img[y + yy][x + xx]) or bgCol + totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1 + end + end + + cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals) + counter = counter + 1 + end + + results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow) + end + + results.width, results.height = #results[1][1], #results[1] + + shrinkedGraphic = results + end + + local function redraw() + local w,h = w,h + if(isGraphicShrinked)then w = w*2 h = h*3 end + for k,v in pairs(graphicObjects)do + for a,b in pairs(v[1])do + setBG(b.x, b.y, w, h, v[2]) + end + end + if(isGraphicShrinked)then + shrink() + end + end local object = { + init = function(self) + self.bgColor = self.parent:getTheme("GraphicBG") + end, + getType = function(self) return objectType end; - addCircle = function(self, rad, color, x, y, filled) - table.insert(graphic, {area=geometric.circle(x or 1, y or 1, rad, filled), color=color}) + setSize = function(self, width, height, rel) + base.setSize(self, width, height, rel) + if not(canvasSizeChanged)then + w = width + h = height + redrawCanvasSize() + end + redraw() + return self + end, + + setOffset = function(self, x, y) + xOffset = x or xOffset + yOffset = y or yOffset + return self + end, + + setCanvasSize = function(self, width, height) + w,h = width,height + canvasSizeChanged = true + redrawCanvasSize() + return self + end, + + clearCanvas = function(self) + graphicObjects = {} + graphic = {} + redrawCanvasSize() + end, + + getOffset = function(self) + return xOffset,yOffset + end, + + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end + if(xmlValue("xOffset", data)~=nil)then self:setOffset(xmlValue("xOffset", data), yOffset) end + if(xmlValue("yOffset", data)~=nil)then self:setOffset(xOffset, xmlValue("yOffset", data)) end + if(xmlValue("wCanvas", data)~=nil)then w = xmlValue("wCanvas", data) end + if(xmlValue("hCanvas", data)~=nil)then h = xmlValue("hCanvas", data) end + if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end + if(xmlValue("dragable", data)~=nil)then if(xmlValue("dragable", data))then dragable = true end end + if(data["ellipse"]~=nil)then + local tab = data["ellipse"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + local col = colors[xmlValue("color", v)] + local rad1 = xmlValue("radius", v) + local rad2 = xmlValue("radius2", v) + local x = xmlValue("x", v) + local y = xmlValue("y", v) + local filled = xmlValue("filled", v) + self:addEllipse(col, rad1, rad2, x, y, filled) + end + end + if(data["circle"]~=nil)then + local tab = data["circle"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + local col = colors[xmlValue("color", v)] + local rad = tonumber(xmlValue("radius", v)) + local x = tonumber(xmlValue("x", v)) + local y = tonumber(xmlValue("y", v)) + local filled = xmlValue("filled", v) + self:addCircle(col, rad, x, y, filled) + end + end + if(data["line"]~=nil)then + local tab = data["line"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + local col = colors[xmlValue("color", v)] + local x = tonumber(xmlValue("x", v)) + local x2 = tonumber(xmlValue("x2", v)) + local y = tonumber(xmlValue("y", v)) + local y2 = tonumber(xmlValue("y2", v)) + self:addLine(col, x, y, x2, y2) + end + end + + if(data["rectangle"]~=nil)then + local tab = data["rectangle"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + local col = colors[xmlValue("color", v)] + local x = tonumber(xmlValue("x", v)) + local x2 = tonumber(xmlValue("x2", v)) + local y = tonumber(xmlValue("y", v)) + local y2 = tonumber(xmlValue("y2", v)) + local filled = xmlValue("filled", v)=="true" and true or false + self:addRectangle(col, x, y, x2, y2, filled) + end + end + if(data["triangle"]~=nil)then + local tab = data["triangle"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + local col = colors[xmlValue("color", v)] + local x = tonumber(xmlValue("x", v)) + local x2 = tonumber(xmlValue("x2", v)) + local x3 = tonumber(xmlValue("x2", v)) + local y = tonumber(xmlValue("y", v)) + local y2 = tonumber(xmlValue("y2", v)) + local y3 = tonumber(xmlValue("y3", v)) + local filled = xmlValue("filled", v) + self:addTriangle(col, x, y, x2, y2, x3, y3, filled) + end + end + + return self + end, + + addCircle = function(self, color, rad, x, y, filled) + local col = tHex[color] + table.insert(graphicObjects, {geometric.circle(x or 1, y or 1, rad, filled), tHex[color]}) + redraw() return self end; - addElipse = function(self, rad,rad2, color, x, y, filled) - table.insert(graphic, {area=geometric.elipse(x or 1, y or 1, rad, rad2, filled), color=color}) + addEllipse = function(self, color, rad, rad2, x, y, filled) + table.insert(graphicObjects, {geometric.ellipse(x or 1, y or 1, rad, rad2, filled), tHex[color]}) + redraw() return self end; + addLine = function(self, color, x1, y1, x2, y2) + table.insert(graphicObjects, {geometric.line(x1 or 1, y1 or 1, x2 or 1, y2 or 1), tHex[color]}) + redraw() + return self + end; + + addTriangle = function(self, color, x1, y1, x2, y2, x3, y3, filled) + table.insert(graphicObjects, {geometric.triangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, x3 or 1, y3 or 1, filled), tHex[color]}) + redraw() + return self + end; + + addRectangle = function(self, color, x1, y1, x2, y2, filled) + table.insert(graphicObjects, {geometric.rectangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, filled), tHex[color]}) + redraw() + return self + end; + + shrink = function(self) + isGraphicShrinked = true + redrawCanvasSize() + shrink() + return self + end, + + setDragable = function(self, drag) + dragable = drag == true and true or false + return self + end, + + mouseHandler = function(self, event, button, x, y) + if(base.mouseHandler(self, event, button, x, y))then + if(dragable)then + if(event=="mouse_click")then + xMouse,yMouse = x,y + end + + if(event=="mouse_drag")then + if(xMouse~=nil)and(yMouse~=nil)then + xOffset = max(min(xOffset+xMouse-x, w-self:getWidth()),0) + xMouse = x + yOffset = max(min(yOffset+yMouse-y, h-self:getHeight()),0) + yMouse = y + end + end + end + return true + end + return false + end, + draw = function(self) if (base.draw(self)) then if (self.parent ~= nil) then - if(#graphic>0)then - local obx, oby = self:getAnchorPosition() - if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) - end - for _,v in pairs(graphic)do - local col = tHex[v.color] - for _,b in pairs(v.area)do - if(b.x>=1)and(b.x<=self.width)and(b.y>=1)and(b.y<=self.height)then - self.parent:setBG(obx+b.x-1, oby+b.y-1, col) + local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() + if(self.bgColor~=false)then + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) + end + if (isGraphicShrinked) then + -- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/ + local t, tC, bC = shrinkedGraphic[1], shrinkedGraphic[2], shrinkedGraphic[3] + for i = 1, shrinkedGraphic.height do + local x, y = obx+xOffset, oby + i - 1 + yOffset + if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then + local tI = t[i] + local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w) + if type(tI) == "string" then + self.parent:setText(xpos, y, sub(tI, substart, subend)) + self.parent:setFG(xpos, y, sub(tC[i], substart, subend)) + self.parent:setBG(xpos, y, sub(bC[i], substart, subend)) + elseif type(tI) == "table" then + self.parent:setText(xpos, y, sub(tI[2], substart, subend)) + self.parent:setFG(xpos, y, sub(tC[i], substart, subend)) + self.parent:setBG(xpos, y, sub(bC[i], substart, subend)) end end end + else + for i = 1, #graphic do + local x, y = obx+xOffset, oby + i - 1 + yOffset + if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then + local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w) + self.parent:setBG(xpos, y, sub(graphic[i],substart,subend)) + end + end end end self:setVisualChanged(false) diff --git a/Basalt/objects/Image.lua b/Basalt/objects/Image.lua index 4949b04..b088755 100644 --- a/Basalt/objects/Image.lua +++ b/Basalt/objects/Image.lua @@ -1,3 +1,6 @@ +local Object = require("Object") +local xmlValue = require("utils").getValueFromXML + return function(name) -- Image local base = Object(name) @@ -8,7 +11,6 @@ return function(name) local imageGotShrinked = false local function shrink() - -- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/ local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 }, { 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } } @@ -130,6 +132,9 @@ return function(name) end local object = { + init = function(self) + self.bgColor = self.parent:getTheme("ImageBG") + end, getType = function(self) return objectType end; @@ -147,11 +152,19 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end + if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end + return self + end, + draw = function(self) if (base.draw(self)) then if (self.parent ~= nil) then if (image ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if (imageGotShrinked) then -- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/ local t, tC, bC = shrinkedImage[1], shrinkedImage[2], shrinkedImage[3] @@ -168,9 +181,9 @@ return function(name) end end else - for yPos = 1, math.min(#image, self.height) do + for yPos = 1, math.min(#image, h) do local line = image[yPos] - for xPos = 1, math.min(#line, self.width) do + for xPos = 1, math.min(#line, w) do if line[xPos] > 0 then self.parent:drawBackgroundBox(obx + xPos - 1, oby + yPos - 1, 1, 1, line[xPos]) end diff --git a/Basalt/objects/Input.lua b/Basalt/objects/Input.lua index 9bb754e..c476339 100644 --- a/Basalt/objects/Input.lua +++ b/Basalt/objects/Input.lua @@ -1,6 +1,6 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML return function(name) -- Input @@ -13,8 +13,6 @@ return function(name) base:setValue("") base.width = 10 base.height = 1 - base.bgColor = theme.InputBG - base.fgColor = theme.InputFG local textX = 1 local wIndex = 1 @@ -26,7 +24,10 @@ return function(name) local internalValueChange = false local object = { - + init = function(self) + self.bgColor = self.parent:getTheme("InputBG") + self.fgColor = self.parent:getTheme("InputFG") + end, getType = function(self) return objectType end; @@ -76,6 +77,17 @@ return function(name) return inputLimit end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + local dBG,dFG + if(xmlValue("defaultBG", data)~=nil)then dBG = xmlValue("defaultBG", data) end + if(xmlValue("defaultFG", data)~=nil)then dFG = xmlValue("defaultFG", data) end + if(xmlValue("default", data)~=nil)then self:setDefaultText(xmlValue("default", data), dFG~=nil and colors[dFG], dBG~=nil and colors[dBG]) end + if(xmlValue("limit", data)~=nil)then self:setInputLimit(xmlValue("limit", data)) end + if(xmlValue("type", data)~=nil)then self:setInputType(xmlValue("type", data)) end + return self + end, + getFocusHandler = function(self) base.getFocusHandler(self) if (self.parent ~= nil) then @@ -97,6 +109,7 @@ return function(name) keyHandler = function(self, event, key) if (base.keyHandler(self, event, key)) then + local w,h = self:getSize() internalValueChange = true if (event == "key") then if (key == keys.backspace) then @@ -131,8 +144,8 @@ return function(name) if (textX < 1) then textX = 1 end - if (textX < wIndex) or (textX >= self.width + wIndex) then - wIndex = textX - self.width + 1 + if (textX < wIndex) or (textX >= w + wIndex) then + wIndex = textX - w + 1 end if (wIndex < 1) then wIndex = 1 @@ -143,7 +156,7 @@ return function(name) -- left arrow textX = textX - 1 if (textX >= 1) then - if (textX < wIndex) or (textX >= self.width + wIndex) then + if (textX < wIndex) or (textX >= w + wIndex) then wIndex = textX end end @@ -172,7 +185,7 @@ return function(name) self:setValue(text:sub(1, textX - 1) .. key .. text:sub(textX, text:len())) textX = textX + 1 end - if (textX >= self.width + wIndex) then + if (textX >= w + wIndex) then wIndex = wIndex + 1 end end @@ -181,11 +194,11 @@ return function(name) local val = tostring(base.getValue()) local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1) - if (cursorX > self.x + self.width - 1) then - cursorX = self.x + self.width - 1 + if (cursorX > self.x + w - 1) then + cursorX = self.x + w - 1 end if (self.parent ~= nil) then - self.parent:setCursor(true, obx + cursorX, oby+math.floor(self.height/2), self.fgColor) + self.parent:setCursor(true, obx + cursorX, oby+math.floor(h/2), self.fgColor) end internalValueChange = false end @@ -194,7 +207,7 @@ return function(name) mouseHandler = function(self, event, button, x, y) if (base.mouseHandler(self, event, button, x, y)) then if (event == "mouse_click") and (button == 1) then - + end return true end @@ -205,10 +218,11 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - local verticalAlign = utils.getTextVerticalAlign(self.height, "center") + local w,h = self:getSize() + local verticalAlign = utils.getTextVerticalAlign(h, "center") - if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end - for n = 1, self.height do + if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end + for n = 1, h do if (n == verticalAlign) then local val = tostring(base.getValue()) local bCol = self.bgColor @@ -224,8 +238,8 @@ return function(name) if (val ~= "") then text = val end - text = text:sub(wIndex, self.width + wIndex - 1) - local space = self.width - text:len() + text = text:sub(wIndex, w + wIndex - 1) + local space = w - text:len() if (space < 0) then space = 0 end diff --git a/Basalt/objects/Label.lua b/Basalt/objects/Label.lua index e2fcc44..b35527a 100644 --- a/Basalt/objects/Label.lua +++ b/Basalt/objects/Label.lua @@ -1,6 +1,6 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML local tHex = require("tHex") local bigFont = require("bigfont") @@ -12,7 +12,8 @@ return function(name) base:setZIndex(3) local autoSize = true - base:setValue("") + base:setValue("Label") + base.width = 5 local textHorizontalAlign = "left" local textVerticalAlign = "top" @@ -24,6 +25,7 @@ return function(name) getType = function(self) return objectType end; + setText = function(self, text) text = tostring(text) base:setValue(text) @@ -65,6 +67,15 @@ return function(name) return fontsize+1 end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end + if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end + if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end + if(xmlValue("font", data)~=nil)then self:setFontSize(xmlValue("font", data)) end + return self + end, + setSize = function(self, width, height) base.setSize(self, width, height) autoSize = false @@ -76,38 +87,41 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - local verticalAlign = utils.getTextVerticalAlign(self.height, textVerticalAlign) + local w,h = self:getSize() + local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) - self.parent:drawTextBox(obx, oby, self.width, self.height, " ") end - if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) + self.parent:drawTextBox(obx, oby, w, h, " ") end + if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end if(fontsize==0)then if not(autoSize)then local splittedText = utils.splitString(self:getValue(), " ") local text = {} local line = "" - for k,v in pairs(splittedText)do - if(line:len()+v:len()<=self.width)then + for _,v in pairs(splittedText)do + if(line:len()+v:len()<=w)then line = line=="" and v or line.." "..v - if(k==#splittedText)then table.insert(text, line) end else table.insert(text, line) - line = v:sub(1,self.width) + line = v:sub(1,w) end end for k,v in pairs(text)do self.parent:setText(obx, oby+k-1, v) end else - self.parent:setText(obx, oby, utils.getTextHorizontalAlign(self:getValue(), self.width, textHorizontalAlign)) + for n = 1, h do + if (n == verticalAlign) then + self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), w, textHorizontalAlign)) + end + end end else local tData = bigFont(fontsize, self:getValue(), self.fgColor, self.bgColor or colors.black) if(autoSize)then - self.height = #tData[1]-1 - self.width = #tData[1][1] + self:setSize(#tData[1][1], #tData[1]-1) end - for n = 1, self.height do + for n = 1, h do if (n == verticalAlign) then local oX, oY = self.parent:getSize() local cX, cY = #tData[1][1], #tData[1] @@ -115,9 +129,9 @@ return function(name) oby = oby or math.floor((oY - cY) / 2) + 1 for i = 1, cY do - self.parent:setFG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[2][i], self.width, textHorizontalAlign)) - self.parent:setBG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[3][i], self.width, textHorizontalAlign, tHex[self.bgColor or colors.black])) - self.parent:setText(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[1][i], self.width, textHorizontalAlign)) + self.parent:setFG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[2][i], w, textHorizontalAlign)) + self.parent:setBG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[3][i], w, textHorizontalAlign, tHex[self.bgColor or colors.black])) + self.parent:setText(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[1][i], w, textHorizontalAlign)) end end end diff --git a/Basalt/objects/List.lua b/Basalt/objects/List.lua index 616cb47..f42c7fd 100644 --- a/Basalt/objects/List.lua +++ b/Basalt/objects/List.lua @@ -1,25 +1,29 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML return function(name) local base = Object(name) local objectType = "List" base.width = 16 base.height = 6 - base.bgColor = theme.listBG - base.fgColor = theme.listFG base:setZIndex(5) local list = {} - local itemSelectedBG = theme.selectionBG - local itemSelectedFG = theme.selectionFG + local itemSelectedBG + local itemSelectedFG local selectionColorActive = true local align = "left" local yOffset = 0 local scrollable = true local object = { + init = function(self) + self.bgColor = self.parent:getTheme("ListBG") + self.fgColor = self.parent:getTheme("ListText") + itemSelectedBG = self.parent:getTheme("SelectionBG") + itemSelectedFG = self.parent:getTheme("SelectionText") + end, getType = function(self) return objectType end; @@ -32,12 +36,12 @@ return function(name) return self end; - setIndexOffset = function(self, yOff) + setOffset = function(self, yOff) yOffset = yOff return self end; - getIndexOffset = function(self) + getOffset = function(self) return yOffset end; @@ -96,14 +100,31 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end + if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end + if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end + if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end + if(data["item"]~=nil)then + local tab = data["item"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)]) + end + end + return self + end, + mouseHandler = function(self, event, button, x, y) local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) - if (obx <= x) and (obx + self.width > x) and (oby <= y) and (oby + self.height > y) and (self:isVisible()) then + local w,h = self:getSize() + if (obx <= x) and (obx + w > x) and (oby <= y) and (oby + h > y) and (self:isVisible()) then if (((event == "mouse_click") or (event == "mouse_drag"))and(button==1))or(event=="monitor_touch") then if (#list > 0) then - for n = 1, self.height do + for n = 1, h do if (list[n + yOffset] ~= nil) then - if (obx <= x) and (obx + self.width > x) and (oby + n - 1 == y) then + if (obx <= x) and (obx + w > x) and (oby + n - 1 == y) then self:setValue(list[n + yOffset]) self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", 0, x, y, list[n + yOffset]) end @@ -118,9 +139,9 @@ return function(name) yOffset = 0 end if (button >= 1) then - if (#list > self.height) then - if (yOffset > #list - self.height) then - yOffset = #list - self.height + if (#list > h) then + if (yOffset > #list - h) then + yOffset = #list - h end if (yOffset >= #list) then yOffset = #list - 1 @@ -139,19 +160,20 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end - for n = 1, self.height do + for n = 1, h do if (list[n + yOffset] ~= nil) then if (list[n + yOffset] == self:getValue()) then if (selectionColorActive) then - self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), itemSelectedBG, itemSelectedFG) + self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), itemSelectedBG, itemSelectedFG) else - self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) + self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) end else - self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) + self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) end end end diff --git a/Basalt/objects/Menubar.lua b/Basalt/objects/Menubar.lua index 77189f3..80dade1 100644 --- a/Basalt/objects/Menubar.lua +++ b/Basalt/objects/Menubar.lua @@ -1,6 +1,6 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") +local xmlValue = utils.getValueFromXML local tHex = require("tHex") return function(name) @@ -10,13 +10,11 @@ return function(name) base.width = 30 base.height = 1 - base.bgColor = colors.gray - base.fgColor = colors.lightGray base:setZIndex(5) local list = {} - local itemSelectedBG = theme.selectionBG - local itemSelectedFG = theme.selectionFG + local itemSelectedBG + local itemSelectedFG local selectionColorActive = true local align = "left" local itemOffset = 0 @@ -26,10 +24,11 @@ return function(name) local function maxScroll() local mScroll = 0 local xPos = 0 + local w = object:getWidth() for n = 1, #list do - if (xPos + list[n].text:len() + space * 2 > object.width) then - if(xPos < object.width)then - mScroll = mScroll + (list[n].text:len() + space * 2-(object.width - xPos)) + if (xPos + list[n].text:len() + space * 2 > w) then + if(xPos < w)then + mScroll = mScroll + (list[n].text:len() + space * 2-(w - xPos)) else mScroll = mScroll + list[n].text:len() + space * 2 end @@ -41,12 +40,19 @@ return function(name) end object = { + init = function(self) + self.bgColor = self.parent:getTheme("MenubarBG") + self.fgColor = self.parent:getTheme("MenubarText") + itemSelectedBG = self.parent:getTheme("SelectionBG") + itemSelectedFG = self.parent:getTheme("SelectionText") + end, + getType = function(self) return objectType end; addItem = function(self, text, bgCol, fgCol, ...) - table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) + table.insert(list, { text = tostring(text), bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) if (#list == 1) then self:setValue(list[1]) end @@ -77,7 +83,7 @@ return function(name) return self end; - setPositionOffset = function(self, offset) + setOffset = function(self, offset) itemOffset = offset or 0 if (itemOffset < 0) then itemOffset = 0 @@ -90,7 +96,7 @@ return function(name) return self end; - getPositionOffset = function(self) + getOffset = function(self) return itemOffset end; @@ -100,6 +106,23 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end + if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end + if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end + if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end + if(xmlValue("space", data)~=nil)then space = xmlValue("space", data) end + if(data["item"]~=nil)then + local tab = data["item"] + if(tab.properties~=nil)then tab = {tab} end + for k,v in pairs(tab)do + self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)]) + end + end + return self + end, + removeItem = function(self, index) table.remove(list, index) return self @@ -134,7 +157,8 @@ return function(name) mouseHandler = function(self, event, button, x, y) if(base.mouseHandler(self, event, button, x, y))then local objX, objY = self:getAbsolutePosition(self:getAnchorPosition()) - if (objX <= x) and (objX + self.width > x) and (objY <= y) and (objY + self.height > y) and (self:isVisible()) then + local w,h = self:getSize() + if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) and (self:isVisible()) then if (self.parent ~= nil) then self.parent:setFocusedObject(self) end @@ -174,8 +198,9 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local text = "" local textBGCol = "" @@ -192,9 +217,9 @@ return function(name) end end - self.parent:setText(obx, oby, text:sub(itemOffset+1, self.width+itemOffset)) - self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, self.width+itemOffset)) - self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, self.width+itemOffset)) + self.parent:setText(obx, oby, text:sub(itemOffset+1, w+itemOffset)) + self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, w+itemOffset)) + self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, w+itemOffset)) end self:setVisualChanged(false) end diff --git a/Basalt/objects/Pane.lua b/Basalt/objects/Pane.lua index 7281684..1719fc7 100644 --- a/Basalt/objects/Pane.lua +++ b/Basalt/objects/Pane.lua @@ -6,6 +6,10 @@ return function(name) local objectType = "Pane" local object = { + init = function(self) + self.bgColor = self.parent:getTheme("PaneBG") + self.fgColor = self.parent:getTheme("PaneBG") + end, getType = function(self) return objectType end; @@ -14,8 +18,9 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) - self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.bgColor) + local w,h = self:getSize() + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) + self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end self:setVisualChanged(false) end diff --git a/Basalt/objects/Program.lua b/Basalt/objects/Program.lua index d984c97..1d51370 100644 --- a/Basalt/objects/Program.lua +++ b/Basalt/objects/Program.lua @@ -1,6 +1,7 @@ local Object = require("Object") local tHex = require("tHex") local process = require("process") +local xmlValue = require("utils").getValueFromXML local sub = string.sub @@ -9,6 +10,7 @@ return function(name, parent) local objectType = "Program" base:setZIndex(5) local object + local cachedPath local function createBasaltWindow(x, y, width, height) local xCursor, yCursor = 1, 1 @@ -416,6 +418,9 @@ return function(name, parent) local queuedEvent = {} object = { + init = function(self) + self.bgColor = self.parent:getTheme("ProgramBG") + end, getType = function(self) return objectType end; @@ -440,6 +445,12 @@ return function(name, parent) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("path", data)~=nil)then cachedPath = xmlValue("path", data) end + if(xmlValue("execute", data)~=nil)then if(xmlValue("execute", data))then if(cachedPath~=nil)then self:execute(cachedPath) end end end + end, + getBasaltWindow = function() return pWindow end; @@ -448,9 +459,9 @@ return function(name, parent) return curProcess end; - setSize = function(self, width, height) - base.setSize(self, width, height) - pWindow.basalt_resize(self.width, self.height) + setSize = function(self, width, height, rel) + base.setSize(self, width, height, rel) + pWindow.basalt_resize(self:getSize()) return self end; @@ -462,11 +473,15 @@ return function(name, parent) end; execute = function(self, path, ...) + cachedPath = path curProcess = process:new(path, pWindow, ...) pWindow.setBackgroundColor(colors.black) pWindow.setTextColor(colors.white) pWindow.clear() pWindow.setCursorPos(1, 1) + pWindow.setBackgroundColor(self.bgColor) + pWindow.setTextColor(self.fgColor) + pWindow.basalt_setVisible(true) curProcess:resume() paused = false return self @@ -576,7 +591,8 @@ return function(name, parent) local xCur, yCur = pWindow.getCursorPos() local obx, oby = self:getAnchorPosition() if (self.parent ~= nil) then - if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + self.width - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.height - 1) then + local w,h = self:getSize() + if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor()) end end @@ -610,7 +626,8 @@ return function(name, parent) local obx, oby = self:getAnchorPosition() local xCur, yCur = pWindow.getCursorPos() if (self.parent ~= nil) then - if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + self.width - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.height - 1) then + local w,h = self:getSize() + if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor()) end end @@ -631,9 +648,10 @@ return function(name, parent) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() pWindow.basalt_reposition(obx, oby) if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end pWindow.basalt_update() end diff --git a/Basalt/objects/Progressbar.lua b/Basalt/objects/Progressbar.lua index 1f4eb2a..35f010f 100644 --- a/Basalt/objects/Progressbar.lua +++ b/Basalt/objects/Progressbar.lua @@ -1,5 +1,5 @@ local Object = require("Object") -local theme = require("theme") +local xmlValue = require("utils").getValueFromXML return function(name) -- Checkbox @@ -12,21 +12,37 @@ return function(name) base:setValue(false) base.width = 25 base.height = 1 - base.bgColor = theme.CheckboxBG - base.fgColor = theme.CheckboxFG - local activeBarColor = colors.black + local activeBarColor local activeBarSymbol = "" local activeBarSymbolCol = colors.white local bgBarSymbol = "" local direction = 0 local object = { - + init = function(self) + self.bgColor = self.parent:getTheme("ProgressbarBG") + self.fgColor = self.parent:getTheme("ProgressbarText") + activeBarColor = self.parent:getTheme("ProgressbarActiveBG") + end, getType = function(self) return objectType end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("direction", data)~=nil)then direction = xmlValue("direction", data) end + if(xmlValue("progressColor", data)~=nil)then activeBarColor = colors[xmlValue("progressColor", data)] end + if(xmlValue("progressSymbol", data)~=nil)then activeBarSymbol = xmlValue("progressSymbol", data) end + if(xmlValue("backgroundSymbol", data)~=nil)then bgBarSymbol = xmlValue("backgroundSymbol", data) end + if(xmlValue("progressSymbolColor", data)~=nil)then activeBarSymbolCol = colors[xmlValue("progressSymbolColor", data)] end + if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end + if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end + if(xmlValue("space", data)~=nil)then space = xmlValue("space", data) end + if(xmlValue("onDone", data)~=nil)then self:onProgressDone(baseFrame:getVariable(xmlValue("onDone", data))) end + return self + end, + setDirection = function(self, dir) direction = dir return self @@ -72,25 +88,26 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end - if(bgBarSymbol~="")then self.parent:drawTextBox(obx, oby, self.width, self.height, bgBarSymbol) end - if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end + local w,h = self:getSize() + if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end + if(bgBarSymbol~="")then self.parent:drawTextBox(obx, oby, w, h, bgBarSymbol) end + if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end if (direction == 1) then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height / 100 * progress, activeBarColor) - self.parent:drawForegroundBox(obx, oby, self.width, self.height / 100 * progress, activeBarSymbolCol) - self.parent:drawTextBox(obx, oby, self.width, self.height / 100 * progress, activeBarSymbol) + self.parent:drawBackgroundBox(obx, oby, w, h / 100 * progress, activeBarColor) + self.parent:drawForegroundBox(obx, oby, w, h / 100 * progress, activeBarSymbolCol) + self.parent:drawTextBox(obx, oby, w, h / 100 * progress, activeBarSymbol) elseif (direction == 2) then - self.parent:drawBackgroundBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarColor) - self.parent:drawForegroundBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarSymbolCol) - self.parent:drawTextBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarSymbol) + self.parent:drawBackgroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor) + self.parent:drawForegroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol) + self.parent:drawTextBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol) elseif (direction == 3) then - self.parent:drawBackgroundBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarColor) - self.parent:drawForegroundBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarSymbolCol) - self.parent:drawTextBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarSymbol) + self.parent:drawBackgroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarColor) + self.parent:drawForegroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbolCol) + self.parent:drawTextBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbol) else - self.parent:drawBackgroundBox(obx, oby, self.width / 100 * progress, self.height, activeBarColor) - self.parent:drawForegroundBox(obx, oby, self.width / 100 * progress, self.height, activeBarSymbolCol) - self.parent:drawTextBox(obx, oby, self.width / 100 * progress, self.height, activeBarSymbol) + self.parent:drawBackgroundBox(obx, oby, w / 100 * progress, h, activeBarColor) + self.parent:drawForegroundBox(obx, oby, w / 100 * progress, h, activeBarSymbolCol) + self.parent:drawTextBox(obx, oby, w / 100 * progress, h, activeBarSymbol) end end self:setVisualChanged(false) diff --git a/Basalt/objects/Radio.lua b/Basalt/objects/Radio.lua index ff2a735..d73c9e9 100644 --- a/Basalt/objects/Radio.lua +++ b/Basalt/objects/Radio.lua @@ -1,29 +1,53 @@ local Object = require("Object") -local theme = require("theme") local utils = require("utils") return function(name) local base = Object(name) local objectType = "Radio" base.width = 8 - base.bgColor = theme.listBG - base.fgColor = theme.listFG base:setZIndex(5) local list = {} - local itemSelectedBG = theme.selectionBG - local itemSelectedFG = theme.selectionFG - local boxSelectedBG = base.bgColor - local boxSelectedFG = base.fgColor + local itemSelectedBG + local itemSelectedFG + local boxSelectedBG + local boxSelectedFG local selectionColorActive = true local symbol = "\7" local align = "left" local object = { + + init = function(self) + self.bgColor = self.parent:getTheme("MenubarBG") + self.fgColor = self.parent:getTheme("MenubarFG") + itemSelectedBG = self.parent:getTheme("SelectionBG") + itemSelectedFG = self.parent:getTheme("SelectionText") + boxSelectedBG = self.parent:getTheme("MenubarBG") + boxSelectedFG = self.parent:getTheme("MenubarText") + end, + getType = function(self) return objectType end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end + if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end + if(xmlValue("boxBG", data)~=nil)then itemSelectedBG = colors[xmlValue("boxBG", data)] end + if(xmlValue("boxFG", data)~=nil)then itemSelectedFG = colors[xmlValue("boxFG", data)] end + if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data) end + if(data["item"]~=nil)then + local tab = data["item"] + if(tab.properties~=nil)then tab = {tab} end + for k,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, + addItem = function(self, text, x, y, bgCol, fgCol, ...) table.insert(list, { x = x or 1, y = y or 1, text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) if (#list == 1) then diff --git a/Basalt/objects/Scrollbar.lua b/Basalt/objects/Scrollbar.lua index b8058f6..e03e4d4 100644 --- a/Basalt/objects/Scrollbar.lua +++ b/Basalt/objects/Scrollbar.lua @@ -1,5 +1,5 @@ local Object = require("Object") -local theme = require("theme") +local xmlValue = require("utils").getValueFromXML return function(name) local base = Object(name) @@ -7,20 +7,23 @@ return function(name) base.width = 1 base.height = 8 - base.bgColor = colors.lightGray - base.fgColor = colors.gray base:setValue(1) base:setZIndex(2) local barType = "vertical" local symbol = " " - local symbolColor = colors.black + local symbolColor local bgSymbol = "\127" local maxValue = base.height local index = 1 local symbolSize = 1 local object = { + init = function(self) + self.bgColor = self.parent:getTheme("ScrollbarBG") + self.fgColor = self.parent:getTheme("ScrollbarText") + symbolColor = self.parent:getTheme("ScrollbarSymbolColor") + end, getType = function(self) return objectType end; @@ -31,13 +34,25 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end + if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end + if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end + if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end + if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end + if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end + if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end + end, + setIndex = function(self, _index) index = _index if (index < 1) then index = 1 end - index = math.min(index, (barType == "vertical" and self.height or self.width) - (symbolSize - 1)) - self:setValue(maxValue / (barType == "vertical" and self.height or self.width) * index) + local w,h = self:getSize() + index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) + self:setValue(maxValue / (barType == "vertical" and h or w) * index) return self end, @@ -47,10 +62,11 @@ return function(name) setSymbolSize = function(self, size) symbolSize = tonumber(size) or 1 + local w,h = self:getSize() if (barType == "vertical") then - self:setValue(index - 1 * (maxValue / (self.height - (symbolSize - 1))) - (maxValue / (self.height - (symbolSize - 1)))) + self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1)))) elseif (barType == "horizontal") then - self:setValue(index - 1 * (maxValue / (self.width - (symbolSize - 1))) - (maxValue / (self.width - (symbolSize - 1)))) + self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1)))) end self:setVisualChanged() return self @@ -81,21 +97,22 @@ return function(name) mouseHandler = function(self, event, button, x, y) if (base.mouseHandler(self, event, button, x, y)) then local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) + local w,h = self:getSize() if (((event == "mouse_click") or (event == "mouse_drag")) and (button == 1))or(event=="monitor_touch") then if (barType == "horizontal") then - for _index = 0, self.width do - if (obx + _index == x) and (oby <= y) and (oby + self.height > y) then - index = math.min(_index + 1, self.width - (symbolSize - 1)) - self:setValue(maxValue / self.width * (index)) + for _index = 0, w do + if (obx + _index == x) and (oby <= y) and (oby + h > y) then + index = math.min(_index + 1, w - (symbolSize - 1)) + self:setValue(maxValue / w * (index)) self:setVisualChanged() end end end if (barType == "vertical") then - for _index = 0, self.height do - if (oby + _index == y) and (obx <= x) and (obx + self.width > x) then - index = math.min(_index + 1, self.height - (symbolSize - 1)) - self:setValue(maxValue / self.height * (index)) + for _index = 0, h do + if (oby + _index == y) and (obx <= x) and (obx + w > x) then + index = math.min(_index + 1, h - (symbolSize - 1)) + self:setValue(maxValue / h * (index)) self:setVisualChanged() end end @@ -106,8 +123,8 @@ return function(name) if (index < 1) then index = 1 end - index = math.min(index, (barType == "vertical" and self.height or self.width) - (symbolSize - 1)) - self:setValue(maxValue / (barType == "vertical" and self.height or self.width) * index) + index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) + self:setValue(maxValue / (barType == "vertical" and h or w) * index) end return true end @@ -117,17 +134,17 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if (barType == "horizontal") then self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor) self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor) - self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(self.width - (index + symbolSize - 1)), self.bgColor, self.fgColor) + self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor) end if (barType == "vertical") then - for n = 0, self.height - 1 do - + for n = 0, h - 1 do if (index == n + 1) then - for curIndexOffset = 0, math.min(symbolSize - 1, self.height) do + for curIndexOffset = 0, math.min(symbolSize - 1, h) do self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor) end else diff --git a/Basalt/objects/Slider.lua b/Basalt/objects/Slider.lua index 1f1a930..f2b4499 100644 --- a/Basalt/objects/Slider.lua +++ b/Basalt/objects/Slider.lua @@ -1,5 +1,5 @@ local Object = require("Object") -local theme = require("theme") +local xmlValue = require("utils").getValueFromXML return function(name) local base = Object(name) @@ -7,19 +7,22 @@ return function(name) base.width = 8 base.height = 1 - base.bgColor = colors.lightGray - base.fgColor = colors.gray base:setValue(1) local barType = "horizontal" local symbol = " " - local symbolColor = colors.black + local symbolColor local bgSymbol = "\140" local maxValue = base.width local index = 1 local symbolSize = 1 local object = { + init = function(self) + self.bgColor = self.parent:getTheme("SliderBG") + self.fgColor = self.parent:getTheme("SliderText") + symbolColor = self.parent:getTheme("SliderSymbolColor") + end, getType = function(self) return objectType end; @@ -30,12 +33,38 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end + if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end + if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end + if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end + if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end + if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end + if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end + end, + + setIndex = function(self, _index) + index = _index + if (index < 1) then + index = 1 + end + local w,h = self:getSize() + index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) + self:setValue(maxValue / (barType == "vertical" and h or w) * index) + return self + end, + + getIndex = function(self) + return index + end, + setSymbolSize = function(self, size) symbolSize = tonumber(size) or 1 if (barType == "vertical") then - self:setValue(index - 1 * (maxValue / (self.height - (symbolSize - 1))) - (maxValue / (self.height - (symbolSize - 1)))) + self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1)))) elseif (barType == "horizontal") then - self:setValue(index - 1 * (maxValue / (self.width - (symbolSize - 1))) - (maxValue / (self.width - (symbolSize - 1)))) + self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1)))) end self:setVisualChanged() return self @@ -66,21 +95,22 @@ return function(name) mouseHandler = function(self, event, button, x, y) if (base.mouseHandler(self, event, button, x, y)) then local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) + local w,h = self:getSize() if (((event == "mouse_click") or (event == "mouse_drag")) and (button == 1))or(event=="monitor_touch") then if (barType == "horizontal") then - for _index = 0, self.width do - if (obx + _index == x) and (oby <= y) and (oby + self.height > y) then - index = math.min(_index + 1, self.width - (symbolSize - 1)) - self:setValue(maxValue / self.width * (index)) + for _index = 0, w do + if (obx + _index == x) and (oby <= y) and (oby + h > y) then + index = math.min(_index + 1, w - (symbolSize - 1)) + self:setValue(maxValue / w * (index)) self:setVisualChanged() end end end if (barType == "vertical") then - for _index = 0, self.height do - if (oby + _index == y) and (obx <= x) and (obx + self.width > x) then - index = math.min(_index + 1, self.height - (symbolSize - 1)) - self:setValue(maxValue / self.height * (index)) + for _index = 0, h do + if (oby + _index == y) and (obx <= x) and (obx + w > x) then + index = math.min(_index + 1, h - (symbolSize - 1)) + self:setValue(maxValue / h * (index)) self:setVisualChanged() end end @@ -91,8 +121,8 @@ return function(name) if (index < 1) then index = 1 end - index = math.min(index, (barType == "vertical" and self.height or self.width) - (symbolSize - 1)) - self:setValue(maxValue / (barType == "vertical" and self.height or self.width) * index) + index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) + self:setValue(maxValue / (barType == "vertical" and h or w) * index) end return true end @@ -102,17 +132,18 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if (barType == "horizontal") then self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor) self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor) - self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(self.width - (index + symbolSize - 1)), self.bgColor, self.fgColor) + self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor) end if (barType == "vertical") then - for n = 0, self.height - 1 do + for n = 0, h - 1 do if (index == n + 1) then - for curIndexOffset = 0, math.min(symbolSize - 1, self.height) do + for curIndexOffset = 0, math.min(symbolSize - 1, h) do self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor) end else diff --git a/Basalt/objects/Switch.lua b/Basalt/objects/Switch.lua index a0d8626..5d0aaed 100644 --- a/Basalt/objects/Switch.lua +++ b/Basalt/objects/Switch.lua @@ -1,5 +1,5 @@ local Object = require("Object") -local theme = require("theme") +local xmlValue = require("utils").getValueFromXML return function(name) local base = Object(name) @@ -17,6 +17,13 @@ return function(name) local activeBG = colors.green local object = { + init = function(self) + self.bgColor = self.parent:getTheme("SwitchBG") + self.fgColor = self.parent:getTheme("SwitchText") + bgSymbol = self.parent:getTheme("SwitchBGSymbol") + inactiveBG = self.parent:getTheme("SwitchInactive") + activeBG = self.parent:getTheme("SwitchActive") + end, getType = function(self) return objectType end; @@ -39,6 +46,14 @@ return function(name) return self end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(xmlValue("inactiveBG", data)~=nil)then inactiveBG = colors[xmlValue("inactiveBG", data)] end + if(xmlValue("activeBG", data)~=nil)then activeBG = colors[xmlValue("activeBG", data)] end + if(xmlValue("symbolColor", data)~=nil)then bgSymbol = colors[xmlValue("symbolColor", data)] end + + end, + mouseHandler = function(self, event, button, x, y) if (base.mouseHandler(self, event, button, x, y)) then local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) @@ -53,13 +68,14 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) + local w,h = self:getSize() + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) if(self:getValue())then - self.parent:drawBackgroundBox(obx, oby, 1, self.height, activeBG) - self.parent:drawBackgroundBox(obx+1, oby, 1, self.height, bgSymbol) + self.parent:drawBackgroundBox(obx, oby, 1, h, activeBG) + self.parent:drawBackgroundBox(obx+1, oby, 1, h, bgSymbol) else - self.parent:drawBackgroundBox(obx, oby, 1, self.height, bgSymbol) - self.parent:drawBackgroundBox(obx+1, oby, 1, self.height, inactiveBG) + self.parent:drawBackgroundBox(obx, oby, 1, h, bgSymbol) + self.parent:drawBackgroundBox(obx+1, oby, 1, h, inactiveBG) end end self:setVisualChanged(false) diff --git a/Basalt/objects/Textfield.lua b/Basalt/objects/Textfield.lua index 80c4706..bef156d 100644 --- a/Basalt/objects/Textfield.lua +++ b/Basalt/objects/Textfield.lua @@ -1,5 +1,6 @@ local Object = require("Object") -local theme = require("theme") +local tHex = require("tHex") +local xmlValue = require("utils").getValueFromXML return function(name) local base = Object(name) @@ -7,19 +8,111 @@ return function(name) local hIndex, wIndex, textX, textY = 1, 1, 1, 1 local lines = { "" } - local keyWords = { [colors.purple] = { "break" } } + local bgLines = { "" } + local fgLines = { "" } + local keyWords = { } + local rules = { } - base.width = 20 - base.height = 8 - base.bgColor = theme.textfieldBG - base.fgColor = theme.textfieldFG + base.width = 30 + base.height = 12 base:setZIndex(5) + local function stringGetPositions(str, word) + local pos = {} + if(str:len()>0)then + for w in string.gmatch(str, word)do + local s, e = string.find(str, w) + if(s~=nil)and(e~=nil)then + table.insert(pos,s) + table.insert(pos,e) + local startL = string.sub(str, 1, (s-1)) + local endL = string.sub(str, e+1, str:len()) + str = startL..(":"):rep(w:len())..endL + end + end + end + return pos + end + + local function updateColors() + local fgLine = tHex[base.fgColor]:rep(fgLines[textY]:len()) + local bgLine = tHex[base.bgColor]:rep(bgLines[textY]:len()) + for k,v in pairs(rules)do + local pos = stringGetPositions(lines[textY], v[1]) + if(#pos>0)then + for x=1,#pos/2 do + local xP = x*2 - 1 + if(v[2]~=nil)then + fgLine = fgLine:sub(1, pos[xP]-1)..tHex[v[2]]:rep(pos[xP+1]-(pos[xP]-1))..fgLine:sub(pos[xP+1]+1, fgLine:len()) + end + if(v[3]~=nil)then + bgLine = bgLine:sub(1, pos[xP]-1)..tHex[v[3]]:rep(pos[xP+1]-(pos[xP]-1))..bgLine:sub(pos[xP+1]+1, bgLine:len()) + end + end + end + end + for k,v in pairs(keyWords)do + for _,b in pairs(v)do + local pos = stringGetPositions(lines[textY], b) + if(#pos>0)then + for x=1,#pos/2 do + local xP = x*2 - 1 + fgLine = fgLine:sub(1, pos[xP]-1)..tHex[k]:rep(pos[xP+1]-(pos[xP]-1))..fgLine:sub(pos[xP+1]+1, fgLine:len()) + end + end + end + end + fgLines[textY] = fgLine + bgLines[textY] = bgLine + end + local object = { + init = function(self) + base.bgColor = self.parent:getTheme("TextfieldBG") + base.fgColor = self.parent:getTheme("TextfieldText") + end, getType = function(self) return objectType end; + setValuesByXMLData = function(self, data) + base.setValuesByXMLData(self, data) + if(data["lines"]~=nil)then + for k,v in pairs(data["lines"])do + self:addLine(xmlValue("line", v)) + 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"]["item"]~=nil)then + local tab = data["rules"]["item"] + if(data["rules"]["item"].properties~=nil)then tab = {data["rules"]["item"]} end + for k,v in pairs(tab)do + + if(xmlValue("rule", v)~=nil)then + self:addRule(xmlValue("rule", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)]) + end + end + end + end + end, + getLines = function(self) return lines end; @@ -42,8 +135,43 @@ return function(name) return self end; - addKeyword = function(self, keyword, color) + addKeywords = function(self, color, tab) + if(keyWords[color]==nil)then + keyWords[color] = {} + end + for k,v in pairs(tab)do + table.insert(keyWords[color], v) + end + return self + end; + addRule = function(self, rule, fg, bg) + table.insert(rules, {rule, fg, bg}) + return self + end; + + editRule = function(self, rule, fg, bg) + for k,v in pairs(rules)do + if(v[1]==rule)then + rules[k][2] = fg + rules[k][3] = bg + end + end + return self + end; + + removeRule = function(self, rule) + for k,v in pairs(rules)do + if(v[1]==rule)then + table.remove(rules, k) + end + end + return self + end; + + setKeywords = function(self, color, tab) + keyWords[color] = tab + return self end; removeLine = function(self, index) @@ -78,14 +206,17 @@ return function(name) keyHandler = function(self, event, key) if (base.keyHandler(self, event, key)) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if (event == "key") then if (key == keys.backspace) then -- on backspace if (lines[textY] == "") then if (textY > 1) then table.remove(lines, textY) + table.remove(fgLines, textY) + table.remove(bgLines, textY) textX = lines[textY - 1]:len() + 1 - wIndex = textX - self.width + 1 + wIndex = textX - w + 1 if (wIndex < 1) then wIndex = 1 end @@ -94,16 +225,22 @@ return function(name) elseif (textX <= 1) then if (textY > 1) then textX = lines[textY - 1]:len() + 1 - wIndex = textX - self.width + 1 + wIndex = textX - w + 1 if (wIndex < 1) then wIndex = 1 end lines[textY - 1] = lines[textY - 1] .. lines[textY] + fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY] + bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY] table.remove(lines, textY) + table.remove(fgLines, textY) + table.remove(bgLines, textY) textY = textY - 1 end else lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len()) + fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len()) + bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len()) if (textX > 1) then textX = textX - 1 end @@ -116,6 +253,7 @@ return function(name) if (textY < hIndex) then hIndex = hIndex - 1 end + updateColors() self:setValue("") end @@ -125,20 +263,29 @@ return function(name) if (lines[textY + 1] ~= nil) then lines[textY] = lines[textY] .. lines[textY + 1] table.remove(lines, textY + 1) + table.remove(bgLines, textY + 1) + table.remove(fgLines, textY + 1) end else lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len()) + fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len()) + bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len()) end + updateColors() end if (key == keys.enter) then -- on enter table.insert(lines, textY + 1, lines[textY]:sub(textX, lines[textY]:len())) + table.insert(fgLines, textY + 1, fgLines[textY]:sub(textX, fgLines[textY]:len())) + table.insert(bgLines, textY + 1, bgLines[textY]:sub(textX, bgLines[textY]:len())) lines[textY] = lines[textY]:sub(1, textX - 1) + fgLines[textY] = fgLines[textY]:sub(1, textX - 1) + bgLines[textY] = bgLines[textY]:sub(1, textX - 1) textY = textY + 1 textX = 1 wIndex = 1 - if (textY - hIndex >= self.height) then + if (textY - hIndex >= h) then hIndex = hIndex + 1 end self:setValue("") @@ -153,7 +300,7 @@ return function(name) end if (wIndex > 1) then if (textX < wIndex) then - wIndex = textX - self.width + 1 + wIndex = textX - w + 1 if (wIndex < 1) then wIndex = 1 end @@ -174,7 +321,7 @@ return function(name) textX = lines[textY]:len() + 1 end - if (textY >= hIndex + self.height) then + if (textY >= hIndex + h) then hIndex = hIndex + 1 end end @@ -193,8 +340,8 @@ return function(name) if (textX < 1) then textX = 1 end - if (textX < wIndex) or (textX >= self.width + wIndex) then - wIndex = textX - self.width + 1 + if (textX < wIndex) or (textX >= w + wIndex) then + wIndex = textX - w + 1 end if (wIndex < 1) then wIndex = 1 @@ -205,7 +352,7 @@ return function(name) -- arrow left textX = textX - 1 if (textX >= 1) then - if (textX < wIndex) or (textX >= self.width + wIndex) then + if (textX < wIndex) or (textX >= w + wIndex) then wIndex = textX end end @@ -213,7 +360,7 @@ return function(name) if (textX < 1) then textY = textY - 1 textX = lines[textY]:len() + 1 - wIndex = textX - self.width + 1 + wIndex = textX - w + 1 end end if (textX < 1) then @@ -227,18 +374,21 @@ return function(name) if (event == "char") then lines[textY] = lines[textY]:sub(1, textX - 1) .. key .. lines[textY]:sub(textX, lines[textY]:len()) + fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self.fgColor] .. fgLines[textY]:sub(textX, fgLines[textY]:len()) + bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor] .. bgLines[textY]:sub(textX, bgLines[textY]:len()) textX = textX + 1 - if (textX >= self.width + wIndex) then + if (textX >= w + wIndex) then wIndex = wIndex + 1 end + updateColors() self:setValue("") end local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1) - if (cursorX > self.x + self.width - 1) then - cursorX = self.x + self.width - 1 + if (cursorX > self.x + w - 1) then + cursorX = self.x + w - 1 end - local cursorY = (textY - hIndex < self.height and textY - hIndex or textY - hIndex - 1) + local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1) if (cursorX < 1) then cursorX = 0 end @@ -251,6 +401,7 @@ return function(name) if (base.mouseHandler(self, event, button, x, y)) then local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local anchx, anchy = self:getAnchorPosition() + local w,h = self:getSize() if (event == "mouse_click")or(event=="monitor_touch") then if (lines[y - oby + hIndex] ~= nil) then textX = x - obx + wIndex @@ -290,8 +441,8 @@ return function(name) if (event == "mouse_scroll") then hIndex = hIndex + button - if (hIndex > #lines - (self.height - 1)) then - hIndex = #lines - (self.height - 1) + if (hIndex > #lines - (h - 1)) then + hIndex = #lines - (h - 1) end if (hIndex < 1) then @@ -299,7 +450,7 @@ return function(name) end if (self.parent ~= nil) then - if (obx + textX - wIndex >= obx and obx + textX - wIndex <= obx + self.width) and (oby + textY - hIndex >= oby and oby + textY - hIndex <= oby + self.height) then + if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h) then self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor) else self.parent:setCursor(false) @@ -315,24 +466,35 @@ return function(name) if (base.draw(self)) then if (self.parent ~= nil) then local obx, oby = self:getAnchorPosition() + local w,h = self:getSize() if(self.bgColor~=false)then - self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) + self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end if(self.fgColor~=false)then - self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) + self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end - for n = 1, self.height do + for n = 1, h do local text = "" + local bg = "" + local fg = "" if (lines[n + hIndex - 1] ~= nil) then text = lines[n + hIndex - 1] + fg = fgLines[n + hIndex - 1] + bg = bgLines[n + hIndex - 1] end - text = text:sub(wIndex, self.width + wIndex - 1) - local space = self.width - text:len() + text = text:sub(wIndex, w + wIndex - 1) + bg = bg:sub(wIndex, w + wIndex - 1) + fg = fg:sub(wIndex, w + wIndex - 1) + local space = w - text:len() if (space < 0) then space = 0 end text = text .. string.rep(" ", space) + bg = bg .. string.rep(tHex[self.bgColor], space) + fg = fg .. string.rep(tHex[self.fgColor], space) self.parent:setText(obx, oby + n - 1, text) + self.parent:setBG(obx, oby + n - 1, bg) + self.parent:setFG(obx, oby + n - 1, fg) end end self:setVisualChanged(false) diff --git a/Basalt/objects/Thread.lua b/Basalt/objects/Thread.lua index 16e8595..fa65e0f 100644 --- a/Basalt/objects/Thread.lua +++ b/Basalt/objects/Thread.lua @@ -1,3 +1,5 @@ +local xmlValue = require("utils").getValueFromXML + return function(name) local object local objectType = "Thread" @@ -18,6 +20,20 @@ return function(name) return self.name end; + getBaseFrame = function(self) + if(self.parent~=nil)then + return self.parent:getBaseFrame() + end + return self + end; + + setValuesByXMLData = function(self, data) + local f + if(xmlValue("thread", data)~=nil)then f = self:getBaseFrame():getVariable(xmlValue("thread", data)) end + if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))and(f~=nil)then self:start(f) end end + return self + end, + start = function(self, f) if (f == nil) then error("Function provided to thread is nil") diff --git a/Basalt/objects/Timer.lua b/Basalt/objects/Timer.lua index 55688a1..30ad7a0 100644 --- a/Basalt/objects/Timer.lua +++ b/Basalt/objects/Timer.lua @@ -1,4 +1,5 @@ local basaltEvent = require("basaltEvent") +local xmlValue = require("utils").getValueFromXML return function(name) local objectType = "Timer" @@ -16,6 +17,22 @@ return function(name) return objectType end; + setValuesByXMLData = function(self, data) + local f + if(xmlValue("time", data)~=nil)then timer = xmlValue("time", data) end + if(xmlValue("repeat", data)~=nil)then timer = xmlValue("repeat", data) end + if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))then self:start() end end + if(xmlValue("onCall", data)~=nil)then self:onCall(getBaseFrame():getVariable(xmlValue("onCall", data))) end + return self + end, + + getBaseFrame = function(self) + if(self.parent~=nil)then + return self.parent:getBaseFrame() + end + return self + end; + getZIndex = function(self) return 1 end; diff --git a/Basalt/theme.lua b/Basalt/theme.lua index c51eade..def7755 100644 --- a/Basalt/theme.lua +++ b/Basalt/theme.lua @@ -1,22 +1,43 @@ -return { -- The default theme for basalt! - basaltBG = colors.lightGray, - basaltFG = colors.black, +return { -- The default main theme for basalt! + BasaltBG = colors.lightGray, + BasaltText = colors.black, FrameBG = colors.gray, - FrameFG = colors.black, + FrameText = colors.black, ButtonBG = colors.gray, - ButtonFG = colors.black, + ButtonText = colors.black, CheckboxBG = colors.gray, - CheckboxFG = colors.black, + CheckboxText = colors.black, InputBG = colors.gray, - InputFG = colors.black, - textfieldBG = colors.gray, - textfieldFG = colors.black, - listBG = colors.gray, - listFG = colors.black, - dropdownBG = colors.gray, - dropdownFG = colors.black, - radioBG = colors.gray, - radioFG = colors.black, - selectionBG = colors.black, - selectionFG = colors.lightGray, + InputText = colors.black, + TextfieldBG = colors.gray, + TextfieldText = colors.black, + ListBG = colors.gray, + ListText = colors.black, + MenubarBG = colors.gray, + MenubarText = colors.black, + DropdownBG = colors.gray, + DropdownText = colors.black, + RadioBG = colors.gray, + RadioText = colors.black, + SelectionBG = colors.black, + SelectionText = colors.lightGray, + GraphicBG = colors.black, + ImageBG = colors.black, + PaneBG = colors.black, + ProgramBG = colors.black, + ProgressbarBG = colors.gray, + ProgressbarText = colors.black, + ProgressbarActiveBG = colors.black, + ScrollbarBG = colors.lightGray, + ScrollbarText = colors.gray, + ScrollbarSymbolColor = colors.black, + SliderBG = colors.lightGray, + SliderText = colors.gray, + SliderSymbolColor = colors.black, + SwitchBG = colors.lightGray, + SwitchText = colors.gray, + SwitchBGSymbol = colors.black, + SwitchInactive = colors.red, + SwitchActive = colors.green, + } \ No newline at end of file diff --git a/docs/objects/Animation.md b/docs/objects/Animation.md index da6f798..dd7d2fc 100644 --- a/docs/objects/Animation.md +++ b/docs/objects/Animation.md @@ -4,6 +4,8 @@ For now the animation class is very basic, it will be expanded in the future, bu Right now animation is a class which makes use of the timer event.
You can find more information below: +`The animation object is still a WIP and the way you use it right now could change in the future!` + ## add Adds a new function to an animation #### Parameters: @@ -16,9 +18,9 @@ Adds a new function to an animation #### Usage: * This will set the button position to 3,3, waits 1 second, then sets position to 4,4, waits 2 seconds, and then sets the position to 5,5 ```lua -local mainFrame = basalt.createFrame("myFirstFrame"):show() -local testButton = mainFrame:addButton("myTestButton"):show() -local aAnimation = mainFrame:addAnimation("anim1"):add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end) +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end) aAnimation:play() ``` @@ -32,9 +34,9 @@ Sets a wait timer for the next function after the previous function got executed #### Usage: ```lua -local mainFrame = basalt.createFrame("myFirstFrame"):show() -local testButton = mainFrame:addButton("myTestButton"):show() -local aAnimation = mainFrame:addAnimation("anim1"):add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end) +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end) aAnimation:play() ``` @@ -49,9 +51,9 @@ Plays the animation #### Usage: ```lua -local mainFrame = basalt.createFrame("myFirstFrame"):show() -local testButton = mainFrame:addButton("myTestButton"):show() -local aAnimation = mainFrame:addAnimation("anim1"):add(function() testButton:setBackground(colors.black) end):wait(1):add(function() testButton:setBackground(colors.gray) end):wait(1):add(function() testButton:setBackground(colors.lightGray) end) +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() testButton:setBackground(colors.gray) end):wait(1):add(function() testButton:setBackground(colors.lightGray) end) aAnimation:play() -- changes the background color of that button from black to gray and then to lightGray ``` @@ -65,9 +67,128 @@ Cancels the animation #### Usage: ```lua -local mainFrame = basalt.createFrame("myFirstFrame"):show() -local testButton = mainFrame:addButton("myTestButton"):show() -local aAnimation = mainFrame:addAnimation("anim1"):add(function() testButton:setBackground(colors.black) end):wait(1):add(function() aAnimation:cancel() end):wait(1):add(function() testButton:setBackground(colors.lightGray) end) +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() aAnimation:cancel() end):wait(1):add(function() testButton:setBackground(colors.lightGray) end) aAnimation:play() ``` + + +## setObject +Sets the object which the animation should reposition/resize + +#### Parameters: +1. `table` object + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():setObject(testButton) +``` + +## move +Moves the object which got defined by setObject + +#### Parameters: +1. `number` x coordinate +2. `number` y coordinate +1. `number` time in seconds +1. `number` frames (how fluid it should look like) +1. `table` object - optional, you could also define the object here + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():setObject(testButton):move(15,3,1,5):play() +``` + +## move +Moves the object which got defined by setObject + +#### Parameters: +1. `number` x coordinate +2. `number` y coordinate +1. `number` time in seconds +1. `number` frames (how fluid it should look like) +1. `table` object - optional, you could also define the object here + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():setObject(testButton):move(15,3,1,5):play() +``` + +## offset +Changes the offset on the object which got defined by setObject + +#### Parameters: +1. `number` x offset +2. `number` y offset +1. `number` time in seconds +1. `number` frames (how fluid it should look like) +1. `table` object - optional, you could also define the object here + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local subFrame = mainFrame:addFrame():show() +local aAnimation = mainFrame:addAnimation():setObject(subFrame):offset(1,12,1,5):play() +``` + +## size +Changes the size on the object which got defined by setObject + +#### Parameters: +1. `number` width +2. `number` height +1. `number` time in seconds +1. `number` frames (how fluid it should look like) +1. `table` object - optional, you could also define the object here + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():setObject(testButton):size(15,3,1,5):play() +``` + +## textColoring +Changes the text colors of an object + +#### Parameters: +1. `color|number` multiple colors + +#### Returns: +1. `animation` Animation in use + +#### Usage: + +```lua +local mainFrame = basalt.createFrame():show() +local testButton = mainFrame:addButton():show() +local aAnimation = mainFrame:addAnimation():setObject(testButton):textColoring(colors.black, colors.gray, colors.lightGray):play() +``` diff --git a/docs/objects/Installer.md b/docs/objects/Installer.md deleted file mode 100644 index a90324e..0000000 --- a/docs/objects/Installer.md +++ /dev/null @@ -1,73 +0,0 @@ -This is just a script which helps you to install basalt.lua, if it's not already on the computer. Means, you create your program (which requires basalt) and add this on the top of your program. Now, everytime you execute your program it checks if basalt.lua exists or not. If not, it will download it first and then continue to execute your program. - -## Visual Installer -This is a visual version, it asks the user if he wants to install basalt.lua (if not found)
-![](https://i.imgur.com/b4Ys7FB.png) -```lua ---Basalt configurated installer -local filePath = "basalt.lua" --here you can change the file path default: basalt.lua -if not(fs.exists(filePath))then - local w,h = term.getSize() - term.clear() - local _installerWindow = window.create(term.current(),w/2-8,h/2-3,18,6) - _installerWindow.setBackgroundColor(colors.gray) - _installerWindow.setTextColor(colors.black) - _installerWindow.write(" Basalt Installer ") - _installerWindow.setBackgroundColor(colors.lightGray) - for line=2,6,1 do - _installerWindow.setCursorPos(1,line) - if(line==3)then - _installerWindow.write(" No Basalt found! ") - elseif(line==4)then - _installerWindow.write(" Install it? ") - elseif(line==6)then - _installerWindow.setTextColor(colors.black) - _installerWindow.setBackgroundColor(colors.gray) - _installerWindow.write("Install") - _installerWindow.setBackgroundColor(colors.lightGray) - _installerWindow.write(string.rep(" ",5)) - _installerWindow.setBackgroundColor(colors.red) - _installerWindow.write("Cancel") - else - _installerWindow.write(string.rep(" ",18)) - end - end - _installerWindow.setVisible(true) - _installerWindow.redraw() - while(not(fs.exists(filePath))) do - local event, p1,p2,p3,p4 = os.pullEvent() - if(event=="mouse_click")then - if(p3==math.floor(h/2+2))and(p2>=w/2-8)and(p2<=w/2-2)then - shell.run("pastebin run ESs1mg7P") - _installerWindow.setVisible(false) - term.clear() - break - end - if(p3==h/2+2)and(p2<=w/2+9)and(p2>=w/2+4)then - _installerWindow.clear() - _installerWindow.setVisible(false) - term.setCursorPos(1,1) - term.clear() - return - end - end - end - term.setCursorPos(1,1) - term.clear() -end - -local basalt = dofile(filePath) -- here you can change the variablename in any variablename you want default: basalt ------------------------------- -``` - -## Basic Installer -Here is a very basic one which just installs basalt.lua if don't exist: -```lua ---Basalt configurated installer -local filePath = "basalt.lua" --here you can change the file path default: basalt.lua -if not(fs.exists(filePath))then -shell.run("pastebin run ESs1mg7P") -end -local basalt = dofile(filePath) -- here you can change the variablename in any variablename you want default: basalt - -``` \ No newline at end of file