diff --git a/Basalt/libraries/basaltDraw.lua b/Basalt/libraries/basaltDraw.lua index 8c62a31..c16c0ea 100644 --- a/Basalt/libraries/basaltDraw.lua +++ b/Basalt/libraries/basaltDraw.lua @@ -1,6 +1,4 @@ local tHex = require("tHex") -local utils = require("utils") -local split = utils.splitString local sub,rep = string.sub,string.rep return function(drawTerm) @@ -42,33 +40,27 @@ return function(drawTerm) if #t == #fg and #t == #bg then if y >= 1 and y <= height then if x + #t > 0 and x <= width then - local newCacheT, newCacheFG, newCacheBG + local startN = x < 1 and 1 - x + 1 or 1 + local endN = x + #t > width and width - x + 1 or #t + local oldCacheT, oldCacheFG, oldCacheBG = cacheT[y], cacheFG[y], cacheBG[y] - local startN, endN = 1, #t - - if x < 1 then - startN = 1 - x + 1 - endN = width - x + 1 - elseif x + #t > width then - endN = width - x + 1 - end - - newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN) - newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN) - newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN) - + + local newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN) + local newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN) + local newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN) + if x + #t <= width then newCacheT = newCacheT .. sub(oldCacheT, x + #t, width) newCacheFG = newCacheFG .. sub(oldCacheFG, x + #t, width) newCacheBG = newCacheBG .. sub(oldCacheBG, x + #t, width) end - + cacheT[y], cacheFG[y], cacheBG[y] = newCacheT,newCacheFG,newCacheBG end end end end - + local function setText(x, y, t) if y >= 1 and y <= height then if x + #t > 0 and x <= width then @@ -94,7 +86,7 @@ return function(drawTerm) end end - local function setBG(x, y, bg) + local function setBg(x, y, bg) if y >= 1 and y <= height then if x + #bg > 0 and x <= width then local newCacheBG @@ -119,7 +111,7 @@ return function(drawTerm) end end - local function setFG(x, y, fg) + local function setFg(x, y, fg) if y >= 1 and y <= height then if x + #fg > 0 and x <= width then local newCacheFG @@ -144,32 +136,6 @@ return function(drawTerm) end end - --[[ - local function setText(x, y, text) - if (y >= 1) and (y <= height) then - local emptyLine = rep(" ", #text) - blit(x, y, text, emptyLine, emptyLine) - end - end - - local function setFG(x, y, colorStr) - if (y >= 1) and (y <= height) then - local w = #colorStr - local emptyLine = rep(" ", w) - local text = sub(cacheT[y], x, w) - blit(x, y, text, colorStr, emptyLine) - end - end - - local function setBG(x, y, colorStr) - if (y >= 1) and (y <= height) then - local w = #colorStr - local emptyLine = rep(" ", w) - local text = sub(cacheT[y], x, w) - blit(x, y, text, emptyLine, colorStr) - end - end]] - local drawHelper = { setSize = function(w, h) width, height = w, h @@ -180,17 +146,17 @@ return function(drawTerm) mirrorTerm = mirror end, - setBG = function(x, y, colorStr) - setBG(x, y, colorStr) + setBg = function(x, y, colorStr) + setBg(x, y, colorStr) end, setText = function(x, y, text) setText(x, y, text) end, - setFG = function(x, y, colorStr) - setFG(x, y, colorStr) - end; + setFg = function(x, y, colorStr) + setFg(x, y, colorStr) + end, blit = function(x, y, t, fg, bg) blit(x, y, t, fg, bg) @@ -199,13 +165,13 @@ return function(drawTerm) drawBackgroundBox = function(x, y, width, height, bgCol) local colorStr = rep(tHex[bgCol], width) for n = 1, height do - setBG(x, y + (n - 1), colorStr) + setBg(x, y + (n - 1), colorStr) end end, drawForegroundBox = function(x, y, width, height, fgCol) local colorStr = rep(tHex[fgCol], width) for n = 1, height do - setFG(x, y + (n - 1), colorStr) + setFg(x, y + (n - 1), colorStr) end end, drawTextBox = function(x, y, width, height, symbol) diff --git a/Basalt/libraries/basaltEvent.lua b/Basalt/libraries/basaltEvent.lua index f870ad4..e5e256e 100644 --- a/Basalt/libraries/basaltEvent.lua +++ b/Basalt/libraries/basaltEvent.lua @@ -1,3 +1,5 @@ +local tableCount = require("utils").tableCount + return function() local events = {} @@ -18,7 +20,7 @@ return function() end, getEventCount = function(self, _event) - return events[_event]~=nil and #events[_event] or 0 + return _event~=nil and events[_event]~=nil and tableCount(events[_event]) or tableCount(events) end, getEvents = function(self) diff --git a/Basalt/main.lua b/Basalt/main.lua index d30b721..90a845d 100644 --- a/Basalt/main.lua +++ b/Basalt/main.lua @@ -9,8 +9,9 @@ local wrapText = utils.wrapText local count = utils.tableCount local moveThrottle = 300 local dragThrottle = 0 -local renderingThrottle = 0 +local renderingThrottle = 50 local newObjects = {} +local mousePos = {0, 0} local baseTerm = term.current() local version = "1.7.0" @@ -19,6 +20,7 @@ local projectDirectory = fs.getDir(table.pack(...)[2] or "") local activeKey, frames, monFrames, variables, schedules = {}, {}, {}, {}, {} local mainFrame, activeFrame, focusedObject, updaterActive +local renderingTimer = nil local basalt = {} @@ -82,11 +84,39 @@ local createObject = function(basalt, objectName, id) return getObject(objectName)(id, basalt) end +local setRenderingThrottle = function(amount) + if(amount<=0)then + renderingThrottle = 0 + else + renderingTimer = nil + renderingThrottle = amount + end +end + +local getRenderingThrottle = function() + return renderingThrottle +end + +local debugTimer = 0 +local startTimer = function() + debugTimer = os.clock("utc") + basalt.log("Timer started at "..debugTimer.." seconds") +end + +local endTimer = function() + local endT = os.clock("utc") - debugTimer + basalt.log("Timer ended at "..os.clock().." seconds") + basalt.log("Timer ended after "..endT.." seconds") +end + local bInstance = { getDynamicValueEventSetting = function() return basalt.dynamicValueEvents end, - + + getRenderingThrottle = getRenderingThrottle, + setRenderingThrottle = setRenderingThrottle, + getMainFrame = function() return mainFrame end, @@ -239,15 +269,14 @@ local function mouseDragEvent(_, b, x, y) end -local renderingTimer = nil local function renderingUpdateTimer() renderingTimer = nil - drawFrames() + drawFrames() end local function renderingUpdateEvent(timer) - if(renderingThrottle<50)then - drawFrames() + if(renderingThrottle<50)then + drawFrames() else if(renderingTimer==nil)then renderingTimer = os.startTimer(renderingThrottle/1000) @@ -269,6 +298,10 @@ local function basaltUpdateEvent(event, ...) } local mouseEvent = mouseEvents[event] if(mouseEvent~=nil)then + local mouseX, mouseY = a[3], a[4] + if(mouseX~=nil and mouseY~=nil)then + mousePos = {mouseX, mouseY} + end mouseEvent(mainFrame, ...) handleSchedules(event, ...) renderingUpdateEvent() @@ -379,9 +412,9 @@ local function InitializeBasalt() loadedPlugins = true end end +InitializeBasalt() local function createFrame(name) - InitializeBasalt() for _, v in pairs(frames) do if (v:getName() == name) then return nil @@ -433,6 +466,9 @@ basalt = { end return objectNames end, + getMousePosition = function() + return mousePos[1], mousePos[2] + end, setVariable = setVariable, getVariable = getVariable, @@ -467,14 +503,9 @@ basalt = { return false end, - setRenderingThrottle = function(amount) - if(amount<=0)then - renderingThrottle = 0 - else - renderingTimer = nil - renderingThrottle = amount - end - end, + setRenderingThrottle = setRenderingThrottle, + + getRenderingThrottle = getRenderingThrottle, setMouseDragThrottle = function(amount) if(amount<=0)then @@ -559,7 +590,6 @@ basalt = { createFrame = createFrame, addMonitor = function(name) - InitializeBasalt() for _, v in pairs(frames) do if (v:getName() == name) then return nil @@ -572,7 +602,7 @@ basalt = { table.insert(monFrames, newFrame) return newFrame end, - + removeFrame = function(name) frames[name] = nil end, diff --git a/Basalt/objects/BaseFrame.lua b/Basalt/objects/BaseFrame.lua index f04985d..cb84feb 100644 --- a/Basalt/objects/BaseFrame.lua +++ b/Basalt/objects/BaseFrame.lua @@ -5,9 +5,7 @@ local max,min,sub,rep = math.max,math.min,string.sub,string.rep return function(name, basalt) local base = basalt.getObject("Container")(name, basalt) - local objectType = "BaseFrame" - - local xOffset, yOffset = 0, 0 + base:setType("BaseFrame") local colorTheme = {} @@ -18,49 +16,27 @@ return function(name, basalt) local xCursor, yCursor, cursorBlink, cursorColor = 1, 1, false, colors.white - local object = { - getType = function() - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, + base:addProperty("XOffset", "number", 0) + base:addProperty("YOffset", "number", 0) + base:combineProperty("Offset", "XOffset", "YOffset") + base:addProperty("Term", "table", nil, false, function(self, value) + termObject = value + basaltDraw = nil + if(value~=nil)then + basaltDraw = drawSystem(value) + end + end) + base:setSize(termObject.getSize()) + local object = { getBase = function(self) return base end, - getOffset = function(self) - return xOffset, yOffset - end, - - setOffset = function(self, xOff, yOff) - xOffset = xOff or xOffset - yOffset = yOff or yOffset - self:updateDraw() - return self - end, - - getXOffset = function(self) - return xOffset - end, - - setXOffset = function(self, newXOffset) - return self:setOffset(newXOffset, nil) - end, - - getYOffset = function(self) - return yOffset - end, - - setYOffset = function(self, newYOffset) - return self:setOffset(nil, newYOffset) - end, - setPalette = function(self, col, ...) if(self==basalt.getActiveFrame())then if(type(col)=="string")then - local col = colors[col] + col = colors[col] colorTheme[math.log(col, 2)] = ... termObject.setPaletteColor(col, ...) elseif(type(col)=="table")then @@ -84,18 +60,6 @@ return function(name, basalt) return self end, - getSize = function() - return termObject.getSize() - end, - - getWidth = function(self) - return ({termObject.getSize()})[1] - end, - - getHeight = function(self) - return ({termObject.getSize()})[2] - end, - show = function(self) base.show(self) basalt.setActiveFrame(self) @@ -151,20 +115,6 @@ return function(name, basalt) end end, - setTerm = function(self, newTerm) - termObject = newTerm - if(newTerm==nil)then - basaltDraw = nil - else - basaltDraw = drawSystem(termObject) - end - return self - end, - - getTerm = function() - return termObject - end, - blit = function (self, x, y, t, f, b) local obx, oby = self:getPosition() local w, h = self:getSize() @@ -216,7 +166,7 @@ return function(name, basalt) end end - for _,v in pairs({"setBG", "setFG", "setText"}) do + for _,v in pairs({"setBg", "setFg", "setText"}) do object[v] = function(self, x, y, str) local obx, oby = self:getPosition() local w, h = self:getSize() diff --git a/Basalt/objects/Button.lua b/Basalt/objects/Button.lua index f2a5d3b..e601990 100644 --- a/Basalt/objects/Button.lua +++ b/Basalt/objects/Button.lua @@ -4,62 +4,29 @@ local tHex = require("tHex") return function(name, basalt) -- Button local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Button" - local textHorizontalAlign = "center" - local textVerticalAlign = "center" - - local text = "Button" + base:setType("Button") base:setSize(12, 3) - base:setZIndex(5) + base:setZ(5) + + base:addProperty("text", "string", "Button") + base:addProperty("textHorizontalAlign", {"left", "center", "right"}, "center") + base:addProperty("textVerticalAlign", {"left", "center", "right"}, "center") + base:combineProperty("textAlign", "textHorizontalAlign", "textVerticalAlign") local object = { - getType = function(self) - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - getBase = function(self) return base end, - getHorizontalAlign = function(self) - return textHorizontalAlign - end, - - setHorizontalAlign = function(self, pos) - textHorizontalAlign = pos - self:updateDraw() - return self - end, - - getVerticalAlign = function(self) - return textVerticalAlign - end, - - setVerticalAlign = function(self, pos) - textVerticalAlign = pos - self:updateDraw() - return self - end, - - getText = function(self) - return text - end, - - setText = function(self, newText) - text = newText - self:updateDraw() - return self - end, - draw = function(self) base.draw(self) self:addDraw("button", function() local w,h = self:getSize() + local textHorizontalAlign = self:getTextHorizontalAlign() + local textVerticalAlign = self:getTextVerticalAlign() local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) + local text = self:getText() local xOffset if(textHorizontalAlign=="center")then xOffset = math.floor((w - text:len()) / 2) @@ -68,7 +35,7 @@ return function(name, basalt) end self:addText(xOffset + 1, verticalAlign, text) - self:addFG(xOffset + 1, verticalAlign, tHex[self:getForeground() or colors.white]:rep(text:len())) + self:addFg(xOffset + 1, verticalAlign, tHex[self:getForeground() or colors.white]:rep(text:len())) end) end, } diff --git a/Basalt/objects/ChangeableObject.lua b/Basalt/objects/ChangeableObject.lua index 3ef6dd7..0bec0ba 100644 --- a/Basalt/objects/ChangeableObject.lua +++ b/Basalt/objects/ChangeableObject.lua @@ -1,26 +1,21 @@ return function(name, basalt) local base = basalt.getObject("VisualObject")(name, basalt) - -- Base object - local objectType = "ChangeableObject" + base:setType("ChangeableObject") - local value - - local object = { - setValue = function(self, _value, valueChangedHandler) - if (value ~= _value) then - value = _value - self:updateDraw() - if(valueChangedHandler~=false)then - self:valueChangedHandler() - end + base:addProperty("ChangeHandler", "function", nil) + base:addProperty("Value", "any", nil, false, function(self, value) + local _value = self:getValue() + if (value ~= _value) then + local valueChangedHandler = self:getChangeHandler() + if(valueChangedHandler~=nil)then + valueChangedHandler(self, value) end - return self - end, - - getValue = function(self) - return value - end, + self:sendEvent("value_changed", value) + end + return value + end) + local object = { onChange = function(self, ...) for _,v in pairs(table.pack(...))do if(type(v)=="function")then @@ -29,10 +24,6 @@ return function(name, basalt) end return self end, - - valueChangedHandler = function(self) - self:sendEvent("value_changed", value) - end, } object.__index = object diff --git a/Basalt/objects/Checkbox.lua b/Basalt/objects/Checkbox.lua index 298f82c..54a650f 100644 --- a/Basalt/objects/Checkbox.lua +++ b/Basalt/objects/Checkbox.lua @@ -4,72 +4,25 @@ local tHex = require("tHex") return function(name, basalt) -- Checkbox local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Checkbox" + base:setType("Checkbox") - base:setZIndex(5) + base:setZ(5) base:setValue(false) base:setSize(1, 1) - local symbol,inactiveSymbol,text,textPos = "\42"," ","","right" + base:addProperty("activeSymbol", "char", "\42") + base:addProperty("inactiveSymbol", "char", " ") + base:combineProperty("Symbol", "activeSymbol", "inactiveSymbol") + + base:addProperty("text", "string", "") + base:addProperty("textPosition", {"left", "right"}, "right") local object = { load = function(self) self:listenEvent("mouse_click", self) self:listenEvent("mouse_up", self) end, - - getType = function(self) - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - - setSymbol = function(self, sym, inactive) - symbol = sym or symbol - inactiveSymbol = inactive or inactiveSymbol - self:updateDraw() - return self - end, - - setActiveSymbol = function(self, sym) - return self:setSymbol(sym, nil) - end, - - setInactiveSymbol = function(self, inactive) - return self:setSymbol(nil, inactive) - end, - - getSymbol = function(self) - return symbol, inactiveSymbol - end, - - getActiveSymbol = function(self) - return symbol - end, - - getInactiveSymbol = function(self) - return inactiveSymbol - end, - - setText = function(self, _text) - text = _text - return self - end, - - getText = function(self) - return text - end, - - setTextPosition = function(self, pos) - textPos = pos or textPos - return self - end, - - getTextPosition = function(self) - return textPos - end, - + setChecked = base.setValue, getChecked = base.getValue, @@ -92,10 +45,13 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("checkbox", function() - local obx, oby = self:getPosition() local w,h = self:getSize() local verticalAlign = utils.getTextVerticalAlign(h, "center") local bg,fg = self:getBackground(), self:getForeground() + local symbol = self:getActiveSymbol() + local inactiveSymbol = self:getInactiveSymbol() + local text = self:getText() + local textPos = self:getTextPosition() if (self:getValue()) then self:addBlit(1, verticalAlign, utils.getTextHorizontalAlign(symbol, w, "center"), tHex[fg], tHex[bg]) else diff --git a/Basalt/objects/Container.lua b/Basalt/objects/Container.lua index bffad7b..138c362 100644 --- a/Basalt/objects/Container.lua +++ b/Basalt/objects/Container.lua @@ -1,9 +1,10 @@ local utils = require("utils") local tableCount = utils.tableCount +local rpairs = utils.rpairs return function(name, basalt) local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Container" + base:setType("Container") local children = {} @@ -66,7 +67,7 @@ return function(name, basalt) return end objId = objId + 1 - local zIndex = element:getZIndex() + local zIndex = element:getZ() table.insert(children, {element = element, zIndex = zIndex, objId = objId}) sorted = false element:setParent(self, true) @@ -95,11 +96,11 @@ return function(name, basalt) for i, v in ipairs(children) do if v.element == element then table.remove(children, i) + self:removeEvents(element) + sorted = false return true end end - self:removeEvents(element) - sorted = false end local function removeChildren(self) @@ -110,7 +111,8 @@ return function(name, basalt) objId = 0 evId = 0 focusedChild = nil - if parent ~= nil then parent:removeEvents(self) end + parent:removeEvents(self) + self:updateEvents() end local function updateZIndex(self, element, newZ) @@ -145,7 +147,10 @@ return function(name, basalt) end if(tableCount(events[a])<=0)then if(parent~=nil)then - parent:removeEvent(a, self) + if(self:getEventSystem().getEventCount(a)<=0)then + parent:removeEvent(a, self) + self:updateEvents() + end end end end @@ -167,7 +172,7 @@ return function(name, basalt) if (getEvent(self, event, element:getName()) ~= nil) then return end - local zIndex = element:getZIndex() + local zIndex = element:getZ() evId = evId + 1 if(events[event]==nil)then events[event] = {} end table.insert(events[event], {element = element, zIndex = zIndex, evId = evId}) @@ -195,18 +200,10 @@ return function(name, basalt) end container = { - getType = function() - return objectType - end, - getBase = function(self) return base - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false end, - + setSize = function(self, ...) base.setSize(self, ...) self:customEventHandler("basalt_FrameResize") @@ -308,6 +305,23 @@ return function(name, basalt) getFocused = function(self) return focusedChild end, + + getChildrenAt = function(self, x, y) + local results = {} + for _, child in rpairs(children) do + if(child.element.getPosition~=nil)and(child.element.getSize~=nil)then + local xObj, yObj = child.element:getPosition() + local wObj, hObj = child.element:getSize() + local isVisible = child.element:getVisible() + if(isVisible)then + if (x >= xObj and x <= xObj + wObj - 1 and y >= yObj and y <= yObj + hObj - 1) then + table.insert(results, child.element) + end + end + end + end + return results + end, getChild = getChild, getChildren = getChildren, @@ -384,7 +398,7 @@ return function(name, basalt) xO, yO = 0, 0 end end - if (obj.element[v[1]](obj.element, btn, x+xO, y+yO, ...)) then + if (obj.element[v[1]](obj.element, btn, x+xO, y+yO, ...)) then return true end end @@ -426,4 +440,4 @@ return function(name, basalt) container.__index = container return setmetatable(container, base) -end +end \ No newline at end of file diff --git a/Basalt/objects/Dropdown.lua b/Basalt/objects/Dropdown.lua index 0e538df..e801bfa 100644 --- a/Basalt/objects/Dropdown.lua +++ b/Basalt/objects/Dropdown.lua @@ -3,31 +3,21 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("List")(name, basalt) - local objectType = "Dropdown" + base:setType("Dropdown") base:setSize(12, 1) - base:setZIndex(6) + base:setZ(6) - local selectionColorActive = true - local align = "left" - local yOffset = 0 - - local dropdownW = 0 - local dropdownH = 0 - local autoSize = true - local closedSymbol = "\16" - local openedSymbol = "\31" - local isOpened = false + base:addProperty("Align", {"left", "center", "right"}, "left") + base:addProperty("AutoSize", "boolean", true) + base:addProperty("ClosedSymbol", "char", "\16") + base:addProperty("OpenedSymbol", "char", "\31") + base:addProperty("Opened", "boolean", false) + base:addProperty("DropdownWidth", "number", 12) + base:addProperty("DropdownHeight", "number", 0) + base:combineProperty("DropdownSize", "DropdownWidth", "DropdownHeight") local object = { - getType = function(self) - return objectType - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - load = function(self) self:listenEvent("mouse_click", self) self:listenEvent("mouse_up", self) @@ -35,84 +25,49 @@ return function(name, basalt) self:listenEvent("mouse_drag", self) end, - setOffset = function(self, yOff) - yOffset = yOff - self:updateDraw() - return self - end, - - getOffset = function(self) - return yOffset - end, - addItem = function(self, t, ...) base.addItem(self, t, ...) - if(autoSize)then - dropdownW = math.max(dropdownW, #t) - dropdownH = dropdownH + 1 + if(self:getAutoSize())then + local dropdownW, dropdownH = self:getDropdownSize() + self:setDropdownSize(math.max(dropdownW, #t), dropdownH + 1) end return self end, removeItem = function(self, index) base.removeItem(self, index) - if(autoSize)then + local list = self:getAll() + if(self:getAutoSize())then + local dropdownW, dropdownH = self:getDropdownSize() dropdownW = 0 dropdownH = 0 for n = 1, #list do dropdownW = math.max(dropdownW, #list[n].text) end dropdownH = #list + self:setDropdownSize(dropdownW, dropdownH) end + return self end, isOpened = function(self) - return isOpened - end, - - setOpened = function(self, open) - isOpened = open - self:updateDraw() - return self - end, - - setDropdownSize = function(self, width, height) - dropdownW, dropdownH = width, height - autoSize = false - self:updateDraw() - return self - end, - - setDropdownWidth = function(self, width) - return self:setDropdownSize(width, dropdownH) - end, - - setDropdownHeight = function(self, height) - return self:setDropdownSize(dropdownW, height) - end, - - getDropdownSize = function(self) - return dropdownW, dropdownH - end, - - getDropdownWidth = function(self) - return dropdownW - end, - - getDropdownHeight = function(self) - return dropdownH + return self:getOpened() end, mouseHandler = function(self, button, x, y, isMon) + local isOpened = self:getOpened() if (isOpened) then local obx, oby = self:getAbsolutePosition() if(button==1)then local list = self:getAll() if (#list > 0) then + local dropdownW, dropdownH = self:getDropdownSize() + local offset = self:getOffset() for n = 1, dropdownH do - if (list[n + yOffset] ~= nil) then + if (list[n + offset] ~= nil) then if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then - self:setValue(list[n + yOffset]) + self:setValue(list[n + offset]) + self:selectHandler() self:updateDraw() local val = self:sendEvent("mouse_click", self, "mouse_click", button, x, y) if(val==false)then return val end @@ -131,29 +86,32 @@ return function(name, basalt) end local base = base:getBase() if (base.mouseHandler(self, button, x, y)) then - isOpened = not isOpened + self:setOpened(not isOpened) self:getParent():setImportant(self) self:updateDraw() return true else if(isOpened)then self:updateDraw() - isOpened = false - end + self:setOpened(false) + end return false end end, mouseUpHandler = function(self, button, x, y) + local isOpened = self:getOpened() if (isOpened) then local obx, oby = self:getAbsolutePosition() if(button==1)then local list = self:getAll() if (#list > 0) then + local dropdownW, dropdownH = self:getDropdownSize() + local offset = self:getOffset() for n = 1, dropdownH do - if (list[n + yOffset] ~= nil) then + if (list[n + offset] ~= nil) then if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then - isOpened = false + self:setOpened(false) self:updateDraw() local val = self:sendEvent("mouse_up", self, "mouse_up", button, x, y) if(val==false)then return val end @@ -168,11 +126,13 @@ return function(name, basalt) dragHandler = function(self, btn, x, y) if(base.dragHandler(self, btn, x, y))then - isOpened = true + self:setOpened(true) end end, scrollHandler = function(self, dir, x, y) + local isOpened = self:getOpened() + local dropdownW, dropdownH = self:getDropdownSize() if(isOpened)then local xPos, yPos = self:getAbsolutePosition() if(x >= xPos)and(x <= xPos + dropdownW)and(y >= yPos)and(y <= yPos + dropdownH)then @@ -187,19 +147,21 @@ return function(name, basalt) if(#self:getAll() <= dropdownH)then return false end local list = self:getAll() - yOffset = yOffset + dir - if (yOffset < 0) then - yOffset = 0 + + local offset = self:getOffset() + dir + if (offset < 0) then + offset = 0 end if (dir == 1) then if (#list > dropdownH) then - if (yOffset > #list - dropdownH) then - yOffset = #list - dropdownH + if (offset > #list - dropdownH) then + offset = #list - dropdownH end else - yOffset = math.min(#list - 1, 0) + offset = math.min(#list - 1, 0) end end + self:setOffset(offset) local val = self:sendEvent("mouse_scroll", self, "mouse_scroll", dir, x, y) if(val==false)then return val end self:updateDraw() @@ -211,11 +173,16 @@ return function(name, basalt) base.draw(self) self:setDrawState("list", false) self:addDraw("dropdown", function() - local obx, oby = self:getPosition() local w,h = self:getSize() local val = self:getValue() local list = self:getAll() local bgCol, fgCol = self:getBackground(), self:getForeground() + local openedSymbol, closedSymbol = self:getOpenedSymbol(), self:getClosedSymbol() + local align = self:getAlign() + local dropdownW, dropdownH = self:getDropdownSize() + local offset = self:getOffset() + local selectionColorActive = self:getSelectionColorActive() + local isOpened = self:getOpened() local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), w, align):sub(1, w - 1) .. (isOpened and openedSymbol or closedSymbol) self:addBlit(1, 1, text, tHex[fgCol]:rep(#text), tHex[bgCol]:rep(#text)) @@ -224,17 +191,17 @@ return function(name, basalt) self:addBackgroundBox(1, 2, dropdownW, dropdownH, bgCol) self:addForegroundBox(1, 2, dropdownW, dropdownH, fgCol) for n = 1, dropdownH do - if (list[n + yOffset] ~= nil) then - local t =utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align) - if (list[n + yOffset] == val) then + if (list[n + offset] ~= nil) then + local t =utils.getTextHorizontalAlign(list[n + offset].text, dropdownW, align) + if (list[n + offset] == val) then if (selectionColorActive) then local itemSelectedBG, itemSelectedFG = self:getSelectionColor() self:addBlit(1, n+1, t, tHex[itemSelectedFG]:rep(#t), tHex[itemSelectedBG]:rep(#t)) else - self:addBlit(1, n+1, t, tHex[list[n + yOffset].fgCol]:rep(#t), tHex[list[n + yOffset].bgCol]:rep(#t)) + self:addBlit(1, n+1, t, tHex[list[n + offset].fgCol]:rep(#t), tHex[list[n + offset].bgCol]:rep(#t)) end else - self:addBlit(1, n+1, t, tHex[list[n + yOffset].fgCol]:rep(#t), tHex[list[n + yOffset].bgCol]:rep(#t)) + self:addBlit(1, n+1, t, tHex[list[n + offset].fgCol]:rep(#t), tHex[list[n + offset].bgCol]:rep(#t)) end end end diff --git a/Basalt/objects/Flexbox.lua b/Basalt/objects/Flexbox.lua index d0aa4f9..bae60bd 100644 --- a/Basalt/objects/Flexbox.lua +++ b/Basalt/objects/Flexbox.lua @@ -1,39 +1,14 @@ local function flexObjectPlugin(base, basalt) - local flexGrow = 0 - local flexShrink = 0 - local flexBasis = 0 - local baseWidth, baseHeight = base:getSize() + if(base:getType()~="lineBreakFakeObject")then + base:addProperty("FlexGrow", "number", 0) + base:addProperty("FlexShrink", "number", 0) + base:addProperty("FlexBasis", "number", 0) + end + local object = { - getFlexGrow = function(self) - return flexGrow - end, - - setFlexGrow = function(self, value) - flexGrow = value - return self - end, - - getFlexShrink = function(self) - return flexShrink - end, - - setFlexShrink = function(self, value) - flexShrink = value - return self - end, - - getFlexBasis = function(self) - return flexBasis - end, - - setFlexBasis = function(self, value) - flexBasis = value - return self - end, - getBaseSize = function(self) return baseWidth, baseHeight end, @@ -61,15 +36,29 @@ end return function(name, basalt) local base = basalt.getObject("ScrollableFrame")(name, basalt) - local objectType = "Flexbox" + base:setType("Flexbox") + + local updateLayout = false + + base:addProperty("FlexDirection", {"row", "column"}, "row", nil, function(self, direction) + if(direction=="row")then + self:setScrollDirection("horizontal") + elseif(direction=="column")then + self:setScrollDirection("vertical") + end + end) + base:addProperty("Spacing", "number", 1, nil, function(self, spacing) + updateLayout = true + end) + base:addProperty("JustifyContent", {"flex-start", "flex-end", "center", "space-between", "space-around", "space-evenly"}, "flex-start", nil, function(self, justifyContent) + updateLayout = true + end) + base:addProperty("Wrap", {"nowrap", "wrap"}, "nowrap", nil, function(self, wrap) + updateLayout = true + end) - local direction = "row" - local spacing = 1 - local justifyContent = "flex-start" - local wrap = "nowrap" local children = {} local sortedChildren = {} - local updateLayout = false local lineBreakFakeObject = flexObjectPlugin({ getBaseHeight = function(self) return 0 end, getBaseWidth = function(self) return 0 end, @@ -79,10 +68,15 @@ return function(name, basalt) getType = function(self) return "lineBreakFakeObject" end, setPosition = function(self) end, setSize = function(self) end, + getFlexGrow = function(self) return 0 end, + getFlexShrink = function(self) return 0 end, + getFlexBasis = function(self) return 0 end, }) - lineBreakFakeObject:setFlexBasis(0):setFlexGrow(0):setFlexShrink(0) - local function sortChildren(self) + local direction = self:getDirection() + local spacing = self:getSpacing() + local wrap = self:getWrap() + if(wrap=="nowrap")then sortedChildren = {} local index = 1 @@ -146,6 +140,9 @@ return function(name, basalt) local function calculateRow(self, children) local containerWidth, containerHeight = self:getSize() + local spacing = self:getSpacing() + local justifyContent = self:getJustifyContent() + local totalFlexGrow = 0 local totalFlexShrink = 0 local totalFlexBasis = 0 @@ -234,6 +231,9 @@ return function(name, basalt) local function calculateColumn(self, children) local containerWidth, containerHeight = self:getSize() + local spacing = self:getSpacing() + local justifyContent = self:getJustifyContent() + local totalFlexGrow = 0 local totalFlexShrink = 0 local totalFlexBasis = 0 @@ -324,7 +324,7 @@ return function(name, basalt) local function applyLayout(self) sortChildren(self) - if direction == "row" then + if self:getDirection() == "row" then for _,v in pairs(sortedChildren)do calculateRow(self, v) end @@ -337,58 +337,6 @@ return function(name, basalt) end local object = { - getType = function() - return objectType - end, - - isType = function(self, t) - return objectType == t or base.isType ~= nil and base.isType(t) or false - end, - - setJustifyContent = function(self, value) - justifyContent = value - updateLayout = true - self:updateDraw() - return self - end, - - getJustifyContent = function(self) - return justifyContent - end, - - setDirection = function(self, value) - direction = value - updateLayout = true - self:updateDraw() - return self - end, - - getDirection = function(self) - return direction - end, - - setSpacing = function(self, value) - spacing = value - updateLayout = true - self:updateDraw() - return self - end, - - getSpacing = function(self) - return spacing - end, - - setWrap = function(self, value) - wrap = value - updateLayout = true - self:updateDraw() - return self - end, - - getWrap = function(self) - return wrap - end, - updateLayout = function(self) updateLayout = true self:updateDraw() @@ -430,5 +378,4 @@ return function(name, basalt) object.__index = object return setmetatable(object, base) -end - +end \ No newline at end of file diff --git a/Basalt/objects/Frame.lua b/Basalt/objects/Frame.lua index 472f488..c2c9847 100644 --- a/Basalt/objects/Frame.lua +++ b/Basalt/objects/Frame.lua @@ -4,54 +4,19 @@ local max,min,sub,rep,len = math.max,math.min,string.sub,string.rep,string.len return function(name, basalt) local base = basalt.getObject("Container")(name, basalt) - local objectType = "Frame" + base:setType("Frame") local parent - local updateRender = true - - local xOffset, yOffset = 0, 0 - base:setSize(30, 10) - base:setZIndex(10) + base:setZ(10) - local object = { - getType = function() - return objectType - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, + base:addProperty("XOffset", "number", 0) + base:addProperty("YOffset", "number", 0) + base:combineProperty("Offset", "XOffset", "YOffset") + local object = { getBase = function(self) return base - end, - - getOffset = function(self) - return xOffset, yOffset - end, - - setOffset = function(self, xOff, yOff) - xOffset = xOff or xOffset - yOffset = yOff or yOffset - self:updateDraw() - return self - end, - - getXOffset = function(self) - return xOffset - end, - - setXOffset = function(self, newXOffset) - return self:setOffset(newXOffset, nil) - end, - - getYOffset = function(self) - return yOffset - end, - - setYOffset = function(self, newYOffset) - return self:setOffset(nil, newYOffset) end, setParent = function(self, p, ...) @@ -93,7 +58,7 @@ return function(name, basalt) local b_visible = sub(b, max(1 - x + 1, 1), max(w - x + 1, 1)) parent:blit(max(x + (obx - 1), obx), oby + y - 1, t_visible, f_visible, b_visible) end - end, + end, setCursor = function(self, blink, x, y, color) local obx, oby = self:getPosition() @@ -103,7 +68,7 @@ return function(name, basalt) end, } - for k,v in pairs({"drawBackgroundBox", "drawForegroundBox", "drawTextBox"})do + for _,v in pairs({"drawBackgroundBox", "drawForegroundBox", "drawTextBox"})do object[v] = function(self, x, y, width, height, symbol) local obx, oby = self:getPosition() local xO, yO = parent:getOffset() @@ -115,7 +80,7 @@ return function(name, basalt) end end - for k,v in pairs({"setBG", "setFG", "setText"})do + for _,v in pairs({"setBg", "setFg", "setText"})do object[v] = function(self, x, y, str) local obx, oby = self:getPosition() local xO, yO = parent:getOffset() diff --git a/Basalt/objects/Graph.lua b/Basalt/objects/Graph.lua index f6a145c..37a4263 100644 --- a/Basalt/objects/Graph.lua +++ b/Basalt/objects/Graph.lua @@ -1,50 +1,24 @@ return function(name, basalt) - local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Graph" + local base = basalt.getObject("VisualObject")(name, basalt) + base:setType("Graph") - base:setZIndex(5) + base:setZ(5) base:setSize(30, 10) + base:addProperty("GraphColor", "color", colors.gray) + base:addProperty("GraphSymbol", "char", "\7") + base:addProperty("GraphSymbolColor", "color", colors.black) + base:addProperty("MaxValue", "number", 100) + base:addProperty("MinValue", "number", 0) + base:addProperty("GraphType", {"bar", "line", "scatter"}, "line") + base:addProperty("MaxEntries", "number", 10) + local graphData = {} - local graphColor = colors.gray - local graphSymbol = "\7" - local graphSymbolCol = colors.black - local maxValue = 100 - local minValue = 0 - local graphType = "line" - local maxEntries = 10 local object = { - getType = function(self) - return objectType - end, - - setGraphColor = function(self, color) - graphColor = color or graphColor - self:updateDraw() - return self - end, - - setGraphSymbol = function(self, symbol, symbolcolor) - graphSymbol = symbol or graphSymbol - graphSymbolCol = symbolcolor or graphSymbolCol - self:updateDraw() - return self - end, - - setGraphSymbolColor = function(self, symbolColor) - return self:setGraphSymbolColor(nil, symbolColor) - end, - - getGraphSymbol = function(self) - return graphSymbol, graphSymbolCol - end, - - getGraphSymbolColor = function(self) - return graphSymbolCol - end, - addDataPoint = function(self, value) + local minValue = self:getMinValue() + local maxValue = self:getMaxValue() if value >= minValue and value <= maxValue then table.insert(graphData, value) self:updateDraw() @@ -55,48 +29,6 @@ return function(name, basalt) return self end, - setMaxValue = function(self, value) - maxValue = value - self:updateDraw() - return self - end, - - getMaxValue = function(self) - return maxValue - end, - - setMinValue = function(self, value) - minValue = value - self:updateDraw() - return self - end, - - getMinValue = function(self) - return minValue - end, - - setGraphType = function(self, graph_type) - if graph_type == "scatter" or graph_type == "line" or graph_type == "bar" then - graphType = graph_type - self:updateDraw() - end - return self - end, - - getGraphType = function(self) - return graphType - end, - - setMaxEntries = function(self, value) - maxEntries = value - self:updateDraw() - return self - end, - - getMaxEntries = function(self) - return maxEntries - end, - clear = function(self) graphData = {} self:updateDraw() @@ -106,9 +38,14 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("graph", function() - local obx, oby = self:getPosition() local w, h = self:getSize() - local bgCol, fgCol = self:getBackground(), self:getForeground() + local graphColor = self:getGraphColor() + local graphSymbol = self:getGraphSymbol() + local graphSymbolCol = self:getGraphSymbolColor() + local maxValue = self:getMaxValue() + local minValue = self:getMinValue() + local graphType = self:getGraphType() + local maxEntries = self:getMaxEntries() local range = maxValue - minValue local prev_x, prev_y @@ -133,23 +70,23 @@ return function(name, basalt) local sx = prev_x < x and 1 or -1 local sy = prev_y < y and 1 or -1 local err = dx - dy - + while true do self:addBackgroundBox(prev_x, prev_y, 1, 1, graphColor) self:addForegroundBox(prev_x, prev_y, 1, 1, graphSymbolCol) self:addTextBox(prev_x, prev_y, 1, 1, graphSymbol) - + if prev_x == x and prev_y == y then break end - + local e2 = 2 * err - + if e2 > -dy then err = err - dy prev_x = prev_x + sx end - + if e2 < dx then err = err + dx prev_y = prev_y + sy diff --git a/Basalt/objects/Image.lua b/Basalt/objects/Image.lua index 63e8fd9..0db4f10 100644 --- a/Basalt/objects/Image.lua +++ b/Basalt/objects/Image.lua @@ -4,7 +4,7 @@ local unpack,sub,max,min = table.unpack,string.sub,math.max,math.min return function(name, basalt) -- Image local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Image" + base:setType("Image") local bimgLibrary = bimg() local bimgFrame = bimgLibrary.getFrameObject(1) @@ -16,11 +16,14 @@ return function(name, basalt) local animTimer local usePalette = false local autoSize = true + local x, y = 1, 1 - local xOffset, yOffset = 0, 0 + base:addProperty("XOffset", "number", 0) + base:addProperty("YOffset", "number", 0) + base:combineProperty("Offset", "XOffset", "YOffset") base:setSize(24, 8) - base:setZIndex(2) + base:setZ(2) local function getPalette() local p = {} @@ -53,51 +56,12 @@ return function(name, basalt) end local object = { - getType = function(self) - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - - setOffset = function(self, _x, _y, rel) - if(rel)then - xOffset = xOffset + _x or 0 - yOffset = yOffset + _y or 0 - else - xOffset = _x or xOffset - yOffset = _y or yOffset - end - self:updateDraw() - return self - end, - - setXOffset = function(self, _x) - return self:setOffset(self, _x, nil) - end, - - setYOffset = function(self, _y) - return self:setOffset(self, nil, _y) - end, - setSize = function(self, _x, _y) base:setSize(_x, _y) autoSize = false return self end, - getOffset = function(self) - return xOffset, yOffset - end, - - getXOffset = function(self) - return xOffset - end, - - getYOffset = function(self) - return yOffset - end, - selectFrame = function(self, id) if(bimgLibrary.getFrameObject(id)==nil)then bimgLibrary.addFrame(id) @@ -145,7 +109,7 @@ return function(name, basalt) loadImage = function(self, path) if(fs.exists(path))then - local newBimg = images.loadImageAsBimg(path) + local newBimg = images.loadBIMG(path) bimgLibrary = bimg(newBimg) activeFrame = 1 bimgFrame = bimgLibrary.getFrameObject(1) @@ -334,10 +298,11 @@ return function(name, basalt) end if(usePalette)then - self:getParent():setPalette(getPalette(activeFrame)) + self:getParent():setPalette(getPalette()) end if(image~=nil)then + local xOffset, yOffset = self:getOffset() for k,v in pairs(image)do if(k+yOffset<=h)and(k+yOffset>=1)then local t,f,b = v[1],v[2],v[3] diff --git a/Basalt/objects/Input.lua b/Basalt/objects/Input.lua index f2819b8..e6763fd 100644 --- a/Basalt/objects/Input.lua +++ b/Basalt/objects/Input.lua @@ -4,21 +4,26 @@ local tHex = require("tHex") return function(name, basalt) -- Input local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Input" + base:setType("Input") - local inputType = "text" - local inputLimit = 0 - base:setZIndex(5) + base:setZ(5) base:setValue("") base:setSize(12, 1) - local textX = 1 - local wIndex = 1 + local showingText = "" + + base:addProperty("defaultText", "string", "", nil, function(self, value) + showingText = value + end) + base:addProperty("defaultForeground", "color", nil) + base:addProperty("defaultBackground", "color", nil) + base:combineProperty("default", "defaultText", "defaultForeground", "defaultBackground") + base:addProperty("offset", "number", 1) + base:addProperty("cursorPosition", "number", 1) + base:addProperty("inputType", {"text", "number", "password"}, "text") + base:addProperty("inputLimit", "number", 0) + base:addProperty("align", {"left", "center", "right"}, "left") - local defaultText = "" - local defaultBGCol = colors.black - local defaultFGCol = colors.lightGray - local showingText = defaultText local internalValueChange = false local object = { @@ -30,73 +35,13 @@ return function(name, basalt) self:listenEvent("mouse_drag") end, - getType = function(self) - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - - setDefaultFG = function(self, fCol) - return self:setDefaultText(self, defaultText, fCol, nil) - end, - - setDefaultBG = function(self, bCol) - return self:setDefaultText(self, defaultText, nil, bCol) - end, - - setDefaultText = function(self, text, fCol, bCol) - defaultText = text - defaultFGCol = fCol or defaultFGCol - defaultBGCol = bCol or defaultBGCol - if (self:isFocused()) then - showingText = "" - else - showingText = defaultText - end - self:updateDraw() - return self - end, - - getDefaultText = function(self) - return defaultText, defaultFGCol, defaultBGCol - end, - - setOffset = function(self, x) - wIndex = x - self:updateDraw() - return self - end, - - getOffset = function(self) - return wIndex - end, - - setTextOffset = function(self, x) - textX = x - self:updateDraw() - return self - end, - - getTextOffset = function(self) - return textX - end, - - setInputType = function(self, t) - inputType = t - self:updateDraw() - return self - end, - - getInputType = function(self) - return inputType - end, - setValue = function(self, val) base.setValue(self, tostring(val)) if not (internalValueChange) then - textX = tostring(val):len() + 1 - wIndex = math.max(1, textX-self:getWidth()+1) + local textX = tostring(val):len() + 1 + local wIndex = math.max(1, textX-self:getWidth()+1) + self:setOffset(wIndex) + self:setCursorPosition(textX) if(self:isFocused())then local parent = self:getParent() local obx, oby = self:getPosition() @@ -107,39 +52,23 @@ return function(name, basalt) return self end, - getValue = function(self) - local val = base.getValue(self) - return inputType == "number" and tonumber(val) or val - end, - - setInputLimit = function(self, limit) - inputLimit = tonumber(limit) or inputLimit - self:updateDraw() - return self - end, - - getInputLimit = function(self) - return inputLimit - end, - getFocusHandler = function(self) base.getFocusHandler(self) local parent = self:getParent() if (parent ~= nil) then - local obx, oby = self:getPosition() + local defaultText = self:getDefaultText() showingText = "" if(defaultText~="")then self:updateDraw() end - parent:setCursor(true, obx + textX - wIndex, oby+math.max(math.ceil(self:getHeight()/2-1, 1)), self:getForeground()) end end, loseFocusHandler = function(self) base.loseFocusHandler(self) local parent = self:getParent() - showingText = defaultText - if(defaultText~="")then + showingText = self:getDefaultText() + if(showingText~="")then self:updateDraw() end parent:setCursor(false) @@ -150,9 +79,11 @@ return function(name, basalt) local w,h = self:getSize() local parent = self:getParent() internalValueChange = true + local wIndex = self:getOffset() + local textX = self:getCursorPosition() if (key == keys.backspace) then -- on backspace - local text = tostring(base.getValue()) + local text = tostring(self:getValue()) if (textX > 1) then self:setValue(text:sub(1, textX - 2) .. text:sub(textX, text:len())) textX = math.max(textX - 1, 1) @@ -165,7 +96,7 @@ return function(name, basalt) parent:clearFocusedChild(self) end if (key == keys.right) then - local tLength = tostring(base.getValue()):len() + local tLength = tostring(self:getValue()):len() textX = textX + 1 if (textX > tLength) then @@ -189,9 +120,18 @@ return function(name, basalt) textX = math.max(textX, 1) wIndex = math.max(wIndex, 1) end - local obx, oby = self:getPosition() - local val = tostring(base.getValue()) - + if (key == keys.home) then + -- home + textX = 1 + wIndex = 1 + end + if (key == keys["end"]) then + -- end + textX = tostring(self:getValue()):len() + 1 + wIndex = math.max(textX - w + 1, 1) + end + self:setOffset(wIndex) + self:setCursorPosition(textX) self:updateDraw() internalValueChange = false return true @@ -201,8 +141,12 @@ return function(name, basalt) charHandler = function(self, char) if (base.charHandler(self, char)) then internalValueChange = true + local wIndex = self:getOffset() + local textX = self:getCursorPosition() local w,h = self:getSize() - local text = base.getValue() + local text = tostring(self:getValue()) + local inputType = self:getInputType() + local inputLimit = self:getInputLimit() if (text:len() < inputLimit or inputLimit <= 0) then if (inputType == "number") then local cache = text @@ -210,7 +154,7 @@ return function(name, basalt) self:setValue(text:sub(1, textX - 1) .. char .. text:sub(textX, text:len())) textX = textX + 1 if(char==".")or(char=="-")and(#text>0)then - if (tonumber(base.getValue()) == nil) then + if (tonumber(self:getValue()) == nil) then self:setValue(cache) textX = textX - 1 end @@ -223,9 +167,9 @@ return function(name, basalt) if (textX >= w + wIndex) then wIndex = wIndex + 1 end + self:setOffset(wIndex) + self:setCursorPosition(textX) end - local obx, oby = self:getPosition() - local val = tostring(base.getValue()) internalValueChange = false self:updateDraw() @@ -235,12 +179,12 @@ return function(name, basalt) mouseHandler = function(self, button, x, y) if(base.mouseHandler(self, button, x, y))then - local parent = self:getParent() local ax, ay = self:getPosition() local obx, oby = self:getAbsolutePosition(ax, ay) - local w, h = self:getSize() + local wIndex = self:getOffset() + local textX = self:getCursorPosition() textX = x - obx + wIndex - local text = base.getValue() + local text = tostring(self:getValue()) if (textX > text:len()) then textX = text:len() + 1 end @@ -250,7 +194,8 @@ return function(name, basalt) wIndex = 1 end end - parent:setCursor(true, ax + textX - wIndex, ay+math.max(math.ceil(h/2-1, 1)), self:getForeground()) + self:setOffset(wIndex) + self:setCursorPosition(textX) return true end end, @@ -270,7 +215,24 @@ return function(name, basalt) eventHandler = function(self, event, paste, ...) base.eventHandler(self, event, paste, ...) if(event=="paste")then - self:setValue(self:getValue()..paste) + if(self:isFocused())then + local text = tostring(self:getValue()) + local textX = self:getCursorPosition() + local inputType = self:getInputType() + if (inputType == "number") then + local cache = text + if (paste == ".") or (tonumber(paste) ~= nil) then + self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len())) + end + if (tonumber(self:getValue()) == nil) then + self:setValue(cache) + end + else + self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len())) + end + + self:updateDraw() + end end end, @@ -280,16 +242,24 @@ return function(name, basalt) local parent = self:getParent() local obx, oby = self:getPosition() local w,h = self:getSize() - local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) + local wIndex = self:getOffset() + local textX = self:getCursorPosition() + local defaultBGCol = self:getDefaultBackground() + local defaultFGCol = self:getDefaultForeground() + local inputType = self:getInputType() + + local verticalAlign = utils.getTextVerticalAlign(h, "center") - local val = tostring(base.getValue()) + local val = tostring(self:getValue() or "") local bCol = self:getBackground() local fCol = self:getForeground() local text if (val:len() <= 0) then - text = showingText - bCol = defaultBGCol or bCol - fCol = defaultFGCol or fCol + if not(self:isFocused())then + text = showingText + bCol = defaultBGCol or bCol + fCol = defaultFGCol or fCol + end end text = showingText diff --git a/Basalt/objects/Label.lua b/Basalt/objects/Label.lua index 823a363..0db5c92 100644 --- a/Basalt/objects/Label.lua +++ b/Basalt/objects/Label.lua @@ -1,123 +1,65 @@ local utils = require("utils") local wrapText = utils.wrapText local writeWrappedText = utils.writeWrappedText -local tHex = require("tHex") return function(name, basalt) -- Label local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Label" + base:setType("Label") - base:setZIndex(3) + base:setZ(3) base:setSize(5, 1) - base:setBackground(false) - local fgChanged = false - - local autoSize = true - local text, textAlign = "Label", "left" + base:addProperty("text", "string", "Label", nil, function(self, value) + local autoSize = self:getAutoSize() + if(autoSize)then + local t = wrapText(value, #value) + local newW, newH = 1,1 + for _,v in pairs(t)do + newH = newH+1 + newW = math.max(newW, v:len()) + end + self:setSize(newW, newH) + self:setAutoSize(true) + end + end) + base:addProperty("autoSize", "boolean", true) + base:addProperty("textAlign", {"left", "center", "right"}, "left") local object = { - --- Returns the object type. - --- @return string - getType = function(self) - return objectType + init = function(self) + base.init(self) + local parent = self:getParent() + self:setBackground(nil) + self:setForeground(parent:getForeground()) end, - --- Returns the label's base object. --- @return object getBase = function(self) return base end, - --- Changes the label's text. - --- @param newText string The new text of the label. - --- @return object - setText = function(self, newText) - text = tostring(newText) - if(autoSize)then - local t = wrapText(text, #text) - local newW, newH = 1,1 - for k,v in pairs(t)do - newH = newH+1 - newW = math.max(newW, v:len()) - end - self:setSize(newW, newH) - autoSize = true - end - self:updateDraw() - return self - end, - - setForeground = function(self, col) - base.setForeground(self, col) - fgChanged = true - return self - end, - - --- Returns the label's autoSize property. - --- @return boolean - getAutoSize = function(self) - return autoSize - end, - - --- Sets the label's autoSize property. - --- @param bool boolean The new value of the autoSize property. - --- @return object - setAutoSize = function(self, bool) - autoSize = bool - return self - end, - - --- Returns the label's text. - --- @return string - getText = function(self) - return text - end, - --- Sets the size of the label. --- @param width number The width of the label. --- @param height number The height of the label. --- @return object setSize = function(self, width, height) base.setSize(self, width, height) - autoSize = false + self:setAutoSize(false) return self end, - --- Gets the text alignment of the label. - --- @return string - getTextAlign = function(self) - return textAlign - end, - - --- Sets the text alignment of the label. - --- @param align string The alignment of the text. Can be "left", "center", or "right". - --- @return object - setTextAlign = function(self, align) - textAlign = align or textAlign - return self; - end, - --- Queues a new draw function to be called when the object is drawn. draw = function(self) base.draw(self) self:addDraw("label", function() local w, h = self:getSize() + local text = self:getText() + local textAlign = self:getTextAlign() local align = textAlign=="center" and math.floor(w/2-text:len()/2+0.5) or textAlign=="right" and w-(text:len()-1) or 1 writeWrappedText(self, align, 1, text, w+1, h) end) end, - - --- Initializes the label. - init = function(self) - base.init(self) - local parent = self:getParent() - if not(fgChanged)then - self:setForeground(parent:getForeground()) - end - end - } object.__index = object diff --git a/Basalt/objects/List.lua b/Basalt/objects/List.lua index 1927638..16a18cf 100644 --- a/Basalt/objects/List.lua +++ b/Basalt/objects/List.lua @@ -3,22 +3,23 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "List" + base:setType("List") local list = {} - local itemSelectedBG = colors.black - local itemSelectedFG = colors.lightGray - local selectionColorActive = true - local textAlign = "left" - local yOffset = 0 - local scrollable = true base:setSize(16, 8) - base:setZIndex(5) + base:setZ(5) + + base:addProperty("SelectionBackground", "color", colors.black) + base:addProperty("SelectionForeground", "color", colors.lightGray) + base:combineProperty("SelectionColor", "SelectionBackground", "SelectionForeground") + base:addProperty("selectionColorActive", "boolean", true) + base:addProperty("textAlign", {"left", "center", "right"}, "left") + base:addProperty("scrollable", "boolean", true) + base:addProperty("offset", "number", 0) local object = { init = function(self) - local parent = self:getParent() self:listenEvent("mouse_click") self:listenEvent("mouse_drag") self:listenEvent("mouse_scroll") @@ -29,27 +30,6 @@ return function(name, basalt) return base end, - setTextAlign = function(self, align) - textAlign = align - return self - end, - - getTextAlign = function(self) - return textAlign - end, - - getBase = function(self) - return base - end, - - getType = function(self) - return objectType - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, - addItem = function(self, text, bgCol, fgCol, ...) table.insert(list, { text = text, bgCol = bgCol or self:getBackground(), fgCol = fgCol or self:getForeground(), args = { ... } }) if (#list <= 1) then @@ -73,16 +53,6 @@ return function(name, basalt) return self end, - setOffset = function(self, yOff) - yOffset = yOff - self:updateDraw() - return self - end, - - getOffset = function(self) - return yOffset - end, - removeItem = function(self, index) if(type(index)=="number")then table.remove(list, index) @@ -143,69 +113,29 @@ return function(name, basalt) return self end, - setSelectionColor = function(self, bgCol, fgCol, active) - itemSelectedBG = bgCol or self:getBackground() - itemSelectedFG = fgCol or self:getForeground() - selectionColorActive = active~=nil and active or true - self:updateDraw() - return self - end, - - setSelectionBG = function(self, bgCol) - return self:setSelectionColor(bgCol, nil, selectionColorActive) - end, - - setSelectionFG = function(self, fgCol) - return self:setSelectionColor(nil, fgCol, selectionColorActive) - end, - - getSelectionColor = function(self) - return itemSelectedBG, itemSelectedFG - end, - - getSelectionBG = function(self) - return itemSelectedBG - end, - - getSelectionFG = function(self) - return itemSelectedFG - end, - - isSelectionColorActive = function(self) - return selectionColorActive - end, - - setScrollable = function(self, scroll) - scrollable = scroll - if(scroll==nil)then scrollable = true end - self:updateDraw() - return self - end, - - getScrollable = function(self) - return scrollable - end, - scrollHandler = function(self, dir, x, y) if(base.scrollHandler(self, dir, x, y))then + local scrollable = self:getScrollable() if(scrollable)then + local offset = self:getOffset() local w,h = self:getSize() - yOffset = yOffset + dir - if (yOffset < 0) then - yOffset = 0 + offset = offset + dir + if (offset < 0) then + offset = 0 end if (dir >= 1) then if (#list > h) then - if (yOffset > #list - h) then - yOffset = #list - h + if (offset > #list - h) then + offset = #list - h end - if (yOffset >= #list) then - yOffset = #list - 1 + if (offset >= #list) then + offset = #list - 1 end else - yOffset = yOffset - 1 + offset = offset - 1 end end + self:setOffset(offset) self:updateDraw() end return true @@ -218,10 +148,11 @@ return function(name, basalt) local obx, oby = self:getAbsolutePosition() local w,h = self:getSize() if (#list > 0) then + local offset = self:getOffset() for n = 1, h do - if (list[n + yOffset] ~= nil) then + if (list[n + offset] ~= nil) then if (obx <= x) and (obx + w > x) and (oby + n - 1 == y) then - self:setValue(list[n + yOffset]) + self:setValue(list[n + offset]) self:selectHandler() self:updateDraw() end @@ -258,16 +189,21 @@ return function(name, basalt) base.draw(self) self:addDraw("list", function() local w, h = self:getSize() + local offset = self:getOffset() + local selectionColorActive = self:getSelectionColorActive() + local itemSelectedBG = self:getSelectionBackground() + local itemSelectedFG = self:getSelectionForeground() + local activeObject = self:getValue() for n = 1, h do - if list[n + yOffset] then - local t = list[n + yOffset].text - local fg, bg = list[n + yOffset].fgCol, list[n + yOffset].bgCol - if list[n + yOffset] == self:getValue() and selectionColorActive then + if list[n + offset] then + local t = list[n + offset].text + local fg, bg = list[n + offset].fgCol, list[n + offset].bgCol + if list[n + offset] == activeObject and selectionColorActive then fg, bg = itemSelectedFG, itemSelectedBG end - self:addText(1, n, t:sub(1,w)) - self:addBG(1, n, tHex[bg]:rep(w)) - self:addFG(1, n, tHex[fg]:rep(w)) + self:addText(1, n, t:sub(1, w)) + self:addFg(1, n, tHex[fg]:rep(w)) + self:addBg(1, n, tHex[bg]:rep(w)) end end end) diff --git a/Basalt/objects/Menubar.lua b/Basalt/objects/Menubar.lua index da2eb44..4d32b7d 100644 --- a/Basalt/objects/Menubar.lua +++ b/Basalt/objects/Menubar.lua @@ -3,20 +3,20 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("List")(name, basalt) - local objectType = "Menubar" + base:setType("Menubar") local object = {} base:setSize(30, 1) - base:setZIndex(5) + base:setZ(5) - local itemOffset = 0 - local space, outerSpace = 1, 1 - local scrollable = true + base:addProperty("ItemOffset", "number", 0) + base:addProperty("Space", "number", 1) local function maxScroll() local mScroll = 0 local w = base:getWidth() local list = base:getAll() + local space = base:getSpace() for n = 1, #list do mScroll = mScroll + list[n].text:len() + space * 2 end @@ -25,52 +25,29 @@ return function(name, basalt) object = { init = function(self) - local parent = self:getParent() self:listenEvent("mouse_click") self:listenEvent("mouse_drag") self:listenEvent("mouse_scroll") return base.init(self) end, - getType = function(self) - return objectType - end, - getBase = function(self) return base end, - setSpace = function(self, _space) - space = _space or space - self:updateDraw() - return self - end, - - getSpace = function(self) - return space - end, - - setScrollable = function(self, scroll) - scrollable = scroll - if(scroll==nil)then scrollable = true end - return self - end, - - getScrollable = function(self) - return scrollable - end, - mouseHandler = function(self, button, x, y) if(base:getBase().mouseHandler(self, button, x, y))then local objX, objY = self:getAbsolutePosition() local w,h = self:getSize() local xPos = 0 local list = self:getAll() + local space = self:getSpace() + local itemOffset = self:getItemOffset() for n = 1, #list do if (list[n] ~= nil) then if (objX + xPos <= x + itemOffset) and (objX + xPos + list[n].text:len() + (space*2) > x + itemOffset) and (objY == y) then self:setValue(list[n]) - self:sendEvent(event, self, event, 0, x, y, list[n]) + self:selectHandler() end xPos = xPos + list[n].text:len() + space * 2 end @@ -82,7 +59,9 @@ return function(name, basalt) scrollHandler = function(self, dir, x, y) if(base:getBase().scrollHandler(self, dir, x, y))then + local scrollable = self:getScrollable() if(scrollable)then + local itemOffset = self:getItemOffset() itemOffset = itemOffset + dir if (itemOffset < 0) then itemOffset = 0 @@ -93,6 +72,7 @@ return function(name, basalt) if (itemOffset > mScroll) then itemOffset = mScroll end + self:setItemOffset(itemOffset) self:updateDraw() end return true @@ -103,12 +83,13 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("list", function() - local parent = self:getParent() local w,h = self:getSize() local text = "" local textBGCol = "" local textFGCol = "" local itemSelectedBG, itemSelectedFG = self:getSelectionColor() + local itemOffset = self:getItemOffset() + local space = self:getSpace() for _, v in pairs(self:getAll()) do local newItem = (" "):rep(space) .. v.text .. (" "):rep(space) text = text .. newItem diff --git a/Basalt/objects/MonitorFrame.lua b/Basalt/objects/MonitorFrame.lua index 5b8c621..bc628af 100644 --- a/Basalt/objects/MonitorFrame.lua +++ b/Basalt/objects/MonitorFrame.lua @@ -4,54 +4,37 @@ local max,min,sub,rep = math.max,math.min,string.sub,string.rep return function(name, basalt) local base = basalt.getObject("BaseFrame")(name, basalt) - local objectType = "MonitorFrame" + base:setType("MonitorFrame") + + local isMonitorGroup = false + + base:addProperty("Monitor", "string|table", nil, false, function(self, value) + if(type(value)=="string")then + local mon = peripheral.wrap(value) + if(mon~=nil)then + self:setTerm(mon) + end + elseif(type(value)=="table")then + self:setTerm(value) + end + end) + + base:addProperty("MonitorGroup", "string|table", nil, false, function(self, value) + self:setTerm(basaltMon(value)) + isMonitorGroup = true + end) base:setTerm(nil) - local isMonitorGroup = false - local monGroup - - local object = { - - getType = function() - return objectType - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, + local object = { getBase = function(self) return base end, - - setMonitor = function(self, newMon) - if(type(newMon)=="string")then - local mon = peripheral.wrap(newMon) - if(mon~=nil)then - self:setTerm(mon) - end - elseif(type(newMon)=="table")then - self:setTerm(newMon) - end - return self - end, - - setMonitorGroup = function(self, monGrp) - monGroup = basaltMon(monGrp) - self:setTerm(monGroup) - isMonitorGroup = true - return self - end, - - render = function(self) - if(self:getTerm()~=nil)then - base.render(self) - end - end, } object.mouseHandler = function(self, btn, x, y, isMon, monitor, ...) if(isMonitorGroup)then + local monGroup = self:getTerm() x, y = monGroup.calculateClick(monitor, x, y) end base.mouseHandler(self, btn, x, y, isMon, monitor, ...) diff --git a/Basalt/objects/MovableFrame.lua b/Basalt/objects/MovableFrame.lua index e77acd9..9eb93e0 100644 --- a/Basalt/objects/MovableFrame.lua +++ b/Basalt/objects/MovableFrame.lua @@ -2,37 +2,19 @@ local max,min,sub,rep = math.max,math.min,string.sub,string.rep return function(name, basalt) local base = basalt.getObject("Frame")(name, basalt) - local objectType = "MovableFrame" + base:setType("MovableFrame") local parent local dragXOffset, dragYOffset, isDragging = 0, 0, false + local renderThrottle = basalt.getRenderingThrottle() - local dragMap = { - {x1 = 1, x2 = "width", y1 = 1, y2 = 1} - } - - local object = { - getType = function() - return objectType - end, - - setDraggingMap = function(self, t) - dragMap = t - return self - end, - - getDraggingMap = function(self) - return dragMap - end, - - isType = function(self, t) - return objectType==t or (base.isType~=nil and base.isType(t)) or false - end, + base:addProperty("DraggingMap", "table", {{x1 = 1, x2 = "width", y1 = 1, y2 = 1}}) + local object = { getBase = function(self) return base - end, - + end, + load = function(self) base.load(self) self:listenEvent("mouse_click") @@ -65,10 +47,13 @@ return function(name, basalt) parent:setImportant(self) local fx, fy = self:getAbsolutePosition() local w, h = self:getSize() + local dragMap = self:getDraggingMap() for k,v in pairs(dragMap)do local x1, x2 = v.x1=="width" and w or v.x1, v.x2=="width" and w or v.x2 local y1, y2= v.y1=="height" and h or v.y1, v.y2=="height" and h or v.y2 if(x>=fx+x1-1)and(x<=fx+x2-1)and(y>=fy+y1-1)and(y<=fy+y2-1)then + renderThrottle = basalt.getRenderingThrottle() + basalt.setRenderingThrottle(50) isDragging = true dragXOffset = fx - x dragYOffset = fy - y @@ -81,6 +66,7 @@ return function(name, basalt) mouseUpHandler = function(self, ...) isDragging = false + basalt.setRenderingThrottle(0) return base.mouseUpHandler(self, ...) end, diff --git a/Basalt/objects/Object.lua b/Basalt/objects/Object.lua index 4dc3e00..bf0f295 100644 --- a/Basalt/objects/Object.lua +++ b/Basalt/objects/Object.lua @@ -1,5 +1,6 @@ local basaltEvent = require("basaltEvent") local utils = require("utils") +local split = utils.splitString local uuid = utils.uuid local unpack,sub = table.unpack,string.sub @@ -9,52 +10,191 @@ return function(name, basalt) assert(basalt~=nil, "Unable to find basalt instance! ID: "..name) -- Base object - local objectType = "Object" -- not changeable - local isEnabled,initialized = true,false + local initialized = false local eventSystem = basaltEvent() local registeredEvents = {} local activeEvents = {} + local properties = {} + local propertyConfig = {} + + local function defaultRule(typ) + return function(self, value) + local isValid = false + if(type(typ)=="string")then + local types = split(typ, "|") + + for _,v in pairs(types)do + if(type(value)==v)then + isValid = true + end + end + end + if(typ=="table")then + for _,v in pairs(typ)do + if(v==value)then + isValid = true + end + end + end + if(typ=="color")then + if(type(value)=="string")then + if(colors[value]~=nil)then + isValid = true + value = colors[value] + end + else + for _,v in pairs(colors)do + if(v==value)then + isValid = true + end + end + end + end + if(typ=="char")then + if(type(value)=="string")then + if(#value==1)then + isValid = true + end + end + end + if(typ=="any")or(value==nil)or(type(value)=="function")then + isValid = true + end + + if(not isValid)then + if(type(typ)=="table")then + typ = table.concat(typ, ", ") + end + error(self:getType()..": Invalid type for property "..name.."! Expected "..typ..", got "..type(value)) + end + return value + end + end local parent - - local object = { + local object + + object = { init = function(self) if(initialized)then return false end initialized = true return true end, + isType = function(self, typ) + for k,v in pairs(properties["Type"])do + if(v==typ)then + return true + end + end + return false + end, + + getTypes = function(self) + return properties["Type"] + end, + load = function(self) end, - getType = function(self) - return objectType - end, - isType = function(self, t) - return objectType==t - end, - - getProperty = function(self, name) - local get = self["get" .. name:gsub("^%l", string.upper)] - if (get ~= nil) then - return get(self) - end - end, - - setProperty = function(self, name, ...) - local set = self["set" .. name:gsub("^%l", string.upper)] - if (set ~= nil) then - return set(self, ...) - end - end, - getName = function(self) return name end, - getParent = function(self) - return parent + getProperty = function(self, name) + local prop = properties[name:gsub("^%l", string.upper)] + if(type(prop)=="function")then + return prop() + end + return prop + end, + + getProperties = function(self) + local p = {} + for k,v in pairs(properties)do + if(type(v)=="function")then + p[k] = v() + else + p[k] = v + end + end + return p + end, + + setProperty = function(self, name, value, rule) + name = name:gsub("^%l", string.upper) + if(rule~=nil)then + value = rule(self, value) + end + --if(properties[name]~=value)then + properties[name] = value + if(self.updateDraw~=nil)then + self:updateDraw() + end + --end + return self + end, + + getPropertyConfig = function(self, name) + return propertyConfig[name] + end, + + addProperty = function(self, name, typ, defaultValue, readonly, setLogic, getLogic, alteredRule) + name = name:gsub("^%l", string.upper) + propertyConfig[name] = {type=typ, defaultValue=defaultValue, readonly=readonly} + if(properties[name]~=nil)then + error("Property "..name.." in "..self:getType().." already exists!") + end + self:setProperty(name, defaultValue) + + object["get" .. name] = function(self, ...) + if(self~=nil)then + local prop = self:getProperty(name) + if(getLogic~=nil)then + return getLogic(self, prop, ...) + end + return prop + end + end + if(not readonly)then + object["set" .. name] = function(self, value, ...) + if(self~=nil)then + if(setLogic~=nil)then + local modifiedVal = setLogic(self, value, ...) + if(modifiedVal~=nil)then + value = modifiedVal + end + end + self:setProperty(name, value, alteredRule~=nil and alteredRule(typ) or defaultRule(typ)) + end + return self + end + end + return self + end, + + combineProperty = function(self, name, ...) + name = name:gsub("^%l", string.upper) + local args = {...} + object["get" .. name] = function(self) + local result = {} + for _,v in pairs(args)do + v = v:gsub("^%l", string.upper) + result[#result+1] = self["get" .. v](self) + end + return unpack(result) + end + object["set" .. name] = function(self, ...) + local values = {...} + for k,v in pairs(args)do + if(self["set"..v]~=nil)then -- if später entfernen + self["set" .. v](self, values[k]) + end + end + return self + end + return self end, setParent = function(self, newParent, noRemove) @@ -62,14 +202,15 @@ return function(name, basalt) if (newParent.getType ~= nil and newParent:isType("Container")) then self:remove() newParent:addChild(self) - if (self.show) then - self:show() - end parent = newParent end return self end, + getParent = function(self) + return parent + end, + updateEvents = function(self) for k,v in pairs(activeEvents)do parent:removeEvent(k, self) @@ -93,22 +234,18 @@ return function(name, basalt) return self end, - getZIndex = function(self) - return 1 - end, - enable = function(self) - isEnabled = true + self:setProperty("Enabled", true) return self end, disable = function(self) - isEnabled = false + self:setProperty("Enabled", false) return self end, isEnabled = function(self) - return isEnabled + return self:getProperty("Enabled") end, remove = function(self) @@ -282,6 +419,24 @@ return function(name, basalt) end, } + object:addProperty("Z", "number", 1, false, function(self, value) + if (parent ~= nil) then + parent:updateZIndex(self, value) + self:updateDraw() + end + return value + end) + object:addProperty("Type", "string|table", {"Object"}, false, function(self, value) + if(type(value)=="string")then + table.insert(properties["Type"], 1, value) + return properties["Type"] + end + end, + function(self, _, depth) + return properties["Type"][depth or 1] + end) + object:addProperty("Enabled", "boolean", true) + object.__index = object return object end \ No newline at end of file diff --git a/Basalt/objects/Pane.lua b/Basalt/objects/Pane.lua index 9f4ec9a..4bf5185 100644 --- a/Basalt/objects/Pane.lua +++ b/Basalt/objects/Pane.lua @@ -1,15 +1,11 @@ return function(name, basalt) -- Pane local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Pane" + base:setType("Pane") base:setSize(25, 10) - local object = { - getType = function(self) - return objectType - end, - } + local object = {} object.__index = object return setmetatable(object, base) diff --git a/Basalt/objects/Program.lua b/Basalt/objects/Program.lua index 32e9380..8f2a84d 100644 --- a/Basalt/objects/Program.lua +++ b/Basalt/objects/Program.lua @@ -5,10 +5,11 @@ local sub = string.sub return function(name, basalt) local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Program" + base:setType("Program") local object - local cachedPath - local enviroment = {} + + base:addProperty("Path", "string", nil) + base:addProperty("Enviroment", "table", nil) local function createBasaltWindow(x, y, width, height) local xCursor, yCursor = 1, 1 @@ -346,7 +347,7 @@ return function(name, basalt) return basaltwindow end - base:setZIndex(5) + base:setZ(5) base:setSize(30, 12) local pWindow = createBasaltWindow(1, 1, 30, 12) local curProcess @@ -405,23 +406,19 @@ return function(name, basalt) end object = { - getType = function(self) - return objectType - end; - show = function(self) base.show(self) pWindow.setBackgroundColor(self:getBackground()) pWindow.setTextColor(self:getForeground()) pWindow.basalt_setVisible(true) return self - end; + end, hide = function(self) base.hide(self) pWindow.basalt_setVisible(false) return self - end; + end, setPosition = function(self, x, y, rel) base.setPosition(self, x, y, rel) @@ -431,32 +428,32 @@ return function(name, basalt) getBasaltWindow = function() return pWindow - end; + end, getBasaltProcess = function() return curProcess - end; + end, setSize = function(self, width, height, rel) base.setSize(self, width, height, rel) pWindow.basalt_resize(self:getWidth(), self:getHeight()) return self - end; + end, getStatus = function(self) if (curProcess ~= nil) then return curProcess:getStatus() end return "inactive" - end; - - setEnviroment = function(self, env) - enviroment = env or {} - return self end, execute = function(self, path, ...) + local cachedPath = self:getPath() + local enviroment = self:getEnviroment() cachedPath = path or cachedPath + if(path~=nil)then + self:setPath(path) + end curProcess = process:new(cachedPath, pWindow, enviroment, ...) pWindow.setBackgroundColor(colors.black) pWindow.setTextColor(colors.white) @@ -477,7 +474,7 @@ return function(name, basalt) self:listenEvent("char", self) self:listenEvent("other_event", self) return self - end; + end, setExecute = function(self, path, ...) return self:execute(path, ...) @@ -495,7 +492,7 @@ return function(name, basalt) end parent:removeEvents(self) return self - end; + end, pause = function(self, p) paused = p or (not paused) @@ -508,11 +505,11 @@ return function(name, basalt) end end return self - end; + end, isPaused = function(self) return paused - end; + end, injectEvent = function(self, event, ign, ...) if (curProcess ~= nil) then @@ -525,16 +522,16 @@ return function(name, basalt) end end return self - end; + end, getQueuedEvents = function(self) return queuedEvent - end; + end, updateQueuedEvents = function(self, events) queuedEvent = events or queuedEvent return self - end; + end, injectEvents = function(self, ...) if (curProcess ~= nil) then @@ -545,7 +542,7 @@ return function(name, basalt) end end return self - end; + end, mouseHandler = function(self, button, x, y) if (base.mouseHandler(self, button, x, y)) then @@ -684,10 +681,6 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("program", function() - local parent = self:getParent() - local obx, oby = self:getPosition() - local xCur, yCur = pWindow.getCursorPos() - local w,h = self:getSize() pWindow.basalt_update() end) end, @@ -698,7 +691,6 @@ return function(name, basalt) self:registerEvent("program_error", v) end end - local parent = self:getParent() self:listenEvent("other_event") return self end, @@ -709,7 +701,6 @@ return function(name, basalt) self:registerEvent("program_done", v) end end - local parent = self:getParent() self:listenEvent("other_event") return self end, diff --git a/Basalt/objects/Progressbar.lua b/Basalt/objects/Progressbar.lua index 6520862..37920a0 100644 --- a/Basalt/objects/Progressbar.lua +++ b/Basalt/objects/Progressbar.lua @@ -1,96 +1,30 @@ return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Progressbar" + base:setType("ProgressBar") - local progress = 0 - - base:setZIndex(5) + base:setZ(5) base:setValue(false) base:setSize(25, 3) - local activeBarColor = colors.black - local activeBarSymbol = "" - local activeBarSymbolCol = colors.white - local bgBarSymbol = "" - local direction = 0 + base:addProperty("Progress", "number", 0, false, function(self, value) + local progress = self:getProgress() + if (value >= 0) and (value <= 100) and (progress ~= value) then + self:setValue(progress) + if (progress == 100) then + self:progressDoneHandler() + end + return value + end + return progress + end) + base:addProperty("Direction", "number", 0) + base:addProperty("ActiveBarSymbol", "char", "") + base:addProperty("ActiveBarColor", "color", colors.black) + base:addProperty("ActiveBarSymbolColor", "color", colors.white) + base:combineProperty("ProgressBar", "ActiveBarColor", "ActiveBarSymbol", "ActiveBarSymbolColor") + base:addProperty("BackgroundSymbol", "char", "") local object = { - getType = function(self) - return objectType - end, - - setDirection = function(self, dir) - direction = dir - self:updateDraw() - return self - end, - - getDirection = function(self) - return direction - end, - - setProgressBar = function(self, color, symbol, symbolcolor) - activeBarColor = color or activeBarColor - activeBarSymbol = symbol or activeBarSymbol - activeBarSymbolCol = symbolcolor or activeBarSymbolCol - self:updateDraw() - return self - end, - - getProgressBar = function(self) - return activeBarColor, activeBarSymbol, activeBarSymbolCol - end, - - setActiveBarColor = function(self, color) - return self:setProgressBar(color, nil, nil) - end, - - getActiveBarColor = function(self) - return activeBarColor - end, - - setActiveBarSymbol = function(self, symbol) - return self:setProgressBar(nil, symbol, nil) - end, - - getActiveBarSymbol = function(self) - return activeBarSymbol - end, - - setActiveBarSymbolColor = function(self, symbolColor) - return self:setProgressBar(nil, nil, symbolColor) - end, - - getActiveBarSymbolColor = function(self) - return activeBarSymbolCol - end, - - setBackgroundSymbol = function(self, symbol) - bgBarSymbol = symbol:sub(1, 1) - self:updateDraw() - return self - end, - - getBackgroundSymbol = function(self) - return bgBarSymbol - end, - - setProgress = function(self, value) - if (value >= 0) and (value <= 100) and (progress ~= value) then - progress = value - self:setValue(progress) - if (progress == 100) then - self:progressDoneHandler() - end - end - self:updateDraw() - return self - end, - - getProgress = function(self) - return progress - end, - onProgressDone = function(self, f) self:registerEvent("progress_done", f) return self @@ -103,28 +37,28 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("progressbar", function() - local obx, oby = self:getPosition() local w,h = self:getSize() - local bgCol,fgCol = self:getBackground(), self:getForeground() - if(bgCol~=false)then self:addBackgroundBox(1, 1, w, h, bgCol) end - if(bgBarSymbol~="")then self:addTextBox(1, 1, w, h, bgBarSymbol) end - if(fgCol~=false)then self:addForegroundBox(1, 1, w, h, fgCol) end - if (direction == 1) then - self:addBackgroundBox(1, 1, w, h / 100 * progress, activeBarColor) - self:addForegroundBox(1, 1, w, h / 100 * progress, activeBarSymbolCol) - self:addTextBox(1, 1, w, h / 100 * progress, activeBarSymbol) - elseif (direction == 3) then - self:addBackgroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor) - self:addForegroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol) - self:addTextBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol) - elseif (direction == 2) then - self:addBackgroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarColor) - self:addForegroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbolCol) - self:addTextBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbol) + local p = self:getProperties() + local activeBarColor, activeBarSymbol, activeBarSymbolCol = self:getProgressBar() + if(p.Background~=nil)then self:addBackgroundBox(1, 1, w, h, p.Background) end + if(p.BgSymbol~="")then self:addTextBox(1, 1, w, h, p.BgSymbol) end + if(p.Foreground~=nil)then self:addForegroundBox(1, 1, w, h, p.Foreground) end + if (p.Direction == 1) then + self:addBackgroundBox(1, 1, w, h / 100 * p.Progress, activeBarColor) + self:addForegroundBox(1, 1, w, h / 100 * p.Progress, activeBarSymbolCol) + self:addTextBox(1, 1, w, h / 100 * p.Progress, activeBarSymbol) + elseif (p.Direction == 3) then + self:addBackgroundBox(1, 1 + math.ceil(h - h / 100 * p.Progress), w, h / 100 * p.Progress, activeBarColor) + self:addForegroundBox(1, 1 + math.ceil(h - h / 100 * p.Progress), w, h / 100 * p.Progress, activeBarSymbolCol) + self:addTextBox(1, 1 + math.ceil(h - h / 100 * p.Progress), w, h / 100 * p.Progress, activeBarSymbol) + elseif (p.Direction == 2) then + self:addBackgroundBox(1 + math.ceil(w - w / 100 * p.Progress), 1, w / 100 * p.Progress, h, activeBarColor) + self:addForegroundBox(1 + math.ceil(w - w / 100 * p.Progress), 1, w / 100 * p.Progress, h, activeBarSymbolCol) + self:addTextBox(1 + math.ceil(w - w / 100 * p.Progress), 1, w / 100 * p.Progress, h, activeBarSymbol) else - self:addBackgroundBox(1, 1, math.ceil( w / 100 * progress), h, activeBarColor) - self:addForegroundBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbolCol) - self:addTextBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbol) + self:addBackgroundBox(1, 1, math.ceil( w / 100 * p.Progress), h, activeBarColor) + self:addForegroundBox(1, 1, math.ceil(w / 100 * p.Progress), h, activeBarSymbolCol) + self:addTextBox(1, 1, math.ceil(w / 100 * p.Progress), h, activeBarSymbol) end end) end, diff --git a/Basalt/objects/Radio.lua b/Basalt/objects/Radio.lua index 19303d1..d314d5c 100644 --- a/Basalt/objects/Radio.lua +++ b/Basalt/objects/Radio.lua @@ -3,25 +3,26 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("List")(name, basalt) - local objectType = "Radio" + base:setType("Radio") base:setSize(1, 1) - base:setZIndex(5) + base:setZ(5) + + base:addProperty("BoxSelectionBG", "color", colors.black) + base:addProperty("BoxSelectionFG", "color", colors.green) + base:combineProperty("BoxSelectionColor", "BoxSelectionBG", "BoxSelectionFG") + + base:addProperty("BoxNotSelectionBG", "color", colors.black) + base:addProperty("BoxNotSelectionFG", "color", colors.red) + base:combineProperty("BoxNotSelectionColor", "BoxNotSelectionBG", "BoxNotSelectionFG") + + base:addProperty("SelectionColorActive", "boolean", true) + base:addProperty("Symbol", "char", "\7") + base:addProperty("Align", "string", { "left", "right" }, "left") local list = {} - local boxSelectedBG = colors.black - local boxSelectedFG = colors.green - local boxNotSelectedBG = colors.black - local boxNotSelectedFG = colors.red - local selectionColorActive = true - local symbol = "\7" - local align = "left" local object = { - getType = function(self) - return objectType - end, - addItem = function(self, text, x, y, bgCol, fgCol, ...) base.addItem(self, text, bgCol, fgCol, ...) table.insert(list, { x = x or 1, y = y or #list * 2 }) @@ -47,58 +48,6 @@ return function(name, basalt) return self end, - setBoxSelectionColor = function(self, bg, fg) - boxSelectedBG = bg - boxSelectedFG = fg - return self - end, - - setBoxSelectionBG = function(self, bg) - return self:setBoxSelectionColor(bg, boxSelectedFG) - end, - - setBoxSelectionFG = function(self, fg) - return self:setBoxSelectionColor(boxSelectedBG, fg) - end, - - getBoxSelectionColor = function(self) - return boxSelectedBG, boxSelectedFG - end, - - getBoxSelectionBG = function(self) - return boxSelectedBG - end, - - getBoxSelectionFG = function(self) - return boxSelectedFG - end, - - setBoxDefaultColor = function(self, bg, fg) - boxNotSelectedBG = bg - boxNotSelectedFG = fg - return self - end, - - setBoxDefaultBG = function(self, bg) - return self:setBoxDefaultColor(bg, boxNotSelectedFG) - end, - - setBoxDefaultFG = function(self, fg) - return self:setBoxDefaultColor(boxNotSelectedBG, fg) - end, - - getBoxDefaultColor = function(self) - return boxNotSelectedBG, boxNotSelectedFG - end, - - getBoxDefaultBG = function(self) - return boxNotSelectedBG - end, - - getBoxDefaultFG = function(self) - return boxNotSelectedFG - end, - mouseHandler = function(self, button, x, y, ...) if (#list > 0) then local obx, oby = self:getAbsolutePosition() @@ -106,6 +55,7 @@ return function(name, basalt) for k, value in pairs(baseList) do if (obx + list[k].x - 1 <= x) and (obx + list[k].x - 1 + value.text:len() + 1 >= x) and (oby + list[k].y - 1 == y) then self:setValue(value) + self:selectHandler() local val = self:sendEvent("mouse_click", self, "mouse_click", button, x, y, ...) self:updateDraw() if(val==false)then return val end @@ -119,6 +69,9 @@ return function(name, basalt) self:addDraw("radio", function() local itemSelectedBG, itemSelectedFG = self:getSelectionColor() local baseList = self:getAll() + local boxSelectedBG, boxSelectedFG = self:getBoxSelectionColor() + local boxNotSelectedBG, boxNotSelectedFG = self:getBoxNotSelectionColor() + local symbol = self:getSymbol() for k, value in pairs(baseList) do if (value == self:getValue()) then self:addBlit(list[k].x, list[k].y, symbol, tHex[boxSelectedFG], tHex[boxSelectedBG]) diff --git a/Basalt/objects/ScrollableFrame.lua b/Basalt/objects/ScrollableFrame.lua index bdec82e..17db4ed 100644 --- a/Basalt/objects/ScrollableFrame.lua +++ b/Basalt/objects/ScrollableFrame.lua @@ -1,13 +1,30 @@ local max,min,sub,rep = math.max,math.min,string.sub,string.rep +local tHex = require("tHex") + return function(name, basalt) local base = basalt.getObject("Frame")(name, basalt) - local objectType = "ScrollableFrame" - local parent + base:setType("ScrollableFrame") - local direction = 0 - local manualScrollAmount = 0 - local calculateScrollAmount = true + base:addProperty("AutoCalculate", "boolean", true) + base:addProperty("Direction", {"vertical", "horizontal"}, "vertical") + base:addProperty("Scrollbar", "boolean", false) + base:addProperty("ScrollbarSymbolBackground", "number", colors.black) + base:addProperty("ScrollbarSymbolForeground", "number", colors.black) + base:addProperty("ScrollbarSymbol", "char", " ") + base:combineProperty("ScrollbarFront", "ScrollbarSymbol", "ScrollbarSymbolBackground", "ScrollbarSymbolForeground") + base:addProperty("ScrollbarBackgroundSymbol", "char", "\127") + base:addProperty("ScrollbarBackground", "number", colors.gray) + base:addProperty("ScrollbarForeground", "number", colors.black) + base:combineProperty("ScrollbarBack", "ScrollbarBackgroundSymbol", "ScrollbarBackground", "ScrollbarForeground") + base:addProperty("ScrollbarArrowForeground", "number", colors.lightGray) + base:addProperty("ScrollbarArrowBackground", "number", colors.black) + base:combineProperty("ScrollbarArrowColor", "ScrollbarArrowBackground", "ScrollbarArrowForeground") + + base:addProperty("ScrollAmount", "number", 0, false, function(self, value) + self:setAutoCalculate(false) + end) + base:addProperty("ScrollSpeed", "number", 1) local function getHorizontalScrollAmount(self) local amount = 0 @@ -59,55 +76,69 @@ return function(name, basalt) local function scrollHandler(self, dir) local xO, yO = self:getOffset() local scrollAmn - if(direction==1)then + local direction = self:getDirection() + local calculateScrollAmount = self:getAutoCalculate() + local manualScrollAmount = self:getScrollAmount() + local scrollSpeed = self:getScrollSpeed() + if(direction=="horizontal")then scrollAmn = calculateScrollAmount and getHorizontalScrollAmount(self) or manualScrollAmount - self:setOffset(min(scrollAmn, max(0, xO + dir)), yO) - elseif(direction==0)then + self:setOffset(min(scrollAmn, max(0, xO + dir * scrollSpeed)), yO) + elseif(direction=="vertical")then scrollAmn = calculateScrollAmount and getVerticalScrollAmount(self) or manualScrollAmount - self:setOffset(xO, min(scrollAmn, max(0, yO + dir))) + self:setOffset(xO, min(scrollAmn, max(0, yO + dir * scrollSpeed))) end self:updateDraw() end - - local object = { - getType = function() - return objectType - end, - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false - end, + local function scrollWithMouse(self, x, y) + local direction = self:getDirection() + local scrollAmn + local calculateScrollAmount = self:getAutoCalculate() + local manualScrollAmount = self:getScrollAmount() - setDirection = function(self, dir) - direction = dir=="horizontal" and 1 or dir=="vertical" and 0 or direction - return self - end, + if(direction=="horizontal") then + if(y==self:getHeight()) then + if(x>1)and(x1)and(y=scrollBarY)and(y<=scrollBarY+scrollBarHeight)then + char = fgSymbol + bg = fgColor + fg = fgFgColor + end + self:blit(width, y, char, fg, bg) + end + self:blit(width, 1, "\30", arrowFg, arrowBg) + self:blit(width, height, "\31", arrowFg, arrowBg) + elseif(p.Direction=="horizontal")then + local scrollAmount = getHorizontalScrollAmount(self) + local scrollBarWidth = max(1, math.floor(width * width / (width + scrollAmount))) + local scrollBarX = xO * (width - scrollBarWidth) / scrollAmount + + local bgSymbol, bgColor, bgFgColor = self:getScrollbarBack() + local fgSymbol, fgColor, fgFgColor = self:getScrollbarFront() + local arrowBg, arrowFg = self:getScrollbarArrowColor() + + bgColor = tHex[bgColor] + fgColor = tHex[fgColor] + bgFgColor = tHex[bgFgColor] + fgFgColor = tHex[fgFgColor] + arrowBg = tHex[arrowBg] + arrowFg = tHex[arrowFg] + + for x=2, width-1 do + local char = bgSymbol + local bg = bgColor + local fg = bgFgColor + if(x>=scrollBarX)and(x<=scrollBarX+scrollBarWidth)then + char = fgSymbol + bg = fgColor + fg = fgFgColor + end + self:blit(x, height, char, fg, bg) + end + self:blit(1, height, "\17", arrowFg, arrowBg) + self:blit(width, height, "\16", arrowFg, arrowBg) + end end - end, 0) + end) end, } diff --git a/Basalt/objects/Scrollbar.lua b/Basalt/objects/Scrollbar.lua index 63ecf94..10fabc1 100644 --- a/Basalt/objects/Scrollbar.lua +++ b/Basalt/objects/Scrollbar.lua @@ -2,33 +2,43 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("VisualObject")(name, basalt) - local objectType = "Scrollbar" + base:setType("Scrollbar") - base:setZIndex(2) + base:setZ(2) base:setSize(1, 8) - base:setBackground(colors.lightGray, "\127", colors.gray) + base:setBackground(colors.lightGray, "\127", colors.black) + + base:addProperty("SymbolChar", "char", " ") + base:addProperty("SymbolBG", "color", colors.black) + base:addProperty("SymbolFG", "color", colors.black) + base:combineProperty("Symbol", "SymbolChar", "SymbolBG", "SymbolFG") + base:addProperty("SymbolAutoSize", "boolean", true) - local barType = "vertical" - local symbol = " " - local symbolBG = colors.black - local symbolFG = colors.black - local scrollAmount = 3 local index = 1 - local symbolSize = 1 - local symbolAutoSize = true local function updateSymbolSize() local w,h = base:getSize() + local symbolAutoSize = base:getSymbolAutoSize() if(symbolAutoSize)then - symbolSize = math.max((barType == "vertical" and h or w-(#symbol)) - (scrollAmount-1), 1) + local barType = base:getBarType() + local scrollAmount = base:getScrollAmount() + local symbol = base:getSymbolChar() + base:setSymbolSize(math.max((barType == "vertical" and h or w-(#symbol)) - (scrollAmount-1), 1)) end end + + base:addProperty("ScrollAmount", "number", 3, false, updateSymbolSize) + base:addProperty("SymbolSize", "number", 1) + base:addProperty("BarType", {"vertical", "horizontal"}, "vertical", false, updateSymbolSize) updateSymbolSize() - local function mouseEvent(self, button, x, y) + local function mouseEvent(self, _, x, y) local obx, oby = self:getAbsolutePosition() local w,h = self:getSize() updateSymbolSize() + local barType = self:getBarType() + local symbol = self:getSymbolChar() + local symbolSize = self:getSymbolSize() local size = barType == "vertical" and h or w for i = 0, size do if ((barType == "vertical" and oby + i == y) or (barType == "horizontal" and obx + i == x)) and (obx <= x) and (obx + w > x) and (oby <= y) and (oby + h > y) then @@ -40,99 +50,31 @@ return function(name, basalt) end local object = { - getType = function(self) - return objectType - end, - load = function(self) base.load(self) - local parent = self:getParent() self:listenEvent("mouse_click") self:listenEvent("mouse_up") self:listenEvent("mouse_scroll") self:listenEvent("mouse_drag") end, - setSymbol = function(self, _symbol, bg, fg) - symbol = _symbol:sub(1,1) - symbolBG = bg or symbolBG - symbolFG = fg or symbolFG - updateSymbolSize() - self:updateDraw() - return self - end, - - setSymbolBG = function(self, bg) - return self:setSymbol(symbol, bg, nil) - end, - - setSymbolFG = function(self, fg) - return self:setSymbol(symbol, nil, fg) - end, - - getSymbol = function(self) - return symbol - end, - - getSymbolBG = function(self) - return symbolBG - end, - - getSymbolFG = function(self) - return symbolFG - 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)) updateSymbolSize() self:updateDraw() return self end, - setScrollAmount = function(self, amount) - scrollAmount = amount - updateSymbolSize() - self:updateDraw() - return self - end, - - getScrollAmount = function(self) - return scrollAmount - end, - getIndex = function(self) local w,h = self:getSize() + local barType = self:getBarType() + local scrollAmount = self:getScrollAmount() return scrollAmount > (barType=="vertical" and h or w) and math.floor(scrollAmount/(barType=="vertical" and h or w) * index) or index end, - setSymbolSize = function(self, size) - symbolSize = tonumber(size) or 1 - symbolAutoSize = size~=false and false or true - updateSymbolSize() - self:updateDraw() - return self - end, - - getSymbolSize = function(self) - return symbolSize - end, - - setBarType = function(self, _typ) - barType = _typ:lower() - updateSymbolSize() - self:updateDraw() - return self - end, - - getBarType = function(self) - return barType - end, - mouseHandler = function(self, button, x, y, ...) if (base.mouseHandler(self, button, x, y, ...)) then mouseEvent(self, button, x, y) @@ -163,6 +105,9 @@ return function(name, basalt) if (index < 1) then index = 1 end + local barType = self:getBarType() + local symbol = self:getSymbolChar() + local symbolSize = self:getSymbolSize() index = math.min(index, (barType == "vertical" and h or w) - (barType == "vertical" and symbolSize - 1 or #symbol+symbolSize-2)) self:scrollbarMoveHandler() self:updateDraw() @@ -187,24 +132,23 @@ return function(name, basalt) base.customEventHandler(self, event, ...) if(event=="basalt_FrameResize")then updateSymbolSize() - end + end end, draw = function(self) base.draw(self) self:addDraw("scrollbar", function() - local parent = self:getParent() - local w,h = self:getSize() - local bgCol,fgCol = self:getBackground(), self:getForeground() - if (barType == "horizontal") then + local p = self:getProperties() + local w, h = p.Width, p.Height + if (p.BarType == "horizontal") then for n = 0, h - 1 do - self:addBlit(index, 1 + n, symbol:rep(symbolSize), tHex[symbolFG]:rep(#symbol*symbolSize), tHex[symbolBG]:rep(#symbol*symbolSize)) + self:addBlit(index, 1 + n, p.SymbolChar:rep(p.SymbolSize), tHex[p.SymbolFG]:rep(#p.SymbolChar*p.SymbolSize), tHex[p.SymbolBG]:rep(#p.SymbolChar*p.SymbolSize)) end - elseif (barType == "vertical") then + elseif (p.BarType == "vertical") then for n = 0, h - 1 do if (index == n + 1) then - for curIndexOffset = 0, math.min(symbolSize - 1, h) do - self:addBlit(1, index + curIndexOffset, symbol:rep(math.max(#symbol, w)), tHex[symbolFG]:rep(math.max(#symbol, w)), tHex[symbolBG]:rep(math.max(#symbol, w))) + for curIndexOffset = 0, math.min(p.SymbolSize - 1, h) do + self:addBlit(1, index + curIndexOffset, p.SymbolChar:rep(math.max(#p.SymbolChar, w)), tHex[p.SymbolFG]:rep(math.max(#p.SymbolChar, w)), tHex[p.SymbolBG]:rep(math.max(#p.SymbolChar, w))) end end end diff --git a/Basalt/objects/Slider.lua b/Basalt/objects/Slider.lua index dd567e1..0dbb51b 100644 --- a/Basalt/objects/Slider.lua +++ b/Basalt/objects/Slider.lua @@ -2,24 +2,29 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Slider" + base:setType("Slider") base:setSize(12, 1) base:setValue(1) - base:setBackground(false, "\140", colors.black) - local barType = "horizontal" - local symbol = " " - local symbolFG = colors.black - local symbolBG = colors.gray - local maxValue = 12 + base:addProperty("SymbolText", "char", " ") + base:addProperty("SymbolForeground", "color", colors.black) + base:addProperty("SymbolBackground", "color", colors.gray) + base:combineProperty("Symbol", "SymbolText", "SymbolForeground", "SymbolBackground") + base:addProperty("SymbolSize", "number", 1) + base:addProperty("BarType", {"vertical", "horizontal"}, "horizontal") + base:addProperty("MaxValue", "number", 12) + local index = 1 - local symbolSize = 1 - local function mouseEvent(self, button, x, y) + local function mouseEvent(self, _, x, y) local obx, oby = self:getPosition() local w,h = self:getSize() + local barType = self:getBarType() local size = barType == "vertical" and h or w + local symbolSize = self:getSymbolSize() + local symbol = self:getSymbol() + local maxValue = self:getMaxValue() for i = 0, size do if ((barType == "vertical" and oby + i == y) or (barType == "horizontal" and obx + i == x)) and (obx <= x) and (obx + w > x) and (oby <= y) and (oby + h > y) then index = math.min(i + 1, size - (#symbol + symbolSize - 2)) @@ -30,32 +35,27 @@ return function(name, basalt) end local object = { - getType = function(self) - return objectType + init = function(self) + base.init(self) + base:setBgSymbol("\140") + base:setBgSymbolColor(colors.black) + base:setBackground(nil) end, - load = function(self) self:listenEvent("mouse_click") self:listenEvent("mouse_drag") self:listenEvent("mouse_scroll") end, - setSymbol = function(self, _symbol) - symbol = _symbol:sub(1, 1) - self:updateDraw() - return self - end, - - getSymbol = function(self) - return symbol - end, - setIndex = function(self, _index) index = _index if (index < 1) then index = 1 end local w,h = self:getSize() + local symbolSize = self:getSymbolSize() + local maxValue = self:getMaxValue() + local barType = self:getBarType() index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) self:setValue(maxValue / (barType == "vertical" and h or w) * index) self:updateDraw() @@ -66,35 +66,6 @@ return function(name, basalt) return index end, - setMaxValue = function(self, val) - maxValue = val - return self - end, - - getMaxValue = function(self) - return maxValue - end, - - setSymbolColor = function(self, col) - symbolColor = col - self:updateDraw() - return self - end, - - getSymbolColor = function(self) - return symbolColor - end, - - setBarType = function(self, _typ) - barType = _typ:lower() - self:updateDraw() - return self - end, - - getBarType = function(self) - return barType - end, - mouseHandler = function(self, button, x, y) if (base.mouseHandler(self, button, x, y)) then mouseEvent(self, button, x, y) @@ -118,6 +89,9 @@ return function(name, basalt) if (index < 1) then index = 1 end + local symbolSize = self:getSymbolSize() + local maxValue = self:getMaxValue() + local barType = self:getBarType() index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) self:setValue(maxValue / (barType == "vertical" and h or w) * index) self:updateDraw() @@ -131,21 +105,27 @@ return function(name, basalt) self:addDraw("slider", function() local w,h = self:getSize() local bgCol,fgCol = self:getBackground(), self:getForeground() + local symbolSize = self:getSymbolSize() + local symbol = self:getSymbolText() + local symbolFG = self:getSymbolForeground() + local symbolBG = self:getSymbolBackground() + local barType = self:getBarType() + local obx, oby = self:getPosition() if (barType == "horizontal") then - self:addText(index, 1, symbol:rep(symbolSize)) - if(symbolBG~=false)then self:addBG(index, 1, tHex[symbolBG]:rep(#symbol*symbolSize)) end - if(symbolFG~=false)then self:addFG(index, 1, tHex[symbolFG]:rep(#symbol*symbolSize)) end + self:addText(index, oby, symbol:rep(symbolSize)) + if(symbolBG~=false)then self:addBg(index, 1, tHex[symbolBG]:rep(#symbol*symbolSize)) end + if(symbolFG~=false)then self:addFg(index, 1, tHex[symbolFG]:rep(#symbol*symbolSize)) end end if (barType == "vertical") then for n = 0, h - 1 do if (index == n + 1) then for curIndexOffset = 0, math.min(symbolSize - 1, h) do - self:addBlit(1, 1+n+curIndexOffset, symbol, tHex[symbolColor], tHex[symbolColor]) + self:addBlit(1, 1+n+curIndexOffset, symbol, tHex[symbolFG], tHex[symbolFG]) end else if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then - self:addBlit(1, 1+n, bgSymbol, tHex[fgCol], tHex[bgCol]) + self:addBlit(1, 1+n, " ", tHex[fgCol], tHex[bgCol]) end end end @@ -156,4 +136,4 @@ return function(name, basalt) object.__index = object return setmetatable(object, base) -end +end \ No newline at end of file diff --git a/Basalt/objects/Switch.lua b/Basalt/objects/Switch.lua index 19a7367..1d1237d 100644 --- a/Basalt/objects/Switch.lua +++ b/Basalt/objects/Switch.lua @@ -1,48 +1,16 @@ return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Switch" + base:setType("Switch") base:setSize(4, 1) base:setValue(false) - base:setZIndex(5) + base:setZ(5) - local bgSymbol = colors.black - local inactiveBG = colors.red - local activeBG = colors.green + base:addProperty("SymbolColor", "color", colors.black) + base:addProperty("ActiveBackground", "color", colors.green) + base:addProperty("InactiveBackground", "color", colors.red) local object = { - getType = function(self) - return objectType - end, - - setSymbol = function(self, col) - bgSymbol = col - return self - end, - - getSymbol = function(self) - return bgSymbol - end, - - setActiveBackground = function(self, col) - activeBG = col - return self - end, - - getActiveBackground = function(self) - return activeBG - end, - - setInactiveBackground = function(self, col) - inactiveBG = col - return self - end, - - getInactiveBackground = function(self) - return inactiveBG - end, - - load = function(self) self:listenEvent("mouse_click") end, @@ -58,8 +26,9 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("switch", function() - local parent = self:getParent() - local bgCol,fgCol = self:getBackground(), self:getForeground() + local activeBG = self:getActiveBackground() + local inactiveBG = self:getInactiveBackground() + local bgSymbol = self:getSymbolColor() local w,h = self:getSize() if(self:getValue())then self:addBackgroundBox(1, 1, w, h, activeBG) diff --git a/Basalt/objects/Textfield.lua b/Basalt/objects/Textfield.lua index 48e571f..922a7e7 100644 --- a/Basalt/objects/Textfield.lua +++ b/Basalt/objects/Textfield.lua @@ -4,8 +4,7 @@ local rep,find,gmatch,sub,len = string.rep,string.find,string.gmatch,string.sub, return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Textfield" - local hIndex, wIndex, textX, textY = 1, 1, 1, 1 + base:setType("Textfield") local lines = { "" } local bgLines = { "" } @@ -15,10 +14,18 @@ return function(name, basalt) local startSelX,endSelX,startSelY,endSelY - local selectionBG,selectionFG = colors.lightBlue,colors.black + base:addProperty("SelectionForeground", "color", colors.black) + base:addProperty("SelectionBackground", "color", colors.lightBlue) + base:combineProperty("SelectionColor", "SelectionBackground", "SelectionForeground") + base:addProperty("XOffset", "number", 1) + base:addProperty("YOffset", "number", 1) + base:combineProperty("Offset", "XOffset", "YOffset") + base:addProperty("TextXPosition", "number", 1) + base:addProperty("TextYPosition", "number", 1) + base:combineProperty("TextPosition", "TextXPosition", "TextYPosition") base:setSize(30, 12) - base:setZIndex(5) + base:setZ(5) local function isSelected() if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then @@ -76,11 +83,28 @@ return function(name, basalt) end end - textX, textY = sx, sy + self:setTextPosition(sx, sy) startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil return self end + local function getSelectedContent(self) + local sx, ex, sy, ey = getSelectionCoordinates() + local content = {} + if isSelected() then + if sy == ey then + table.insert(content, lines[sy]:sub(sx, ex)) + else + table.insert(content, lines[sy]:sub(sx, lines[sy]:len())) + for i = sy + 1, ey - 1 do + table.insert(content, lines[i]) + end + table.insert(content, lines[ey]:sub(1, ex)) + end + end + return content + end + local function stringGetPositions(str, word) local pos = {} if(str:len()>0)then @@ -98,8 +122,21 @@ return function(name, basalt) return pos end + local function stringGetKeywordPositions(str, keyword) + local pattern = "%f[%a]"..keyword.."%f[%A]" + local positions = {} + local start, finish = str:find(pattern) + while start do + table.insert(positions, start) + table.insert(positions, finish) + start, finish = str:find(pattern, finish + 1) + end + return positions + end + + local function updateColors(self, l) - l = l or textY + l = l or self:getTextYPosition() local fgLine = tHex[self:getForeground()]:rep(fgLines[l]:len()) local bgLine = tHex[self:getBackground()]:rep(bgLines[l]:len()) for k,v in pairs(rules)do @@ -118,7 +155,7 @@ return function(name, basalt) end for k,v in pairs(keyWords)do for _,b in pairs(v)do - local pos = stringGetPositions(lines[l], b) + local pos = stringGetKeywordPositions(lines[l], b) if(#pos>0)then for x=1,#pos/2 do local xP = x*2 - 1 @@ -139,10 +176,6 @@ return function(name, basalt) end local object = { - getType = function(self) - return objectType - end; - setBackground = function(self, bg) base.setBackground(self, bg) updateAllColors(self) @@ -155,32 +188,6 @@ return function(name, basalt) return self end, - setSelection = function(self, fg, bg) - selectionFG = fg or selectionFG - selectionBG = bg or selectionBG - return self - end, - - setSelectionFG = function(self, fg) - return self:setSelection(fg, nil) - end, - - setSelectionBG = function(self, bg) - return self:setSelection(nil, bg) - end, - - getSelection = function(self) - return selectionFG, selectionBG - end, - - getSelectionFG = function(self) - return selectionFG - end, - - getSelectionBG = function(self) - return selectionBG - end, - getLines = function(self) return lines end, @@ -201,7 +208,8 @@ return function(name, basalt) bgLines = {""} fgLines = {""} startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil - hIndex, wIndex, textX, textY = 1, 1, 1, 1 + self:setTextPosition(1, 1) + self:setOffset(1, 1) self:updateDraw() return self end, @@ -236,18 +244,18 @@ return function(name, basalt) if(keyWords[color]==nil)then keyWords[color] = {} end - for k,v in pairs(tab)do + for _,v in pairs(tab)do table.insert(keyWords[color], v) end self:updateDraw() return self - end; + end, addRule = function(self, rule, fg, bg) table.insert(rules, {rule, fg, bg}) self:updateDraw() return self - end; + end, editRule = function(self, rule, fg, bg) for k,v in pairs(rules)do @@ -290,40 +298,22 @@ return function(name, basalt) return self end, - getTextCursor = function(self) - return textX, textY + getLineCount = function(self) + return #lines end, - getOffset = function(self) - return wIndex, hIndex + getLineLength = function(self, index) + return lines[index]:len() end, - setOffset = function(self, xOff, yOff) - wIndex = xOff or wIndex - hIndex = yOff or hIndex - self:updateDraw() - return self - end, - - getXOffset = function(self) - return wIndex - end, - - setXOffset = function(self, xOff) - return self:setOffset(xOff, nil) - end, - - getYOffset = function(self) - return hIndex - end, - - setYOffset = function(self, yOff) - return self:setOffset(nil, yOff) - end, + getSelectedContent = getSelectedContent, getFocusHandler = function(self) base.getFocusHandler(self) + basalt.setRenderingThrottle(50) local obx, oby = self:getPosition() + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() self:getParent():setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self:getForeground()) end, @@ -337,6 +327,8 @@ return function(name, basalt) local parent = self:getParent() local obx, oby = self:getPosition() local w,h = self:getSize() + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() if (key == keys.backspace) then -- on backspace if(isSelected())then @@ -540,6 +532,8 @@ return function(name, basalt) cursorX = 0 end parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground()) + self:setOffset(wIndex, hIndex) + self:setTextPosition(textX, textY) self:updateDraw() return true end @@ -553,6 +547,9 @@ return function(name, basalt) if(isSelected())then removeSelection(self) end + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() + lines[textY] = lines[textY]:sub(1, textX - 1) .. char .. lines[textY]:sub(textX, lines[textY]:len()) fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self:getForeground()] .. fgLines[textY]:sub(textX, fgLines[textY]:len()) bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self:getBackground()] .. bgLines[textY]:sub(textX, bgLines[textY]:len()) @@ -577,6 +574,8 @@ return function(name, basalt) cursorX = 0 end parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground()) + self:setOffset(wIndex, hIndex) + self:setTextPosition(textX, textY) self:updateDraw() return true end @@ -588,6 +587,8 @@ return function(name, basalt) local obx, oby = self:getAbsolutePosition() local ox, oy = self:getPosition() local w,h = self:getSize() + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() if (lines[y - oby + hIndex] ~= nil) then if(x - obx + wIndex > 0)and(x - obx + wIndex <= w)then textX = x - obx + wIndex @@ -605,6 +606,8 @@ return function(name, basalt) wIndex = 1 end end + self:setOffset(wIndex, hIndex) + self:setTextPosition(textX, textY) parent:setCursor(not isSelected(), ox + textX - wIndex, oy + textY - hIndex, self:getForeground()) self:updateDraw() end @@ -619,6 +622,8 @@ return function(name, basalt) local obx, oby = self:getAbsolutePosition() local anchx, anchy = self:getPosition() local w,h = self:getSize() + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() hIndex = hIndex + dir if (hIndex > #lines - (h - 1)) then hIndex = #lines - (h - 1) @@ -628,6 +633,7 @@ return function(name, basalt) hIndex = 1 end + self:setOffset(wIndex, hIndex) if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (anchy + textY - hIndex >= anchy and anchy + textY - hIndex < anchy + h) then parent:setCursor(not isSelected(), anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground()) else @@ -643,6 +649,8 @@ return function(name, basalt) local parent = self:getParent() local obx, oby = self:getAbsolutePosition() local anchx, anchy = self:getPosition() + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() if (lines[y - oby + hIndex] ~= nil) then textX = x - obx + wIndex textY = y - oby + hIndex @@ -662,6 +670,8 @@ return function(name, basalt) end self:updateDraw() end + self:setOffset(wIndex, hIndex) + self:setTextPosition(textX, textY) parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground()) return true end @@ -670,6 +680,7 @@ return function(name, basalt) mouseUpHandler = function(self, button, x, y) if (base.mouseUpHandler(self, button, x, y)) then local obx, oby = self:getAbsolutePosition() + local wIndex, hIndex = self:getOffset() if (lines[y - oby + hIndex] ~= nil) then endSelX = x - obx + wIndex endSelY = y - oby + hIndex @@ -691,6 +702,11 @@ return function(name, basalt) if(self:isFocused())then local parent = self:getParent() local fgColor, bgColor = self:getForeground(), self:getBackground() + if(isSelected())then + removeSelection(self) + end + local wIndex, hIndex = self:getOffset() + local textX, textY = self:getTextPosition() local w, h = self:getSize() lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len()) fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len()) @@ -701,6 +717,8 @@ return function(name, basalt) end local anchx, anchy = self:getPosition() parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, fgColor) + self:setOffset(wIndex, hIndex) + self:setTextPosition(textX, textY) updateColors(self) self:updateDraw() end @@ -711,9 +729,9 @@ return function(name, basalt) base.draw(self) self:addDraw("textfield", function() local w, h = self:getSize() - local bgColor = tHex[self:getBackground()] - local fgColor = tHex[self:getForeground()] - + local wIndex, hIndex = self:getOffset() + local selectionBG = self:getSelectionBackground() + local selectionFG = self:getSelectionForeground() for n = 1, h do local text = "" local bg = "" @@ -725,12 +743,12 @@ return function(name, basalt) end text = sub(text, wIndex, w + wIndex - 1) - bg = rep(bgColor, w) - fg = rep(fgColor, w) + bg = sub(bg, wIndex, w + wIndex - 1) + fg = sub(fg, wIndex, w + wIndex - 1) self:addText(1, n, text) - self:addBG(1, n, bg) - self:addFG(1, n, fg) + self:addBg(1, n, bg) + self:addFg(1, n, fg) self:addBlit(1, n, text, fg, bg) end @@ -751,8 +769,8 @@ return function(name, basalt) local visible_line_length = math.min(line, w - xOffset) - self:addBG(1 + xOffset, n, rep(tHex[selectionBG], visible_line_length)) - self:addFG(1 + xOffset, n, rep(tHex[selectionFG], visible_line_length)) + self:addBg(1 + xOffset, n, rep(tHex[selectionBG], visible_line_length)) + self:addFg(1 + xOffset, n, rep(tHex[selectionFG], visible_line_length)) end end end) diff --git a/Basalt/objects/Thread.lua b/Basalt/objects/Thread.lua index 36129df..64b1215 100644 --- a/Basalt/objects/Thread.lua +++ b/Basalt/objects/Thread.lua @@ -1,7 +1,6 @@ return function(name, basalt) local base = basalt.getObject("Object")(name, basalt) - - local objectType = "Thread" + base:setType("Thread") local func local cRoutine @@ -9,10 +8,6 @@ return function(name, basalt) local filter local object = { - getType = function(self) - return objectType - 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 9d2b575..f6e1e24 100644 --- a/Basalt/objects/Timer.lua +++ b/Basalt/objects/Timer.lua @@ -1,33 +1,34 @@ return function(name, basalt) local base = basalt.getObject("Object")(name, basalt) - local objectType = "Timer" + base:setType("Timer") + + base:addProperty("Timer", "number", 0, false, function(self, value) + if (value < 0) then + value = 0 + end + return value + end) + + base:addProperty("Repeat", "number", 1, false, function(self, value) + if (value < 0) then + value = 0 + end + return value + end) + + base:combineProperty("Time", "Timer", "Repeat") - local timer = 0 - local savedRepeats = 0 local repeats = 0 local timerObj local timerIsActive = false local object = { - getType = function(self) - return objectType - end, - - setTime = function(self, _timer, _repeats) - timer = _timer or 0 - savedRepeats = _repeats or 1 - return self - end, - - getTime = function(self) - return timer - end, - start = function(self) if(timerIsActive)then os.cancelTimer(timerObj) end - repeats = savedRepeats + local timer, repeatAmount = self:getTime() + repeats = repeatAmount timerObj = os.startTimer(timer) timerIsActive = true self:listenEvent("other_event") @@ -64,6 +65,7 @@ return function(name, basalt) base.eventHandler(self, event, ...) if event == "timer" and tObj == timerObj and timerIsActive then self:sendEvent("timed_event") + local timer = self:getTimer() if (repeats >= 1) then repeats = repeats - 1 if (repeats >= 1) then diff --git a/Basalt/objects/Treeview.lua b/Basalt/objects/Treeview.lua index 03f63aa..b03b586 100644 --- a/Basalt/objects/Treeview.lua +++ b/Basalt/objects/Treeview.lua @@ -3,18 +3,30 @@ local tHex = require("tHex") return function(name, basalt) local base = basalt.getObject("ChangeableObject")(name, basalt) - local objectType = "Treeview" + base:setType("Treeview") - local nodes = {} - local itemSelectedBG = colors.black - local itemSelectedFG = colors.lightGray - local selectionColorActive = true - local textAlign = "left" - local xOffset, yOffset = 0, 0 - local scrollable = true + base:addProperty("Nodes", "table", {}) + base:addProperty("SelectionBackground", "color", colors.black) + base:addProperty("SelectionForeground", "color", colors.lightGray) + base:combineProperty("SelectionColor", "SelectionBackground", "SelectionForeground") + base:addProperty("XOffset", "number", 0) + base:addProperty("YOffset", "number", 0) + base:combineProperty("Offset", "XOffset", "YOffset") + base:addProperty("Scrollable", "boolean", true) + base:addProperty("TextAlign", {"left", "center", "right"}, "left") + base:addProperty("ExpandableSymbol", "char", "\7") + base:addProperty("ExpandableSymbolForeground", "color", colors.lightGray) + base:addProperty("ExpandableSymbolBackground", "color", colors.black) + base:combineProperty("ExpandableSymbolColor", "ExpandableSymbolForeground", "ExpandableSymbolBackground") + base:addProperty("ExpandedSymbol", "char", "\8") + base:addProperty("ExpandedSymbolForeground", "color", colors.lightGray) + base:addProperty("ExpandedSymbolBackground", "color", colors.black) + base:combineProperty("ExpandedSymbolColor", "ExpandedSymbolForeground", "ExpandedSymbolBackground") + base:addProperty("ExpandableSymbolSpacing", "number", 1) + base:addProperty("selectionColorActive", "boolean", true) base:setSize(16, 8) - base:setZIndex(5) + base:setZ(5) local function newNode(text, expandable) text = text or "" @@ -129,6 +141,9 @@ return function(name, basalt) end local root = newNode("Root", true) + base:addProperty("Root", "table", root, false, function(self, value) + value.setParent(nil) + end) root:setExpanded(true) local object = { @@ -143,91 +158,6 @@ return function(name, basalt) return base end, - getType = function(self) - return objectType - end, - - isType = function(self, t) - return objectType == t or base.isType ~= nil and base.isType(t) or false - end, - - setOffset = function(self, x, y) - xOffset = x - yOffset = y - return self - end, - - setXOffset = function(self, x) - return self:setOffset(x, yOffset) - end, - - setYOffset = function(self, y) - return self:setOffset(xOffset, y) - end, - - getOffset = function(self) - return xOffset, yOffset - end, - - getXOffset = function(self) - return xOffset - end, - - getYOffset = function(self) - return yOffset - end, - - setScrollable = function(self, scroll) - scrollable = scroll - return self - end, - - getScrollable = function(self, scroll) - return scrollable - end, - - setSelectionColor = function(self, bgCol, fgCol, active) - itemSelectedBG = bgCol or self:getBackground() - itemSelectedFG = fgCol or self:getForeground() - selectionColorActive = active~=nil and active or true - self:updateDraw() - return self - end, - - setSelectionBG = function(self, bgCol) - return self:setSelectionColor(bgCol, nil, selectionColorActive) - end, - - setSelectionFG = function(self, fgCol) - return self:setSelectionColor(nil, fgCol, selectionColorActive) - end, - - getSelectionColor = function(self) - return itemSelectedBG, itemSelectedFG - end, - - getSelectionBG = function(self) - return itemSelectedBG - end, - - getSelectionFG = function(self) - return itemSelectedFG - end, - - isSelectionColorActive = function(self) - return selectionColorActive - end, - - getRoot = function(self) - return root - end, - - setRoot = function(self, node) - root = node - node.setParent(nil) - return self - end, - onSelect = function(self, ...) for _,v in pairs(table.pack(...))do if(type(v)=="function")then @@ -245,7 +175,7 @@ return function(name, basalt) mouseHandler = function(self, button, x, y) if base.mouseHandler(self, button, x, y) then - local currentLine = 1 - yOffset + local currentLine = 1 - self:getYOffset() local obx, oby = self:getAbsolutePosition() local w, h = self:getSize() local function checkNodeClick(node, level) @@ -279,6 +209,8 @@ return function(name, basalt) scrollHandler = function(self, dir, x, y) if base.scrollHandler(self, dir, x, y) then + local scrollable = self:getScrollable() + local yOffset = self:getYOffset() if scrollable then local _, h = self:getSize() yOffset = yOffset + dir @@ -310,6 +242,7 @@ return function(name, basalt) yOffset = yOffset - 1 end end + self:setYOffset(yOffset) self:updateDraw() end return true @@ -320,6 +253,9 @@ return function(name, basalt) draw = function(self) base.draw(self) self:addDraw("treeview", function() + local xOffset, yOffset = self:getOffset() + local itemSelectedBG self:getSelectionBackground() + local itemSelectedFG self:getSelectionForeground() local currentLine = 1 - yOffset local lastClickedNode = self:getValue() local function drawNode(node, level) @@ -347,8 +283,6 @@ return function(name, basalt) end end) end, - - } object.__index = object diff --git a/Basalt/objects/VisualObject.lua b/Basalt/objects/VisualObject.lua index 27bf953..a3ef03d 100644 --- a/Basalt/objects/VisualObject.lua +++ b/Basalt/objects/VisualObject.lua @@ -3,18 +3,31 @@ local tHex = require("tHex") local sub, find, insert = string.sub, string.find, table.insert +local function split(str, d) + local result = {} + if str == "" then + return result + end + d = d or " " + local start = 1 + local delim_start, delim_end = find(str, d, start) + while delim_start do + insert(result, {x=start, value=sub(str, start, delim_start - 1)}) + start = delim_end + 1 + delim_start, delim_end = find(str, d, start) + end + insert(result, {x=start, value=sub(str, start)}) + return result +end + return function(name, basalt) local base = basalt.getObject("Object")(name, basalt) - -- Base object - local objectType = "VisualObject" -- not changeable + base:setType("VisualObject") - local isVisible,ignOffset,isHovered,isClicked,isDragging = true,false,false,false,false - local zIndex = 1 + local ignOffset,isHovered,isClicked,isDragging = false,false,false,false - local x, y, width, height = 1,1,1,1 - local dragStartX, dragStartY, dragXOffset, dragYOffset = 0, 0, 0, 0 + local dragStartX, dragStartY = 0, 0 - local bgColor,fgColor, transparency = colors.black, colors.white, false local parent local preDrawQueue = {} @@ -23,35 +36,54 @@ return function(name, basalt) local renderObject = {} - local function split(str, d) - local result = {} - if str == "" then - return result + base:addProperty("Visible", "boolean", true, false, function(self, val) + self:setProperty("Enabled", val) + end) + base:addProperty("Transparent", "boolean", false) + base:addProperty("Background", "color", colors.black) + base:addProperty("BgSymbol", "char", "") + base:addProperty("BgSymbolColor", "color", colors.red) + base:addProperty("Foreground", "color", colors.white) + base:addProperty("X", "number", 1, false, function(self, val) + local y = self:getProperty("Y") + if (parent ~= nil) then + parent:customEventHandler("basalt_FrameReposition", self, val, y) end - d = d or " " - local start = 1 - local delim_start, delim_end = find(str, d, start) - while delim_start do - insert(result, {x=start, value=sub(str, start, delim_start - 1)}) - start = delim_end + 1 - delim_start, delim_end = find(str, d, start) - end - insert(result, {x=start, value=sub(str, start)}) - return result - end + self:repositionHandler(val, y) + end) + base:addProperty("Y", "number", 1, false, function(self, val) + local x = self:getProperty("X") + if (parent ~= nil) then + parent:customEventHandler("basalt_FrameReposition", self, x, val) + end + self:repositionHandler(x, val) + end) + base:addProperty("Width", "number", 1, false, function(self, val) + local height = self:getProperty("Height") + if (parent ~= nil) then + parent:customEventHandler("basalt_FrameResize", self, val, height) + end + self:resizeHandler(val, height) + end) + base:addProperty("Height", "number", 1, false, function(self, val) + local width = self:getProperty("Width") + if (parent ~= nil) then + parent:customEventHandler("basalt_FrameResize", self, width, val) + end + self:resizeHandler(width, val) + end) + base:addProperty("IgnoreOffset", "boolean", false, false) + base:combineProperty("Position", "X", "Y") + base:combineProperty("Size", "Width", "Height") + base:setProperty("Clicked", false) + base:setProperty("Hovered", false) + base:setProperty("Dragging", false) + base:setProperty("Focused", false) local object = { - getType = function(self) - return objectType - end, - getBase = function(self) return base - end, - - isType = function(self, t) - return objectType==t or base.isType~=nil and base.isType(t) or false end, getBasalt = function(self) @@ -59,36 +91,22 @@ return function(name, basalt) end, show = function(self) - isVisible = true - self:updateDraw() + self:setVisible(true) return self end, hide = function(self) - isVisible = false - self:updateDraw() + self:setVisible(false) return self end, isVisible = function(self) - return isVisible - end, - - setVisible = function(self, _isVisible) - isVisible = _isVisible or not isVisible - self:updateDraw() - return self - end, - - setTransparency = function(self, _transparency) - transparency = _transparency~= nil and _transparency or true - self:updateDraw() - return self + return self:getVisible() end, setParent = function(self, newParent, noRemove) - base.setParent(self, newParent, noRemove) parent = newParent + base.setParent(self, newParent, noRemove) return self end, @@ -99,19 +117,6 @@ return function(name, basalt) return self end, - setZIndex = function(self, index) - zIndex = index - if (parent ~= nil) then - parent:updateZIndex(self, zIndex) - self:updateDraw() - end - return self - end, - - getZIndex = function(self) - return zIndex - end, - updateDraw = function(self) if (parent ~= nil) then parent:updateDraw() @@ -119,100 +124,7 @@ return function(name, basalt) return self end, - setPosition = function(self, xPos, yPos, rel) - local curX, curY = x, y - if(type(xPos)=="number")then - x = rel and x+xPos or xPos - end - if(type(yPos)=="number")then - y = rel and y+yPos or yPos - end - if(parent~=nil)then parent:customEventHandler("basalt_FrameReposition", self) end - if(self:getType()=="Container")then parent:customEventHandler("basalt_FrameReposition", self) end - self:updateDraw() - self:repositionHandler(curX, curY) - return self - end, - - getX = function(self) - return x - end, - - setX = function(self, newX) - return self:setPosition(newX, y) - end, - - getY = function(self) - return y - end, - - setY = function(self, newY) - return self:setPosition(x, newY) - end, - - getPosition = function(self) - return x, y - end, - - setSize = function(self, newWidth, newHeight, rel) - local oldW, oldH = width, height - if(type(newWidth)=="number")then - width = rel and width+newWidth or newWidth - end - if(type(newHeight)=="number")then - height = rel and height+newHeight or newHeight - end - if(parent~=nil)then - parent:customEventHandler("basalt_FrameResize", self) - if(self:getType()=="Container")then parent:customEventHandler("basalt_FrameResize", self) end - end - self:resizeHandler(oldW, oldH) - self:updateDraw() - return self - end, - - getHeight = function(self) - return height - end, - - setHeight = function(self, newHeight) - return self:setSize(width, newHeight) - end, - - getWidth = function(self) - return width - end, - - setWidth = function(self, newWidth) - return self:setSize(newWidth, height) - end, - - getSize = function(self) - return width, height - end, - - setBackground = function(self, color) - bgColor = color - self:updateDraw() - return self - end, - - getBackground = function(self) - return bgColor - end, - - setForeground = function(self, color) - fgColor = color or false - self:updateDraw() - return self - end, - - getForeground = function(self) - return fgColor - end, - getAbsolutePosition = function(self, x, y) - -- relative position to absolute position if (x == nil) or (y == nil) then x, y = self:getPosition() end @@ -225,21 +137,24 @@ return function(name, basalt) return x, y end, - ignoreOffset = function(self, ignore) - ignOffset = ignore - if(ignore==nil)then ignOffset = true end - return self - end, + getRelativePosition = function(self, x, y) + if (x == nil) or (y == nil) then + x, y = 1, 1 + end - getIgnoreOffset = function(self) - return ignOffset + if (parent ~= nil) then + local xO, yO = self:getAbsolutePosition() + x = xO - x + 1 + y = yO - y + 1 + end + return x, y end, isCoordsInObject = function(self, x, y) - if(isVisible)and(self:isEnabled())then + if(self:getVisible())and(self:getEnabled())then if(x==nil)or(y==nil)then return false end local objX, objY = self:getAbsolutePosition() - local w, h = self:getSize() + local w, h = self:getSize() if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) then return true end @@ -316,7 +231,9 @@ return function(name, basalt) end isClicked = true isDragging = true - dragStartX, dragStartY = x, y + self:setProperty("Dragging", true) + self:setProperty("Clicked", true) + dragStartX, dragStartY = x, y return true end end, @@ -327,6 +244,8 @@ return function(name, basalt) local objX, objY = self:getAbsolutePosition() local val = self:sendEvent("mouse_release", button, x - (objX-1), y - (objY-1), x, y) isClicked = false + self:setProperty("Clicked", false) + self:setProperty("Dragging", false) end if(self:isCoordsInObject(x, y))then local objX, objY = self:getAbsolutePosition() @@ -349,9 +268,7 @@ return function(name, basalt) end if(self:isCoordsInObject(x, y))then - local objX, objY = self:getAbsolutePosition() - dragStartX, dragStartY = x, y - dragXOffset, dragYOffset = objX - x, objY - y + dragStartX, dragStartY = x, y end end, @@ -372,17 +289,19 @@ return function(name, basalt) local val = self:sendEvent("mouse_hover", x, y, stopped) if(val==false)then return false end isHovered = true + self:setProperty("Hovered", true) return true end if(isHovered)then local val = self:sendEvent("mouse_leave", x, y, stopped) if(val==false)then return false end isHovered = false + self:setProperty("Hovered", false) end end, keyHandler = function(self, key, isHolding) - if(self:isEnabled())and(isVisible)then + if(self:isEnabled())and(self:getVisible())then if (self:isFocused()) then local val = self:sendEvent("key", key, isHolding) if(val==false)then return false end @@ -392,7 +311,7 @@ return function(name, basalt) end, keyUpHandler = function(self, key) - if(self:isEnabled())and(isVisible)then + if(self:isEnabled())and(self:getVisible())then if (self:isFocused()) then local val = self:sendEvent("key_up", key) if(val==false)then return false end @@ -402,7 +321,7 @@ return function(name, basalt) end, charHandler = function(self, char) - if(self:isEnabled())and(isVisible)then + if(self:isEnabled())and(self:getVisible())then if(self:isFocused())then local val = self:sendEvent("char", char) if(val==false)then return false end @@ -413,12 +332,15 @@ return function(name, basalt) getFocusHandler = function(self) local val = self:sendEvent("get_focus") + self:setProperty("Focused", true) if(val~=nil)then return val end return true end, loseFocusHandler = function(self) isDragging = false + self:setProperty("Dragging", false) + self:setProperty("Focused", false) local val = self:sendEvent("lose_focus") if(val~=nil)then return val end return true @@ -454,7 +376,7 @@ return function(name, basalt) setDrawState = function(self, name, state, typ) local queue = (typ==nil or typ==1) and drawQueue or typ==2 and preDrawQueue or typ==3 and postDrawQueue for k,v in pairs(queue)do - if(v.name==name)then + if(v.name==name)then v.active = state break end @@ -475,12 +397,13 @@ return function(name, basalt) addText = function(self, x, y, text) local obj = self:getParent() or self local xPos,yPos = self:getPosition() + local transparent = self:getTransparent() if(parent~=nil)then local xO, yO = parent:getOffset() xPos = ignOffset and xPos or xPos - xO yPos = ignOffset and yPos or yPos - yO end - if not(transparency)then + if not(transparent)then obj:setText(x+xPos-1, y+yPos-1, text) return end @@ -492,48 +415,50 @@ return function(name, basalt) end end, - addBG = function(self, x, y, bg, noText) + addBg = function(self, x, y, bg, noText) local obj = parent or self local xPos,yPos = self:getPosition() + local transparent = self:getTransparent() if(parent~=nil)then local xO, yO = parent:getOffset() xPos = ignOffset and xPos or xPos - xO yPos = ignOffset and yPos or yPos - yO end - if not(transparency)then - obj:setBG(x+xPos-1, y+yPos-1, bg) + if not(transparent)then + obj:setBg(x+xPos-1, y+yPos-1, bg) return end local t = split(bg) - for k,v in pairs(t)do + for _,v in pairs(t)do if(v.value~="")and(v.value~=" ")then if(noText~=true)then obj:setText(x+v.x+xPos-2, y+yPos-1, (" "):rep(#v.value)) - obj:setBG(x+v.x+xPos-2, y+yPos-1, v.value) + obj:setBg(x+v.x+xPos-2, y+yPos-1, v.value) else table.insert(renderObject, {x=x+v.x-1,y=y,bg=v.value}) - obj:setBG(x+xPos-1, y+yPos-1, fg) + obj:setBg(x+xPos-1, y+yPos-1, v.value) end end end end, - addFG = function(self, x, y, fg) + addFg = function(self, x, y, fg) local obj = parent or self local xPos,yPos = self:getPosition() + local transparent = self:getTransparent() if(parent~=nil)then local xO, yO = parent:getOffset() xPos = ignOffset and xPos or xPos - xO yPos = ignOffset and yPos or yPos - yO end - if not(transparency)then - obj:setFG(x+xPos-1, y+yPos-1, fg) + if not(transparent)then + obj:setFg(x+xPos-1, y+yPos-1, fg) return end local t = split(fg) - for k,v in pairs(t)do + for _,v in pairs(t)do if(v.value~="")and(v.value~=" ")then - obj:setFG(x+v.x+xPos-2, y+yPos-1, v.value) + obj:setFg(x+v.x+xPos-2, y+yPos-1, v.value) end end end, @@ -541,31 +466,32 @@ return function(name, basalt) addBlit = function(self, x, y, t, fg, bg) local obj = parent or self local xPos,yPos = self:getPosition() + local transparent = self:getTransparent() if(parent~=nil)then local xO, yO = parent:getOffset() xPos = ignOffset and xPos or xPos - xO yPos = ignOffset and yPos or yPos - yO end - if not(transparency)then + if not(transparent)then obj:blit(x+xPos-1, y+yPos-1, t, fg, bg) return end local _text = split(t, "\0") local _fg = split(fg) local _bg = split(bg) - for k,v in pairs(_text)do + for _,v in pairs(_text)do if(v.value~="")or(v.value~="\0")then obj:setText(x+v.x+xPos-2, y+yPos-1, v.value) end end - for k,v in pairs(_bg)do + for _,v in pairs(_bg)do if(v.value~="")or(v.value~=" ")then - obj:setBG(x+v.x+xPos-2, y+yPos-1, v.value) + obj:setBg(x+v.x+xPos-2, y+yPos-1, v.value) end end - for k,v in pairs(_fg)do + for _,v in pairs(_fg)do if(v.value~="")or(v.value~=" ")then - obj:setFG(x+v.x+xPos-2, y+yPos-1, v.value) + obj:setFg(x+v.x+xPos-2, y+yPos-1, v.value) end end end, @@ -604,7 +530,7 @@ return function(name, basalt) end, render = function(self) - if (isVisible)then + if (self:getVisible())then self:redraw() end end, @@ -631,16 +557,25 @@ return function(name, basalt) draw = function(self) self:addDraw("base", function() local w,h = self:getSize() - if(bgColor~=false)then + local bgColor = self:getBackground() + local bgSymbol = self:getBgSymbol() + local bgSymbolColor = self:getBgSymbolColor() + local fgColor = self:getForeground() + if(bgColor~=nil)then self:addTextBox(1, 1, w, h, " ") self:addBackgroundBox(1, 1, w, h, bgColor) end - if(fgColor~=false)then + if(bgSymbol~=nil)and(bgSymbol~="")then + self:addTextBox(1, 1, w, h, bgSymbol) + self:addForegroundBox(1, 1, w, h, bgSymbolColor) + end + if(fgColor~=nil)then self:addForegroundBox(1, 1, w, h, fgColor) end end, 1) end, } + object.__index = object return setmetatable(object, base) end \ No newline at end of file diff --git a/Basalt/plugins/animations.lua b/Basalt/plugins/animations.lua index 99fe8f0..acbf426 100644 --- a/Basalt/plugins/animations.lua +++ b/Basalt/plugins/animations.lua @@ -217,10 +217,16 @@ local lerp = { local XMLParser = require("xmlParser") +local animationCount = 0 +local renderThrottleCACHE + return { VisualObject = function(base, basalt) local activeAnimations = {} local defaultMode = "linear" + if(renderThrottleCACHE==nil)then + renderThrottleCACHE = basalt.getRenderingThrottle() + end local function getAnimation(self, timerId) for k,v in pairs(activeAnimations)do @@ -244,6 +250,10 @@ return { end activeAnimations[typ].finished = function() set(self, v1, v2) + animationCount = animationCount - 1 + if(animationCount==0)then + basalt.setRenderingThrottle(renderThrottleCACHE) + end if(f~=nil)then f(self) end end @@ -251,6 +261,8 @@ return { activeAnimations[typ].progress=0 activeAnimations[typ].duration=duration activeAnimations[typ].mode=mode + animationCount = animationCount + 1 + basalt.setRenderingThrottle(0) self:listenEvent("other_event") end diff --git a/Basalt/plugins/bigfonts.lua b/Basalt/plugins/bigfonts.lua index 040a508..2dd01bb 100644 --- a/Basalt/plugins/bigfonts.lua +++ b/Basalt/plugins/bigfonts.lua @@ -164,22 +164,6 @@ return { return self end, - setBackground = function(self, newColor) - base.setBackground(self, newColor) - if(fontsize>1)then - self:setFontSize(fontsize) - end - return self - end, - - setForeground = function(self, newColor) - base.setForeground(self, newColor) - if(fontsize>1)then - self:setFontSize(fontsize) - end - return self - end, - getFontSize = function(self) return fontsize end, @@ -233,4 +217,4 @@ return { } return object end -} +} \ No newline at end of file diff --git a/Basalt/plugins/border.lua b/Basalt/plugins/border.lua index 517cd86..3e120f5 100644 --- a/Basalt/plugins/border.lua +++ b/Basalt/plugins/border.lua @@ -74,7 +74,7 @@ return { end if(borderColors["bottom"]~=false)and(borderColors["left"]~=false)then self:addTextBox(1, h, 1, 1, "\138") - if(bgCol~=false)then self:addForegroundBox(0, h, 1, 1, bgCol) end + if(bgCol~=false)then self:addForegroundBox(1, h, 1, 1, bgCol) end self:addBackgroundBox(1, h, 1, 1, borderColors["left"]) end end diff --git a/Basalt/plugins/debug.lua b/Basalt/plugins/debug.lua index efe9e87..16d04ea 100644 --- a/Basalt/plugins/debug.lua +++ b/Basalt/plugins/debug.lua @@ -3,27 +3,28 @@ local wrapText = utils.wrapText return { basalt = function(basalt) - local mainFrame = basalt.getMainFrame() + local mainFrame local debugFrame local debugList local debugLabel local debugExitButton local function createDebuggingFrame() + if(mainFrame==nil)then mainFrame = basalt.getMainFrame() end local minW = 16 local minH = 6 local maxW = 99 local maxH = 99 local w, h = mainFrame:getSize() - debugFrame = mainFrame:addMovableFrame("basaltDebuggingFrame"):setSize(w-20, h-10):setBackground(colors.gray):setForeground(colors.white):setZIndex(100):hide() - debugFrame:addPane():setSize("parent.w", 1):setPosition(1, 1):setBackground(colors.black):setForeground(colors.white) - debugFrame:setPosition(-w, h/2-debugFrame:getHeight()/2):setBorder(colors.black) + debugFrame = mainFrame:addMovableFrame("basaltDebuggingFrame"):setSize(w-10, h-6):setBackground(colors.black):setForeground(colors.white):setZ(100):hide() + debugFrame:addPane():setSize("{parent.w}", 1):setPosition(1, 1):setBackground(colors.cyan):setForeground(colors.black) + debugFrame:setPosition(-w, h/2-debugFrame:getHeight()/2):setBorder(colors.cyan) local resizeButton = debugFrame:addButton() - :setPosition("parent.w", "parent.h") + :setPosition("{parent.w}", "{parent.h}") :setSize(1, 1) :setText("\133") - :setForeground(colors.gray) - :setBackground(colors.black) + :setForeground(colors.black) + :setBackground(colors.cyan) :onClick(function() end) :onDrag(function(self, event, btn, xOffset, yOffset) local w, h = debugFrame:getSize() @@ -37,21 +38,21 @@ return { debugFrame:setSize(wOff, hOff) end) - debugExitButton = debugFrame:addButton():setText("Close"):setPosition("parent.w - 6", 1):setSize(7, 1):setBackground(colors.red):setForeground(colors.white):onClick(function() + debugExitButton = debugFrame:addButton():setText("Close"):setPosition("{parent.w - 6}", 1):setSize(7, 1):setBackground(colors.red):setForeground(colors.white):onClick(function() debugFrame:animatePosition(-w, h/2-debugFrame:getHeight()/2, 0.5) end) debugList = debugFrame:addList() - :setSize("parent.w - 2", "parent.h - 3") + :setSize("{parent.w - 2}", "{parent.h - 3}") :setPosition(2, 3) - :setBackground(colors.gray) + :setBackground(colors.black) :setForeground(colors.white) - :setSelectionColor(colors.gray, colors.white) + :setSelectionColor(colors.black, colors.white) if(debugLabel==nil)then debugLabel = mainFrame:addLabel() - :setPosition(1, "parent.h") + :setPosition(1, "{parent.h}") :setBackground(colors.black) :setForeground(colors.white) - :setZIndex(100) + :setZ(100) :onClick(function() debugFrame:show() debugFrame:animatePosition(w/2-debugFrame:getWidth()/2, h/2-debugFrame:getHeight()/2, 0.5) diff --git a/Basalt/plugins/dynamicValues.lua b/Basalt/plugins/dynamicValues.lua index 7a6f3ea..ff66146 100644 --- a/Basalt/plugins/dynamicValues.lua +++ b/Basalt/plugins/dynamicValues.lua @@ -1,124 +1,209 @@ -local utils = require("utils") -local count = utils.tableCount +local protectedNames = {clamp=true, round=true, math=true, colors=true} +local function replace(word) + if(protectedNames[word])then return word end + if word:sub(1, 1):find('%a') and not word:find('.', 1, true) then + return '"' .. word .. '"' + end + return word +end + +local function parseString(str) + str = str:gsub("{", "") + str = str:gsub("}", "") + for k,v in pairs(colors)do + if(type(k)=="string")then + str = str:gsub("%f[%w]"..k.."%f[%W]", "colors."..k) + end + end + str = str:gsub("(%s?)([%w.]+)", function(a, b) return a .. replace(b) end) + str = str:gsub("%s?%?", " and ") + str = str:gsub("%s?:", " or ") + str = str:gsub("%.w%f[%W]", ".width") + str = str:gsub("%.h%f[%W]", ".height") + return str +end + + + +local function processString(str, env) + env.math = math + env.colors = colors + env.clamp = function(val, min, max) + return math.min(math.max(val, min), max) + end + env.round = function(val) + return math.floor(val + 0.5) + end + local f = load("return " .. str, "", nil, env) + + if(f==nil)then error(str.." - is not a valid dynamic value string") end + return f() +end + +local function dynamicValue(object, name, dynamicString, basalt) + local objectGroup = {} + local observers = {} + dynamicString = parseString(dynamicString) + local cachedValue = nil + local needsUpdate = true + + local function updateFunc() + needsUpdate = true + end + + for v in dynamicString:gmatch("%a+%.%a+")do + local name = v:gsub("%.%a+", "") + local prop = v:gsub("%a+%.", "") + if(objectGroup[name]==nil)then + objectGroup[name] = {} + end + table.insert(objectGroup[name], prop) + end + + for k,v in pairs(objectGroup) do + if(k=="self") then + for _, b in pairs(v) do + if(name~=b)then + object:addPropertyObserver(b, updateFunc) + if(b=="clicked")or(b=="dragging")then + object:listenEvent("mouse_click") + object:listenEvent("mouse_up") + end + if(b=="dragging")then + object:listenEvent("mouse_drag") + end + if(b=="hovered")then + --object:listenEvent("mouse_enter") + --object:listenEvent("mouse_exit") + end + table.insert(observers, {obj=object, name=b}) + else + error("Dynamic Values - self reference to self") + end + end + end + + if(k=="parent") then + for _, b in pairs(v) do + object:getParent():addPropertyObserver(b, updateFunc) + table.insert(observers, {obj=object:getParent(), name=b}) + end + end + + if(k~="self" and k~="parent")and(protectedNames[k]==nil)then + local obj = object:getParent():getChild(k) + for _, b in pairs(v) do + obj:addPropertyObserver(b, updateFunc) + table.insert(observers, {obj=obj, name=b}) + end + end + end + + + local function calculate() + local env = {} + local parent = object:getParent() + for k,v in pairs(objectGroup)do + local objTable = {} + + if(k=="self")then + for _,b in pairs(v)do + objTable[b] = object:getProperty(b) + end + end + + if(k=="parent")then + for _,b in pairs(v)do + objTable[b] = parent:getProperty(b) + end + end + + if(k~="self")and(k~="parent")and(protectedNames[k]==nil)then + local obj = parent:getChild(k) + if(obj==nil)then + error("Dynamic Values - unable to find object: "..k) + end + for _,b in pairs(v)do + objTable[b] = obj:getProperty(b) + end + end + env[k] = objTable + end + return processString(dynamicString, env) + end + + return { + get = function(self) + if(needsUpdate)then + cachedValue = calculate() + needsUpdate = false + object:updatePropertyObservers(name) + end + return cachedValue + end, + removeObservers = function(self) + for _,v in pairs(observers)do + v.obj:removePropertyObserver(v.name, updateFunc) + end + end, + } +end return { - VisualObject = function(base, basalt) - local dynObjects = {} - local curProperties = {} - local properties = {x="getX", y="getY", w="getWidth", h="getHeight"} + Object = function(base, basalt) + local observers = {} + local activeDynValues = {} - local function stringToNumber(str) - local ok, result = pcall(load("return " .. str, "", nil, {math=math})) - if not(ok)then error(str.." - is not a valid dynamic value string") end - return result + local function filterDynValues(self, name, value) + if(type(value)=="string")and(value:sub(1,1)=="{")and(value:sub(-1)=="}")then + if(activeDynValues[name]~=nil)then + activeDynValues[name].removeObservers() + end + activeDynValues[name] = dynamicValue(self, name, value, basalt) + value = activeDynValues[name].get + end + return value end - local function createDynamicValue(self, key, val) - local objectGroup = {} - local properties = properties - for a,b in pairs(properties)do - for v in val:gmatch("%a+%."..a)do - local name = v:gsub("%."..a, "") - if(name~="self")and(name~="parent")then - table.insert(objectGroup, name) + return { + updatePropertyObservers = function(self, name) + if(observers[name]~=nil)then + for _,v in pairs(observers[name])do + v(self, name) end end - end - - local parent = self:getParent() - local objects = {} - for k,v in pairs(objectGroup)do - objects[v] = parent:getChild(v) - if(objects[v]==nil)then - error("Dynamic Values - unable to find object: "..v) - end - end - objects["self"] = self - objects["parent"] = parent - - dynObjects[key] = function() - local mainVal = val - for a,b in pairs(properties)do - for v in val:gmatch("%w+%."..a) do - local obj = objects[v:gsub("%."..a, "")] - if(obj~=nil)then - mainVal = mainVal:gsub(v, obj[b](obj)) - else - error("Dynamic Values - unable to find object: "..v) - end - end - end - curProperties[key] = math.floor(stringToNumber(mainVal)+0.5) - end - dynObjects[key]() - end - - local function updatePositions(self) - if(count(dynObjects)>0)then - for k,v in pairs(dynObjects)do - v() - end - local properties = {x="getX", y="getY", w="getWidth", h="getHeight"} - for k,v in pairs(properties)do - if(dynObjects[k]~=nil)then - if(curProperties[k]~=self[v](self))then - if(k=="x")or(k=="y")then - base.setPosition(self, curProperties["x"] or self:getX(), curProperties["y"] or self:getY()) - end - if(k=="w")or(k=="h")then - base.setSize(self, curProperties["w"] or self:getWidth(), curProperties["h"] or self:getHeight()) - end - end - end - end - end - end - - local object = { - updatePositions = updatePositions, - createDynamicValue = createDynamicValue, - - setPosition = function(self, xPos, yPos, rel) - curProperties.x = xPos - curProperties.y = yPos - if(type(xPos)=="string")then - createDynamicValue(self, "x", xPos) - else - dynObjects["x"] = nil - end - if(type(yPos)=="string")then - createDynamicValue(self, "y", yPos) - else - dynObjects["y"] = nil - end - base.setPosition(self, curProperties.x, curProperties.y, rel) return self end, - setSize = function(self, w, h, rel) - curProperties.w = w - curProperties.h = h - if(type(w)=="string")then - createDynamicValue(self, "w", w) - else - dynObjects["w"] = nil + setProperty = function(self, name, value, rule) + value = filterDynValues(self, name, value) + base.setProperty(self, name, value, rule) + if(observers[name]~=nil)then + for _,v in pairs(observers[name])do + v(self, name) + end end - if(type(h)=="string")then - createDynamicValue(self, "h", h) - else - dynObjects["h"] = nil - end - base.setSize(self, curProperties.w, curProperties.h, rel) return self end, - customEventHandler = function(self, event, ...) - base.customEventHandler(self, event, ...) - if(event=="basalt_FrameReposition")or(event=="basalt_FrameResize")then - updatePositions(self) + addPropertyObserver = function(self, name, func) + name = name:gsub("^%l", string.upper) + if(observers[name]==nil)then + observers[name] = {} + end + table.insert(observers[name], func) + end, + + removePropertyObserver = function(self, name, func) + name = name:gsub("^%l", string.upper) + if(observers[name]~=nil)then + for k,v in pairs(observers[name])do + if(v==func)then + table.remove(observers[name], k) + end + end end end, } - return object end -} \ No newline at end of file +} diff --git a/Basalt/plugins/moreDrawing.lua b/Basalt/plugins/moreDrawing.lua new file mode 100644 index 0000000..fd009ff --- /dev/null +++ b/Basalt/plugins/moreDrawing.lua @@ -0,0 +1,321 @@ +local tHex = require("tHex") + +local function line(x1, y1, x2, y2) + local points = {} + local dx = math.abs(x2 - x1) + local dy = math.abs(y2 - y1) + local sx = (x1 < x2) and 1 or -1 + local sy = (y1 < y2) and 1 or -1 + local err = dx - dy + + while true do + table.insert(points, {x = x1, y = y1}) + + if (x1 == x2 and y1 == y2) then break end + local e2 = err * 2 + if e2 > -dy then + err = err - dy + x1 = x1 + sx + end + if e2 < dx then + err = err + dx + y1 = y1 + sy + end + end + return points +end + +local function circle(xPos, yPos, radius, filled) + local points = {} + + local function plotPoints(xc, yc, x, y) + table.insert(points, {x = xc + x, y = yc + y}) + table.insert(points, {x = xc - x, y = yc + y}) + table.insert(points, {x = xc + x, y = yc - y}) + table.insert(points, {x = xc - x, y = yc - y}) + table.insert(points, {x = xc + y, y = yc + x}) + table.insert(points, {x = xc - y, y = yc + x}) + table.insert(points, {x = xc + y, y = yc - x}) + table.insert(points, {x = xc - y, y = yc - x}) + end + + local function fillPoints(xc, yc, x, y) + for fillX = -x, x do + table.insert(points, {x = xc + fillX, y = yc + y}) + table.insert(points, {x = xc + fillX, y = yc - y}) + end + for fillY = -y, y do + table.insert(points, {x = xc + fillY, y = yc + x}) + table.insert(points, {x = xc + fillY, y = yc - x}) + end + end + + local x = 0 + local y = radius + local d = 3 - 2 * radius + + if filled then + fillPoints(xPos, yPos, x, y) + else + plotPoints(xPos, yPos, x, y) + end + + while y >= x do + x = x + 1 + + if d > 0 then + y = y - 1 + d = d + 4 * (x - y) + 10 + else + d = d + 4 * x + 6 + end + + if filled then + fillPoints(xPos, yPos, x, y) + else + plotPoints(xPos, yPos, x, y) + end + end + + return points +end + +local function ellipse(xPos, yPos, radiusX, radiusY, filled) + local points = {} + local function plotPoints(xc, yc, x, y) + table.insert(points, {x = xc + x, y = yc + y}) + table.insert(points, {x = xc - x, y = yc + y}) + table.insert(points, {x = xc + x, y = yc - y}) + table.insert(points, {x = xc - x, y = yc - y}) + end + + local function fillPoints(xc, yc, x, y) + for fillX = -x, x do + table.insert(points, {x = xc + fillX, y = yc + y}) + table.insert(points, {x = xc + fillX, y = yc - y}) + end + end + + local x = 0 + local y = radiusY + local d1 = (radiusY * radiusY) - (radiusX * radiusX * radiusY) + (0.25 * radiusX * radiusX) + + plotPoints(xPos, yPos, x, y) + + while ((radiusX * radiusX * (y - 0.5)) > (radiusY * radiusY * (x + 1))) do + if (d1 < 0) then + d1 = d1 + (2 * radiusY * radiusY * x) + (3 * radiusY * radiusY) + else + d1 = d1 + (2 * radiusY * radiusY * x) - (2 * radiusX * radiusX * y) + (2 * radiusX * radiusX) + y = y - 1 + end + x = x + 1 + if filled then fillPoints(xPos, yPos, x, y) end + end + + local d2 = ((radiusY * radiusY) * ((x + 0.5) * (x + 0.5))) + ((radiusX * radiusX) * ((y - 1) * (y - 1))) - (radiusX * radiusX * radiusY * radiusY) + + while y > 0 do + y = y - 1 + if d2 < 0 then + d2 = d2 + (2 * radiusY * radiusY * x) - (2 * radiusX * radiusX * y) + (radiusX * radiusX) + x = x + 1 + else + d2 = d2 - (2 * radiusX * radiusX * y) + (radiusX * radiusX) + end + if filled then fillPoints(xPos, yPos, x, y) end + end + return points +end + +local function polygon(points, filled) + local newPoints = {} + + local pointsCopy = {} + for i, point in ipairs(points) do + table.insert(pointsCopy, {x = point.x, y = point.y}) + end + if pointsCopy[1].x ~= pointsCopy[#pointsCopy].x or pointsCopy[1].y ~= pointsCopy[#pointsCopy].y then + table.insert(pointsCopy, {x = pointsCopy[1].x, y = pointsCopy[1].y}) + end + + local lines = {} + for i = 1, #pointsCopy - 1 do + local linePoints = line(pointsCopy[i].x, pointsCopy[i].y, pointsCopy[i+1].x, pointsCopy[i+1].y) + for _, point in ipairs(linePoints) do + table.insert(lines, point) + end + end + + if filled then + local minX, maxX, minY, maxY = math.huge, -math.huge, math.huge, -math.huge + for _, point in ipairs(pointsCopy) do + minX = math.min(minX, point.x) + maxX = math.max(maxX, point.x) + minY = math.min(minY, point.y) + maxY = math.max(maxY, point.y) + end + + local fillPoints = {} + for y = minY, maxY do + for x = minX, maxX do + local numCrossings = 0 + for i = 1, #pointsCopy - 1 do + if ((pointsCopy[i].y > y) ~= (pointsCopy[i+1].y > y)) and + (x < (pointsCopy[i+1].x - pointsCopy[i].x) * (y - pointsCopy[i].y) / + (pointsCopy[i+1].y - pointsCopy[i].y) + pointsCopy[i].x) then + numCrossings = numCrossings + 1 + end + end + if numCrossings % 2 == 1 then + table.insert(fillPoints, {x = x, y = y}) + end + end + end + return fillPoints + end + return lines +end + +local function rectangle(xPos, yPos, width, height, filled) + local points = {} + + if filled then + for y = yPos, yPos + height - 1 do + for x = xPos, xPos + width - 1 do + table.insert(points, {x = x, y = y}) + end + end + else + for x = xPos, xPos + width - 1 do + table.insert(points, {x = x, y = yPos}) + table.insert(points, {x = x, y = yPos + height - 1}) + end + for y = yPos, yPos + height - 1 do + table.insert(points, {x = xPos, y = y}) + table.insert(points, {x = xPos + width - 1, y = y}) + end + end + return points +end + +local rep,sub = string.rep, string.sub + +return { + VisualObject = function(base) + local object = {} + + for _,v in pairs({"Text", "Bg", "Fg"})do + object["add"..v.."Line"] = function(self, x1, y1, x2, y2, val) + if(type(val)=="number")then + val = tHex[val] + end + if(#val>1)then + val = sub(val, 1, 1) + end + local points = line(x1, y1, x2, y2) + for _,point in ipairs(points)do + self["add"..v](self, point.x, point.y, val) + end + return self + end + + object["add"..v.."Circle"] = function(self, xPos, yPos, radius, filled, val) + if(type(val)=="number")then + val = tHex[val] + end + if(#val>1)then + val = sub(val, 1, 1) + end + + local points = circle(xPos, yPos, radius, filled) + + for _,point in ipairs(points)do + self["add"..v](self, point.x, point.y, val) + end + return self + end + + object["add"..v.."Ellipse"] = function(self, xPos, yPos, radiusX, radiusY, filled, val) + if(type(val)=="number")then + val = tHex[val] + end + if(#val>1)then + val = sub(val, 1, 1) + end + + local points = ellipse(xPos, yPos, radiusX, radiusY, filled) + for _,point in ipairs(points)do + self["add"..v](self, point.x, point.y, val) + end + return self + end + + object["add"..v.."Polygon"] = function(self, points, filled, val) + if(type(val)=="number")then + val = tHex[val] + end + if(#val>1)then + val = sub(val, 1 ,1) + end + local newPoints = polygon(points, filled) + for _,point in ipairs(newPoints)do + self["add"..v](self, point.x, point.y, val) + end + return self + end + + object["add"..v.."Rectangle"] = function(self, xPos, yPos, width, height, filled, val) + if(type(val)=="number")then + val = tHex[val] + end + if(#val>1)then + val = sub(val, 1, 1) + end + local points = rectangle(xPos, yPos, width, height, filled) + for _,point in ipairs(points)do + self["add"..v](self, point.x, point.y, val) + end + return self + end + end + + --[[ + function object.addInlineBorder(self, x, y, width, height, color, bg) + self:addTextBox(x, y, 1, h, "\149") + self:addBackgroundBox(x, y, 1, h, bgCol) + self:addForegroundBox(x, y, 1, h, borderColors["left"]) + + + self:addTextBox(x, y, x+width-1, 1, "\131") + self:addBackgroundBox(x, y, x+width-1, 1, bgCol) + self:addForegroundBox(x, y, x+width-1, 1, borderColors["top"]) + + self:addTextBox(x, y, 1, 1, "\151") + self:addBackgroundBox(x, y, 1, 1, bgCol) + self:addForegroundBox(x, y, 1, 1, borderColors["left"]) + + self:addTextBox(x+width-1, 1, 1, h, "\149") + self:addForegroundBox(x+width-1, 1, 1, h, bgCol) + self:addBackgroundBox(x+width-1, 1, 1, h, borderColors["right"]) + + self:addTextBox(1, h, x+width-1, 1, "\143") + self:addForegroundBox(1, h, x+width-1, 1, bgCol) + self:addBackgroundBox(1, h, x+width-1, 1, borderColors["bottom"]) + + self:addTextBox(x+width-1, 1, 1, 1, "\148") + self:addForegroundBox(x+width-1, 1, 1, 1, bgCol) + self:addBackgroundBox(x+width-1, 1, 1, 1, borderColors["right"]) + + self:addTextBox(x+width-1, h, 1, 1, "\133") + self:addForegroundBox(x+width-1, h, 1, 1, bgCol) + self:addBackgroundBox(x+width-1, h, 1, 1, borderColors["right"]) + + self:addTextBox(1, h, 1, 1, "\138") + self:addForegroundBox(1, h, 1, 1, bgCol) + self:addBackgroundBox(1, h, 1, 1, borderColors["left"]) + end]] + + return object + end +} \ No newline at end of file diff --git a/Basalt/plugins/templates.lua b/Basalt/plugins/templates.lua new file mode 100644 index 0000000..919789c --- /dev/null +++ b/Basalt/plugins/templates.lua @@ -0,0 +1,135 @@ +local split = require("utils").splitString + +local function copy(t) + local new = {} + for k,v in pairs(t)do + new[k] = v + end + return new +end + +local plugin = { + VisualObject = function(base, basalt) + return { + __getElementPathTypes = function(self, types) + if(types~=nil)then + table.insert(types, 1, self:getTypes()) + else + types = {self:getTypes()} + end + local parent = self:getParent() + if(parent~=nil)then + return parent:__getElementPathTypes(types) + else + return types + end + end, + + init = function(self) + base.init(self) + local template = basalt.getTemplate(self) + local objects = basalt.getObjects() + if(template~=nil)then + for k,v in pairs(template)do + if(objects[k]==nil)then + if(colors[v]~=nil)then + self:setProperty(k, colors[v]) + else + self:setProperty(k, v) + end + end + end + end + return self + end, + } + end, + + basalt = function() + local baseTemplate = { + default = { + Background = colors.gray, + Foreground = colors.black, + }, + BaseFrame = { + Background = colors.lightGray, + Foreground = colors.black, + Button = { + Background = "{self.clicked ? black : gray}", + Foreground = "{self.clicked ? lightGray : black}" + }, + Container = { + Background = colors.gray, + Foreground = colors.black, + Button = { + Background = "{self.clicked ? lightGray : black}", + Foreground = "{self.clicked ? black : lightGray}" + }, + }, + Checkbox = { + Background = colors.gray, + Foreground = colors.black, + Text = "Checkbox" + }, + Input = { + Background = "{self.focused ? gray : black}", + Foreground = "{self.focused ? black : lightGray}", + defaultBackground = "{self.focused ? gray : black}", + defaultForeground = "{self.focused ? black : lightGray}", + defaultText = "..." + }, + }, + } + + local function addTemplate(newTemplate) + if(type(newTemplate)=="string")then + local file = fs.open(newTemplate, "r") + if(file~=nil)then + local data = file.readAll() + file.close() + baseTemplate = textutils.unserializeJSON(data) + else + error("Could not open template file "..newTemplate) + end + end + if(type(newTemplate)=="table")then + for k,v in pairs(newTemplate)do + baseTemplate[k] = v + end + end + end + + local function lookUpTemplate(template, allTypes) + local elementData = copy(baseTemplate.default) + local tLink = template + if(tLink~=nil)then + for _, v in pairs(allTypes)do + for _, b in pairs(v)do + if(tLink[b]~=nil)then + tLink = tLink[b] + for k, v in pairs(tLink) do + elementData[k] = v + end + break + else + for k, v in pairs(baseTemplate.default) do + elementData[k] = v + end + end + end + end + end + return elementData + end + + return { + getTemplate = function(element) + return lookUpTemplate(baseTemplate, element:__getElementPathTypes()) + end, + + addTemplate = addTemplate, + } + end +} + +return plugin \ No newline at end of file diff --git a/Basalt/plugins/textures.lua b/Basalt/plugins/textures.lua index 2e7d953..63ffeec 100644 --- a/Basalt/plugins/textures.lua +++ b/Basalt/plugins/textures.lua @@ -1,58 +1,87 @@ local images = require("images") -local utils = require("utils") -local XMLParser = require("xmlParser") + +local sub = string.sub + return { VisualObject = function(base) - local textureId, infinitePlay = 1, true - local bimg, texture, textureTimerId - local textureMode = "default" + local images = {} local object = { - addTexture = function(self, path, animate) - bimg = images.loadImageAsBimg(path) - texture = bimg[1] - if(animate)then - if(bimg.animated)then - self:listenEvent("other_event") - local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2 - textureTimerId = os.startTimer(t) + addTexture = function(self, path, x, y, w, h, stretch, animate, infinitePlay) + if(type(path)=="function")then + table.insert(images, path) + else + if(type(path)=="table")then + x, y, w, h, stretch, animate, infinitePlay = path.x, path.y, path.w, path.h, path.stretch, path.animate, path.infinitePlay + path = path.path + end + local img = images.loadImageAsBimg(path) + local newEntry = { + image = img, + x = x, + y = y, + w = w, + h = h, + animated = animate, + curTextId = 1, + infinitePlay = infinitePlay, + } + if(stretch)then + newEntry.w = self:getWidth() + newEntry.h = self:getHeight() + newEntry.image = images.resizeBIMG(img, newEntry.w, newEntry.h) + end + table.insert(images, newEntry) + if(animate)then + if(img.animated)then + self:listenEvent("other_event") + local t = img[newEntry.curTextId].duration or img.secondsPerFrame or 0.2 + newEntry.timer = os.startTimer(t) + end end end - self:setBackground(false) - self:setForeground(false) self:setDrawState("texture-base", true) self:updateDraw() return self end, - setTextureMode = function(self, mode) - textureMode = mode or textureMode + removeTexture = function(self, id) + table.remove(images, id) + if(#images==0)then + self:setDrawState("texture-base", false) + end self:updateDraw() return self end, - setInfinitePlay = function(self, state) - infinitePlay = state + clearTextures = function(self) + images = {} + self:setDrawState("texture-base", false) + self:updateDraw() return self end, eventHandler = function(self, event, timerId, ...) base.eventHandler(self, event, timerId, ...) if(event=="timer")then - if(timerId == textureTimerId)then - if(bimg[textureId+1]~=nil)then - textureId = textureId + 1 - texture = bimg[textureId] - local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2 - textureTimerId = os.startTimer(t) - self:updateDraw() - else - if(infinitePlay)then - textureId = 1 - texture = bimg[1] - local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2 - textureTimerId = os.startTimer(t) - self:updateDraw() + for _,v in pairs(images)do + if(type(v)=="table")then + if(v.timer==timerId)then + if(v.animated)then + if(v.image[v.curTextId+1]~=nil)then + v.curTextId = v.curTextId + 1 + local t = v.image[v.curTextId].duration or v.image.secondsPerFrame or 0.2 + v.timer = os.startTimer(t) + self:updateDraw() + else + if(v.infinitePlay)then + v.curTextId = 1 + local t = v.image[v.curTextId].duration or v.image.secondsPerFrame or 0.2 + v.timer = os.startTimer(t) + self:updateDraw() + end + end + end end end end @@ -62,50 +91,25 @@ return { draw = function(self) base.draw(self) self:addDraw("texture-base", function() - local obj = self:getParent() or self - local x, y = self:getPosition() - local w,h = self:getSize() - local wP,hP = obj:getSize() - - local textureWidth = bimg.width or #bimg[textureId][1][1] - local textureHeight = bimg.height or #bimg[textureId] - - local startX, startY = 0, 0 - - if (textureMode == "center") then - startX = x + math.floor((w - textureWidth) / 2 + 0.5) - 1 - startY = y + math.floor((h - textureHeight) / 2 + 0.5) - 1 - elseif (textureMode == "default") then - startX, startY = x, y - elseif (textureMode == "right") then - startX, startY = x + w - textureWidth, y + h - textureHeight - end - - local textureX = x - startX - local textureY = y - startY - - if startX < x then - startX = x - textureWidth = textureWidth - textureX - end - if startY < y then - startY = y - textureHeight = textureHeight - textureY - end - if startX + textureWidth > x + w then - textureWidth = (x + w) - startX - end - if startY + textureHeight > y + h then - textureHeight = (y + h) - startY - end - - for k = 1, textureHeight do - if(texture[k+textureY]~=nil)then - local t, f, b = table.unpack(texture[k+textureY]) - self:addBlit(1, k, t:sub(textureX, textureX + textureWidth), f:sub(textureX, textureX + textureWidth), b:sub(textureX, textureX + textureWidth)) + for _,v in pairs(images)do + if(type(v)=="table")then + local tWidth = #v.image[v.curTextId][1][1] + local tHeight = #v.image[v.curTextId][1] + local textureWidth = v.w>tWidth and tWidth or v.w + local textureHeight = v.h>tHeight and tHeight or v.h + for k = 1, textureHeight do + if(v.image[k]~=nil)then + local t, f, b = table.unpack(v.image[k]) + self:addBlit(1, k, sub(t, 1, textureWidth), sub(f, 1, textureWidth), sub(b, 1, textureWidth)) + end + end + else + if(type(v)=="function")then + v(self) + end end end - end, 1) + end) self:setDrawState("texture-base", false) end }