Merge branch 'Pyroxenium:master' into erb3-path-7

This commit is contained in:
Erlend
2023-05-08 15:35:04 +02:00
committed by GitHub
613 changed files with 23908 additions and 8133 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,11 @@ if not(packed)then
local main = format:gsub("path", curDir) local main = format:gsub("path", curDir)
local objFolder = format:gsub("path", curDir.."/objects") local objFolder = format:gsub("path", curDir.."/objects")
local plugFolder = format:gsub("path", curDir.."/plugins")
local libFolder = format:gsub("path", curDir.."/libraries") local libFolder = format:gsub("path", curDir.."/libraries")
package.path = main..objFolder..libFolder..defaultPath package.path = main..objFolder..plugFolder..libFolder..defaultPath
end end
local Basalt = require("main") local Basalt = require("main")
package.path = defaultPath package.path = defaultPath

View File

@@ -1,4 +1,6 @@
local tHex = require("tHex") local tHex = require("tHex")
local utils = require("utils")
local split = utils.splitString
local sub,rep = string.sub,string.rep local sub,rep = string.sub,string.rep
return function(drawTerm) return function(drawTerm)
@@ -9,10 +11,6 @@ return function(drawTerm)
local cacheBG = {} local cacheBG = {}
local cacheFG = {} local cacheFG = {}
local _cacheT = {}
local _cacheBG = {}
local _cacheFG = {}
local emptySpaceLine local emptySpaceLine
local emptyColorLines = {} local emptyColorLines = {}
@@ -40,137 +38,137 @@ return function(drawTerm)
end end
recreateWindowArray() recreateWindowArray()
local function setText(x, y, text) local function blit(x, y, t, fg, bg)
if (y >= 1) and (y <= height) then if #t == #fg and #t == #bg then
if (x + text:len() > 0) and (x <= width) then if y >= 1 and y <= height then
local oldCache = cacheT[y] if x + #t > 0 and x <= width then
local newCache local newCacheT, newCacheFG, newCacheBG
local nEnd = x + #text - 1 local oldCacheT, oldCacheFG, oldCacheBG = cacheT[y], cacheFG[y], cacheBG[y]
local startN, endN = 1, #t
if (x < 1) then if x < 1 then
local startN = 1 - x + 1 startN = 1 - x + 1
local endN = width - x + 1 endN = width - x + 1
text = sub(text, startN, endN) elseif x + #t > width then
elseif (nEnd > width) then endN = width - x + 1
local endN = width - x + 1 end
text = sub(text, 1, endN)
end
if (x > 1) then newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
local endN = x - 1 newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN)
newCache = sub(oldCache, 1, endN) .. text newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN)
else
newCache = text 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
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheT[y] = newCache
end end
end end
end end
local function setBG(x, y, colorStr) local function setText(x, y, t)
if (y >= 1) and (y <= height) then if y >= 1 and y <= height then
if (x + colorStr:len() > 0) and (x <= width) then if x + #t > 0 and x <= width then
local oldCache = cacheBG[y] local newCacheT
local newCache local oldCacheT = cacheT[y]
local nEnd = x + #colorStr - 1 local startN, endN = 1, #t
if (x < 1) then if x < 1 then
colorStr = sub(colorStr, 1 - x + 1, width - x + 1) startN = 1 - x + 1
elseif (nEnd > width) then endN = width - x + 1
colorStr = sub(colorStr, 1, width - x + 1) elseif x + #t > width then
endN = width - x + 1
end end
if (x > 1) then newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
newCache = sub(oldCache, 1, x - 1) .. colorStr
else if x + #t <= width then
newCache = colorStr newCacheT = newCacheT .. sub(oldCacheT, x + #t, width)
end end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width) cacheT[y] = newCacheT
end
cacheBG[y] = newCache
end end
end end
end end
local function setBG(x, y, bg)
if y >= 1 and y <= height then
if x + #bg > 0 and x <= width then
local newCacheBG
local oldCacheBG = cacheBG[y]
local startN, endN = 1, #bg
if x < 1 then
startN = 1 - x + 1
endN = width - x + 1
elseif x + #bg > width then
endN = width - x + 1
end
newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN)
if x + #bg <= width then
newCacheBG = newCacheBG .. sub(oldCacheBG, x + #bg, width)
end
cacheBG[y] = newCacheBG
end
end
end
local function setFG(x, y, fg)
if y >= 1 and y <= height then
if x + #fg > 0 and x <= width then
local newCacheFG
local oldCacheFG = cacheFG[y]
local startN, endN = 1, #fg
if x < 1 then
startN = 1 - x + 1
endN = width - x + 1
elseif x + #fg > width then
endN = width - x + 1
end
newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN)
if x + #fg <= width then
newCacheFG = newCacheFG .. sub(oldCacheFG, x + #fg, width)
end
cacheFG[y] = newCacheFG
end
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) local function setFG(x, y, colorStr)
if (y >= 1) and (y <= height) then if (y >= 1) and (y <= height) then
if (x + colorStr:len() > 0) and (x <= width) then local w = #colorStr
local oldCache = cacheFG[y] local emptyLine = rep(" ", w)
local newCache local text = sub(cacheT[y], x, w)
local nEnd = x + #colorStr - 1 blit(x, y, text, colorStr, emptyLine)
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
colorStr = sub(colorStr, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
colorStr = sub(colorStr, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCache = sub(oldCache, 1, endN) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheFG[y] = newCache
end
end end
end end
local function blit(x, y, t, fg, bg) local function setBG(x, y, colorStr)
if(#t == #fg)or(#t == #bg)then if (y >= 1) and (y <= height) then
if (y >= 1) and (y <= height) then local w = #colorStr
if (x + t:len() > 0) and (x <= width) then local emptyLine = rep(" ", w)
local oldCacheT = cacheT[y] local text = sub(cacheT[y], x, w)
local oldCacheFG = cacheFG[y] blit(x, y, text, emptyLine, colorStr)
local oldCacheBG = cacheBG[y]
local newCacheT, newCacheFG, newCacheBG
local nEnd = x + #t - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
t = sub(t, startN, endN)
fg = sub(fg, startN, endN)
bg = sub(bg, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
t = sub(t, 1, endN)
fg = sub(fg, 1, endN)
bg = sub(bg, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCacheT = sub(oldCacheT, 1, endN) .. t
newCacheFG = sub(oldCacheFG, 1, endN) .. fg
newCacheBG = sub(oldCacheBG, 1, endN) .. bg
else
newCacheT = t
newCacheFG = fg
newCacheBG = bg
end
if nEnd < width then
newCacheT = newCacheT .. sub(oldCacheT, nEnd + 1, width)
newCacheFG = newCacheFG .. sub(oldCacheFG, nEnd + 1, width)
newCacheBG = newCacheBG .. sub(oldCacheBG, nEnd + 1, width)
end
cacheT[y] = newCacheT
cacheFG[y] = newCacheFG
cacheBG[y] = newCacheBG
end
end
end end
end end]]
local drawHelper = { local drawHelper = {
setSize = function(w, h) setSize = function(w, h)
@@ -181,13 +179,14 @@ return function(drawTerm)
setMirror = function(mirror) setMirror = function(mirror)
mirrorTerm = mirror mirrorTerm = mirror
end, end,
setBG = function(x, y, colorStr) setBG = function(x, y, colorStr)
setBG(x, y, colorStr) setBG(x, y, colorStr)
end; end,
setText = function(x, y, text) setText = function(x, y, text)
setText(x, y, text) setText(x, y, text)
end; end,
setFG = function(x, y, colorStr) setFG = function(x, y, colorStr)
setFG(x, y, colorStr) setFG(x, y, colorStr)
@@ -198,31 +197,23 @@ return function(drawTerm)
end, end,
drawBackgroundBox = function(x, y, width, height, bgCol) drawBackgroundBox = function(x, y, width, height, bgCol)
local colorStr = rep(tHex[bgCol], width)
for n = 1, height do for n = 1, height do
setBG(x, y + (n - 1), rep(tHex[bgCol], width)) setBG(x, y + (n - 1), colorStr)
end end
end; end,
drawForegroundBox = function(x, y, width, height, fgCol) drawForegroundBox = function(x, y, width, height, fgCol)
local colorStr = rep(tHex[fgCol], width)
for n = 1, height do for n = 1, height do
setFG(x, y + (n - 1) ,rep(tHex[fgCol], width)) setFG(x, y + (n - 1), colorStr)
end end
end; end,
drawTextBox = function(x, y, width, height, symbol) drawTextBox = function(x, y, width, height, symbol)
local textStr = rep(symbol, width)
for n = 1, height do for n = 1, height do
setText(x, y + (n - 1), rep(symbol, width)) setText(x, y + (n - 1), textStr)
end end
end; end,
writeText = function(x, y, text, bgCol, fgCol)
if(text~=nil)then
setText(x, y, text)
if(bgCol~=nil)and(bgCol~=false)then
setBG(x, y, rep(tHex[bgCol], text:len()))
end
if(fgCol~=nil)and(fgCol~=false)then
setFG(x, y, rep(tHex[fgCol], text:len()))
end
end
end;
update = function() update = function()
local xC, yC = terminal.getCursorPos() local xC, yC = terminal.getCursorPos()
@@ -249,11 +240,11 @@ return function(drawTerm)
mirrorTerm.setCursorPos(xC, yC) mirrorTerm.setCursorPos(xC, yC)
end end
end; end,
setTerm = function(newTerm) setTerm = function(newTerm)
terminal = newTerm; terminal = newTerm
end; end,
} }
return drawHelper return drawHelper
end end

View File

@@ -1,21 +1,41 @@
return function() return function()
local events = {} local events = {}
local index = {}
local event = { local event = {
registerEvent = function(self, _event, func) registerEvent = function(self, _event, func)
if (events[_event] == nil) then if (events[_event] == nil) then
events[_event] = {} events[_event] = {}
index[_event] = 1
end end
events[_event][index[_event]] = func table.insert(events[_event], func)
index[_event] = index[_event] + 1 end,
return index[_event] - 1
end;
removeEvent = function(self, _event, index) removeEvent = function(self, _event, index)
events[_event][index[_event]] = nil events[_event][index[_event]] = nil
end; end,
hasEvent = function(self, _event)
return events[_event]~=nil
end,
getEventCount = function(self, _event)
return events[_event]~=nil and #events[_event] or 0
end,
getEvents = function(self)
local t = {}
for k,v in pairs(events)do
table.insert(t, k)
end
return t
end,
clearEvent = function(self, _event)
events[_event] = nil
end,
clear = function(self, _event)
events = {}
end,
sendEvent = function(self, _event, ...) sendEvent = function(self, _event, ...)
local returnValue local returnValue
@@ -28,7 +48,7 @@ return function()
end end
end end
return returnValue return returnValue
end; end,
} }
event.__index = event event.__index = event
return event return event

View File

@@ -10,7 +10,7 @@ local mt = {
if(text==nil)then return end if(text==nil)then return end
local dirStr = logDir~="" and logDir.."/"..logFileName or logFileName local dirStr = logDir~="" and logDir.."/"..logFileName or logFileName
local handle = fs.open(dirStr, fs.exists(dirStr) and "a" or "w") local handle = fs.open(dirStr, fs.exists(dirStr) and "a" or "w")
handle.writeLine("[Basalt]["..(typ and typ or defaultLogType).."]: "..tostring(text)) handle.writeLine("[Basalt]["..os.date("%Y-%m-%d %H:%M:%S").."]["..(typ and typ or defaultLogType).."]: "..tostring(text))
handle.close() handle.close()
end, end,
} }

View File

@@ -80,9 +80,11 @@ local function frame(base, manager)
end end
if(base~=nil)then if(base~=nil)then
w = #base[1][1] if(#base>0)then
h = #base w = #base[1][1]
setFrame(base) h = #base
setFrame(base)
end
end end
return { return {
@@ -134,7 +136,11 @@ local function frame(base, manager)
end, end,
getFrameData = function(key) getFrameData = function(key)
return (key~= nil and data[key] or data) if(key~=nil)then
return data[key]
else
return data
end
end, end,
blit = function(text, fgCol, bgCol, x, y) blit = function(text, fgCol, bgCol, x, y)
@@ -181,14 +187,22 @@ return function(img)
local metadata = {creator="Bimg Library by NyoriE", date=os.date("!%Y-%m-%dT%TZ")} local metadata = {creator="Bimg Library by NyoriE", date=os.date("!%Y-%m-%dT%TZ")}
local width,height = 0, 0 local width,height = 0, 0
if(img~=nil)then
if(img[1][1][1]~=nil)then
width,height = metadata.width or #img[1][1][1], metadata.height or #img[1]
end
end
local manager = {} local manager = {}
local function addFrame(id, data) local function addFrame(id, data)
id = id or #frames+1 id = id or #frames+1
table.insert(frames, id, frame(data, manager)) local f = frame(data, manager)
table.insert(frames, id, f)
if(data==nil)then if(data==nil)then
frames[id].setSize(width, height) frames[id].setSize(width, height)
end end
return f
end end
local function removeFrame(id) local function removeFrame(id)
@@ -283,7 +297,6 @@ return function(img)
end, end,
addFrame = function(id) addFrame = function(id)
local f = frame()
if(#frames<=1)then if(#frames<=1)then
if(metadata.animated==nil)then if(metadata.animated==nil)then
metadata.animated = true metadata.animated = true
@@ -292,21 +305,10 @@ return function(img)
metadata.secondsPerFrame = 0.2 metadata.secondsPerFrame = 0.2
end end
end end
addFrame(id) return addFrame(id)
return f
end, end,
removeFrame = function(id) removeFrame = removeFrame,
removeFrame(id)
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
end
if(metadata.secondsPerFrame==nil)then
metadata.secondsPerFrame = 0.2
end
end
end,
moveFrame = moveFrame, moveFrame = moveFrame,
@@ -317,7 +319,9 @@ return function(img)
end, end,
getFrameData = function(id, key) getFrameData = function(id, key)
return frames[id]~=nil and frames[id].getFrameData(key) if(frames[id]~=nil)then
return frames[id].getFrameData(key)
end
end, end,
getSize = function() getSize = function()
@@ -339,7 +343,11 @@ return function(img)
end, end,
getMetadata = function(key) getMetadata = function(key)
return key~=nil and metadata[key] or metadata if(key~=nil)then
return metadata[key]
else
return metadata
end
end, end,
createBimg = function() createBimg = function()
@@ -361,18 +369,19 @@ return function(img)
for k,v in pairs(img)do for k,v in pairs(img)do
if(type(k)=="string")then if(type(k)=="string")then
metadata[k] = v metadata[k] = v
else
addFrame(k, v)
end end
end end
if(metadata.width==nil)or(metadata.height==nil)then if(metadata.width==nil)or(metadata.height==nil)then
for k,v in pairs(frames)do width = metadata.width or #img[1][1][1]
local w, h = v.getSize() height = metadata.height or #img[1]
if(w>width)then w = width end
if(h>height)then h = height end
end
manager.updateSize(width, height, true) manager.updateSize(width, height, true)
end end
for k,v in pairs(img)do
if(type(k)=="number")then
addFrame(k, v)
end
end
else else
addFrame(1) addFrame(1)
end end

View File

@@ -1,24 +1,18 @@
local sub,floor,rep = string.sub,math.floor,string.rep local sub,floor = string.sub,math.floor
local function loadNFPAsBimg(path) local function loadNFPAsBimg(path)
local bimg = {{}} return {[1]={{}, {}, paintutils.loadImage(path)}}, "bimg"
local nfp = fs.open(path, "r")
if(nfp~=nil)then
for line in nfp.readLine do
table.insert(bimg[1], {rep(" ",#line), rep(" ",#line), line})
end
nfp.close()
return bimg
end
end end
local function loadNFP(path) local function loadNFP(path)
return paintutils.loadImage(path), "nfp" return paintutils.loadImage(path), "nfp"
end end
local function loadBIMG(path) local function loadBIMG(path, binaryMode)
local f = fs.open(path, "rb") local f = fs.open(path, binaryMode and "rb" or "r")
if(f==nil)then error("Path - "..path.." doesn't exist!") end
local content = textutils.unserialize(f.readAll()) local content = textutils.unserialize(f.readAll())
f.close() f.close()
if(content~=nil)then if(content~=nil)then
return content, "bimg" return content, "bimg"
@@ -33,28 +27,24 @@ local function loadBBFAsBimg(path)
end end
local function loadImage(path, f) local function loadImage(path, f, binaryMode)
if(f==nil)then if(sub(path, -4) == ".bimg")then
if(path:find(".bimg"))then return loadBIMG(path, binaryMode)
return loadBIMG(path) elseif(sub(path, -3) == ".bbf")then
elseif(path:find(".bbf"))then return loadBBF(path, binaryMode)
return loadBBF(path) else
else return loadNFP(path, binaryMode)
return loadNFP(path)
end
end end
-- ... -- ...
end end
local function loadImageAsBimg(path, f) local function loadImageAsBimg(path)
if(f==nil)then if(path:find(".bimg"))then
if(path:find(".bimg"))then return loadBIMG(path)
return loadBIMG(path) elseif(path:find(".bbf"))then
elseif(path:find(".bbf"))then return loadBBFAsBimg(path)
return loadBBFAsBimg(path) else
else return loadNFPAsBimg(path)
return loadNFPAsBimg(path)
end
end end
end end

View File

@@ -1,147 +0,0 @@
local function newNode(name)
local node = {}
node.___value = nil
node.___name = name
node.___children = {}
node.___props = {}
function node:value() return self.___value end
function node:setValue(val) self.___value = val end
function node:name() return self.___name end
function node:setName(name) self.___name = name end
function node:children() return self.___children end
function node:numChildren() return #self.___children end
function node:addChild(child)
if self[child:name()] ~= nil then
if type(self[child:name()].name) == "function" then
local tempTable = {}
table.insert(tempTable, self[child:name()])
self[child:name()] = tempTable
end
table.insert(self[child:name()], child)
else
self[child:name()] = child
end
table.insert(self.___children, child)
end
function node:properties() return self.___props end
function node:numProperties() return #self.___props end
function node:addProperty(name, value)
local lName = "@" .. name
if self[lName] ~= nil then
if type(self[lName]) == "string" then
local tempTable = {}
table.insert(tempTable, self[lName])
self[lName] = tempTable
end
table.insert(self[lName], value)
else
self[lName] = value
end
table.insert(self.___props, { name = name, value = self[name] })
end
return node
end
local XmlParser = {};
function XmlParser:ToXmlString(value)
value = string.gsub(value, "&", "&amp;"); -- '&' -> "&amp;"
value = string.gsub(value, "<", "&lt;"); -- '<' -> "&lt;"
value = string.gsub(value, ">", "&gt;"); -- '>' -> "&gt;"
value = string.gsub(value, "\"", "&quot;"); -- '"' -> "&quot;"
value = string.gsub(value, "([^%w%&%;%p%\t% ])",
function(c)
return string.format("&#x%X;", string.byte(c))
end);
return value;
end
function XmlParser:FromXmlString(value)
value = string.gsub(value, "&#x([%x]+)%;",
function(h)
return string.char(tonumber(h, 16))
end);
value = string.gsub(value, "&#([0-9]+)%;",
function(h)
return string.char(tonumber(h, 10))
end);
value = string.gsub(value, "&quot;", "\"");
value = string.gsub(value, "&apos;", "'");
value = string.gsub(value, "&gt;", ">");
value = string.gsub(value, "&lt;", "<");
value = string.gsub(value, "&amp;", "&");
return value;
end
function XmlParser:ParseArgs(node, s)
string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a)
node:addProperty(w, self:FromXmlString(a))
end)
end
function XmlParser:ParseXmlText(xmlText)
local stack = {}
local top = newNode()
table.insert(stack, top)
local ni, c, label, xarg, empty
local i, j = 1, 1
while true do
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(xmlText, i, ni - 1);
if not string.find(text, "^%s*$") then
local lVal = (top:value() or "") .. self:FromXmlString(text)
stack[#stack]:setValue(lVal)
end
if empty == "/" then -- empty element tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
top:addChild(lNode)
elseif c == "" then -- start tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
table.insert(stack, lNode)
top = lNode
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("XmlParser: nothing to close with " .. label)
end
if toclose:name() ~= label then
error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
end
top:addChild(toclose)
end
i = j + 1
end
local text = string.sub(xmlText, i);
if #stack > 1 then
error("XmlParser: unclosed " .. stack[#stack]:name())
end
return top
end
function XmlParser:loadFile(xmlFilename, base)
if not base then
base = system.ResourceDirectory
end
local path = system.pathForFile(xmlFilename, base)
local hFile, err = io.open(path, "r");
if hFile and not err then
local xmlText = hFile:read("*a"); -- read file content
io.close(hFile);
return self:ParseXmlText(xmlText), nil;
else
print(err)
return nil
end
end
return XmlParser

View File

@@ -1,4 +0,0 @@
return function(path)
local exists, content = pcall(require, path)
return exists and content or nil
end

View File

@@ -17,6 +17,10 @@ function process:new(path, window, newEnv, ...)
local env = setmetatable(newEnv, {__index=_ENV}) local env = setmetatable(newEnv, {__index=_ENV})
env.shell = shell env.shell = shell
env.basaltProgram=true env.basaltProgram=true
env.arg = {[0]=path, table.unpack(args)}
if(pPath==nil)then
error("The path "..path.." does not exist!")
end
env.require, env.package = newPackage(env, fs.getDir(pPath)) env.require, env.package = newPackage(env, fs.getDir(pPath))
if(fs.exists(pPath))then if(fs.exists(pPath))then
local file = fs.open(pPath, "r") local file = fs.open(pPath, "r")
@@ -24,7 +28,7 @@ function process:new(path, window, newEnv, ...)
file.close() file.close()
local program = load(content, path, "bt", env) local program = load(content, path, "bt", env)
if(program~=nil)then if(program~=nil)then
return program(table.unpack(args)) return program()
end end
end end
end) end)

View File

@@ -1,18 +1,6 @@
return { -- copy paste is a very important feature local cols = {}
[colors.white] = "0",
[colors.orange] = "1", for i = 0, 15 do
[colors.magenta] = "2", cols[2^i] = ("%x"):format(i)
[colors.lightBlue] = "3", end
[colors.yellow] = "4", return cols
[colors.lime] = "5",
[colors.pink] = "6",
[colors.gray] = "7",
[colors.lightGray] = "8",
[colors.cyan] = "9",
[colors.purple] = "a",
[colors.blue] = "b",
[colors.brown] = "c",
[colors.green] = "d",
[colors.red] = "e",
[colors.black] = "f",
}

View File

@@ -1,100 +1,227 @@
local sub,find,reverse = string.sub,string.find,string.reverse local tHex = require("tHex")
local sub,find,reverse,rep,insert,len = string.sub,string.find,string.reverse,string.rep,table.insert,string.len
local function splitString(str, delimiter) local function splitString(str, delimiter)
local result = {} local result = {}
if str == "" or delimiter == "" then if str == "" or delimiter == "" then
return result return result
end end
local start = 1 local start = 1
local delim_start, delim_end = find(str, delimiter, start) local delim_start, delim_end = find(str, delimiter, start)
while delim_start do while delim_start do
table.insert(result, sub(str, start, delim_start - 1)) insert(result, sub(str, start, delim_start - 1))
start = delim_end + 1 start = delim_end + 1
delim_start, delim_end = find(str, delimiter, start) delim_start, delim_end = find(str, delimiter, start)
end end
table.insert(result, sub(str, start)) insert(result, sub(str, start))
return result return result
end end
local relations = {[0] = {8, 4, 3, 6, 5}, {4, 14, 8, 7}, {6, 10, 8, 7}, {9, 11, 8, 0}, {1, 14, 8, 0}, {13, 12, 8, 0}, {2, 10, 8, 0}, {15, 8, 10, 11, 12, 14}, local function removeTags(input)
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}} return input:gsub("{[^}]+}", "")
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do exponents[2^i] = i end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
end
end end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do local function wrapText(str, width)
local thisRelation = lastCol[j] str = removeTags(str)
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end if(str=="")or(width==0)then
end return {""}
end
local uniqueLines = splitString(str, "\n")
local result = {}
for k, v in pairs(uniqueLines) do
if #v == 0 then
table.insert(result, "")
else
while #v > width do
local last_space = width
for i = width, 1, -1 do
if sub(v, i, i) == " " then
last_space = i
break
end
end
return 1 if last_space == width then
local line = sub(v, 1, last_space - 1) .. "-"
table.insert(result, line)
v = sub(v, last_space)
else
local line = sub(v, 1, last_space - 1)
table.insert(result, line)
v = sub(v, last_space + 1)
end
if #v <= width then
break
end
end
if #v > 0 then
table.insert(result, v)
end
end
end
return result
end end
local function colsToChar(pattern, totals) --- Coonverts a string with special tags to a table with colors and text
if not totals then -- @param input The string to convert
local newPattern = {} -- @return A table with the following structure: { {text = "Hello", color = colors.red}, {text = "World", color = colors.blue} }
totals = {} local function convertRichText(input)
for i = 1, 6 do local parsedResult = {}
local thisVal = pattern[i] local currentPosition = 1
local thisTot = totals[thisVal] local rawPosition = 1
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {} while currentPosition <= #input do
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end local closestColor, closestBgColor
local color, bgColor
local colorEnd, bgColorEnd
if #usage > 1 then for colorName, _ in pairs(colors) do
-- Reduce the chunk to two colours: local fgPattern = "{fg:" .. colorName.."}"
while #usage > 2 do local bgColorPattern = "{bg:" .. colorName.."}"
table.sort(usage, function (a, b) return a[2] > b[2] end) local colorStart, colorEndCandidate = input:find(fgPattern, currentPosition)
local matchToInd, usageLen = getBestColourMatch(usage), #usage local bgColorStart, bgColorEndCandidate = input:find(bgColorPattern, currentPosition)
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function: if colorStart and (not closestColor or colorStart < closestColor) then
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/ closestColor = colorStart
local data = 128 color = colorName
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end colorEnd = colorEndCandidate
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]] end
else
-- Solid colour character: if bgColorStart and (not closestBgColor or bgColorStart < closestBgColor) then
return "\128", colourChar[pattern[1]], colourChar[pattern[1]] closestBgColor = bgColorStart
end bgColor = colorName
bgColorEnd = bgColorEndCandidate
end
end
local nextPosition
if closestColor and (not closestBgColor or closestColor < closestBgColor) then
nextPosition = closestColor
elseif closestBgColor then
nextPosition = closestBgColor
else
nextPosition = #input + 1
end
local text = input:sub(currentPosition, nextPosition - 1)
if #text > 0 then
table.insert(parsedResult, {
color = nil,
bgColor = nil,
text = text,
position = rawPosition
})
rawPosition = rawPosition + #text
currentPosition = currentPosition + #text
end
if closestColor and (not closestBgColor or closestColor < closestBgColor) then
table.insert(parsedResult, {
color = color,
bgColor = nil,
text = "",
position = rawPosition,
})
currentPosition = colorEnd + 1
elseif closestBgColor then
table.insert(parsedResult, {
color = nil,
bgColor = bgColor,
text = "",
position = rawPosition,
})
currentPosition = bgColorEnd + 1
else
break
end
end
return parsedResult
end end
--- Wrapts text with special color tags, like {fg:red} or {bg:blue} to multiple lines
--- @param text string Text to wrap
--- @param width number Width of the line
--- @return table Table of lines
local function wrapRichText(text, width)
local colorData = convertRichText(text)
local formattedLines = {}
local x, y = 1, 1
local currentColor, currentBgColor
local function addFormattedEntry(entry)
table.insert(formattedLines, {
x = x,
y = y,
text = entry.text,
color = entry.color or currentColor,
bgColor = entry.bgColor or currentBgColor
})
end
for _, entry in ipairs(colorData) do
if entry.color then
currentColor = entry.color
elseif entry.bgColor then
currentBgColor = entry.bgColor
else
local words = splitString(entry.text, " ")
for i, word in ipairs(words) do
local wordLength = #word
if i > 1 then
if x + 1 + wordLength <= width then
addFormattedEntry({ text = " " })
x = x + 1
else
x = 1
y = y + 1
end
end
while wordLength > 0 do
local line = word:sub(1, width - x + 1)
word = word:sub(width - x + 2)
wordLength = #word
addFormattedEntry({ text = line })
if wordLength > 0 then
x = 1
y = y + 1
else
x = x + #line
end
end
end
end
if x > width then
x = 1
y = y + 1
end
end
return formattedLines
end
return { return {
getTextHorizontalAlign = function(text, width, textAlign, replaceChar) getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
text = sub(text, 1, width) text = sub(text, 1, width)
local offset = width - string.len(text) local offset = width - len(text)
if (textAlign == "right") then if (textAlign == "right") then
text = string.rep(replaceChar or " ", offset) .. text text = rep(replaceChar or " ", offset) .. text
elseif (textAlign == "center") then elseif (textAlign == "center") then
text = string.rep(replaceChar or " ", math.floor(offset / 2)) .. text .. string.rep(replaceChar or " ", math.floor(offset / 2)) text = rep(replaceChar or " ", math.floor(offset / 2)) .. text .. rep(replaceChar or " ", math.floor(offset / 2))
text = text .. (string.len(text) < width and (replaceChar or " ") or "") text = text .. (len(text) < width and (replaceChar or " ") or "")
else else
text = text .. string.rep(replaceChar or " ", offset) text = text .. rep(replaceChar or " ", offset)
end end
return text return text
end, end,
@@ -114,6 +241,14 @@ getTextVerticalAlign = function(h, textAlign)
return offset return offset
end, end,
orderedTable = function(t)
local newTable = {}
for _, v in pairs(t) do
newTable[#newTable+1] = v
end
return newTable
end,
rpairs = function(t) rpairs = function(t)
return function(t, i) return function(t, i)
i = i - 1 i = i - 1
@@ -134,31 +269,11 @@ tableCount = function(t)
end, end,
splitString = splitString, splitString = splitString,
removeTags = removeTags,
createText = function(str, width) wrapText = wrapText,
local uniqueLines = splitString(str, "\n")
local result = {}
for k,v in pairs(uniqueLines)do
if(#v==0)then table.insert(result, "") end
while #v > width do
local last_space = find(reverse(sub(v, 1, width)), " ")
if not last_space then
last_space = width
else
last_space = width - last_space + 1
end
local line = sub(v, 1, last_space)
table.insert(result, line)
v = sub(v, last_space + 1)
end
if #v > 0 then
table.insert(result, v)
end
end
return result
end,
getValueFromXML = function(name, tab) xmlValue = function(name, tab)
local var local var
if(type(tab)~="table")then return end if(type(tab)~="table")then return end
if(tab[name]~=nil)then if(tab[name]~=nil)then
@@ -180,51 +295,71 @@ getValueFromXML = function(name, tab)
return var return var
end, end,
numberFromString = function(str) convertRichText = convertRichText,
return load("return " .. str)()
end,
uuid = function() --- Writes text with special color tags
local random = math.random --- @param obj object The object to write to
local function uuid() --- @param x number X-Position
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' --- @param y number Y-Position
return string.gsub(template, '[xy]', function (c) --- @param text string The text to write
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb) writeRichText = function(obj, x, y, text)
return string.format('%x', v) local richText = convertRichText(text)
end) if(#richText==0)then
obj:addText(x, y, text)
return
end
local defaultFG, defaultBG = obj:getForeground(), obj:getBackground()
for _,v in pairs(richText)do
obj:addText(x+v.position-1, y, v.text)
if(v.color~=nil)then
obj:addFG(x+v.position-1, y, tHex[colors[v.color] ]:rep(#v.text))
defaultFG = colors[v.color]
else
obj:addFG(x+v.position-1, y, tHex[defaultFG]:rep(#v.text))
end
if(v.bgColor~=nil)then
obj:addBG(x+v.position-1, y, tHex[colors[v.bgColor] ]:rep(#v.text))
defaultBG = colors[v.bgColor]
else
if(defaultBG~=false)then
obj:addBG(x+v.position-1, y, tHex[defaultBG]:rep(#v.text))
end
end
end end
return uuid()
end, end,
array = function(arraysize, hashsize) wrapRichText = wrapRichText,
return load("return {" .. ("nil,"):rep(arraysize) .. ("[0]=nil,"):rep(hashsize) .. "}")()
--- Writes wrapped Text with special tags.
--- @param obj object The object to write to
--- @param x number X-Position
--- @param y number Y-Position
--- @param text string Text
--- @param width number Width
--- @param height number Height
writeWrappedText = function(obj, x, y, text, width, height)
local wrapped = wrapRichText(text, width)
for _,v in pairs(wrapped)do
if(v.y>height)then
break
end
if(v.text~=nil)then
obj:addText(x+v.x-1, y+v.y-1, v.text)
end
if(v.color~=nil)then
obj:addFG(x+v.x-1, y+v.y-1, tHex[colors[v.color] ]:rep(#v.text))
end
if(v.bgColor~=nil)then
obj:addBG(x+v.x-1, y+v.y-1, tHex[colors[v.bgColor] ]:rep(#v.text))
end
end
end, end,
shrink = function(image, bgCol) --- Returns a random UUID.
local results, width, height, bgCol = {{}, {}, {}}, 0, #image + #image % 3, bgCol or colours.black --- @return string UUID.
for i = 1, #image do if #image[i] > width then width = #image[i] end end uuid = function()
return string.gsub(string.format('%x-%x-%x-%x-%x', math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0x0fff) + 0x4000, math.random(0, 0x3fff) + 0x8000), ' ', '0')
end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do for xx = 1, 2 do
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
return results
end,
} }

View File

@@ -1,4 +1,5 @@
local _OBJECTS = {} local _OBJECTS = {}
if(packaged)then if(packaged)then
for k,v in pairs(getProject("objects"))do for k,v in pairs(getProject("objects"))do
_OBJECTS[k] = v() _OBJECTS[k] = v()
@@ -13,7 +14,7 @@ if(dir==nil)then
end end
for _,v in pairs(fs.list(fs.combine(dir, "objects")))do for _,v in pairs(fs.list(fs.combine(dir, "objects")))do
if(v~="example.lua")then if(v~="example.lua")and not(v:find(".disabled"))then
local name = v:gsub(".lua", "") local name = v:gsub(".lua", "")
_OBJECTS[name] = require(name) _OBJECTS[name] = require(name)
end end

View File

@@ -1,20 +1,21 @@
local basaltEvent = require("basaltEvent")() local basaltEvent = require("basaltEvent")()
local Frame = require("Frame") local _OBJECTS = require("loadObjects")
local theme = require("theme") local pluginSystem = require("plugin")
local utils = require("utils") local utils = require("utils")
local log = require("basaltLogs") local log = require("basaltLogs")
local uuid = utils.uuid local uuid = utils.uuid
local createText = utils.createText local wrapText = utils.wrapText
local count = utils.tableCount local count = utils.tableCount
local moveThrottle = 300 local moveThrottle = 300
local dragThrottle = 50 local dragThrottle = 0
local renderingThrottle = 0
local baseTerm = term.current() local baseTerm = term.current()
local version = "1.6.4" local version = "1.7.0"
local projectDirectory = fs.getDir(table.pack(...)[2] or "") local projectDirectory = fs.getDir(table.pack(...)[2] or "")
local activeKey, frames, monFrames, monGroups, variables, schedules = {}, {}, {}, {}, {}, {} local activeKey, frames, monFrames, variables, schedules = {}, {}, {}, {}, {}
local mainFrame, activeFrame, focusedObject, updaterActive local mainFrame, activeFrame, focusedObject, updaterActive
local basalt = {} local basalt = {}
@@ -42,39 +43,23 @@ local function stop()
end end
end end
local function basaltError(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
local w,h = baseTerm.getSize()
if(basalt.logging)then
log(errMsg, "Error")
end
local text = createText("Basalt error: "..errMsg, w)
local yPos = 1
for k,v in pairs(text)do
baseTerm.setCursorPos(1,yPos)
baseTerm.write(v)
yPos = yPos + 1
end
baseTerm.setCursorPos(1,yPos+1)
updaterActive = false
end
local function schedule(f) local function schedule(f)
assert(f~="function", "Schedule needs a function in order to work!") assert(f~="function", "Schedule needs a function in order to work!")
return function(...) return function(...)
local co = coroutine.create(f) local co = coroutine.create(f)
local ok, result = coroutine.resume(co, ...) local ok, result = coroutine.resume(co, ...)
if(ok)then if(ok)then
table.insert(schedules, {co, result}) table.insert(schedules, co)
else else
basaltError(result) basalt.basaltError(result)
end end
end end
end end
basalt.log = function(...)
log(...)
end
local setVariable = function(name, var) local setVariable = function(name, var)
variables[name] = var variables[name] = var
end end
@@ -83,14 +68,6 @@ local getVariable = function(name)
return variables[name] return variables[name]
end end
local setTheme = function(_theme)
theme = _theme
end
local getTheme = function(name)
return theme[name]
end
local bInstance = { local bInstance = {
getDynamicValueEventSetting = function() getDynamicValueEventSetting = function()
return basalt.dynamicValueEvents return basalt.dynamicValueEvents
@@ -102,7 +79,6 @@ local bInstance = {
setVariable = setVariable, setVariable = setVariable,
getVariable = getVariable, getVariable = getVariable,
getTheme = getTheme,
setMainFrame = function(mFrame) setMainFrame = function(mFrame)
mainFrame = mFrame mainFrame = mFrame
@@ -140,7 +116,7 @@ local bInstance = {
end end
end, end,
getBaseTerm = function() getTerm = function()
return baseTerm return baseTerm
end, end,
@@ -148,32 +124,51 @@ local bInstance = {
stop = stop, stop = stop,
newFrame = Frame, newFrame = Frame,
debug = basalt.debug,
log = basalt.log,
getObjects = function()
return _OBJECTS
end,
getObject = function(id)
return _OBJECTS[id]
end,
getDirectory = function() getDirectory = function()
return projectDirectory return projectDirectory
end end
} }
local function handleSchedules(event, ...) local function defaultErrorHandler(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
local w,h = baseTerm.getSize()
if(basalt.logging)then
log(errMsg, "Error")
end
local text = wrapText("Basalt error: "..errMsg, w)
local yPos = 1
for k,v in pairs(text)do
baseTerm.setCursorPos(1,yPos)
baseTerm.write(v)
yPos = yPos + 1
end
baseTerm.setCursorPos(1,yPos+1)
updaterActive = false
end
local function handleSchedules(event, p1, p2, p3, p4)
if(#schedules>0)then if(#schedules>0)then
local finished = {} local finished = {}
for n=1,#schedules do for n=1,#schedules do
if(schedules[n]~=nil)then if(schedules[n]~=nil)then
if (coroutine.status(schedules[n][1]) == "suspended")then if (coroutine.status(schedules[n]) == "suspended")then
if(schedules[n][2]~=nil)then local ok, result = coroutine.resume(schedules[n], event, p1, p2, p3, p4)
if(schedules[n][2]==event)then if not(ok)then
local ok, result = coroutine.resume(schedules[n][1], event, ...) basalt.basaltError(result)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
end
else
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
end end
else else
table.insert(finished, n) table.insert(finished, n)
@@ -189,17 +184,13 @@ end
local function drawFrames() local function drawFrames()
if(updaterActive==false)then return end if(updaterActive==false)then return end
if(mainFrame~=nil)then if(mainFrame~=nil)then
mainFrame:draw() mainFrame:render()
mainFrame:updateTerm() mainFrame:updateTerm()
end end
for _,v in pairs(monFrames)do for _,v in pairs(monFrames)do
v:draw() v:render()
v:updateTerm() v:updateTerm()
end end
for _,v in pairs(monGroups)do
v[1]:draw()
v[1]:updateTerm()
end
end end
local stopped, moveX, moveY = nil, nil, nil local stopped, moveX, moveY = nil, nil, nil
@@ -236,6 +227,23 @@ local function mouseDragEvent(_, b, x, y)
end end
end end
local renderingTimer = nil
local function renderingUpdateTimer()
renderingTimer = nil
drawFrames()
end
local function renderingUpdateEvent(timer)
if(renderingThrottle<50)then
drawFrames()
else
if(renderingTimer==nil)then
renderingTimer = os.startTimer(renderingThrottle/1000)
end
end
end
local function basaltUpdateEvent(event, ...) local function basaltUpdateEvent(event, ...)
local a = {...} local a = {...}
if(basaltEvent:sendEvent("basaltEventCycle", event, ...)==false)then return end if(basaltEvent:sendEvent("basaltEventCycle", event, ...)==false)then return end
@@ -252,23 +260,19 @@ local function basaltUpdateEvent(event, ...)
if(mouseEvent~=nil)then if(mouseEvent~=nil)then
mouseEvent(mainFrame, ...) mouseEvent(mainFrame, ...)
handleSchedules(event, ...) handleSchedules(event, ...)
drawFrames() renderingUpdateEvent()
return return
end end
end end
if(event == "monitor_touch") then if(event == "monitor_touch") then
if(monFrames[a[1]]~=nil)then for k,v in pairs(monFrames)do
monFrames[a[1]]:mouseHandler(1, a[2], a[3], true) if(v:mouseHandler(1, a[2], a[3], true, a[1]))then
activeFrame = monFrames[a[1]] activeFrame = v
end
if(count(monGroups)>0)then
for k,v in pairs(monGroups)do
v[1]:mouseHandler(1, a[2], a[3], true, a[1])
end end
end end
handleSchedules(event, ...) handleSchedules(event, ...)
drawFrames() renderingUpdateEvent()
return return
end end
@@ -287,7 +291,7 @@ local function basaltUpdateEvent(event, ...)
end end
keyEvent(activeFrame, ...) keyEvent(activeFrame, ...)
handleSchedules(event, ...) handleSchedules(event, ...)
drawFrames() renderingUpdateEvent()
return return
end end
end end
@@ -296,25 +300,51 @@ local function basaltUpdateEvent(event, ...)
moveHandlerTimer() moveHandlerTimer()
elseif(event=="timer")and(a[1]==dragTimer)then elseif(event=="timer")and(a[1]==dragTimer)then
dragHandlerTimer() dragHandlerTimer()
elseif(event=="timer")and(a[1]==renderingTimer)then
renderingUpdateTimer()
else else
for k, v in pairs(frames) do for k, v in pairs(frames) do
v:eventHandler(event, ...) v:eventHandler(event, ...)
end end
for k, v in pairs(monFrames) do
v:eventHandler(event, ...)
end
handleSchedules(event, ...)
renderingUpdateEvent()
end end
handleSchedules(event, ...) end
drawFrames()
local function createFrame(name)
for _, v in pairs(frames) do
if (v:getName() == name) then
return nil
end
end
local newFrame = _OBJECTS["BaseFrame"](name, bInstance)
newFrame:init()
newFrame:load()
newFrame:draw()
table.insert(frames, newFrame)
if(mainFrame==nil)and(newFrame:getName()~="basaltDebuggingFrame")then
newFrame:show()
end
return newFrame
end end
basalt = { basalt = {
basaltError = defaultErrorHandler,
logging = false, logging = false,
dynamicValueEvents = false, dynamicValueEvents = false,
setTheme = setTheme,
getTheme = getTheme,
drawFrames = drawFrames, drawFrames = drawFrames,
log = log,
getVersion = function() getVersion = function()
return version return version
end, end,
memory = function()
return math.floor(collectgarbage("count")+0.5).."KB"
end,
setVariable = setVariable, setVariable = setVariable,
getVariable = getVariable, getVariable = getVariable,
@@ -322,8 +352,12 @@ basalt = {
baseTerm = _baseTerm baseTerm = _baseTerm
end, end,
log = function(...) resetPalette = function()
log(...) for k,v in pairs(colors)do
if(type(v)=="number")then
--baseTerm.setPaletteColor(v, colors.packRGB(table.unpack(defaultColors[k])))
end
end
end, end,
setMouseMoveThrottle = function(amount) setMouseMoveThrottle = function(amount)
@@ -339,6 +373,15 @@ basalt = {
return false return false
end, end,
setRenderingThrottle = function(amount)
if(amount<=0)then
renderingThrottle = 0
else
renderingTimer = nil
renderingThrottle = amount
end
end,
setMouseDragThrottle = function(amount) setMouseDragThrottle = function(amount)
if(amount<=0)then if(amount<=0)then
dragThrottle = 0 dragThrottle = 0
@@ -357,18 +400,20 @@ basalt = {
basaltUpdateEvent(os.pullEventRaw()) basaltUpdateEvent(os.pullEventRaw())
end end
end end
local ok, err = xpcall(f, debug.traceback) while updaterActive do
if not(ok)then local ok, err = xpcall(f, debug.traceback)
basaltError(err) if not(ok)then
return basalt.basaltError(err)
end
end end
end, end,
update = function(event, ...) update = function(event, ...)
if (event ~= nil) then if (event ~= nil) then
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, ...) local args = {...}
local ok, err = xpcall(function() basaltUpdateEvent(event, table.unpack(args)) end, debug.traceback)
if not(ok)then if not(ok)then
basaltError(err) basalt.basaltError(err)
return return
end end
end end
@@ -395,13 +440,17 @@ basalt = {
end, end,
setActiveFrame = function(frame) setActiveFrame = function(frame)
if (frame:getType() == "Frame") then if (frame:getType() == "Container") then
activeFrame = frame activeFrame = frame
return true return true
end end
return false return false
end, end,
getMainFrame = function()
return mainFrame
end,
onEvent = function(...) onEvent = function(...)
for _,v in pairs(table.pack(...))do for _,v in pairs(table.pack(...))do
if(type(v)=="function")then if(type(v)=="function")then
@@ -412,19 +461,20 @@ basalt = {
schedule = schedule, schedule = schedule,
createFrame = function(name) addFrame = createFrame,
name = name or uuid() createFrame = createFrame,
addMonitor = function(name)
for _, v in pairs(frames) do for _, v in pairs(frames) do
if (v.name == name) then if (v:getName() == name) then
return nil return nil
end end
end end
local newFrame = Frame(name,nil,nil,bInstance) local newFrame = _OBJECTS["MonitorFrame"](name, bInstance)
newFrame:init() newFrame:init()
table.insert(frames, newFrame) newFrame:load()
if(mainFrame==nil)and(newFrame:getName()~="basaltDebuggingFrame")then newFrame:draw()
newFrame:show() table.insert(monFrames, newFrame)
end
return newFrame return newFrame
end, end,
@@ -435,37 +485,26 @@ basalt = {
setProjectDir = function(dir) setProjectDir = function(dir)
projectDirectory = dir projectDirectory = dir
end, end,
debug = function(...)
local args = { ... }
if(mainFrame==nil)then print(...) return end
if (mainFrame.name ~= "basaltDebuggingFrame") then
if (mainFrame ~= basalt.debugFrame) then
basalt.debugLabel:setParent(mainFrame)
end
end
local str = ""
for key, value in pairs(args) do
str = str .. tostring(value) .. (#args ~= key and ", " or "")
end
basalt.debugLabel:setText("[Debug] " .. str)
for k,v in pairs(createText(str, basalt.debugList:getWidth()))do
basalt.debugList:addItem(v)
end
if (basalt.debugList:getItemCount() > 50) then
basalt.debugList:removeItem(1)
end
basalt.debugList:setValue(basalt.debugList:getItem(basalt.debugList:getItemCount()))
if(basalt.debugList.getItemCount() > basalt.debugList:getHeight())then
basalt.debugList:setOffset(basalt.debugList:getItemCount() - basalt.debugList:getHeight())
end
basalt.debugLabel:show()
end,
} }
basalt.debugFrame = basalt.createFrame("basaltDebuggingFrame"):showBar():setBackground(colors.lightGray):setBar("Debug", colors.black, colors.gray) _OBJECTS = pluginSystem.addPlugins(_OBJECTS, bInstance)
basalt.debugFrame:addButton("back"):setAnchor("topRight"):setSize(1, 1):setText("\22"):onClick(function() if(basalt.oldFrame~=nil)then basalt.oldFrame:show() end end):setBackground(colors.red):show()
basalt.debugList = basalt.debugFrame:addList("debugList"):setSize("parent.w - 2", "parent.h - 3"):setPosition(2, 3):setScrollable(true):show() local basaltPlugins = pluginSystem.get("basalt")
basalt.debugLabel = basalt.debugFrame:addLabel("debugLabel"):onClick(function() basalt.oldFrame = mainFrame basalt.debugFrame:show() end):setBackground(colors.black):setForeground(colors.white):setAnchor("bottomLeft"):ignoreOffset():setZIndex(20):show() if(basaltPlugins~=nil)then
for k,v in pairs(basaltPlugins)do
for a,b in pairs(v(basalt))do
basalt[a] = b
bInstance[a] = b
end
end
end
local basaltPlugins = pluginSystem.get("basaltInternal")
if(basaltPlugins~=nil)then
for k,v in pairs(basaltPlugins)do
for a,b in pairs(v(basalt))do
bInstance[a] = b
end
end
end
return basalt return basalt

View File

@@ -1,4 +0,0 @@
return function(path)
local exists, content = pcall(require, path)
return exists and content or nil
end

View File

@@ -1,6 +1,3 @@
local xmlValue = require("utils").getValueFromXML
local basaltEvent = require("basaltEvent")
local floor,sin,cos,pi,sqrt,pow = math.floor,math.sin,math.cos,math.pi,math.sqrt,math.pow local floor,sin,cos,pi,sqrt,pow = math.floor,math.sin,math.cos,math.pi,math.sqrt,math.pow
-- You can find the easing curves here https://easings.net -- You can find the easing curves here https://easings.net
@@ -222,7 +219,8 @@ local lerp = {
local activeAnimations = {} local activeAnimations = {}
return function(name) return function(name, basalt)
local base = basalt.getObject("Object")(name, basalt)
local object = {} local object = {}
local objectType = "Animation" local objectType = "Animation"
@@ -234,8 +232,6 @@ return function(name)
local index = 1 local index = 1
local infinitePlay = false local infinitePlay = false
local eventSystem = basaltEvent()
local nextWaitTimer = 0 local nextWaitTimer = 0
local lastFunc local lastFunc
local loop=false local loop=false
@@ -306,7 +302,7 @@ return function(name)
local obj = _OBJ local obj = _OBJ
local x,y local x,y
local name = "" local name = ""
if(obj.parent~=nil)then name = obj.parent:getName() end if(obj:getParent()~=nil)then name = obj:getParent():getName() end
name = name..obj:getName() name = name..obj:getName()
addAnimationPart(t+0.05, function() addAnimationPart(t+0.05, function()
if(typ~=nil)then if(typ~=nil)then
@@ -340,14 +336,7 @@ return function(name)
name = name, name = name,
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setMode = function(self, newMode) setMode = function(self, newMode)
mode = newMode mode = newMode
@@ -359,124 +348,6 @@ return function(name)
return self return self
end, end,
generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
func(self,function()o:internalObjetCall()end)
end
else
func(self,self:getBaseFrame():getVariable(str))
end
end
if(type(val)=="string")then
createF(val)
elseif(type(val)=="table")then
for k,v in pairs(val)do
createF(v)
end
end
return self
end,
setValuesByXMLData = function(self, data)
loop = xmlValue("loop", data)==true and true or false
if(xmlValue("object", data)~=nil)then
local o = self:getBaseFrame():getDeepObject(xmlValue("object", data))
if(o==nil)then
o = self:getBaseFrame():getVariable(xmlValue("object", data))
end
if(o~=nil)then
self:setObject(o)
end
end
if(data["move"]~=nil)then
local x = xmlValue("x", data["move"])
local y = xmlValue("y", data["move"])
local duration = xmlValue("duration", data["move"])
local time = xmlValue("time", data["move"])
self:move(x, y, duration, time)
end
if(data["size"]~=nil)then
local w = xmlValue("width", data["size"])
local h = xmlValue("height", data["size"])
local duration = xmlValue("duration", data["size"])
local time = xmlValue("time", data["size"])
self:size(w, h, duration, time)
end
if(data["offset"]~=nil)then
local x = xmlValue("x", data["offset"])
local y = xmlValue("y", data["offset"])
local duration = xmlValue("duration", data["offset"])
local time = xmlValue("time", data["offset"])
self:offset(x, y, duration, time)
end
if(data["textColor"]~=nil)then
local duration = xmlValue("duration", data["textColor"])
local timer = xmlValue("time", data["textColor"])
local t = {}
local tab = data["textColor"]["color"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, colors[v:value()])
end
end
if(duration~=nil)and(#t>0)then
self:changeTextColor(duration, timer or 0, table.unpack(t))
end
end
if(data["background"]~=nil)then
local duration = xmlValue("duration", data["background"])
local timer = xmlValue("time", data["background"])
local t = {}
local tab = data["background"]["color"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, colors[v:value()])
end
end
if(duration~=nil)and(#t>0)then
self:changeBackground(duration, timer or 0, table.unpack(t))
end
end
if(data["text"]~=nil)then
local duration = xmlValue("duration", data["text"])
local timer = xmlValue("time", data["text"])
local t = {}
local tab = data["text"]["text"]
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
table.insert(t, v:value())
end
end
if(duration~=nil)and(#t>0)then
self:changeText(duration, timer or 0, table.unpack(t))
end
end
if(xmlValue("onDone", data)~=nil)then self:generateXMLEventFunction(self.onDone, xmlValue("onDone", data)) end
if(xmlValue("onStart", data)~=nil)then self:generateXMLEventFunction(self.onDone, xmlValue("onStart", data)) end
if(xmlValue("autoDestroy", data)~=nil)then
if(xmlValue("autoDestroy", data))then
autoDestroy = true
end
end
mode = xmlValue("mode", data) or mode
if(xmlValue("play", data)~=nil)then if(xmlValue("play", data))then self:play(loop) end end
return self
end,
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
setObject = function(self, obj) setObject = function(self, obj)
_OBJ = obj _OBJ = obj
return self return self
@@ -557,12 +428,12 @@ return function(name)
end; end;
onDone = function(self, f) onDone = function(self, f)
eventSystem:registerEvent("animation_done", f) self:registerEvent("animation_done", f)
return self return self
end, end,
onStart = function(self, f) onStart = function(self, f)
eventSystem:registerEvent("animation_start", f) self:registerEvent("animation_start", f)
return self return self
end, end,
@@ -572,16 +443,16 @@ return function(name)
end, end,
animationDoneHandler = function(self) animationDoneHandler = function(self)
eventSystem:sendEvent("animation_done", self) self:sendEvent("animation_done", self)
self.parent:removeEvent("other_event", self) self:listenEvent("other_event", false)
if(autoDestroy)then if(autoDestroy)then
self.parent:removeObject(self) self:getParent():removeObject(self)
self = nil self = nil
end end
end; end;
animationStartHandler = function(self) animationStartHandler = function(self)
eventSystem:sendEvent("animation_start", self) self:sendEvent("animation_start", self)
end; end;
clear = function(self) clear = function(self)
@@ -609,7 +480,7 @@ return function(name)
else else
self:animationDoneHandler() self:animationDoneHandler()
end end
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
return self return self
end; end;
@@ -619,7 +490,7 @@ return function(name)
infinitePlay = false infinitePlay = false
end end
animationActive = false animationActive = false
self.parent:removeEvent("other_event", self) self:listenEvent("other_event", false)
return self return self
end; end;
@@ -639,7 +510,7 @@ return function(name)
end end
end; end;
} }
object.__index = object
return object object.__index = object
return setmetatable(object, base)
end end

View File

@@ -0,0 +1,215 @@
local drawSystem = require("basaltDraw")
local utils = require("utils")
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
local colorTheme = {}
local updateRender = true
local termObject = basalt.getTerm()
local basaltDraw = drawSystem(termObject)
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,
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,
setPalette = function(self, col, ...)
if(self==basalt.getActiveFrame())then
if(type(col)=="string")then
colorTheme[col] = ...
termObject.setPaletteColor(type(col)=="number" and col or colors[col], ...)
elseif(type(col)=="table")then
for k,v in pairs(col)do
colorTheme[k] = v
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
end
end
return self
end,
setSize = function(self, ...)
base.setSize(self, ...)
basaltDraw = drawSystem(termObject)
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)
for k,v in pairs(colors)do
if(type(v)=="number")then
termObject.setPaletteColor(v, colors.packRGB(term.nativePaletteColor((v))))
end
end
for k,v in pairs(colorTheme)do
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
basalt.setMainFrame(self)
return self
end,
render = function(self)
if(base.render~=nil)then
if(self:isVisible())then
if(updateRender)then
base.render(self)
local objects = self:getObjects()
for _, obj in ipairs(objects) do
if (obj.element.render ~= nil) then
obj.element:render()
end
end
updateRender = false
end
end
end
end,
updateDraw = function(self)
updateRender = true
return self
end,
eventHandler = function(self, event, ...)
base.eventHandler(self, event, ...)
if(event=="term_resize")then
self:setSize(termObject.getSize())
end
end,
updateTerm = function(self)
if(basaltDraw~=nil)then
basaltDraw.update()
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()
if y >= 1 and y <= h then
local t_visible = sub(t, max(1 - x + 1, 1), max(w - x + 1, 1))
local f_visible = sub(f, max(1 - x + 1, 1), max(w - x + 1, 1))
local b_visible = sub(b, max(1 - x + 1, 1), max(w - x + 1, 1))
basaltDraw.blit(max(x + (obx - 1), obx), oby + y - 1, t_visible, f_visible, b_visible)
end
end,
setCursor = function(self, _blink, _xCursor, _yCursor, color)
local obx, oby = self:getAbsolutePosition()
local xO, yO = self:getOffset()
cursorBlink = _blink or false
if (_xCursor ~= nil) then
xCursor = obx + _xCursor - 1 - xO
end
if (_yCursor ~= nil) then
yCursor = oby + _yCursor - 1 - yO
end
cursorColor = color or cursorColor
if (cursorBlink) then
termObject.setTextColor(cursorColor)
termObject.setCursorPos(xCursor, yCursor)
termObject.setCursorBlink(cursorBlink)
else
termObject.setCursorBlink(false)
end
return self
end,
}
for k,v in pairs({mouse_click={"mouseHandler", true},mouse_up={"mouseUpHandler", false},mouse_drag={"dragHandler", false},mouse_scroll={"scrollHandler", true},mouse_hover={"hoverHandler", false}})do
object[v[1]] = function(self, btn, x, y, ...)
if(base[v[1]](self, btn, x, y, ...))then
basalt.setActiveFrame(self)
end
end
end
for k,v in pairs({"drawBackgroundBox", "drawForegroundBox", "drawTextBox"})do
object[v] = function(self, x, y, width, height, symbol)
local obx, oby = self:getPosition()
local w, h = self:getSize()
height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height))
width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width))
basaltDraw[v](max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, symbol)
end
end
for k,v in pairs({"setBG", "setFG", "setText"}) do
object[v] = function(self, x, y, str)
local obx, oby = self:getPosition()
local w, h = self:getSize()
if (y >= 1) and (y <= h) then
basaltDraw[v](max(x + (obx - 1), obx), oby + y - 1, sub(str, max(1 - x + 1, 1), max(w - x + 1,1)))
end
end
end
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,74 +1,65 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML
local tHex = require("tHex") local tHex = require("tHex")
return function(name) return function(name, basalt)
-- Button -- Button
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Button" local objectType = "Button"
local textHorizontalAlign = "center" local textHorizontalAlign = "center"
local textVerticalAlign = "center" local textVerticalAlign = "center"
local text = "Button"
base:setSize(12, 3)
base:setZIndex(5) base:setZIndex(5)
base:setValue("Button")
base.width = 12
base.height = 3
local object = { local object = {
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ButtonBG")
self.fgColor = self.parent:getTheme("ButtonText")
end
end,
getType = function(self) getType = function(self)
return objectType return objectType
end; 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,
setHorizontalAlign = function(self, pos) setHorizontalAlign = function(self, pos)
textHorizontalAlign = pos textHorizontalAlign = pos
self:updateDraw() self:updateDraw()
return self return self
end; end,
setVerticalAlign = function(self, pos) setVerticalAlign = function(self, pos)
textVerticalAlign = pos textVerticalAlign = pos
self:updateDraw() self:updateDraw()
return self return self
end; end,
setText = function(self, text) setText = function(self, newText)
base:setValue(tostring(text)) text = newText
self:updateDraw() self:updateDraw()
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end
if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end
return self
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("button", function()
local obx, oby = self:getAnchorPosition() local w,h = self:getSize()
local w,h = self:getSize() local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) local xOffset
if(textHorizontalAlign=="center")then
for n = 1, h do xOffset = math.floor((w - text:len()) / 2)
if (n == verticalAlign) then elseif(textHorizontalAlign=="right")then
local val = self:getValue() xOffset = w - text:len()
self.parent:setText(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(val, val:len(), textHorizontalAlign))
self.parent:setFG(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(tHex[self.fgColor]:rep(val:len()), val:len(), textHorizontalAlign))
end
end
end end
end
end,
self:addText(xOffset + 1, verticalAlign, text)
self:addFG(xOffset + 1, verticalAlign, tHex[self:getForeground() or colors.white]:rep(text:len()))
end)
end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -0,0 +1,40 @@
return function(name, basalt)
local base = basalt.getObject("VisualObject")(name, basalt)
-- Base object
local objectType = "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
end
return self
end,
getValue = function(self)
return value
end,
onChange = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("value_changed", v)
end
end
return self
end,
valueChangedHandler = function(self)
self:sendEvent("value_changed", value)
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,31 +1,53 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML local tHex = require("tHex")
return function(name) return function(name, basalt)
-- Checkbox -- Checkbox
local base = Object(name) local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Checkbox" local objectType = "Checkbox"
base:setZIndex(5) base:setZIndex(5)
base:setValue(false) base:setValue(false)
base.width = 1 base:setSize(1, 1)
base.height = 1
local symbol = "\42" local symbol,inactiveSymbol,text,textPos = "\42"," ","","right"
local object = { local object = {
load = function(self)
self:listenEvent("mouse_click", self)
self:listenEvent("mouse_up", self)
end,
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
isType = function(self, t)
return objectType==t or base.isType~=nil and base.isType(t) or false
end,
setSymbol = function(self, sym) setSymbol = function(self, sym, inactive)
symbol = sym symbol = sym or symbol
inactiveSymbol = inactive or inactiveSymbol
self:updateDraw() self:updateDraw()
return self return self
end, end,
getSymbol = function(self)
return symbol, inactiveSymbol
end,
setText = function(self, _text)
text = _text
return self
end,
setTextPosition = function(self, pos)
textPos = pos or textPos
return self
end,
setChecked = base.setValue,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then if (base.mouseHandler(self, button, x, y)) then
if(button == 1)then if(button == 1)then
@@ -41,45 +63,26 @@ return function(name)
return false return false
end, end,
touchHandler = function(self, x, y)
return self:mouseHandler(1, x, y)
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("checked", data)~=nil)then if(xmlValue("checked", data))then self:setValue(true) else self:setValue(false) end end
return self
end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("checkbox", function()
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, "center") local verticalAlign = utils.getTextVerticalAlign(h, "center")
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local bg,fg = self:getBackground(), self:getForeground()
for n = 1, h do if (self:getValue()) then
if (n == verticalAlign) then self:addBlit(1, verticalAlign, utils.getTextHorizontalAlign(symbol, w, "center"), tHex[fg], tHex[bg])
if (self:getValue() == true) then else
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(symbol, w, "center"), self.bgColor, self.fgColor) self:addBlit(1, verticalAlign, utils.getTextHorizontalAlign(inactiveSymbol, w, "center"), tHex[fg], tHex[bg])
else
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", w, "center"), self.bgColor, self.fgColor)
end
end
end
end end
end if(text~="")then
end, local align = textPos=="left" and -text:len() or 3
self:addText(align, verticalAlign, text)
init = function(self) end
self.parent:addEvent("mouse_click", self) end)
self.parent:addEvent("mouse_up", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("CheckboxBG")
self.fgColor = self.parent:getTheme("CheckboxText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -0,0 +1,395 @@
local utils = require("utils")
local tableCount = utils.tableCount
return function(name, basalt)
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Container"
local elements = {}
local events = {}
local container = {}
local focusedObject
local sorted = true
local objId, evId = 0, 0
local objSort = function(a, b)
if a.zIndex == b.zIndex then
return a.objId < b.objId
else
return a.zIndex < b.zIndex
end
end
local evSort = function(a, b)
if a.zIndex == b.zIndex then
return a.evId > b.evId
else
return a.zIndex > b.zIndex
end
end
local function getObject(self, name)
if(type(name)=="table")then name = name:getName() end
for i, v in ipairs(elements) do
if v.element:getName() == name then
return v.element
end
end
end
local function getDeepObject(self, name)
local o = getObject(name)
if(o~=nil)then return o end
for _, value in pairs(objects) do
if (b:getType() == "Container") then
local oF = b:getDeepObject(name)
if(oF~=nil)then return oF end
end
end
end
local function addObject(self, element, el2)
if (getObject(element:getName()) ~= nil) then
return
end
objId = objId + 1
local zIndex = element:getZIndex()
table.insert(elements, {element = element, zIndex = zIndex, objId = objId})
sorted = false
element:setParent(self, true)
if(element.init~=nil)then element:init() end
if(element.load~=nil)then element:load() end
if(element.draw~=nil)then element:draw() end
return element
end
local function updateZIndex(self, element, newZ)
objId = objId + 1
evId = evId + 1
for _,v in pairs(elements)do
if(v.element==element)then
v.zIndex = newZ
v.objId = objId
break
end
end
for _,v in pairs(events)do
for a,b in pairs(v)do
if(b.element==element)then
b.zIndex = newZ
b.evId = evId
end
end
end
sorted = false
self:updateDraw()
end
local function removeObject(self, element)
if(type(element)=="string")then element = getObject(element:getName()) end
if(element==nil)then return end
for i, v in ipairs(elements) do
if v.element == element then
table.remove(elements, i)
return true
end
end
sorted = false
end
local function removeEvents(self, element)
local parent = self:getParent()
for a, b in pairs(events) do
for c, d in pairs(b) do
if(d.element == element)then
table.remove(events[a], c)
end
end
if(tableCount(events[a])<=0)then
if(parent~=nil)then
parent:removeEvent(a, self)
end
end
end
sorted = false
end
local function getEvent(self, event, name)
if(type(name)=="table")then name = name:getName() end
if(events[event]~=nil)then
for _, obj in pairs(events[event]) do
if (obj.element:getName() == name) then
return obj
end
end
end
end
local function addEvent(self, event, element)
if (getEvent(self, event, element:getName()) ~= nil) then
return
end
local zIndex = element:getZIndex()
evId = evId + 1
if(events[event]==nil)then events[event] = {} end
table.insert(events[event], {element = element, zIndex = zIndex, evId = evId})
sorted = false
self:listenEvent(event)
return element
end
local function removeEvent(self, event, element)
if(events[event]~=nil)then
for a, b in pairs(events[event]) do
if(b.element == element)then
table.remove(events[event], a)
end
end
if(tableCount(events[event])<=0)then
self:listenEvent(event, false)
end
end
sorted = false
end
local function getObjects(self)
self:sortElementOrder()
return elements
end
local function getEvents(self, event)
return event~=nil and events[event] or events
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")
return self
end,
setPosition = function(self, ...)
base.setPosition(self, ...)
self:customEventHandler("basalt_FrameReposition")
return self
end,
searchObjects = function(self, name)
local t = {}
for k,v in pairs(elements)do
if(string.find(k:getName(), name))then
table.insert(t, v)
end
end
return t
end,
getObjectsByType = function(self, t)
local t = {}
for k,v in pairs(elements)do
if(v:isType(t))then
table.insert(t, v)
end
end
return t
end,
setImportant = function(self, element)
objId = objId + 1
evId = evId + 1
for a, b in pairs(events) do
for c, d in pairs(b) do
if(d.element == element)then
d.evId = evId
table.remove(events[a], c)
table.insert(events[a], d)
break
end
end
end
for i, v in ipairs(elements) do
if v.element == element then
v.objId = objId
table.remove(elements, i)
table.insert(elements, v)
break
end
end
if(self.updateDraw~=nil)then
self:updateDraw()
end
sorted = false
end,
sortElementOrder = function(self)
if(sorted)then return end
table.sort(elements, objSort)
for a, b in pairs(events) do
table.sort(events[a], evSort)
end
sorted = true
end,
removeFocusedObject = function(self)
if(focusedObject~=nil)then
if(getObject(self, focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
focusedObject = nil
return self
end,
setFocusedObject = function(self, obj)
if(focusedObject~=obj)then
if(focusedObject~=nil)then
if(getObject(self, focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
if(obj~=nil)then
if(getObject(self, obj)~=nil)then
obj:getFocusHandler()
end
end
focusedObject = obj
return true
end
return false
end,
getFocusedObject = function(self)
return focusedObject
end,
getObject = getObject,
getObjects = getObjects,
getDeepObject = getDeepObject,
addObject = addObject,
removeObject = removeObject,
getEvents = getEvents,
getEvent = getEvent,
addEvent = addEvent,
removeEvent = removeEvent,
removeEvents = removeEvents,
updateZIndex = updateZIndex,
listenEvent = function(self, event, active)
base.listenEvent(self, event, active)
if(events[event]==nil)then events[event] = {} end
return self
end,
customEventHandler = function(self, ...)
base.customEventHandler(self, ...)
for _, o in pairs(elements) do
if (o.element.customEventHandler ~= nil) then
o.element:customEventHandler(...)
end
end
end,
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if(focusedObject~=nil)then focusedObject:loseFocusHandler() focusedObject = nil end
end,
getBasalt = function(self)
return basalt
end,
setPalette = function(self, col, ...)
local parent = self:getParent()
parent:setPalette(col, ...)
return self
end,
eventHandler = function(self, ...)
if(base.eventHandler~=nil)then
base.eventHandler(self, ...)
if(events["other_event"]~=nil)then
self:sortElementOrder()
for _, obj in ipairs(events["other_event"]) do
if (obj.element.eventHandler ~= nil) then
obj.element.eventHandler(obj.element, ...)
end
end
end
end
end,
}
for k,v in pairs({mouse_click={"mouseHandler", true},mouse_up={"mouseUpHandler", false},mouse_drag={"dragHandler", false},mouse_scroll={"scrollHandler", true},mouse_hover={"hoverHandler", false}})do
container[v[1]] = function(self, btn, x, y, ...)
if(base[v[1]]~=nil)then
if(base[v[1]](self, btn, x, y, ...))then
if(events[k]~=nil)then
self:sortElementOrder()
for _, obj in ipairs(events[k]) do
if (obj.element[v[1]] ~= nil) then
local xO, yO = 0, 0
if(self.getOffset~=nil)then
xO, yO = self:getOffset()
end
if(obj.element.getIgnoreOffset~=nil)then
if(obj.element.getIgnoreOffset())then
xO, yO = 0, 0
end
end
if (obj.element[v[1]](obj.element, btn, x+xO, y+yO, ...)) then
return true
end
end
end
if(v[2])then
self:removeFocusedObject()
end
end
return true
end
end
end
end
for k,v in pairs({key="keyHandler",key_up="keyUpHandler",char="charHandler"})do
container[v] = function(self, ...)
if(base[v]~=nil)then
if(base[v](self, ...))then
if(events[k]~=nil)then
self:sortElementOrder()
for _, obj in ipairs(events[k]) do
if (obj.element[v] ~= nil) then
if (obj.element[v](obj.element, ...)) then
return true
end
end
end
end
end
end
end
end
for k,v in pairs(basalt.getObjects())do
container["add"..k] = function(self, name)
return addObject(self, v(name, basalt))
end
end
container.__index = container
return setmetatable(container, base)
end

View File

@@ -1,23 +1,20 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = require("utils").getValueFromXML local tHex = require("tHex")
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("List")(name, basalt)
local objectType = "Dropdown" local objectType = "Dropdown"
base.width = 12
base.height = 1 base:setSize(12, 1)
base:setZIndex(6) base:setZIndex(6)
local list = {}
local itemSelectedBG
local itemSelectedFG
local selectionColorActive = true local selectionColorActive = true
local align = "left" local align = "left"
local yOffset = 0 local yOffset = 0
local dropdownW = 16 local dropdownW = 0
local dropdownH = 6 local dropdownH = 0
local autoSize = true
local closedSymbol = "\16" local closedSymbol = "\16"
local openedSymbol = "\31" local openedSymbol = "\31"
local isOpened = false local isOpened = false
@@ -25,97 +22,63 @@ return function(name)
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
setValuesByXMLData = function(self, data) isType = function(self, t)
base.setValuesByXMLData(self, data) return objectType==t or base.isType~=nil and base.isType(t) or false
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end end,
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("dropdownWidth", data)~=nil)then dropdownW = xmlValue("dropdownWidth", data) end load = function(self)
if(xmlValue("dropdownHeight", data)~=nil)then dropdownH = xmlValue("dropdownHeight", data) end self:listenEvent("mouse_click", self)
if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end self:listenEvent("mouse_up", self)
if(data["item"]~=nil)then self:listenEvent("mouse_scroll", self)
local tab = data["item"] self:listenEvent("mouse_drag", self)
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
end, end,
setOffset = function(self, yOff) setOffset = function(self, yOff)
yOffset = yOff yOffset = yOff
self:updateDraw() self:updateDraw()
return self return self
end; end,
getOffset = function(self) getOffset = function(self)
return yOffset return yOffset
end; end,
addItem = function(self, text, bgCol, fgCol, ...) addItem = function(self, t, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) base.addItem(self, t, ...)
self:updateDraw() if(autoSize)then
dropdownW = math.max(dropdownW, #t)
dropdownH = dropdownH + 1
end
return self return self
end; end,
getAll = function(self)
return list
end;
removeItem = function(self, index) removeItem = function(self, index)
table.remove(list, index) base.removeItem(self, index)
self:updateDraw() if(autoSize)then
return self dropdownW = 0
end; dropdownH = 0
for n = 1, #list do
getItem = function(self, index) dropdownW = math.max(dropdownW, #list[n].text)
return list[index]
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end end
dropdownH = #list
end end
end; end,
clear = function(self) isOpened = function(self)
list = {} return isOpened
self:setValue({}, false) end,
setOpened = function(self, open)
isOpened = open
self:updateDraw() self:updateDraw()
return self return self
end; end,
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
self:updateDraw()
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active~=nil and active
self:updateDraw()
return self
end;
setDropdownSize = function(self, width, height) setDropdownSize = function(self, width, height)
dropdownW, dropdownH = width, height dropdownW, dropdownH = width, height
autoSize = false
self:updateDraw() self:updateDraw()
return self return self
end, end,
@@ -124,18 +87,25 @@ return function(name)
return dropdownW, dropdownH return dropdownW, dropdownH
end, end,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y, isMon)
if (isOpened) then if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
if(button==1)then if(button==1)then
local list = self:getAll()
if (#list > 0) then if (#list > 0) then
for n = 1, dropdownH do for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then
self:setValue(list[n + yOffset]) self:setValue(list[n + yOffset])
self:updateDraw() self:updateDraw()
local val = self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", dir, x, y) local val = self:sendEvent("mouse_click", self, "mouse_click", dir, x, y)
if(val==false)then return val end if(val==false)then return val end
if(isMon)then
basalt.schedule(function()
sleep(0.1)
self:mouseUpHandler(button, x, y)
end)()
end
return true return true
end end
end end
@@ -143,8 +113,10 @@ return function(name)
end end
end end
end end
local base = base:getBase()
if (base.mouseHandler(self, button, x, y)) then if (base.mouseHandler(self, button, x, y)) then
isOpened = (not isOpened) isOpened = not isOpened
self:getParent():setImportant(self)
self:updateDraw() self:updateDraw()
return true return true
else else
@@ -158,15 +130,16 @@ return function(name)
mouseUpHandler = function(self, button, x, y) mouseUpHandler = function(self, button, x, y)
if (isOpened) then if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
if(button==1)then if(button==1)then
local list = self:getAll()
if (#list > 0) then if (#list > 0) then
for n = 1, dropdownH do for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then
isOpened = false isOpened = false
self:updateDraw() self:updateDraw()
local val = self:getEventSystem():sendEvent("mouse_up", self, "mouse_up", dir, x, y) local val = self:sendEvent("mouse_up", self, "mouse_up", dir, x, y)
if(val==false)then return val end if(val==false)then return val end
return true return true
end end
@@ -178,7 +151,20 @@ return function(name)
end, end,
scrollHandler = function(self, dir, x, y) scrollHandler = function(self, dir, x, y)
if(isOpened)then
local xPos, yPos = self:getAbsolutePosition()
if(x >= xPos)and(x <= xPos + dropdownW)and(y >= yPos)and(y <= yPos + dropdownH)then
self:setFocus()
end
end
if (isOpened)and(self:isFocused()) then if (isOpened)and(self:isFocused()) then
local xPos, yPos = self:getAbsolutePosition()
if(x < xPos)or(x > xPos + dropdownW)or(y < yPos)or(y > yPos + dropdownH)then
return false
end
if(#self:getAll() <= dropdownH)then return false end
local list = self:getAll()
yOffset = yOffset + dir yOffset = yOffset + dir
if (yOffset < 0) then if (yOffset < 0) then
yOffset = 0 yOffset = 0
@@ -192,7 +178,7 @@ return function(name)
yOffset = math.min(#list - 1, 0) yOffset = math.min(#list - 1, 0)
end end
end end
local val = self:getEventSystem():sendEvent("mouse_scroll", self, "mouse_scroll", dir, x, y) local val = self:sendEvent("mouse_scroll", self, "mouse_scroll", dir, x, y)
if(val==false)then return val end if(val==false)then return val end
self:updateDraw() self:updateDraw()
return true return true
@@ -200,46 +186,41 @@ return function(name)
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
local obx, oby = self:getAnchorPosition() self:setDrawState("list", false)
self:addDraw("dropdown", function()
local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (self.parent ~= nil) then local val = self:getValue()
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local list = self:getAll()
local val = self:getValue() local bgCol, fgCol = self:getBackground(), self:getForeground()
local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), w, align):sub(1, w - 1) .. (isOpened and openedSymbol or closedSymbol) local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), w, align):sub(1, w - 1) .. (isOpened and openedSymbol or closedSymbol)
self.parent:writeText(obx, oby, text, self.bgColor, self.fgColor) self:addBlit(1, 1, text, tHex[fgCol]:rep(#text), tHex[bgCol]:rep(#text))
if (isOpened) then if (isOpened) then
for n = 1, dropdownH do self:addTextBox(1, 2, dropdownW, dropdownH, " ")
if (list[n + yOffset] ~= nil) then self:addBackgroundBox(1, 2, dropdownW, dropdownH, bgCol)
if (list[n + yOffset] == val) then self:addForegroundBox(1, 2, dropdownW, dropdownH, fgCol)
if (selectionColorActive) then for n = 1, dropdownH do
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG) if (list[n + yOffset] ~= nil) then
else local t =utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align)
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) if (list[n + yOffset] == val) then
end if (selectionColorActive) then
local itemSelectedBG, itemSelectedFG = self:getSelectionColor()
self:addBlit(1, n+1, t, tHex[itemSelectedFG]:rep(#t), tHex[itemSelectedBG]:rep(#t))
else else
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol) self:addBlit(1, n+1, t, tHex[list[n + yOffset].fgCol]:rep(#t), tHex[list[n + yOffset].bgCol]:rep(#t))
end end
else
self:addBlit(1, n+1, t, tHex[list[n + yOffset].fgCol]:rep(#t), tHex[list[n + yOffset].bgCol]:rep(#t))
end end
end end
end end
end end
end end)
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("DropdownBG")
self.fgColor = self.parent:getTheme("DropdownText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

114
Basalt/objects/Flexbox.lua Normal file
View File

@@ -0,0 +1,114 @@
return function(name, basalt)
local base = basalt.getObject("Frame")(name, basalt)
local objectType = "Flexbox"
local flexDirection = "row" -- "row" or "column"
local justifyContent = "flex-start" -- "flex-start", "flex-end", "center", "space-between", "space-around"
local alignItems = "flex-start" -- "flex-start", "flex-end", "center", "space-between", "space-around"
local spacing = 1
local function getObjectOffAxisOffset(self, obj)
local width, height = self:getSize()
local objWidth, objHeight = obj.element:getSize()
local availableSpace = flexDirection == "row" and height - objHeight or width - objWidth
local offset = 1
if alignItems == "center" then
offset = 1 + availableSpace / 2
elseif alignItems == "flex-end" then
offset = 1 + availableSpace
end
return offset
end
local function applyLayout(self)
local objects = self:getObjects()
local totalElements = #objects
local width, height = self:getSize()
local mainAxisTotalChildSize = 0
for _, obj in ipairs(objects) do
local objWidth, objHeight = obj.element:getSize()
if flexDirection == "row" then
mainAxisTotalChildSize = mainAxisTotalChildSize + objWidth
else
mainAxisTotalChildSize = mainAxisTotalChildSize + objHeight
end
end
local mainAxisAvailableSpace = (flexDirection == "row" and width or height) - mainAxisTotalChildSize - (spacing * (totalElements - 1))
local justifyContentOffset = 1
if justifyContent == "center" then
justifyContentOffset = 1 + mainAxisAvailableSpace / 2
elseif justifyContent == "flex-end" then
justifyContentOffset = 1 + mainAxisvailableSpace
end
for _, obj in ipairs(objects) do
local alignItemsOffset = getObjectOffAxisOffset(self, obj)
if flexDirection == "row" then
obj.element:setPosition(justifyContentOffset, alignItemsOffset)
local objWidth, _ = obj.element:getSize()
justifyContentOffset = justifyContentOffset + objWidth + spacing
else
obj.element:setPosition(alignItemsOffset, math.floor(justifyContentOffset+0.5))
local _, objHeight = obj.element:getSize()
justifyContentOffset = justifyContentOffset + objHeight + spacing
end
end
end
local object = {
getType = function()
return objectType
end,
isType = function(self, t)
return objectType == t or base.getBase(self).isType(t) or false
end,
setSpacing = function(self, newSpacing)
spacing = newSpacing
applyLayout(self)
return self
end,
getSpacing = function(self)
return spacing
end,
setFlexDirection = function(self, direction)
if direction == "row" or direction == "column" then
flexDirection = direction
applyLayout(self)
end
return self
end,
setJustifyContent = function(self, alignment)
if alignment == "flex-start" or alignment == "flex-end" or alignment == "center" or alignment == "space-between" or alignment == "space-around" then
justifyContent = alignment
applyLayout(self)
end
return self
end,
setAlignItems = function(self, alignment)
if alignment == "flex-start" or alignment == "flex-end" or alignment == "center" or alignment == "space-between" or alignment == "space-around" then
alignItems = alignment
applyLayout(self)
end
return self
end,
}
for k,v in pairs(basalt.getObjects())do
object["add"..k] = function(self, name)
local obj = base["add"..k](self, name)
applyLayout(base)
return obj
end
end
object.__index = object
return setmetatable(object, base)
end

117
Basalt/objects/Frame.lua Normal file
View File

@@ -0,0 +1,117 @@
local utils = require("utils")
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"
local parent
local updateRender = true
local xOffset, yOffset = 0, 0
base:setSize(30, 10)
base:setZIndex(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,
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,
setParent = function(self, p, ...)
base.setParent(self, p, ...)
parent = p
return self
end,
render = function(self)
if(base.render~=nil)then
if(self:isVisible())then
base.render(self)
local objects = self:getObjects()
for _, obj in ipairs(objects) do
if (obj.element.render ~= nil) then
obj.element:render()
end
end
end
end
end,
updateDraw = function(self)
if(parent~=nil)then
parent:updateDraw()
end
return self
end,
blit = function (self, x, y, t, f, b)
local obx, oby = self:getPosition()
local xO, yO = parent:getOffset()
obx = obx - xO
oby = oby - yO
local w, h = self:getSize()
if y >= 1 and y <= h then
local t_visible = sub(t, max(1 - x + 1, 1), max(w - x + 1, 1))
local f_visible = sub(f, max(1 - x + 1, 1), max(w - x + 1, 1))
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,
setCursor = function(self, blink, x, y, color)
local obx, oby = self:getPosition()
local xO, yO = self:getOffset()
parent:setCursor(blink or false, (x or 0)+obx-1 - xO, (y or 0)+oby-1 - yO, color or colors.white)
return self
end,
}
for k,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()
obx = obx - xO
oby = oby - yO
height = (y < 1 and (height + y > self:getHeight() and self:getHeight() or height + y - 1) or (height + y > self:getHeight() and self:getHeight() - y + 1 or height))
width = (x < 1 and (width + x > self:getWidth() and self:getWidth() or width + x - 1) or (width + x > self:getWidth() and self:getWidth() - x + 1 or width))
parent[v](parent, max(x + (obx - 1), obx), max(y + (oby - 1), oby), width, height, symbol)
end
end
for k,v in pairs({"setBG", "setFG", "setText"})do
object[v] = function(self, x, y, str)
local obx, oby = self:getPosition()
local xO, yO = parent:getOffset()
obx = obx - xO
oby = oby - yO
local w, h = self:getSize()
if (y >= 1) and (y <= h) then
parent[v](parent, max(x + (obx - 1), obx), oby + y - 1, sub(str, max(1 - x + 1, 1), max(w - x + 1,1)))
end
end
end
object.__index = object
return setmetatable(object, base)
end

159
Basalt/objects/Graph.lua Normal file
View File

@@ -0,0 +1,159 @@
return function(name, basalt)
local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Graph"
base:setZIndex(5)
base:setSize(30, 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,
getGraphSymbol = function(self)
return graphSymbol, graphSymbolCol
end,
addDataPoint = function(self, value)
if value >= minValue and value <= maxValue then
table.insert(graphData, value)
self:updateDraw()
end
if(#graphData>100)then -- 100 is hard capped to prevent memory leaks
table.remove(graphData,1)
end
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,
setMaxEntries = function(self, value)
maxEntries = value
self:updateDraw()
return self
end,
getMaxEntries = function(self)
return maxEntries
end,
clear = function(self)
graphData = {}
self:updateDraw()
return self
end,
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 range = maxValue - minValue
local prev_x, prev_y
local startIndex = #graphData - maxEntries + 1
if startIndex < 1 then startIndex = 1 end
for i = startIndex, #graphData do
local data = graphData[i]
local x = math.floor(((w - 1) / (maxEntries - 1)) * (i - startIndex) + 1.5)
local y = math.floor((h - 1) - ((h - 1) / range) * (data - minValue) + 1.5)
if graphType == "scatter" then
self:addBackgroundBox(x, y, 1, 1, graphColor)
self:addForegroundBox(x, y, 1, 1, graphSymbolCol)
self:addTextBox(x, y, 1, 1, graphSymbol)
elseif graphType == "line" then
if prev_x and prev_y then
local dx = math.abs(x - prev_x)
local dy = math.abs(y - prev_y)
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
end
end
end
prev_x, prev_y = x, y
elseif graphType == "bar" then
self:addBackgroundBox(x - 1, y, 1, h - y, graphColor)
end
end
end)
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,214 +0,0 @@
local Object = require("Object")
local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
local bimgLib = require("bimg")
local images = require("images")
local sub,len,max,min = string.sub,string.len,math.max,math.min
return function(name)
-- Graphic
local base = Object(name)
local objectType = "Graphic"
local imgData = bimgLib()
local bimgFrame = imgData.getFrameObject(1)
local bimg
local selectedFrame = 1
base:setZIndex(5)
local xOffset, yOffset = 0, 0
local object = {
getType = function(self)
return objectType
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,
getOffset = function(self)
return xOffset,yOffset
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
return self
end,
selectFrame = function(self, id)
if(imgData.getFrameObject(id)==nil)then
imgData.addFrame(id)
end
bimgFrame = imgData.getFrameObject(id)
bimg = bimgFrame.getImage(id)
selectedFrame = id
self:updateDraw()
end,
addFrame = function(self, id)
imgData.addFrame(id)
return self
end,
getFrameMetadata = function(self, id, key)
return imgData.getFrameData(id, key)
end,
setFrameMetadata = function(self, id, key, val)
imgData.setFrameData(id, key, val)
return self
end,
getMetadata = function(self, key)
return imgData.getMetadata(key)
end,
setMetadata = function(self, key, value)
return imgData.setMetadata(key, value)
end,
getFrame = function(self, id)
return imgData.getFrame(id)
end,
getFrameObject = function(self, id)
return imgData.getFrameObject(id)
end,
removeFrame = function(self, id)
imgData.removeFrame(id)
return self
end,
moveFrame = function(self, id, dir)
imgData.moveFrame(id, dir)
return self
end,
getFrames = function(self)
return imgData.getFrames()
end,
getFrameCount = function(self)
return #imgData.getFrames()
end,
getSelectedFrame = function(self)
return selectedFrame
end,
blit = function(self, text, fg, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.blit(text, fg, bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setText = function(self, text, _x, _y)
x = _x or x
y = _y or y
bimgFrame.text(text, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setBg = function(self, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.bg(bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setFg = function(self, fg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.fg(fg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
getImageSize = function(self)
return imgData.getSize()
end,
setImageSize = function(self, w, h)
imgData.setSize(w, h)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
resizeImage = function(self, w, h)
local newBimg = images.resizeBIMG(imgData.createBimg(), w, h)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
loadImage = function(self, path)
if(fs.exists(path))then
local newBimg = images.loadBIMG(path)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
end
return self
end,
clear = function(self)
imgData = bimgLib()
bimg = nil
self:updateDraw()
return self
end,
getImage = function(self)
return imgData.createBimg()
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(bimg~=nil)then
for k,v in pairs(bimg)do
if(k<=h-yOffset)and(k+yOffset>=1)then
self.parent:blit(obx+xOffset, oby+k-1+yOffset, v[1], v[2], v[3])
end
end
end
end
end
end,
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("GraphicBG")
end
end,
}
return setmetatable(object, base)
end

View File

@@ -1,115 +1,212 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
local images = require("images") local images = require("images")
local bimg = require("bimg")
local unpack,sub = table.unpack,string.sub local unpack,sub,max,min = table.unpack,string.sub,math.max,math.min
return function(name) return function(name, basalt)
-- Image -- Image
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Image" local objectType = "Image"
base:setZIndex(2)
local bimgLibrary = bimg()
local bimgFrame = bimgLibrary.getFrameObject(1)
local originalImage local originalImage
local image local image
local curFrame = 1 local activeFrame = 1
local infinitePlay = false local infinitePlay = false
local animTimer local animTimer
local usePalette = false local usePalette = false
local autoSize = true
base.width = 24 local xOffset, yOffset = 0, 0
base.height = 8
base:setSize(24, 8)
base:setZIndex(2)
local function getPalette(id) local function getPalette(id)
if(originalImage~=nil)then local p = {}
local p = {} for k,v in pairs(colors)do
for k,v in pairs(colors)do if(type(v)=="number")then
if(type(v)=="number")then p[k] = {term.nativePaletteColor(v)}
p[k] = {term.nativePaletteColor(v)}
end
end end
if(originalImage.palette~=nil)then end
for k,v in pairs(originalImage.palette)do local globalPalette = bimgLibrary.getMetadata("palette")
p[k] = tonumber(v) if(globalPalette~=nil)then
end for k,v in pairs(globalPalette)do
p[k] = tonumber(v)
end end
if(originalImage[id]~=nil)and(originalImage[id].palette~=nil)then end
for k,v in pairs(originalImage[id].palette)do local localPalette = bimgLibrary.getFrameData("palette")
p[k] = tonumber(v) basalt.log(localPalette)
end if(localPalette~=nil)then
for k,v in pairs(localPalette)do
p[k] = tonumber(v)
end
end
return p
end
local function checkAutoSize()
if(autoSize)then
if(bimgLibrary~=nil)then
base:setSize(bimgLibrary.getSize())
end end
return p
end end
end end
local object = { local object = {
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ImageBG")
end
end,
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
isType = function(self, t)
return objectType==t or base.isType~=nil and base.isType(t) or false
end,
loadImage = function(self, path, f) setOffset = function(self, _x, _y, rel)
if not(fs.exists(path))then error("No valid path: "..path) end if(rel)then
originalImage = images.loadImageAsBimg(path, f) xOffset = xOffset + _x or 0
curFrame = 1 yOffset = yOffset + _y or 0
image = originalImage else
if(animTimer~=nil)then xOffset = _x or xOffset
os.cancelTimer(animTimer) yOffset = _y or yOffset
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
setImage = function(self, data) setSize = function(self, _x, _y)
originalImage = data base:setSize(_x, _y)
image = originalImage autoSize = false
curFrame = 1 return self
if(animTimer~=nil)then end,
os.cancelTimer(animTimer)
getOffset = function(self)
return xOffset, yOffset
end,
selectFrame = function(self, id)
if(bimgLibrary.getFrameObject(id)==nil)then
bimgLibrary.addFrame(id)
end end
bimgFrame = bimgLibrary.getFrameObject(id)
image = bimgFrame.getImage(id)
activeFrame = id
self:updateDraw()
end,
addFrame = function(self, id)
bimgLibrary.addFrame(id)
return self
end,
getFrame = function(self, id)
return bimgLibrary.getFrame(id)
end,
getFrameObject = function(self, id)
return bimgLibrary.getFrameObject(id)
end,
removeFrame = function(self, id)
bimgLibrary.removeFrame(id)
return self
end,
moveFrame = function(self, id, dir)
bimgLibrary.moveFrame(id, dir)
return self
end,
getFrames = function(self)
return bimgLibrary.getFrames()
end,
getFrameCount = function(self)
return #bimgLibrary.getFrames()
end,
getActiveFrame = function(self)
return activeFrame
end,
loadImage = function(self, path)
if(fs.exists(path))then
local newBimg = images.loadBIMG(path)
bimgLibrary = bimg(newBimg)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
originalImage = bimgLibrary.createBimg()
image = bimgFrame.getImage()
checkAutoSize()
self:updateDraw()
end
return self
end,
setImage = function(self, t)
if(type(t)=="table")then
bimgLibrary = bimg(t)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
originalImage = bimgLibrary.createBimg()
image = bimgFrame.getImage()
checkAutoSize()
self:updateDraw()
end
return self
end,
clear = function(self)
bimgLibrary = bimg()
bimgFrame = bimgLibrary.getFrameObject(1)
image = nil
self:updateDraw() self:updateDraw()
return self return self
end, end,
getImage = function(self)
return bimgLibrary.createBimg()
end,
getImageFrame = function(self, id)
return bimgFrame.getImage(id)
end,
usePalette = function(self, use) usePalette = function(self, use)
usePalette = use~=nil and use or true usePalette = use~=nil and use or true
return self return self
end, end,
play = function(self, inf) play = function(self, inf)
if(originalImage.animated)then if(bimgLibrary.getMetadata("animated"))then
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2 local t = bimgLibrary.getMetadata("duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
animTimer = os.startTimer(t) animTimer = os.startTimer(t)
infinitePlay = inf or false infinitePlay = inf or false
end end
return self return self
end, end,
selectFrame = function(self, fr) stop = function(self)
if(originalImage[fr]~=nil)then os.cancelTimer(animTimer)
curFrame = fr animTimer = nil
if(animTimer~=nil)then infinitePlay = false
os.cancelTimer(animTimer) return self
end
self:updateDraw()
end
end, end,
eventHandler = function(self, event, timerId, ...) eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...) base.eventHandler(self, event, timerId, ...)
if(event=="timer")then if(event=="timer")then
if(timerId==animTimer)then if(timerId==animTimer)then
if(originalImage[curFrame+1]~=nil)then if(bimgLibrary.getFrame(activeFrame+1)~=nil)then
curFrame = curFrame + 1 activeFrame = activeFrame + 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2 self:selectFrame(activeFrame)
local t = bimgLibrary.getFrameData(activeFrame, "duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
animTimer = os.startTimer(t) animTimer = os.startTimer(t)
else else
if(infinitePlay)then if(infinitePlay)then
curFrame = 1 activeFrame = 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2 self:selectFrame(activeFrame)
local t = bimgLibrary.getFrameData(activeFrame, "duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
animTimer = os.startTimer(t) animTimer = os.startTimer(t)
end end
end end
@@ -118,46 +215,117 @@ return function(name)
end end
end, end,
setMetadata = function(self, key, value)
bimgLibrary.setMetadata(key, value)
return self
end,
getMetadata = function(self, key) getMetadata = function(self, key)
return originalImage[key] return bimgLibrary.getMetadata(key)
end, end,
getImageSize = function(self) getFrameMetadata = function(self, id, key)
return originalImage.width, originalImage.height return bimgLibrary.getFrameData(id, key)
end, end,
resizeImage = function(self, w, h) setFrameMetadata = function(self, id, key, value)
image = images.resizeBIMG(originalImage, w, h) bimgLibrary.setFrameData(id, key, value)
return self
end,
blit = function(self, text, fg, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.blit(text, fg, bg, x, y)
image = bimgFrame.getImage()
self:updateDraw() self:updateDraw()
return self return self
end, end,
setValuesByXMLData = function(self, data) setText = function(self, text, _x, _y)
base.setValuesByXMLData(self, data) x = _x or x
if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end y = _y or y
bimgFrame.text(text, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
setBg = function(self, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.bg(bg, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
setFg = function(self, fg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.fg(fg, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
getImageSize = function(self)
return bimgLibrary.getSize()
end,
setImageSize = function(self, w, h)
bimgLibrary.setSize(w, h)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
resizeImage = function(self, w, h)
local newBimg = images.resizeBIMG(originalImage, w, h)
bimgLibrary = bimg(newBimg)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
image = bimgFrame.getImage()
self:updateDraw()
return self return self
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (image ~= nil) then self:addDraw("image", function()
if(usePalette)then local w,h = self:getSize()
self:getBaseFrame():setThemeColor(getPalette(curFrame)) local x, y = self:getPosition()
end local wParent, hParent = self:getParent():getSize()
local obx, oby = self:getAnchorPosition() local parentXOffset, parentYOffset = self:getParent():getOffset()
local w,h = self:getSize()
for y,v in ipairs(image[curFrame])do if(x - parentXOffset > wParent)or(y - parentYOffset > hParent)or(x - parentXOffset + w < 1)or(y - parentYOffset + h < 1)then
local t, f, b = unpack(v) return
t = sub(t, 1,w) end
f = sub(f, 1,w)
b = sub(b, 1,w) if(usePalette)then
self.parent:blit(obx, oby+y-1, t, f, b) self:getParent():setPalette(getPalette(activeFrame))
if(y==h)then break end end
if(image~=nil)then
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]
local startIdx = max(1 - xOffset, 1)
local endIdx = min(w - xOffset, #t)
t = sub(t, startIdx, endIdx)
f = sub(f, startIdx, endIdx)
b = sub(b, startIdx, endIdx)
self:addBlit(max(1 + xOffset, 1), k + yOffset, t, f, b)
end
end end
end end
end end)
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,46 +1,46 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local log = require("basaltLogs") local tHex = require("tHex")
local xmlValue = utils.getValueFromXML
return function(name) return function(name, basalt)
-- Input -- Input
local base = Object(name) local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Input" local objectType = "Input"
local inputType = "text" local inputType = "text"
local inputLimit = 0 local inputLimit = 0
base:setZIndex(5) base:setZIndex(5)
base:setValue("") base:setValue("")
base.width = 10 base:setSize(12, 1)
base.height = 1
local textX = 1 local textX = 1
local wIndex = 1 local wIndex = 1
local defaultText = "" local defaultText = ""
local defaultBGCol local defaultBGCol = colors.black
local defaultFGCol local defaultFGCol = colors.lightGray
local showingText = defaultText local showingText = defaultText
local internalValueChange = false local internalValueChange = false
local object = { local object = {
load = function(self)
self:listenEvent("mouse_click")
self:listenEvent("key")
self:listenEvent("char")
self:listenEvent("other_event")
self:listenEvent("mouse_drag")
end,
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
isType = function(self, t)
setInputType = function(self, iType) return objectType==t or base.isType~=nil and base.isType(t) or false
if (iType == "password") or (iType == "number") or (iType == "text") then end,
inputType = iType
end
self:updateDraw()
return self
end;
setDefaultText = function(self, text, fCol, bCol) setDefaultText = function(self, text, fCol, bCol)
defaultText = text defaultText = text
defaultBGCol = bCol or defaultBGCol
defaultFGCol = fCol or defaultFGCol defaultFGCol = fCol or defaultFGCol
defaultBGCol = bCol or defaultBGCol
if (self:isFocused()) then if (self:isFocused()) then
showingText = "" showingText = ""
else else
@@ -48,11 +48,41 @@ return function(name)
end end
self:updateDraw() self:updateDraw()
return self return self
end; 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) getInputType = function(self)
return inputType return inputType
end; end,
setValue = function(self, val) setValue = function(self, val)
base.setValue(self, tostring(val)) base.setValue(self, tostring(val))
@@ -60,105 +90,84 @@ return function(name)
textX = tostring(val):len() + 1 textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1) wIndex = math.max(1, textX-self:getWidth()+1)
if(self:isFocused())then if(self:isFocused())then
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor) local obx, oby = self:getPosition()
parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self:getForeground())
end end
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
getValue = function(self) getValue = function(self)
local val = base.getValue(self) local val = base.getValue(self)
return inputType == "number" and tonumber(val) or val return inputType == "number" and tonumber(val) or val
end; end,
setInputLimit = function(self, limit) setInputLimit = function(self, limit)
inputLimit = tonumber(limit) or inputLimit inputLimit = tonumber(limit) or inputLimit
self:updateDraw() self:updateDraw()
return self return self
end; end,
getInputLimit = function(self) getInputLimit = function(self)
return inputLimit return inputLimit
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
local dBG,dFG
if(xmlValue("defaultBG", data)~=nil)then dBG = xmlValue("defaultBG", data) end
if(xmlValue("defaultFG", data)~=nil)then dFG = xmlValue("defaultFG", data) end
if(xmlValue("default", data)~=nil)then self:setDefaultText(xmlValue("default", data), dFG~=nil and colors[dFG], dBG~=nil and colors[dBG]) end
if(xmlValue("limit", data)~=nil)then self:setInputLimit(xmlValue("limit", data)) end
if(xmlValue("type", data)~=nil)then self:setInputType(xmlValue("type", data)) end
return self
end, end,
getFocusHandler = function(self) getFocusHandler = function(self)
base.getFocusHandler(self) base.getFocusHandler(self)
if (self.parent ~= nil) then local parent = self:getParent()
local obx, oby = self:getAnchorPosition() if (parent ~= nil) then
local obx, oby = self:getPosition()
showingText = "" showingText = ""
if(defaultText~="")then if(defaultText~="")then
self:updateDraw() self:updateDraw()
end end
self.parent:setCursor(true, obx + textX - wIndex, oby+math.max(math.ceil(self:getHeight()/2-1, 1)), self.fgColor) parent:setCursor(true, obx + textX - wIndex, oby+math.max(math.ceil(self:getHeight()/2-1, 1)), self:getForeground())
end end
end; end,
loseFocusHandler = function(self) loseFocusHandler = function(self)
base.loseFocusHandler(self) base.loseFocusHandler(self)
if (self.parent ~= nil) then local parent = self:getParent()
showingText = defaultText showingText = defaultText
if(defaultText~="")then if(defaultText~="")then
self:updateDraw() self:updateDraw()
end
self.parent:setCursor(false)
end end
end; parent:setCursor(false)
end,
keyHandler = function(self, key) keyHandler = function(self, key)
if (base.keyHandler(self, key)) then if (base.keyHandler(self, key)) then
local w,h = self:getSize() local w,h = self:getSize()
local parent = self:getParent()
internalValueChange = true internalValueChange = true
if (key == keys.backspace) then if (key == keys.backspace) then
-- on backspace -- on backspace
local text = tostring(base.getValue()) local text = tostring(base.getValue())
if (textX > 1) then if (textX > 1) then
self:setValue(text:sub(1, textX - 2) .. text:sub(textX, text:len())) self:setValue(text:sub(1, textX - 2) .. text:sub(textX, text:len()))
if (textX > 1) then textX = math.max(textX - 1, 1)
textX = textX - 1 if (textX < wIndex) then
end wIndex = math.max(wIndex - 1, 1)
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
end
end end
end end
end end
if (key == keys.enter) then if (key == keys.enter) then
-- on enter parent:removeFocusedObject(self)
if (self.parent ~= nil) then
--self.parent:removeFocusedObject(self)
end
end end
if (key == keys.right) then if (key == keys.right) then
-- right arrow
local tLength = tostring(base.getValue()):len() local tLength = tostring(base.getValue()):len()
textX = textX + 1 textX = textX + 1
if (textX > tLength) then if (textX > tLength) then
textX = tLength + 1 textX = tLength + 1
end end
if (textX < 1) then textX = math.max(textX, 1)
textX = 1
end
if (textX < wIndex) or (textX >= w + wIndex) then if (textX < wIndex) or (textX >= w + wIndex) then
wIndex = textX - w + 1 wIndex = textX - w + 1
end end
if (wIndex < 1) then wIndex = math.max(wIndex, 1)
wIndex = 1
end
end end
if (key == keys.left) then if (key == keys.left) then
@@ -169,29 +178,16 @@ return function(name)
wIndex = textX wIndex = textX
end end
end end
if (textX < 1) then textX = math.max(textX, 1)
textX = 1 wIndex = math.max(wIndex, 1)
end
if (wIndex < 1) then
wIndex = 1
end
end end
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local val = tostring(base.getValue()) local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local inpX = self:getX()
if (cursorX > inpX + w - 1) then
cursorX = inpX + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw() self:updateDraw()
internalValueChange = false internalValueChange = false
return true return true
end end
return false
end, end,
charHandler = function(self, char) charHandler = function(self, char)
@@ -220,27 +216,19 @@ return function(name)
wIndex = wIndex + 1 wIndex = wIndex + 1
end end
end end
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local val = tostring(base.getValue()) local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
internalValueChange = false internalValueChange = false
self:updateDraw() self:updateDraw()
return true return true
end end
return false
end, end,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if(base.mouseHandler(self, button, x, y))then if(base.mouseHandler(self, button, x, y))then
local ax, ay = self:getAnchorPosition() local parent = self:getParent()
local ax, ay = self:getPosition()
local obx, oby = self:getAbsolutePosition(ax, ay) local obx, oby = self:getAbsolutePosition(ax, ay)
local w, h = self:getSize() local w, h = self:getSize()
textX = x - obx + wIndex textX = x - obx + wIndex
@@ -254,7 +242,7 @@ return function(name)
wIndex = 1 wIndex = 1
end end
end end
self.parent:setCursor(true, ax + textX - wIndex, ay+math.max(math.ceil(h/2-1, 1)), self.fgColor) parent:setCursor(true, ax + textX - wIndex, ay+math.max(math.ceil(h/2-1, 1)), self:getForeground())
return true return true
end end
end, end,
@@ -266,108 +254,51 @@ return function(name)
return true return true
end end
end end
self.parent:removeFocusedObject() local parent = self:getParent()
end parent:removeFocusedObject()
end,
eventHandler = function(self, event, paste, ...)
base.eventHandler(self, event, paste, ...)
if(event=="paste")then
if(self:isFocused())then
local text = base.getValue()
local w, h = self:getSize()
internalValueChange = true
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()))
textX = textX + paste:len()
end
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
else
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw()
internalValueChange = false
end
end end
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("input", function()
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local w,h = self:getSize() local obx, oby = self:getPosition()
local verticalAlign = utils.getTextVerticalAlign(h, "center") local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local val = tostring(base.getValue())
for n = 1, h do local bCol = self:getBackground()
if (n == verticalAlign) then local fCol = self:getForeground()
local val = tostring(base.getValue()) local text
local bCol = self.bgColor if (val:len() <= 0) then
local fCol = self.fgColor text = showingText
local text bCol = defaultBGCol or bCol
if (val:len() <= 0) then fCol = defaultFGCol or fCol
text = showingText
bCol = defaultBGCol or bCol
fCol = defaultFGCol or fCol
end
text = showingText
if (val ~= "") then
text = val
end
text = text:sub(wIndex, w + wIndex - 1)
local space = w - text:len()
if (space < 0) then
space = 0
end
if (inputType == "password") and (val ~= "") then
text = string.rep("*", text:len())
end
text = text .. string.rep(self.bgSymbol, space)
self.parent:writeText(obx, oby + (n - 1), text, bCol, fCol)
end
end
if(self:isFocused())then
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor)
end
end end
end
end,
init = function(self) text = showingText
if(self.parent~=nil)then if (val ~= "") then
self.parent:addEvent("mouse_click", self) text = val
self.parent:addEvent("key", self) end
self.parent:addEvent("char", self) text = text:sub(wIndex, w + wIndex - 1)
self.parent:addEvent("other_event", self) local space = w - text:len()
self.parent:addEvent("mouse_drag", self) if (space < 0) then
end space = 0
if(base.init(self))then end
self.bgColor = self.parent:getTheme("InputBG") if (inputType == "password") and (val ~= "") then
self.fgColor = self.parent:getTheme("InputText") text = string.rep("*", text:len())
end end
text = text .. string.rep(" ", space)
self:addBlit(1, verticalAlign, text, tHex[fCol]:rep(text:len()), tHex[bCol]:rep(text:len()))
if(self:isFocused())then
parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self:getForeground())
end
end)
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,170 +1,109 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML local wrapText = utils.wrapText
local createText = utils.createText local writeWrappedText = utils.writeWrappedText
local tHex = require("tHex") local tHex = require("tHex")
local bigFont = require("bigfont")
return function(name) return function(name, basalt)
-- Label -- Label
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Label" local objectType = "Label"
base:setZIndex(3) base:setZIndex(3)
base:setSize(5, 1)
base:setBackground(false)
local autoSize = true local autoSize = true
base:setValue("Label") local text, textAlign = "Label", "left"
base.width = 5
local textHorizontalAlign = "left"
local textVerticalAlign = "top"
local fontsize = 0
local fgColChanged,bgColChanged = false,false
local object = { local object = {
--- Returns the object type.
--- @return string
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
setText = function(self, text) --- Returns the label's base object.
text = tostring(text) --- @return object
base:setValue(text) getBase = function(self)
if (autoSize) then return base
local xOffset = self.parent:getOffset() end,
if(text:len()+self:getX()>self.parent:getWidth()+xOffset)then
local newW = self.parent:getWidth()+xOffset - self:getX() --- Changes the label's text.
base.setSize(self, newW, #createText(text, newW)) --- @param newText string The new text of the label.
else --- @return object
base.setSize(self, text:len(), 1) 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 end
self:setSize(newW, newH)
autoSize = true
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
setBackground = function(self, col) --- Returns the label's autoSize property.
base.setBackground(self, col) --- @return boolean
bgColChanged = true getAutoSize = function(self)
self:updateDraw() 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 return self
end, end,
setForeground = function(self, col) --- Returns the label's text.
base.setForeground(self, col) --- @return string
fgColChanged = true getText = function(self)
self:updateDraw() return text
return self
end, end,
setTextAlign = function(self, hor, vert) --- Sets the size of the label.
textHorizontalAlign = hor or textHorizontalAlign --- @param width number The width of the label.
textVerticalAlign = vert or textVerticalAlign --- @param height number The height of the label.
self:updateDraw() --- @return object
return self setSize = function(self, width, height)
end; base.setSize(self, width, height)
setFontSize = function(self, size)
if(size>0)and(size<=4)then
fontsize = size-1 or 0
end
self:updateDraw()
return self
end;
getFontSize = function(self)
return fontsize+1
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end
if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end
if(xmlValue("font", data)~=nil)then self:setFontSize(xmlValue("font", data)) end
return self
end,
setSize = function(self, width, height, rel)
base.setSize(self, width, height, rel)
autoSize = false autoSize = false
self:updateDraw()
return self return self
end;
eventHandler = function(self, event)
if(event=="basalt_resize")then
if (autoSize) then
local text = self:getValue()
if(text:len()+self:getX()>self.parent:getWidth())then
local newW = self.parent:getWidth() - self:getX()
base.setSize(self, newW, #createText(text, newW))
else
base.setSize(self, text:len(), 1)
end
else
--self.parent:removeEvent("other_event", self)
end
end
end, 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) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("label", function()
local obx, oby = self:getAnchorPosition() local w, h = self:getSize()
local w,h = self:getSize() local align = textAlign=="center" and math.floor(w/2-text:len()/2+0.5) or textAlign=="right" and w-(text:len()-1) or 1
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) writeWrappedText(self, align, 1, text, w, h)
if(fontsize==0)then end)
if not(autoSize)then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
if(#self:getValue()+obx>self.parent:getWidth())then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
self.parent:writeText(obx, oby, self:getValue(), self.bgColor, self.fgColor)
end
end
else
local tData = bigFont(fontsize, self:getValue(), self.fgColor, self.bgColor or colors.lightGray)
if(autoSize)then
self:setSize(#tData[1][1], #tData[1]-1)
end
local oX, oY = self.parent:getSize()
local cX, cY = #tData[1][1], #tData[1]
obx = obx or math.floor((oX - cX) / 2) + 1
oby = oby or math.floor((oY - cY) / 2) + 1
for i = 1, cY do
self.parent:setFG(obx, oby + i - 1, tData[2][i])
self.parent:setBG(obx, oby + i - 1, tData[3][i])
self.parent:setText(obx, oby + i - 1, tData[1][i])
end
end
end
end
end, end,
--- Initializes the label.
init = function(self) init = function(self)
self.parent:addEvent("other_event", self) base.init(self)
if(base.init(self))then local parent = self:getParent()
self.bgColor = self.parent:getTheme("LabelBG") self:setForeground(parent:getForeground())
self.fgColor = self.parent:getTheme("LabelText")
if(self.parent.bgColor==colors.black)and(self.fgColor==colors.black)then
self.fgColor = colors.lightGray
end
end
end end
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,59 +1,105 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML local tHex = require("tHex")
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "List" local objectType = "List"
base.width = 16
base.height = 6
base:setZIndex(5)
local list = {} local list = {}
local itemSelectedBG local itemSelectedBG = colors.black
local itemSelectedFG local itemSelectedFG = colors.lightGray
local selectionColorActive = true local selectionColorActive = true
local align = "left" local textAlign = "left"
local yOffset = 0 local yOffset = 0
local scrollable = true local scrollable = true
base:setSize(16, 8)
base:setZIndex(5)
local object = { local 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,
getBase = function(self)
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) getType = function(self)
return objectType return objectType
end; 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, ...) addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) table.insert(list, { text = text, bgCol = bgCol or self:getBackground(), fgCol = fgCol or self:getForeground(), args = { ... } })
if (#list <= 1) then if (#list <= 1) then
self:setValue(list[1], false) self:setValue(list[1], false)
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
setOptions = function(self, ...)
list = {}
for k,v in pairs(...)do
if(type(v)=="string")then
table.insert(list, { text = v, bgCol = self:getBackground(), fgCol = self:getForeground(), args = {} })
else
table.insert(list, { text = v[1], bgCol = v[2] or self:getBackground(), fgCol = v[3] or self:getForeground(), args = v[4] or {} })
end
end
self:setValue(list[1], false)
self:updateDraw()
return self
end,
setOffset = function(self, yOff) setOffset = function(self, yOff)
yOffset = yOff yOffset = yOff
self:updateDraw() self:updateDraw()
return self return self
end; end,
getOffset = function(self) getOffset = function(self)
return yOffset return yOffset
end; end,
removeItem = function(self, index) removeItem = function(self, index)
table.remove(list, index) table.remove(list, index)
self:updateDraw() self:updateDraw()
return self return self
end; end,
getItem = function(self, index) getItem = function(self, index)
return list[index] return list[index]
end; end,
getAll = function(self) getAll = function(self)
return list return list
end; end,
getOptions = function(self)
return list
end,
getItemIndex = function(self) getItemIndex = function(self)
local selected = self:getValue() local selected = self:getValue()
@@ -62,61 +108,53 @@ return function(name)
return key return key
end end
end end
end; end,
clear = function(self) clear = function(self)
list = {} list = {}
self:setValue({}, false) self:setValue({}, false)
self:updateDraw() self:updateDraw()
return self return self
end; end,
getItemCount = function(self) getItemCount = function(self)
return #list return #list
end; end,
editItem = function(self, index, text, bgCol, fgCol, ...) editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index) table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) table.insert(list, index, { text = text, bgCol = bgCol or self:getBackground(), fgCol = fgCol or self:getForeground(), args = { ... } })
self:updateDraw() self:updateDraw()
return self return self
end; end,
selectItem = function(self, index) selectItem = function(self, index)
self:setValue(list[index] or {}, false) self:setValue(list[index] or {}, false)
self:updateDraw() self:updateDraw()
return self return self
end; end,
setSelectedItem = function(self, bgCol, fgCol, active) setSelectionColor = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor itemSelectedBG = bgCol or self:getBackground()
itemSelectedFG = fgCol or self.fgColor itemSelectedFG = fgCol or self:getForeground()
selectionColorActive = active~=nil and active or true selectionColorActive = active~=nil and active or true
self:updateDraw() self:updateDraw()
return self return self
end; end,
getSelectionColor = function(self)
return itemSelectedBG, itemSelectedFG
end,
isSelectionColorActive = function(self)
return selectionColorActive
end,
setScrollable = function(self, scroll) setScrollable = function(self, scroll)
scrollable = scroll scrollable = scroll
if(scroll==nil)then scrollable = true end if(scroll==nil)then scrollable = true end
self:updateDraw() self:updateDraw()
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end
if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end, end,
scrollHandler = function(self, dir, x, y) scrollHandler = function(self, dir, x, y)
@@ -148,7 +186,7 @@ return function(name)
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if(base.mouseHandler(self, button, x, y))then if(base.mouseHandler(self, button, x, y))then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
local w,h = self:getSize() local w,h = self:getSize()
if (#list > 0) then if (#list > 0) then
for n = 1, h do for n = 1, h do
@@ -174,42 +212,25 @@ return function(name)
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("list", function()
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local w,h = self:getSize() local obx, oby = self:getPosition()
if(self.bgColor~=false)then local w, h = self:getSize()
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) for n = 1, h do
end if list[n + yOffset] then
for n = 1, h do local t = list[n + yOffset].text
if (list[n + yOffset] ~= nil) then local fg, bg = list[n + yOffset].fgCol, list[n + yOffset].bgCol
if (list[n + yOffset] == self:getValue()) then if list[n + yOffset] == self:getValue() and selectionColorActive then
if (selectionColorActive) then fg, bg = itemSelectedFG, itemSelectedBG
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), itemSelectedBG, itemSelectedFG)
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
end end
self:addBlit(1, n, t, tHex[fg]:rep(#t), tHex[bg]:rep(#t))
end end
end end
end end)
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ListBG")
self.fgColor = self.parent:getTheme("ListText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,170 +1,69 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML
local tHex = require("tHex") local tHex = require("tHex")
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("List")(name, basalt)
local objectType = "Menubar" local objectType = "Menubar"
local object = {} local object = {}
base.width = 30 base:setSize(30, 1)
base.height = 1
base:setZIndex(5) base:setZIndex(5)
local list = {}
local itemSelectedBG
local itemSelectedFG
local selectionColorActive = true
local align = "left"
local itemOffset = 0 local itemOffset = 0
local space = 1 local space, outerSpace = 1, 1
local scrollable = false local scrollable = true
local function maxScroll() local function maxScroll()
local mScroll = 0 local mScroll = 0
local xPos = 0 local w = base:getWidth()
local w = object:getWidth() local list = base:getAll()
for n = 1, #list do for n = 1, #list do
if (xPos + list[n].text:len() + space * 2 > w) then mScroll = mScroll + list[n].text:len() + space * 2
if(xPos < w)then
mScroll = mScroll + (list[n].text:len() + space * 2-(w - xPos))
else
mScroll = mScroll + list[n].text:len() + space * 2
end
end
xPos = xPos + list[n].text:len() + space * 2
end end
return mScroll return math.max(mScroll - w, 0)
end end
object = { 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) getType = function(self)
return objectType return objectType
end; end,
addItem = function(self, text, bgCol, fgCol, ...) getBase = function(self)
table.insert(list, { text = tostring(text), bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) return base
if (#list == 1) then end,
self:setValue(list[1])
end
self:updateDraw()
return self
end;
getAll = function(self)
return list
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({}, false)
self:updateDraw()
return self
end;
setSpace = function(self, _space) setSpace = function(self, _space)
space = _space or space space = _space or space
self:updateDraw() self:updateDraw()
return self return self
end; end,
setOffset = function(self, offset)
itemOffset = offset or 0
if (itemOffset < 0) then
itemOffset = 0
end
local mScroll = maxScroll()
if (itemOffset > mScroll) then
itemOffset = mScroll
end
self:updateDraw()
return self
end;
getOffset = function(self)
return itemOffset
end;
setScrollable = function(self, scroll) setScrollable = function(self, scroll)
scrollable = scroll scrollable = scroll
if(scroll==nil)then scrollable = true end if(scroll==nil)then scrollable = true end
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("scrollable", data)~=nil)then if(xmlValue("scrollable", data))then self:setScrollable(true) else self:setScrollable(false) end end
if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end
if(xmlValue("space", data)~=nil)then space = xmlValue("space", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end, end,
removeItem = function(self, index)
table.remove(list, index)
self:updateDraw()
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
self:updateDraw()
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
self:updateDraw()
return self
end;
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if(base.mouseHandler(self, button, x, y))then if(base:getBase().mouseHandler(self, button, x, y))then
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition()) local objX, objY = self:getAbsolutePosition()
local w,h = self:getSize() local w,h = self:getSize()
local xPos = 0 local xPos = 0
local list = self:getAll()
for n = 1, #list do for n = 1, #list do
if (list[n] ~= nil) then 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 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:setValue(list[n])
self:getEventSystem():sendEvent(event, self, event, 0, x, y, list[n]) self:sendEvent(event, self, event, 0, x, y, list[n])
end end
xPos = xPos + list[n].text:len() + space * 2 xPos = xPos + list[n].text:len() + space * 2
end end
@@ -172,11 +71,10 @@ return function(name)
self:updateDraw() self:updateDraw()
return true return true
end end
return false
end, end,
scrollHandler = function(self, dir, x, y) scrollHandler = function(self, dir, x, y)
if(base.scrollHandler(self, dir, x, y))then if(base:getBase().scrollHandler(self, dir, x, y))then
if(scrollable)then if(scrollable)then
itemOffset = itemOffset + dir itemOffset = itemOffset + dir
if (itemOffset < 0) then if (itemOffset < 0) then
@@ -196,46 +94,31 @@ return function(name)
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("list", function()
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local w,h = self:getSize() local w,h = self:getSize()
if(self.bgColor~=false)then local text = ""
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) local textBGCol = ""
local textFGCol = ""
local itemSelectedBG, itemSelectedFG = self:getSelectionColor()
for _, v in pairs(self:getAll()) do
local newItem = (" "):rep(space) .. v.text .. (" "):rep(space)
text = text .. newItem
if(v == self:getValue())then
textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self:getBackground()]:rep(newItem:len())
textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self:getForeground()]:rep(newItem:len())
else
textBGCol = textBGCol .. tHex[v.bgCol or self:getBackground()]:rep(newItem:len())
textFGCol = textFGCol .. tHex[v.FgCol or self:getForeground()]:rep(newItem:len())
end end
local text = ""
local textBGCol = ""
local textFGCol = ""
for _, v in pairs(list) do
local newItem = (" "):rep(space) .. v.text .. (" "):rep(space)
text = text .. newItem
if(v == self:getValue())then
textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self.bgColor]:rep(newItem:len())
textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self.fgColor]:rep(newItem:len())
else
textBGCol = textBGCol .. tHex[v.bgCol or self.bgColor]:rep(newItem:len())
textFGCol = textFGCol .. tHex[v.FgCol or self.fgColor]:rep(newItem:len())
end
end
self.parent:setText(obx, oby, text:sub(itemOffset+1, w+itemOffset))
self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, w+itemOffset))
self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, w+itemOffset))
end end
end
end,
init = function(self) self:addBlit(1, 1, text:sub(itemOffset+1, w+itemOffset), textFGCol:sub(itemOffset+1, w+itemOffset), textBGCol:sub(itemOffset+1, w+itemOffset))
self.parent:addEvent("mouse_click", self) end)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -0,0 +1,81 @@
local basaltMon = require("basaltMon")
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: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,
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,
show = function(self)
base:getBase().show(self)
basalt.setActiveFrame(self)
for k,v in pairs(colors)do
if(type(v)=="number")then
termObject.setPaletteColor(v, colors.packRGB(term.nativePaletteColor((v))))
end
end
for k,v in pairs(colorTheme)do
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
return self
end,
}
object.mouseHandler = function(self, btn, x, y, isMon, monitor, ...)
if(isMonitorGroup)then
x, y = monGroup.calculateClick(monitor, x, y)
end
base.mouseHandler(self, btn, x, y, isMon, monitor, ...)
end
object.__index = object
return setmetatable(object, base)
end

View File

@@ -0,0 +1,92 @@
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"
local parent
local dragXOffset, dragYOffset = 0, 0
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,
getBase = function(self)
return base
end,
load = function(self)
base.load(self)
self:listenEvent("mouse_click")
self:listenEvent("mouse_up")
self:listenEvent("mouse_drag")
end,
dragHandler = function(self, btn, x, y)
if(base.dragHandler(self, btn, x, y))then
if (isDragging) then
local xO, yO = parent:getOffset()
xO = xO < 0 and math.abs(xO) or -xO
yO = yO < 0 and math.abs(yO) or -yO
local parentX = 1
local parentY = 1
parentX, parentY = parent:getAbsolutePosition()
self:setPosition(x + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO)
self:updateDraw()
end
return true
end
end,
mouseHandler = function(self, btn, x, y, ...)
if(base.mouseHandler(self, btn, x, y, ...))then
parent:setImportant(self)
local fx, fy = self:getAbsolutePosition()
local w, h = self:getSize()
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
isDragging = true
dragXOffset = fx - x
dragYOffset = fy - y
return true
end
end
return true
end
end,
mouseUpHandler = function(self, ...)
isDragging = false
return base.mouseUpHandler(self, ...)
end,
setParent = function(self, p, ...)
base.setParent(self, p, ...)
parent = p
return self
end,
}
object.__index = object
return setmetatable(object, base)
end

255
Basalt/objects/Object.lua Normal file
View File

@@ -0,0 +1,255 @@
local basaltEvent = require("basaltEvent")
local utils = require("utils")
local uuid = utils.uuid
local unpack,sub = table.unpack,string.sub
return function(name, basalt)
name = name or uuid()
assert(basalt~=nil, "Unable to find basalt instance! ID: "..name)
-- Base object
local objectType = "Object" -- not changeable
local isEnabled,initialized = true,false
local eventSystem = basaltEvent()
local activeEvents = {}
local parent
local object = {
init = function(self)
if(initialized)then return false end
initialized = true
return true
end,
load = function(self)
end,
getType = function(self)
return objectType
end,
isType = function(self, t)
return objectType==t
end,
getName = function(self)
return name
end,
getParent = function(self)
return parent
end,
setParent = function(self, newParent, noRemove)
if(noRemove)then parent = newParent return self end
if (newParent.getType ~= nil and newParent:isType("Container")) then
self:remove()
newParent:addObject(self)
if (self.show) then
self:show()
end
parent = newParent
end
return self
end,
updateEvents = function(self)
for k,v in pairs(activeEvents)do
parent:removeEvent(k, self)
if(v)then
parent:addEvent(k, self)
end
end
return self
end,
listenEvent = function(self, event, active)
if(parent~=nil)then
if(active)or(active==nil)then
activeEvents[event] = true
parent:addEvent(event, self)
elseif(active==false)then
activeEvents[event] = false
parent:removeEvent(event, self)
end
end
return self
end,
getZIndex = function(self)
return 1
end,
enable = function(self)
isEnabled = true
return self
end,
disable = function(self)
isEnabled = false
return self
end,
isEnabled = function(self)
return isEnabled
end,
remove = function(self)
if (parent ~= nil) then
parent:removeObject(self)
parent:removeEvents(self)
end
self:updateDraw()
return self
end,
getBaseFrame = function(self)
if(parent~=nil)then
return parent:getBaseFrame()
end
return self
end,
onEvent = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("other_event", v)
end
end
return self
end,
getEventSystem = function(self)
return eventSystem
end,
registerEvent = function(self, event, func)
if(parent~=nil)then
parent:addEvent(event, self)
end
return eventSystem:registerEvent(event, func)
end,
removeEvent = function(self, event, index)
if(eventSystem:getEventCount(event)<1)then
if(parent~=nil)then
parent:removeEvent(event, self)
end
end
return eventSystem:removeEvent(event, index)
end,
eventHandler = function(self, event, ...)
local val = self:sendEvent("other_event", event, ...)
if(val~=nil)then return val end
end,
customEventHandler = function(self, event, ...)
local val = self:sendEvent("custom_event", event, ...)
if(val~=nil)then return val end
return true
end,
sendEvent = function(self, event, ...)
if(event=="other_event")or(event=="custom_event")then
return eventSystem:sendEvent(event, self, ...)
end
return eventSystem:sendEvent(event, self, event, ...)
end,
onClick = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_click", v)
end
end
return self
end,
onClickUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_up", v)
end
end
return self
end,
onRelease = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_release", v)
end
end
return self
end,
onScroll = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_scroll", v)
end
end
return self
end,
onHover = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_hover", v)
end
end
return self
end,
onLeave = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_leave", v)
end
end
return self
end,
onDrag = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_drag", v)
end
end
return self
end,
onKey = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key", v)
end
end
return self
end,
onChar = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("char", v)
end
end
return self
end,
onKeyUp = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key_up", v)
end
end
return self
end,
}
object.__index = object
return object
end

View File

@@ -1,28 +1,16 @@
local Object = require("Object") return function(name, basalt)
local log = require("basaltLogs")
return function(name)
-- Pane -- Pane
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Pane" local objectType = "Pane"
base:setSize(25, 10)
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end;
setBackground = function(self, col, sym, symC)
base.setBackground(self, col, sym, symC)
return self
end,
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("PaneBG")
self.fgColor = self.parent:getTheme("PaneBG")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,19 +1,16 @@
local Object = require("Object")
local tHex = require("tHex") local tHex = require("tHex")
local process = require("process") local process = require("process")
local xmlValue = require("utils").getValueFromXML
local sub = string.sub local sub = string.sub
return function(name, parent) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Program" local objectType = "Program"
base:setZIndex(5)
local object local object
local cachedPath local cachedPath
local enviroment = {} local enviroment = {}
local function createBasaltWindow(x, y, width, height, self) local function createBasaltWindow(x, y, width, height)
local xCursor, yCursor = 1, 1 local xCursor, yCursor = 1, 1
local bgColor, fgColor = colors.black, colors.white local bgColor, fgColor = colors.black, colors.white
local cursorBlink = false local cursorBlink = false
@@ -30,7 +27,7 @@ return function(name, parent)
for i = 0, 15 do for i = 0, 15 do
local c = 2 ^ i local c = 2 ^ i
tPalette[c] = { parent:getBasaltInstance().getBaseTerm().getPaletteColour(c) } tPalette[c] = { basalt.getTerm().getPaletteColour(c) }
end end
local function createEmptyLines() local function createEmptyLines()
@@ -66,67 +63,17 @@ return function(name, parent)
end end
local function internalBlit(sText, sTextColor, sBackgroundColor) local function internalBlit(sText, sTextColor, sBackgroundColor)
-- copy pasti strikes again (cc: window.lua) if yCursor < 1 or yCursor > height or xCursor < 1 or xCursor + #sText - 1 > width then
local nStart = xCursor return
local nEnd = nStart + #sText - 1
if yCursor >= 1 and yCursor <= height then
if nStart <= width and nEnd >= 1 then
-- Modify line
if nStart == 1 and nEnd == width then
cacheT[yCursor] = sText
cacheFG[yCursor] = sTextColor
cacheBG[yCursor] = sBackgroundColor
else
local sClippedText, sClippedTextColor, sClippedBackgroundColor
if nStart < 1 then
local nClipStart = 1 - nStart + 1
local nClipEnd = width - nStart + 1
sClippedText = sub(sText, nClipStart, nClipEnd)
sClippedTextColor = sub(sTextColor, nClipStart, nClipEnd)
sClippedBackgroundColor = sub(sBackgroundColor, nClipStart, nClipEnd)
elseif nEnd > width then
local nClipEnd = width - nStart + 1
sClippedText = sub(sText, 1, nClipEnd)
sClippedTextColor = sub(sTextColor, 1, nClipEnd)
sClippedBackgroundColor = sub(sBackgroundColor, 1, nClipEnd)
else
sClippedText = sText
sClippedTextColor = sTextColor
sClippedBackgroundColor = sBackgroundColor
end
local sOldText = cacheT[yCursor]
local sOldTextColor = cacheFG[yCursor]
local sOldBackgroundColor = cacheBG[yCursor]
local sNewText, sNewTextColor, sNewBackgroundColor
if nStart > 1 then
local nOldEnd = nStart - 1
sNewText = sub(sOldText, 1, nOldEnd) .. sClippedText
sNewTextColor = sub(sOldTextColor, 1, nOldEnd) .. sClippedTextColor
sNewBackgroundColor = sub(sOldBackgroundColor, 1, nOldEnd) .. sClippedBackgroundColor
else
sNewText = sClippedText
sNewTextColor = sClippedTextColor
sNewBackgroundColor = sClippedBackgroundColor
end
if nEnd < width then
local nOldStart = nEnd + 1
sNewText = sNewText .. sub(sOldText, nOldStart, width)
sNewTextColor = sNewTextColor .. sub(sOldTextColor, nOldStart, width)
sNewBackgroundColor = sNewBackgroundColor .. sub(sOldBackgroundColor, nOldStart, width)
end
cacheT[yCursor] = sNewText
cacheFG[yCursor] = sNewTextColor
cacheBG[yCursor] = sNewBackgroundColor
end
object:updateDraw()
end
xCursor = nEnd + 1
if (visible) then
updateCursor()
end
end end
cacheT[yCursor] = sub(cacheT[yCursor], 1, xCursor - 1) .. sText .. sub(cacheT[yCursor], xCursor + #sText, width)
cacheFG[yCursor] = sub(cacheFG[yCursor], 1, xCursor - 1) .. sTextColor .. sub(cacheFG[yCursor], xCursor + #sText, width)
cacheBG[yCursor] = sub(cacheBG[yCursor], 1, xCursor - 1) .. sBackgroundColor .. sub(cacheBG[yCursor], xCursor + #sText, width)
xCursor = xCursor + #sText
if visible then
updateCursor()
end
object:updateDraw()
end end
local function setText(_x, _y, text) local function setText(_x, _y, text)
@@ -233,7 +180,7 @@ return function(name, parent)
if (visible) then if (visible) then
updateCursor() updateCursor()
end end
end; end,
getCursorPos = function() getCursorPos = function()
return xCursor, yCursor return xCursor, yCursor
@@ -310,57 +257,40 @@ return function(name, parent)
end end
end; end;
writeText = function(_x, _y, text, bgCol, fgCol)
bgCol = bgCol or bgColor
fgCol = fgCol or fgColor
setText(x, _y, text)
setBG(_x, _y, tHex[bgCol]:rep(text:len()))
setFG(_x, _y, tHex[fgCol]:rep(text:len()))
end;
basalt_update = function() basalt_update = function()
if (parent ~= nil) then for n = 1, height do
for n = 1, height do object:addBlit(1, n, cacheT[n], cacheFG[n], cacheBG[n])
parent:setText(x, y + (n - 1), cacheT[n])
parent:setBG(x, y + (n - 1), cacheBG[n])
parent:setFG(x, y + (n - 1), cacheFG[n])
end
end end
end; end,
scroll = function(offset) scroll = function(offset)
if type(offset) ~= "number" then assert(type(offset) == "number", "bad argument #1 (expected number, got " .. type(offset) .. ")")
error("bad argument #1 (expected number, got " .. type(offset) .. ")", 2)
end
if offset ~= 0 then if offset ~= 0 then
local sEmptyText = emptySpaceLine for newY = 1, height do
local sEmptyTextColor = emptyColorLines[fgColor] local y = newY + offset
local sEmptyBackgroundColor = emptyColorLines[bgColor] if y < 1 or y > height then
for newY = 1, height do cacheT[newY] = emptySpaceLine
local y = newY + offset cacheFG[newY] = emptyColorLines[fgColor]
if y >= 1 and y <= height then cacheBG[newY] = emptyColorLines[bgColor]
cacheT[newY] = cacheT[y] else
cacheBG[newY] = cacheBG[y] cacheT[newY] = cacheT[y]
cacheFG[newY] = cacheFG[y] cacheBG[newY] = cacheBG[y]
else cacheFG[newY] = cacheFG[y]
cacheT[newY] = sEmptyText
cacheFG[newY] = sEmptyTextColor
cacheBG[newY] = sEmptyBackgroundColor
end
end end
end
end end
if (visible) then if (visible) then
updateCursor() updateCursor()
end end
end; end,
isColor = function() isColor = function()
return parent:getBasaltInstance().getBaseTerm().isColor() return basalt.getTerm().isColor()
end; end;
isColour = function() isColour = function()
return parent:getBasaltInstance().getBaseTerm().isColor() return basalt.getTerm().isColor()
end; end;
write = function(text) write = function(text)
@@ -416,19 +346,20 @@ return function(name, parent)
return basaltwindow return basaltwindow
end end
base.width = 30 base:setZIndex(5)
base.height = 12 base:setSize(30, 12)
local pWindow = createBasaltWindow(1, 1, base.width, base.height) local pWindow = createBasaltWindow(1, 1, 30, 12)
local curProcess local curProcess
local paused = false local paused = false
local queuedEvent = {} local queuedEvent = {}
local function updateCursor(self) local function updateCursor(self)
local parent = self:getParent()
local xCur, yCur = pWindow.getCursorPos() local xCur, yCur = pWindow.getCursorPos()
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(self:isFocused() and pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor()) parent:setCursor(self:isFocused() and pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end end
end end
@@ -452,7 +383,7 @@ return function(name, parent)
end end
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
if not (paused) then if not (paused) then
local absX, absY = self:getAbsolutePosition(self:getAnchorPosition(nil, nil, true)) local absX, absY = self:getAbsolutePosition()
resumeProcess(self, event, p1, x-absX+1, y-absY+1) resumeProcess(self, event, p1, x-absX+1, y-absY+1)
updateCursor(self) updateCursor(self)
end end
@@ -480,8 +411,8 @@ return function(name, parent)
show = function(self) show = function(self)
base.show(self) base.show(self)
pWindow.setBackgroundColor(self.bgColor) pWindow.setBackgroundColor(self:getBackground())
pWindow.setTextColor(self.fgColor) pWindow.setTextColor(self:getForeground())
pWindow.basalt_setVisible(true) pWindow.basalt_setVisible(true)
return self return self
end; end;
@@ -494,14 +425,8 @@ return function(name, parent)
setPosition = function(self, x, y, rel) setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel) base.setPosition(self, x, y, rel)
pWindow.basalt_reposition(self:getAnchorPosition()) pWindow.basalt_reposition(self:getPosition())
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("path", data)~=nil)then cachedPath = xmlValue("path", data) end
if(xmlValue("execute", data)~=nil)then if(xmlValue("execute", data))then if(cachedPath~=nil)then self:execute(cachedPath) end end end
end, end,
getBasaltWindow = function() getBasaltWindow = function()
@@ -537,37 +462,34 @@ return function(name, parent)
pWindow.setTextColor(colors.white) pWindow.setTextColor(colors.white)
pWindow.clear() pWindow.clear()
pWindow.setCursorPos(1, 1) pWindow.setCursorPos(1, 1)
pWindow.setBackgroundColor(self.bgColor) pWindow.setBackgroundColor(self:getBackground())
pWindow.setTextColor(self.fgColor) pWindow.setTextColor(self:getForeground() or colors.white)
pWindow.basalt_setVisible(true) pWindow.basalt_setVisible(true)
resumeProcess(self) resumeProcess(self)
paused = false paused = false
if(self.parent~=nil)then self:listenEvent("mouse_click", self)
self.parent:addEvent("mouse_click", self) self:listenEvent("mouse_up", self)
self.parent:addEvent("mouse_up", self) self:listenEvent("mouse_drag", self)
self.parent:addEvent("mouse_drag", self) self:listenEvent("mouse_scroll", self)
self.parent:addEvent("mouse_scroll", self) self:listenEvent("key", self)
self.parent:addEvent("key", self) self:listenEvent("key_up", self)
self.parent:addEvent("key_up", self) self:listenEvent("char", self)
self.parent:addEvent("char", self) self:listenEvent("other_event", self)
self.parent:addEvent("other_event", self)
end
return self return self
end; end;
stop = function(self) stop = function(self)
local parent = self:getParent()
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
resumeProcess(self, "terminate") resumeProcess(self, "terminate")
if (curProcess:isDead()) then if (curProcess:isDead()) then
if (self.parent ~= nil) then parent:setCursor(false)
self.parent:setCursor(false)
end
end end
end end
end end
self.parent:removeEvents(self) parent:removeEvents(self)
return self return self
end; end;
@@ -576,7 +498,7 @@ return function(name, parent)
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
if not (paused) then if not (paused) then
self:injectEvents(queuedEvent) self:injectEvents(table.unpack(queuedEvent))
queuedEvent = {} queuedEvent = {}
end end
end end
@@ -588,13 +510,13 @@ return function(name, parent)
return paused return paused
end; end;
injectEvent = function(self, event, p1, p2, p3, p4, ign) injectEvent = function(self, event, ign, ...)
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
if (paused == false) or (ign) then if (paused == false) or (ign) then
resumeProcess(self, event, p1, p2, p3, p4) resumeProcess(self, event, ...)
else else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } }) table.insert(queuedEvent, { event = event, args = {...} })
end end
end end
end end
@@ -610,10 +532,10 @@ return function(name, parent)
return self return self
end; end;
injectEvents = function(self, events) injectEvents = function(self, ...)
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
for _, value in pairs(events) do for _, value in pairs({...}) do
resumeProcess(self, value.event, table.unpack(value.args)) resumeProcess(self, value.event, table.unpack(value.args))
end end
end end
@@ -682,12 +604,13 @@ return function(name, parent)
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
if not (paused) then if not (paused) then
if (self.parent ~= nil) then local parent = self:getParent()
if (parent ~= nil) then
local xCur, yCur = pWindow.getCursorPos() local xCur, yCur = pWindow.getCursorPos()
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor()) parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end end
end end
end end
@@ -699,77 +622,70 @@ return function(name, parent)
base.loseFocusHandler(self) base.loseFocusHandler(self)
if (curProcess ~= nil) then if (curProcess ~= nil) then
if not (curProcess:isDead()) then if not (curProcess:isDead()) then
if (self.parent ~= nil) then local parent = self:getParent()
self.parent:setCursor(false) if (parent ~= nil) then
parent:setCursor(false)
end end
end end
end end
end, end,
customEventHandler = function(self, event, ...) eventHandler = function(self, event, ...)
base.customEventHandler(self, event, ...) base.eventHandler(self, event, ...)
if (curProcess == nil) then if curProcess == nil then
return return
end end
if(event=="basalt_resize")then if not curProcess:isDead() then
local w, h = pWindow.getSize() if not paused then
local pW, pH = self:getSize() resumeProcess(self, event, ...)
if(w~=pW)or(h~=pH)then if self:isFocused() then
pWindow.basalt_resize(pW, pH) local parent = self:getParent()
if not (curProcess:isDead()) then local obx, oby = self:getPosition()
resumeProcess(self, "term_resize")
end
end
pWindow.basalt_reposition(self:getAnchorPosition())
end
end,
eventHandler = function(self, event, p1, p2, p3, p4)
base.eventHandler(self, event, p1, p2, p3, p4)
if (curProcess == nil) then
return
end
if not (curProcess:isDead()) then
if not (paused) then
if(event ~= "terminate") then
resumeProcess(self, event, p1, p2, p3, p4)
end
if (self:isFocused()) then
local obx, oby = self:getAnchorPosition()
local xCur, yCur = pWindow.getCursorPos() local xCur, yCur = pWindow.getCursorPos()
if (self.parent ~= nil) then local w,h = self:getSize()
local w,h = self:getSize() if obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1 then
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
if (event == "terminate") then
resumeProcess(self, event)
self.parent:setCursor(false)
return true
end end
end end
else else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } }) table.insert(queuedEvent, { event = event, args = { ... } })
end
end
end,
resizeHandler = function(self, ...)
base.resizeHandler(self, ...)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if not (paused) then
pWindow.basalt_resize(self:getSize())
resumeProcess(self, "term_resize", self:getSize())
else
pWindow.basalt_resize(self:getSize())
table.insert(queuedEvent, { event = "term_resize", args = { self:getSize() } })
end
end
end
end,
repositionHandler = function(self, ...)
base.repositionHandler(self, ...)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
pWindow.basalt_reposition(self:getPosition())
end end
end end
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("program", function()
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local xCur, yCur = pWindow.getCursorPos() local obx, oby = self:getPosition()
local w,h = self:getSize() local xCur, yCur = pWindow.getCursorPos()
pWindow.basalt_reposition(obx, oby) local w,h = self:getSize()
pWindow.basalt_update() pWindow.basalt_update()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then end)
self.parent:setCursor(self:isFocused() and pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
end
end, end,
onError = function(self, ...) onError = function(self, ...)
@@ -778,9 +694,8 @@ return function(name, parent)
self:registerEvent("program_error", v) self:registerEvent("program_error", v)
end end
end end
if(self.parent~=nil)then local parent = self:getParent()
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
end
return self return self
end, end,
@@ -790,19 +705,13 @@ return function(name, parent)
self:registerEvent("program_done", v) self:registerEvent("program_done", v)
end end
end end
if(self.parent~=nil)then local parent = self:getParent()
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
end
return self return self
end, end,
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ProgramBG")
end
end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,52 +1,29 @@
local Object = require("Object") return function(name, basalt)
local xmlValue = require("utils").getValueFromXML local base = basalt.getObject("ChangeableObject")(name, basalt)
return function(name)
-- Checkbox
local base = Object(name)
local objectType = "Progressbar" local objectType = "Progressbar"
local progress = 0 local progress = 0
base:setZIndex(5) base:setZIndex(5)
base:setValue(false) base:setValue(false)
base.width = 25 base:setSize(25, 3)
base.height = 1
local activeBarColor local activeBarColor = colors.black
local activeBarSymbol = "" local activeBarSymbol = ""
local activeBarSymbolCol = colors.white local activeBarSymbolCol = colors.white
local bgBarSymbol = "" local bgBarSymbol = ""
local direction = 0 local direction = 0
local object = { local object = {
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ProgressbarBG")
self.fgColor = self.parent:getTheme("ProgressbarText")
activeBarColor = self.parent:getTheme("ProgressbarActiveBG")
end
end,
getType = function(self) getType = function(self)
return objectType return objectType
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("direction", data)~=nil)then direction = xmlValue("direction", data) end
if(xmlValue("progressColor", data)~=nil)then activeBarColor = colors[xmlValue("progressColor", data)] end
if(xmlValue("progressSymbol", data)~=nil)then activeBarSymbol = xmlValue("progressSymbol", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgBarSymbol = xmlValue("backgroundSymbol", data) end
if(xmlValue("progressSymbolColor", data)~=nil)then activeBarSymbolCol = colors[xmlValue("progressSymbolColor", data)] end
if(xmlValue("onDone", data)~=nil)then self:generateXMLEventFunction(self.onProgressDone, xmlValue("onDone", data)) end
return self
end, end,
setDirection = function(self, dir) setDirection = function(self, dir)
direction = dir direction = dir
self:updateDraw() self:updateDraw()
return self return self
end; end,
setProgressBar = function(self, color, symbol, symbolcolor) setProgressBar = function(self, color, symbol, symbolcolor)
activeBarColor = color or activeBarColor activeBarColor = color or activeBarColor
@@ -54,13 +31,17 @@ return function(name)
activeBarSymbolCol = symbolcolor or activeBarSymbolCol activeBarSymbolCol = symbolcolor or activeBarSymbolCol
self:updateDraw() self:updateDraw()
return self return self
end; end,
getProgressBar = function(self)
return activeBarColor, activeBarSymbol, activeBarSymbolCol
end,
setBackgroundSymbol = function(self, symbol) setBackgroundSymbol = function(self, symbol)
bgBarSymbol = symbol:sub(1, 1) bgBarSymbol = symbol:sub(1, 1)
self:updateDraw() self:updateDraw()
return self return self
end; end,
setProgress = function(self, value) setProgress = function(self, value)
if (value >= 0) and (value <= 100) and (progress ~= value) then if (value >= 0) and (value <= 100) and (progress ~= value) then
@@ -72,51 +53,52 @@ return function(name)
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
getProgress = function(self) getProgress = function(self)
return progress return progress
end; end,
onProgressDone = function(self, f) onProgressDone = function(self, f)
self:registerEvent("progress_done", f) self:registerEvent("progress_done", f)
return self return self
end; end,
progressDoneHandler = function(self) progressDoneHandler = function(self)
self:sendEvent("progress_done", self) self:sendEvent("progress_done")
end; end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("progressbar", function()
local obx, oby = self:getAnchorPosition() local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end local bgCol,fgCol = self:getBackground(), self:getForeground()
if(bgBarSymbol~="")then self.parent:drawTextBox(obx, oby, w, h, bgBarSymbol) end if(bgCol~=false)then self:addBackgroundBox(1, 1, w, h, bgCol) end
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, w, h, self.fgColor) end if(bgBarSymbol~="")then self:addTextBox(1, 1, w, h, bgBarSymbol) end
if (direction == 1) then if(fgCol~=false)then self:addForegroundBox(1, 1, w, h, fgCol) end
self.parent:drawBackgroundBox(obx, oby, w, h / 100 * progress, activeBarColor) if (direction == 1) then
self.parent:drawForegroundBox(obx, oby, w, h / 100 * progress, activeBarSymbolCol) self:addBackgroundBox(1, 1, w, h / 100 * progress, activeBarColor)
self.parent:drawTextBox(obx, oby, w, h / 100 * progress, activeBarSymbol) self:addForegroundBox(1, 1, w, h / 100 * progress, activeBarSymbolCol)
elseif (direction == 2) then self:addTextBox(1, 1, w, h / 100 * progress, activeBarSymbol)
self.parent:drawBackgroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor) elseif (direction == 3) then
self.parent:drawForegroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol) self:addBackgroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor)
self.parent:drawTextBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol) self:addForegroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol)
elseif (direction == 3) then self:addTextBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol)
self.parent:drawBackgroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarColor) elseif (direction == 2) then
self.parent:drawForegroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbolCol) self:addBackgroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarColor)
self.parent:drawTextBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbol) self:addForegroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbolCol)
else self:addTextBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbol)
self.parent:drawBackgroundBox(obx, oby, w / 100 * progress, h, activeBarColor) else
self.parent:drawForegroundBox(obx, oby, w / 100 * progress, h, activeBarSymbolCol) self:addBackgroundBox(1, 1, math.ceil( w / 100 * progress), h, activeBarColor)
self.parent:drawTextBox(obx, oby, w / 100 * progress, h, activeBarSymbol) self:addForegroundBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbolCol)
end self:addTextBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbol)
end end
end end)
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,20 +1,18 @@
local Object = require("Object")
local utils = require("utils") local utils = require("utils")
local xmlValue = utils.getValueFromXML local tHex = require("tHex")
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("List")(name, basalt)
local objectType = "Radio" local objectType = "Radio"
base.width = 8
base:setSize(1, 1)
base:setZIndex(5) base:setZIndex(5)
local list = {} local list = {}
local itemSelectedBG local boxSelectedBG = colors.black
local itemSelectedFG local boxSelectedFG = colors.green
local boxSelectedBG local boxNotSelectedBG = colors.black
local boxSelectedFG local boxNotSelectedFG = colors.red
local boxNotSelectedBG
local boxNotSelectedFG
local selectionColorActive = true local selectionColorActive = true
local symbol = "\7" local symbol = "\7"
local align = "left" local align = "left"
@@ -22,148 +20,87 @@ return function(name)
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("selectionBG", data)~=nil)then itemSelectedBG = colors[xmlValue("selectionBG", data)] end
if(xmlValue("selectionFG", data)~=nil)then itemSelectedFG = colors[xmlValue("selectionFG", data)] end
if(xmlValue("boxBG", data)~=nil)then boxSelectedBG = colors[xmlValue("boxBG", data)] end
if(xmlValue("inactiveBoxBG", data)~=nil)then boxNotSelectedBG = colors[xmlValue("inactiveBoxBG", data)] end
if(xmlValue("inactiveBoxFG", data)~=nil)then boxNotSelectedFG = colors[xmlValue("inactiveBoxFG", data)] end
if(xmlValue("boxFG", data)~=nil)then boxSelectedFG = colors[xmlValue("boxFG", data)] end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), xmlValue("x", v), xmlValue("y", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
return self
end, end,
addItem = function(self, text, x, y, bgCol, fgCol, ...) addItem = function(self, text, x, y, bgCol, fgCol, ...)
table.insert(list, { x = x or 1, y = y or 1, text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } }) base.addItem(self, text, bgCol, fgCol, ...)
if (#list == 1) then table.insert(list, { x = x or 1, y = y or #list * 2 })
self:setValue(list[1])
end
self:updateDraw()
return self
end;
getAll = function(self)
return list
end;
removeItem = function(self, index)
table.remove(list, index)
self:updateDraw()
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({}, false)
self:updateDraw()
return self
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, x, y, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { x = x or 1, y = y or 1, text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
self:updateDraw()
return self
end;
selectItem = function(self, index)
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
setActiveSymbol = function(self, sym)
symbol = sym:sub(1,1)
self:updateDraw()
return self return self
end, end,
setSelectedItem = function(self, bgCol, fgCol, boxBG, boxFG, active) removeItem = function(self, index)
itemSelectedBG = bgCol or itemSelectedBG base.removeItem(self, index)
itemSelectedFG = fgCol or itemSelectedFG table.remove(list, index)
boxSelectedBG = boxBG or boxSelectedBG
boxSelectedFG = boxFG or boxSelectedFG
selectionColorActive = active~=nil and active or true
self:updateDraw()
return self return self
end; end,
mouseHandler = function(self, button, x, y) clear = function(self)
base.clear(self)
list = {}
return self
end,
editItem = function(self, index, text, x, y, bgCol, fgCol, ...)
base.editItem(self, index, text, bgCol, fgCol, ...)
table.remove(list, index)
table.insert(list, index, { x = x or 1, y = y or 1 })
return self
end,
setBoxSelectionColor = function(self, bg, fg)
boxSelectedBG = bg
boxSelectedFG = fg
return self
end,
getBoxSelectionColor = function(self)
return boxSelectedBG, boxSelectedFG
end,
setBoxDefaultColor = function(self, bg, fg)
boxNotSelectedBG = bg
boxNotSelectedFG = fg
return self
end,
getBoxDefaultColor = function(self)
return boxNotSelectedBG, boxNotSelectedFG
end,
mouseHandler = function(self, button, x, y, ...)
if (#list > 0) then if (#list > 0) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
for _, value in pairs(list) do local baseList = self:getAll()
if (obx + value.x - 1 <= x) and (obx + value.x - 1 + value.text:len() + 1 >= x) and (oby + value.y - 1 == y) then 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:setValue(value)
local val = self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", button, x, y) local val = self:sendEvent("mouse_click", self, "mouse_click", button, x, y, ...)
if(val==false)then return val end
if(self.parent~=nil)then
self.parent:setFocusedObject(self)
end
self:updateDraw() self:updateDraw()
if(val==false)then return val end
return true return true
end end
end end
end end
return false end,
end;
draw = function(self) draw = function(self)
if (self.parent ~= nil) then self:addDraw("radio", function()
local obx, oby = self:getAnchorPosition() local itemSelectedBG, itemSelectedFG = self:getSelectionColor()
for _, value in pairs(list) do local baseList = self:getAll()
for k, value in pairs(baseList) do
if (value == self:getValue()) then if (value == self:getValue()) then
if (align == "left") then self:addBlit(list[k].x, list[k].y, symbol, tHex[boxSelectedFG], tHex[boxSelectedBG])
self.parent:writeText(value.x + obx - 1, value.y + oby - 1, symbol, boxSelectedBG, boxSelectedFG) self:addBlit(list[k].x + 2, list[k].y, value.text, tHex[itemSelectedFG]:rep(#value.text), tHex[itemSelectedBG]:rep(#value.text))
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, itemSelectedBG, itemSelectedFG)
end
else else
self.parent:drawBackgroundBox(value.x + obx - 1, value.y + oby - 1, 1, 1, boxNotSelectedBG or self.bgColor) self:addBackgroundBox(list[k].x, list[k].y, 1, 1, boxNotSelectedBG or colors.black)
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, value.bgCol, value.fgCol) self:addBlit(list[k].x + 2, list[k].y, value.text, tHex[value.fgCol]:rep(#value.text), tHex[value.bgCol]:rep(#value.text))
end end
end end
return true return true
end end)
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarFG")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
boxSelectedBG = self.parent:getTheme("MenubarBG")
boxSelectedFG = self.parent:getTheme("MenubarText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -0,0 +1,142 @@
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 = "ScrollableFrame"
local parent
local direction = 0
local manualScrollAmount = 0
local calculateScrollAmount = true
local function getHorizontalScrollAmount(self)
local amount = 0
local objects = self:getObjects()
for _, b in pairs(objects) do
if(b.element.getWidth~=nil)and(b.element.getX~=nil)then
local w, x = b.element:getWidth(), b.element:getX()
local width = self:getWidth()
if(b.element:getType()=="Dropdown")then
if(b.element:isOpened())then
local dropdownW = b.element:getDropdownSize()
if (dropdownW + x - width >= amount) then
amount = max(dropdownW + x - width, 0)
end
end
end
if (h + x - width >= amount) then
amount = max(w + x - width, 0)
end
end
end
return amount
end
local function getVerticalScrollAmount(self)
local amount = 0
local objects = self:getObjects()
for _, b in pairs(objects) do
if(b.element.getHeight~=nil)and(b.element.getY~=nil)then
local h, y = b.element:getHeight(), b.element:getY()
local height = self:getHeight()
if(b.element:getType()=="Dropdown")then
if(b.element:isOpened())then
local _,dropdownH = b.element:getDropdownSize()
if (dropdownH + y - height >= amount) then
amount = max(dropdownH + y - height, 0)
end
end
end
if (h + y - height >= amount) then
amount = max(h + y - height, 0)
end
end
end
return amount
end
local function scrollHandler(self, dir)
local xO, yO = self:getOffset()
local scrollAmn
if(direction==1)then
scrollAmn = calculateScrollAmount and getHorizontalScrollAmount(self) or manualScrollAmount
self:setOffset(min(scrollAmn, max(0, xO + dir)), yO)
elseif(direction==0)then
scrollAmn = calculateScrollAmount and getVerticalScrollAmount(self) or manualScrollAmount
self:setOffset(xO, min(scrollAmn, max(0, yO + dir)))
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,
setDirection = function(self, dir)
direction = dir=="horizontal" and 1 or dir=="vertical" and 0 or direction
return self
end,
setScrollAmount = function(self, amount)
manualScrollAmount = amount
calculateScrollAmount = false
return self
end,
getBase = function(self)
return base
end,
load = function(self)
base.load(self)
self:listenEvent("mouse_scroll")
end,
setParent = function(self, p, ...)
base.setParent(self, p, ...)
parent = p
return self
end,
scrollHandler = function(self, dir, x, y)
if(base:getBase().scrollHandler(self, dir, x, y))then
self:sortElementOrder()
for _, obj in ipairs(self:getEvents("mouse_scroll")) do
if (obj.element.scrollHandler ~= nil) then
local xO, yO = 0, 0
if(self.getOffset~=nil)then
xO, yO = self:getOffset()
end
if(obj.element.getIgnoreOffset())then
xO, yO = 0, 0
end
if (obj.element.scrollHandler(obj.element, dir, x+xO, y+yO)) then
return true
end
end
end
scrollHandler(self, dir, x, y)
self:removeFocusedObject()
return true
end
end,
draw = function(self)
base.draw(self)
self:addDraw("scrollableFrame", function()
if(calculateScrollAmount)then
scrollHandler(self, 0)
end
end, 0)
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,42 +1,40 @@
local Object = require("Object") local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Scrollbar" local objectType = "Scrollbar"
base.width = 1
base.height = 8
base:setValue(1)
base:setZIndex(2) base:setZIndex(2)
base:setSize(1, 8)
base:setBackground(colors.lightGray, "\127", colors.gray)
local barType = "vertical" local barType = "vertical"
local symbol = " " local symbol = " "
local symbolColor local symbolBG = colors.black
local bgSymbol = "\127" local symbolFG = colors.black
local maxValue = base.height local scrollAmount = 3
local index = 1 local index = 1
local symbolSize = 1 local symbolSize = 1
local symbolAutoSize = true
local function updateSymbolSize()
local w,h = base:getSize()
if(symbolAutoSize)then
symbolSize = math.max((barType == "vertical" and h or w-(#symbol)) - (scrollAmount-1), 1)
end
end
updateSymbolSize()
local function mouseEvent(self, button, x, y) local function mouseEvent(self, button, x, y)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
local w,h = self:getSize() local w,h = self:getSize()
if (barType == "horizontal") then updateSymbolSize()
for _index = 0, w do local size = barType == "vertical" and h or w
if (obx + _index == x) and (oby <= y) and (oby + h > y) then for i = 0, size do
index = math.min(_index + 1, w - (symbolSize - 1)) 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
self:setValue(maxValue / w * (index)) index = math.min(i + 1, size - (#symbol + symbolSize - 2))
self:updateDraw() self:scrollbarMoveHandler()
end self:updateDraw()
end
end
if (barType == "vertical") then
for _index = 0, h do
if (oby + _index == y) and (obx <= x) and (obx + w > x) then
index = math.min(_index + 1, h - (symbolSize - 1))
self:setValue(maxValue / h * (index))
self:updateDraw()
end
end end
end end
end end
@@ -44,23 +42,24 @@ return function(name)
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
setSymbol = function(self, _symbol) load = function(self)
symbol = _symbol:sub(1, 1) 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() self:updateDraw()
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end
if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
end, end,
setIndex = function(self, _index) setIndex = function(self, _index)
@@ -69,54 +68,41 @@ return function(name)
index = 1 index = 1
end end
local w,h = self:getSize() local w,h = self:getSize()
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) --index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index) updateSymbolSize()
self:updateDraw()
return self
end,
setScrollAmount = function(self, amount)
scrollAmount = amount
updateSymbolSize()
self:updateDraw() self:updateDraw()
return self return self
end, end,
getIndex = function(self) getIndex = function(self)
return index local w,h = self:getSize()
return scrollAmount > (barType=="vertical" and h or w) and math.floor(scrollAmount/(barType=="vertical" and h or w) * index) or index
end, end,
setSymbolSize = function(self, size) setSymbolSize = function(self, size)
symbolSize = tonumber(size) or 1 symbolSize = tonumber(size) or 1
local w,h = self:getSize() symbolAutoSize = size~=false and false or true
if (barType == "vertical") then updateSymbolSize()
self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1))))
elseif (barType == "horizontal") then
self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1))))
end
self:updateDraw() self:updateDraw()
return self return self
end; end,
setMaxValue = function(self, val)
maxValue = val
self:updateDraw()
return self
end;
setBackgroundSymbol = function(self, _bgSymbol)
bgSymbol = string.sub(_bgSymbol, 1, 1)
self:updateDraw()
return self
end;
setSymbolColor = function(self, col)
symbolColor = col
self:updateDraw()
return self
end;
setBarType = function(self, _typ) setBarType = function(self, _typ)
barType = _typ:lower() barType = _typ:lower()
updateSymbolSize()
self:updateDraw() self:updateDraw()
return self return self
end; end,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y, ...)
if (base.mouseHandler(self, button, x, y)) then if (base.mouseHandler(self, button, x, y, ...)) then
mouseEvent(self, button, x, y) mouseEvent(self, button, x, y)
return true return true
end end
@@ -131,58 +117,70 @@ return function(name)
return false return false
end, end,
setSize = function(self, ...)
base.setSize(self, ...)
updateSymbolSize()
return self
end,
scrollHandler = function(self, dir, x, y) scrollHandler = function(self, dir, x, y)
if(base.scrollHandler(self, dir, x, y))then if(base.scrollHandler(self, dir, x, y))then
local w,h = self:getSize() local w,h = self:getSize()
updateSymbolSize()
index = index + dir index = index + dir
if (index < 1) then if (index < 1) then
index = 1 index = 1
end end
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1)) index = math.min(index, (barType == "vertical" and h or w) - (barType == "vertical" and symbolSize - 1 or #symbol+symbolSize-2))
self:setValue(maxValue / (barType == "vertical" and h or w) * index) self:scrollbarMoveHandler()
self:updateDraw() self:updateDraw()
end end
end, end,
draw = function(self) onChange = function(self, ...)
if (base.draw(self)) then for _,v in pairs(table.pack(...))do
if (self.parent ~= nil) then if(type(v)=="function")then
local obx, oby = self:getAnchorPosition() self:registerEvent("scrollbar_moved", v)
local w,h = self:getSize() end
if (barType == "horizontal") then end
self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor) return self
self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor) end,
self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor)
end
if (barType == "vertical") then
for n = 0, h - 1 do scrollbarMoveHandler = function(self)
if (index == n + 1) then self:sendEvent("scrollbar_moved", self:getIndex())
for curIndexOffset = 0, math.min(symbolSize - 1, h) do end,
self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor)
end customEventHandler = function(self, event, ...)
else base.customEventHandler(self, event, ...)
if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then if(event=="basalt_FrameResize")then
self.parent:writeText(obx, oby + n, bgSymbol, self.bgColor, self.fgColor) 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
for n = 0, h - 1 do
self:addBlit(index, 1 + n, symbol:rep(symbolSize), tHex[symbolFG]:rep(#symbol*symbolSize), tHex[symbolBG]:rep(#symbol*symbolSize))
end
elseif (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)))
end end
end end
end end
end end
end end)
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ScrollbarBG")
self.fgColor = self.parent:getTheme("ScrollbarText")
symbolColor = self.parent:getTheme("ScrollbarSymbolColor")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,66 +1,49 @@
local Object = require("Object") local tHex = require("tHex")
local log = require("basaltLogs")
local xmlValue = require("utils").getValueFromXML
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Slider" local objectType = "Slider"
base.width = 8 base:setSize(12, 1)
base.height = 1
base:setValue(1) base:setValue(1)
base:setBackground(false, "\140", colors.black)
local barType = "horizontal" local barType = "horizontal"
local symbol = " " local symbol = " "
local symbolColor local symbolFG = colors.black
local bgSymbol = "\140" local symbolBG = colors.gray
local maxValue = base.width local maxValue = 12
local index = 1 local index = 1
local symbolSize = 1 local symbolSize = 1
local function mouseEvent(self, button, x, y) local function mouseEvent(self, button, x, y)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (barType == "horizontal") then local size = barType == "vertical" and h or w
for _index = 0, w do for i = 0, size do
if (obx + _index == x) and (oby <= y) and (oby + h > y) then 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(_index + 1, w - (symbolSize - 1)) index = math.min(i + 1, size - (#symbol + symbolSize - 2))
self:setValue(maxValue / w * (index)) self:setValue(maxValue / size * index)
self:updateDraw() self:updateDraw()
end
end
end
if (barType == "vertical") then
for _index = 0, h do
if (oby + _index == y) and (obx <= x) and (obx + w > x) then
index = math.min(_index + 1, h - (symbolSize - 1))
self:setValue(maxValue / h * (index))
self:updateDraw()
end
end
end end
end end
end
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
load = function(self)
self:listenEvent("mouse_click")
self:listenEvent("mouse_drag")
self:listenEvent("mouse_scroll")
end,
setSymbol = function(self, _symbol) setSymbol = function(self, _symbol)
symbol = _symbol:sub(1, 1) symbol = _symbol:sub(1, 1)
self:updateDraw() self:updateDraw()
return self return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end
if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
end, end,
setIndex = function(self, _index) setIndex = function(self, _index)
@@ -79,39 +62,22 @@ return function(name)
return index return index
end, end,
setSymbolSize = function(self, size)
symbolSize = tonumber(size) or 1
if (barType == "vertical") then
self:setValue(index - 1 * (maxValue / (h - (symbolSize - 1))) - (maxValue / (h - (symbolSize - 1))))
elseif (barType == "horizontal") then
self:setValue(index - 1 * (maxValue / (w - (symbolSize - 1))) - (maxValue / (w - (symbolSize - 1))))
end
self:updateDraw()
return self
end;
setMaxValue = function(self, val) setMaxValue = function(self, val)
maxValue = val maxValue = val
return self return self
end; end,
setBackgroundSymbol = function(self, _bgSymbol)
bgSymbol = string.sub(_bgSymbol, 1, 1)
self:updateDraw()
return self
end;
setSymbolColor = function(self, col) setSymbolColor = function(self, col)
symbolColor = col symbolColor = col
self:updateDraw() self:updateDraw()
return self return self
end; end,
setBarType = function(self, _typ) setBarType = function(self, _typ)
barType = _typ:lower() barType = _typ:lower()
self:updateDraw() self:updateDraw()
return self return self
end; end,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then if (base.mouseHandler(self, button, x, y)) then
@@ -145,44 +111,33 @@ return function(name)
end, end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("slider", function()
local obx, oby = self:getAnchorPosition() local w,h = self:getSize()
local w,h = self:getSize() local bgCol,fgCol = self:getBackground(), self:getForeground()
if (barType == "horizontal") then if (barType == "horizontal") then
self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor) self:addText(index, oby, symbol:rep(symbolSize))
self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor) if(symbolBG~=false)then self:addBG(index, 1, tHex[symbolBG]:rep(#symbol*symbolSize)) end
self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor) if(symbolFG~=false)then self:addFG(index, 1, tHex[symbolFG]:rep(#symbol*symbolSize)) end
end end
if (barType == "vertical") then if (barType == "vertical") then
for n = 0, h - 1 do for n = 0, h - 1 do
if (index == n + 1) then if (index == n + 1) then
for curIndexOffset = 0, math.min(symbolSize - 1, h) do for curIndexOffset = 0, math.min(symbolSize - 1, h) do
self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor) self:addBlit(1, 1+n+curIndexOffset, symbol, tHex[symbolColor], tHex[symbolColor])
end end
else else
if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then
self.parent:writeText(obx, oby + n, bgSymbol, self.bgColor, self.fgColor) self:addBlit(1, 1+n, bgSymbol, tHex[fgCol], tHex[bgCol])
end
end end
end end
end end
end end
end end)
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("SliderBG")
self.fgColor = self.parent:getTheme("SliderText")
symbolColor = self.parent:getTheme("SliderSymbolColor")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,14 +1,8 @@
local Object = require("Object") return function(name, basalt)
local xmlValue = require("utils").getValueFromXML local base = basalt.getObject("ChangeableObject")(name, basalt)
return function(name)
local base = Object(name)
local objectType = "Switch" local objectType = "Switch"
base.width = 2 base:setSize(4, 1)
base.height = 1
base.bgColor = colors.lightGray
base.fgColor = colors.gray
base:setValue(false) base:setValue(false)
base:setZIndex(5) base:setZIndex(5)
@@ -19,71 +13,53 @@ return function(name)
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end;
setSymbolColor = function(self, symbolColor)
bgSymbol = symbolColor
self:updateDraw()
return self
end;
setActiveBackground = function(self, bgcol)
activeBG = bgcol
self:updateDraw()
return self
end;
setInactiveBackground = function(self, bgcol)
inactiveBG = bgcol
self:updateDraw()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("inactiveBG", data)~=nil)then inactiveBG = colors[xmlValue("inactiveBG", data)] end
if(xmlValue("activeBG", data)~=nil)then activeBG = colors[xmlValue("activeBG", data)] end
if(xmlValue("symbolColor", data)~=nil)then bgSymbol = colors[xmlValue("symbolColor", data)] end
end, end,
mouseHandler = function(self, button, x, y) setSymbol = function(self, col)
if (base.mouseHandler(self, button, x, y)) then bgSymbol = col
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) return self
end,
setActiveBackground = function(self, col)
activeBG = col
return self
end,
setInactiveBackground = function(self, col)
inactiveBG = col
return self
end,
load = function(self)
self:listenEvent("mouse_click")
end,
mouseHandler = function(self, ...)
if (base.mouseHandler(self, ...)) then
self:setValue(not self:getValue()) self:setValue(not self:getValue())
self:updateDraw() self:updateDraw()
return true return true
end end
end;
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
if(self:getValue())then
self.parent:drawBackgroundBox(obx, oby, 1, h, activeBG)
self.parent:drawBackgroundBox(obx+1, oby, 1, h, bgSymbol)
else
self.parent:drawBackgroundBox(obx, oby, 1, h, bgSymbol)
self.parent:drawBackgroundBox(obx+1, oby, 1, h, inactiveBG)
end
end
end
end, end,
init = function(self) draw = function(self)
self.parent:addEvent("mouse_click", self) base.draw(self)
if(base.init(self))then self:addDraw("switch", function()
self.bgColor = self.parent:getTheme("SwitchBG") local parent = self:getParent()
self.fgColor = self.parent:getTheme("SwitchText") local bgCol,fgCol = self:getBackground(), self:getForeground()
bgSymbol = self.parent:getTheme("SwitchBGSymbol") local w,h = self:getSize()
inactiveBG = self.parent:getTheme("SwitchInactive") if(self:getValue())then
activeBG = self.parent:getTheme("SwitchActive") self:addBackgroundBox(1, 1, w, h, activeBG)
end self:addBackgroundBox(w, 1, 1, h, bgSymbol)
else
self:addBackgroundBox(1, 1, w, h, inactiveBG)
self:addBackgroundBox(1, 1, 1, h, bgSymbol)
end
end)
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,12 +1,9 @@
local Object = require("Object")
local tHex = require("tHex") local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
local log = require("basaltLogs")
local rep,find,gmatch,sub,len = string.rep,string.find,string.gmatch,string.sub,string.len local rep,find,gmatch,sub,len = string.rep,string.find,string.gmatch,string.sub,string.len
return function(name) return function(name, basalt)
local base = Object(name) local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Textfield" local objectType = "Textfield"
local hIndex, wIndex, textX, textY = 1, 1, 1, 1 local hIndex, wIndex, textX, textY = 1, 1, 1, 1
@@ -20,8 +17,7 @@ return function(name)
local selectionBG,selectionFG = colors.lightBlue,colors.black local selectionBG,selectionFG = colors.lightBlue,colors.black
base.width = 30 base:setSize(30, 12)
base.height = 12
base:setZIndex(5) base:setZIndex(5)
local function isSelected() local function isSelected()
@@ -32,57 +28,56 @@ return function(name)
end end
local function getSelectionCoordinates() local function getSelectionCoordinates()
local sx,ex,sy,ey local sx, ex, sy, ey = startSelX, endSelX, startSelY, endSelY
if(isSelected())then if isSelected() then
if(startSelX>endSelX)then if startSelX < endSelX and startSelY <= endSelY then
sx,ex = endSelX,startSelX sx = startSelX
else ex = endSelX
sx,ex = startSelX,endSelX if startSelY < endSelY then
end sy = startSelY
if(startSelY>endSelY)then ey = endSelY
sy,ey = endSelY,startSelY else
else sy = endSelY
sy,ey = startSelY,endSelY ey = startSelY
end
elseif startSelX > endSelX and startSelY >= endSelY then
sx = endSelX
ex = startSelX
if startSelY > endSelY then
sy = endSelY
ey = startSelY
else
sy = startSelY
ey = endSelY
end
elseif startSelY > endSelY then
sx = endSelX
ex = startSelX
sy = endSelY
ey = startSelY
end end
return sx, ex, sy, ey
end end
return sx,ex,sy,ey
end
local function getSelection()
end end
local function removeSelection(self) local function removeSelection(self)
local sx,ex,sy,ey = getSelectionCoordinates(self) local sx, ex, sy, ey = getSelectionCoordinates(self)
for n=ey,sy,-1 do local startLine = lines[sy]
if(n==sy)or(n==ey)then local endLine = lines[ey]
local l = lines[n] lines[sy] = startLine:sub(1, sx - 1) .. endLine:sub(ex + 1, endLine:len())
local b = bgLines[n] bgLines[sy] = bgLines[sy]:sub(1, sx - 1) .. bgLines[ey]:sub(ex + 1, bgLines[ey]:len())
local f = fgLines[n] fgLines[sy] = fgLines[sy]:sub(1, sx - 1) .. fgLines[ey]:sub(ex + 1, fgLines[ey]:len())
if(n==sy)and(n==ey)then
l = l:sub(1,sx-1)..l:sub(ex+1,l:len()) for i = ey, sy + 1, -1 do
b = b:sub(1,sx-1)..b:sub(ex+1,b:len()) if i ~= sy then
f = f:sub(1,sx-1)..f:sub(ex+1,f:len()) table.remove(lines, i)
elseif(n==sx)then table.remove(bgLines, i)
l = l:sub(1, sx) table.remove(fgLines, i)
b = b:sub(1, sx)
f = f:sub(1, sx)
elseif(n==sy)then
l = l:sub(ex, l:len())
b = b:sub(ex, b:len())
f = f:sub(ex, f:len())
end
lines[n] = l
bgLines[n] = b
fgLines[n] = f
else
table.remove(lines, n)
table.remove(bgLines, n)
table.remove(fgLines, n)
end end
end end
textX,textY = startSelX,startSelY
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil textX, textY = sx, sy
startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil
return self return self
end end
@@ -105,8 +100,8 @@ return function(name)
local function updateColors(self, l) local function updateColors(self, l)
l = l or textY l = l or textY
local fgLine = tHex[self.fgColor]:rep(fgLines[l]:len()) local fgLine = tHex[self:getForeground()]:rep(fgLines[l]:len())
local bgLine = tHex[self.bgColor]:rep(bgLines[l]:len()) local bgLine = tHex[self:getBackground()]:rep(bgLines[l]:len())
for k,v in pairs(rules)do for k,v in pairs(rules)do
local pos = stringGetPositions(lines[l], v[1]) local pos = stringGetPositions(lines[l], v[1])
if(#pos>0)then if(#pos>0)then
@@ -160,60 +155,30 @@ return function(name)
return self return self
end, end,
setValuesByXMLData = function(self, data) setSelection = function(self, fg, bg)
base.setValuesByXMLData(self, data) selectionFG = fg or selectionFG
if(data["lines"]~=nil)then selectionBG = bg or selectionBG
local l = data["lines"]["line"] return self
if(l.properties~=nil)then l = {l} end end,
for k,v in pairs(l)do
self:addLine(v:value())
end
end
if(data["keywords"]~=nil)then
for k,v in pairs(data["keywords"])do
if(colors[k]~=nil)then
local entry = v
if(entry.properties~=nil)then entry = {entry} end
local tab = {}
for a,b in pairs(entry)do
local keywordList = b["keyword"]
if(b["keyword"].properties~=nil)then keywordList = {b["keyword"]} end
for c,d in pairs(keywordList)do
table.insert(tab, d:value())
end
end
self:addKeywords(colors[k], tab)
end
end
end
if(data["rules"]~=nil)then
if(data["rules"]["rule"]~=nil)then
local tab = data["rules"]["rule"]
if(data["rules"]["rule"].properties~=nil)then tab = {data["rules"]["rule"]} end
for k,v in pairs(tab)do
if(xmlValue("pattern", v)~=nil)then getSelection = function(self)
self:addRule(xmlValue("pattern", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)]) return selectionFG, selectionBG
end
end
end
end
end, end,
getLines = function(self) getLines = function(self)
return lines return lines
end; end,
getLine = function(self, index) getLine = function(self, index)
return lines[index] return lines[index]
end; end,
editLine = function(self, index, text) editLine = function(self, index, text)
lines[index] = text or lines[index] lines[index] = text or lines[index]
updateColors(self, index) updateColors(self, index)
self:updateDraw() self:updateDraw()
return self return self
end; end,
clear = function(self) clear = function(self)
lines = {""} lines = {""}
@@ -227,21 +192,23 @@ return function(name)
addLine = function(self, text, index) addLine = function(self, text, index)
if(text~=nil)then if(text~=nil)then
local bgColor = self:getBackground()
local fgColor = self:getForeground()
if(#lines==1)and(lines[1]=="")then if(#lines==1)and(lines[1]=="")then
lines[1] = text lines[1] = text
bgLines[1] = tHex[self.bgColor]:rep(text:len()) bgLines[1] = tHex[bgColor]:rep(text:len())
fgLines[1] = tHex[self.fgColor]:rep(text:len()) fgLines[1] = tHex[fgColor]:rep(text:len())
updateColors(self, 1) updateColors(self, 1)
return self return self
end end
if (index ~= nil) then if (index ~= nil) then
table.insert(lines, index, text) table.insert(lines, index, text)
table.insert(bgLines, index, tHex[self.bgColor]:rep(text:len())) table.insert(bgLines, index, tHex[bgColor]:rep(text:len()))
table.insert(fgLines, index, tHex[self.fgColor]:rep(text:len())) table.insert(fgLines, index, tHex[fgColor]:rep(text:len()))
else else
table.insert(lines, text) table.insert(lines, text)
table.insert(bgLines, tHex[self.bgColor]:rep(text:len())) table.insert(bgLines, tHex[bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len())) table.insert(fgLines, tHex[fgColor]:rep(text:len()))
end end
end end
updateColors(self, index or #lines) updateColors(self, index or #lines)
@@ -285,13 +252,13 @@ return function(name)
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
setKeywords = function(self, color, tab) setKeywords = function(self, color, tab)
keyWords[color] = tab keyWords[color] = tab
self:updateDraw() self:updateDraw()
return self return self
end; end,
removeLine = function(self, index) removeLine = function(self, index)
if(#lines>1)then if(#lines>1)then
@@ -305,83 +272,91 @@ return function(name)
end end
self:updateDraw() self:updateDraw()
return self return self
end; end,
getTextCursor = function(self) getTextCursor = function(self)
return textX, textY return textX, textY
end; end,
getOffset = function(self)
return wIndex, hIndex
end,
setOffset = function(self, xOff, yOff)
wIndex = xOff or wIndex
hIndex = yOff or hIndex
self:updateDraw()
return self
end,
getFocusHandler = function(self) getFocusHandler = function(self)
base.getFocusHandler(self) base.getFocusHandler(self)
if (self.parent ~= nil) then local obx, oby = self:getPosition()
local obx, oby = self:getAnchorPosition() self:getParent():setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self:getForeground())
if (self.parent ~= nil) then end,
self.parent:setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self.fgColor)
end
end
end;
loseFocusHandler = function(self) loseFocusHandler = function(self)
base.loseFocusHandler(self) base.loseFocusHandler(self)
if (self.parent ~= nil) then self:getParent():setCursor(false)
self.parent:setCursor(false) end,
end
end;
keyHandler = function(self, key) keyHandler = function(self, key)
if (base.keyHandler(self, event, key)) then if (base.keyHandler(self, event, key)) then
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (key == keys.backspace) then if (key == keys.backspace) then
-- on backspace -- on backspace
if (lines[textY] == "") then if(isSelected())then
if (textY > 1) then removeSelection(self)
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
textY = textY - 1
end
elseif (textX <= 1) then
if (textY > 1) then
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
lines[textY - 1] = lines[textY - 1] .. lines[textY]
fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY]
bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY]
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textY = textY - 1
end
else else
lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len()) if (lines[textY] == "") then
fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len()) if (textY > 1) then
bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len()) table.remove(lines, textY)
if (textX > 1) then table.remove(fgLines, textY)
textX = textX - 1 table.remove(bgLines, textY)
end textX = lines[textY - 1]:len() + 1
if (wIndex > 1) then wIndex = textX - w + 1
if (textX < wIndex) then if (wIndex < 1) then
wIndex = wIndex - 1 wIndex = 1
end
textY = textY - 1
end
elseif (textX <= 1) then
if (textY > 1) then
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
lines[textY - 1] = lines[textY - 1] .. lines[textY]
fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY]
bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY]
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textY = textY - 1
end
else
lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
if (textX > 1) then
textX = textX - 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
end
end end
end end
end if (textY < hIndex) then
if (textY < hIndex) then hIndex = hIndex - 1
hIndex = hIndex - 1 end
end end
updateColors(self) updateColors(self)
self:setValue("") self:setValue("")
end elseif (key == keys.delete) then
if (key == keys.delete) then
-- on delete -- on delete
if(isSelected())then if(isSelected())then
removeSelection(self) removeSelection(self)
@@ -400,9 +375,10 @@ return function(name)
end end
end end
updateColors(self) updateColors(self)
end elseif (key == keys.enter) then
if(isSelected())then
if (key == keys.enter) then removeSelection(self)
end
-- on enter -- on enter
table.insert(lines, textY + 1, lines[textY]:sub(textX, lines[textY]:len())) table.insert(lines, textY + 1, lines[textY]:sub(textX, lines[textY]:len()))
table.insert(fgLines, textY + 1, fgLines[textY]:sub(textX, fgLines[textY]:len())) table.insert(fgLines, textY + 1, fgLines[textY]:sub(textX, fgLines[textY]:len()))
@@ -417,9 +393,8 @@ return function(name)
hIndex = hIndex + 1 hIndex = hIndex + 1
end end
self:setValue("") self:setValue("")
end elseif (key == keys.up) then
startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
if (key == keys.up) then
-- arrow up -- arrow up
if (textY > 1) then if (textY > 1) then
textY = textY - 1 textY = textY - 1
@@ -440,8 +415,8 @@ return function(name)
end end
end end
end end
end elseif (key == keys.down) then
if (key == keys.down) then startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow down -- arrow down
if (textY < #lines) then if (textY < #lines) then
textY = textY + 1 textY = textY + 1
@@ -460,8 +435,8 @@ return function(name)
hIndex = hIndex + 1 hIndex = hIndex + 1
end end
end end
end elseif (key == keys.right) then
if (key == keys.right) then startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow right -- arrow right
textX = textX + 1 textX = textX + 1
if (textY < #lines) then if (textY < #lines) then
@@ -482,8 +457,8 @@ return function(name)
wIndex = 1 wIndex = 1
end end
end elseif (key == keys.left) then
if (key == keys.left) then startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow left -- arrow left
textX = textX - 1 textX = textX - 1
if (textX >= 1) then if (textX >= 1) then
@@ -504,6 +479,19 @@ return function(name)
if (wIndex < 1) then if (wIndex < 1) then
wIndex = 1 wIndex = 1
end end
elseif(key == keys.tab)then
if(textX % 3 == 0 )then
lines[textY] = lines[textY]:sub(1, textX - 1) .. " " .. 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())
textX = textX + 1
end
while textX % 3 ~= 0 do
lines[textY] = lines[textY]:sub(1, textX - 1) .. " " .. 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())
textX = textX + 1
end
end end
if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then
@@ -519,7 +507,7 @@ return function(name)
if (cursorX < 1) then if (cursorX < 1) then
cursorX = 0 cursorX = 0
end end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor) parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground())
self:updateDraw() self:updateDraw()
return true return true
end end
@@ -527,11 +515,15 @@ return function(name)
charHandler = function(self, char) charHandler = function(self, char)
if(base.charHandler(self, char))then if(base.charHandler(self, char))then
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local obx, oby = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if(isSelected())then
removeSelection(self)
end
lines[textY] = lines[textY]:sub(1, textX - 1) .. char .. lines[textY]:sub(textX, lines[textY]:len()) 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.fgColor] .. fgLines[textY]:sub(textX, fgLines[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.bgColor] .. bgLines[textY]:sub(textX, bgLines[textY]:len()) bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self:getBackground()] .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + 1 textX = textX + 1
if (textX >= w + wIndex) then if (textX >= w + wIndex) then
wIndex = wIndex + 1 wIndex = wIndex + 1
@@ -552,10 +544,7 @@ return function(name)
if (cursorX < 1) then if (cursorX < 1) then
cursorX = 0 cursorX = 0
end end
if(isSelected())then parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground())
removeSelection(self)
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
self:updateDraw() self:updateDraw()
return true return true
end end
@@ -563,28 +552,29 @@ return function(name)
dragHandler = function(self, button, x, y) dragHandler = function(self, button, x, y)
if (base.dragHandler(self, button, x, y)) then if (base.dragHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local parent = self:getParent()
local anchx, anchy = self:getAnchorPosition() local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
if (lines[y - oby + hIndex] ~= nil) then if (lines[y - oby + hIndex] ~= nil) then
if(anchx+w > anchx + x - (obx+1)+ wIndex)and(anchx < anchx + x - obx+ wIndex)then if anchx <= x - obx + wIndex and anchx + w > x - obx + wIndex then
textX = x - obx + wIndex textX = x - obx + wIndex
textY = y - oby + hIndex textY = y - oby + hIndex
endSelX = textX
endSelY = textY if textX > lines[textY]:len() then
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1 textX = lines[textY]:len() + 1
endSelX = textX
end end
if (textX < wIndex) then endSelX = textX
endSelY = textY
if textX < wIndex then
wIndex = textX - 1 wIndex = textX - 1
if (wIndex < 1) then if wIndex < 1 then
wIndex = 1 wIndex = 1
end end
end end
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor) parent:setCursor(not isSelected(), anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground())
self:updateDraw() self:updateDraw()
end end
end end
@@ -594,8 +584,9 @@ return function(name)
scrollHandler = function(self, dir, x, y) scrollHandler = function(self, dir, x, y)
if (base.scrollHandler(self, dir, x, y)) then if (base.scrollHandler(self, dir, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local parent = self:getParent()
local anchx, anchy = self:getAnchorPosition() local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
local w,h = self:getSize() local w,h = self:getSize()
hIndex = hIndex + dir hIndex = hIndex + dir
if (hIndex > #lines - (h - 1)) then if (hIndex > #lines - (h - 1)) then
@@ -607,9 +598,9 @@ return function(name)
end end
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (anchy + textY - hIndex >= anchy and anchy + textY - hIndex < anchy + h) then if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (anchy + textY - hIndex >= anchy and anchy + textY - hIndex < anchy + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor) parent:setCursor(not isSelected(), anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground())
else else
self.parent:setCursor(false) parent:setCursor(false)
end end
self:updateDraw() self:updateDraw()
return true return true
@@ -618,8 +609,9 @@ return function(name)
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then if (base.mouseHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local parent = self:getParent()
local anchx, anchy = self:getAnchorPosition() local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
if (lines[y - oby + hIndex] ~= nil) then if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex textX = x - obx + wIndex
textY = y - oby + hIndex textY = y - oby + hIndex
@@ -639,17 +631,15 @@ return function(name)
end end
self:updateDraw() self:updateDraw()
end end
if (self.parent ~= nil) then parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground())
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
return true return true
end end
end, end,
mouseUpHandler = function(self, button, x, y) mouseUpHandler = function(self, button, x, y)
if (base.mouseUpHandler(self, button, x, y)) then if (base.mouseUpHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getAnchorPosition() local anchx, anchy = self:getPosition()
if (lines[y - oby + hIndex] ~= nil) then if (lines[y - oby + hIndex] ~= nil) then
endSelX = x - obx + wIndex endSelX = x - obx + wIndex
endSelY = y - oby + hIndex endSelY = y - oby + hIndex
@@ -669,16 +659,18 @@ return function(name)
if(base.eventHandler(self, event, paste, p2, p3, p4))then if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then if(event=="paste")then
if(self:isFocused())then if(self:isFocused())then
local parent = self:getParent()
local fgColor, bgColor = self:getForeground(), self:getBackground()
local w, h = self:getSize() local w, h = self:getSize()
lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len()) 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[self.fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len()) fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor]:rep(paste:len()) .. bgLines[textY]:sub(textX, bgLines[textY]:len()) bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[bgColor]:rep(paste:len()) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + paste:len() textX = textX + paste:len()
if (textX >= w + wIndex) then if (textX >= w + wIndex) then
wIndex = (textX+1)-w wIndex = (textX+1)-w
end end
local anchx, anchy = self:getAnchorPosition() local anchx, anchy = self:getPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor) parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, fgColor)
updateColors(self) updateColors(self)
self:updateDraw() self:updateDraw()
end end
@@ -686,81 +678,67 @@ return function(name)
end end
end, end,
setSelectionColor = function(self, bg, fg)
selectionBG = bg or selectionBG
selectionFG = fg or selectionFG
return self
end,
draw = function(self) draw = function(self)
if (base.draw(self)) then base.draw(self)
if (self.parent ~= nil) then self:addDraw("textfield", function()
local obx, oby = self:getAnchorPosition() local parent = self:getParent()
local w,h = self:getSize() local obx, oby = self:getPosition()
for n = 1, h do local w, h = self:getSize()
local text = "" local bgColor = tHex[self:getBackground()]
local bg = "" local fgColor = tHex[self:getForeground()]
local fg = ""
if (lines[n + hIndex - 1] ~= nil) then for n = 1, h do
text = lines[n + hIndex - 1] local text = ""
fg = fgLines[n + hIndex - 1] local bg = ""
bg = bgLines[n + hIndex - 1] local fg = ""
end if lines[n + hIndex - 1] then
text = text:sub(wIndex, w + wIndex - 1) text = lines[n + hIndex - 1]
bg = bg:sub(wIndex, w + wIndex - 1) fg = fgLines[n + hIndex - 1]
fg = fg:sub(wIndex, w + wIndex - 1) bg = bgLines[n + hIndex - 1]
local space = w - text:len()
if (space < 0) then
space = 0
end
text = text .. rep(self.bgSymbol, space)
bg = bg .. rep(tHex[self.bgColor], space)
fg = fg .. rep(tHex[self.fgColor], space)
self.parent:setText(obx, oby + n - 1, text)
self.parent:setBG(obx, oby + n - 1, bg)
self.parent:setFG(obx, oby + n - 1, fg)
end end
--[[
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then text = sub(text, wIndex, w + wIndex - 1)
local sx,ex,sy,ey = getSelectionCoordinates(self) bg = rep(bgColor, w)
for n=sy,ey do fg = rep(fgColor, w)
local line = lines[n]:len()
local xOffset = 0 self:addText(1, n, text)
if(n==sy)and(n==ey)then self:addBG(1, n, bg)
xOffset = sx-1 self:addFG(1, n, fg)
line = line - (sx-1) - (line - ex) self:addBlit(1, n, text, fg, bg)
elseif(n==ey)then end
line = line - (line - ex)
elseif(n==sy)then if startSelX and endSelX and startSelY and endSelY then
line = line-(sx-1) local sx, ex, sy, ey = getSelectionCoordinates(self)
xOffset = sx-1 for n = sy, ey do
end local line = #lines[n]
self.parent:setBG(obx + xOffset, oby + n - 1, rep(tHex[selectionBG], line)) local xOffset = 0
self.parent:setFG(obx + xOffset, oby + n - 1, rep(tHex[selectionFG], line)) if n == sy and n == ey then
xOffset = sx - 1
line = line - (sx - 1) - (line - ex)
elseif n == ey then
line = line - (line - ex)
elseif n == sy then
line = line - (sx - 1)
xOffset = sx - 1
end end
end]] self:addBG(1 + xOffset, n, rep(tHex[selectionBG], line))
if(self:isFocused())then self:addFG(1 + xOffset, n, rep(tHex[selectionFG], line))
local anchx, anchy = self:getAnchorPosition()
--self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end end
end end
end end)
end, end,
init = function(self) load = function(self)
self.parent:addEvent("mouse_click", self) self:listenEvent("mouse_click")
self.parent:addEvent("mouse_up", self) self:listenEvent("mouse_up")
self.parent:addEvent("mouse_scroll", self) self:listenEvent("mouse_scroll")
self.parent:addEvent("mouse_drag", self) self:listenEvent("mouse_drag")
self.parent:addEvent("key", self) self:listenEvent("key")
self.parent:addEvent("char", self) self:listenEvent("char")
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
if(base.init(self))then
self.bgColor = self.parent:getTheme("TextfieldBG")
self.fgColor = self.parent:getTheme("TextfieldText")
end
end, end,
} }
object.__index = object
return setmetatable(object, base) return setmetatable(object, base)
end end

View File

@@ -1,7 +1,6 @@
local xmlValue = require("utils").getValueFromXML return function(name, basalt)
local base = basalt.getObject("Object")(name, basalt)
return function(name)
local object
local objectType = "Thread" local objectType = "Thread"
local func local func
@@ -9,42 +8,9 @@ return function(name)
local isActive = false local isActive = false
local filter local filter
local generateXMLEventFunction = function(self, str) local object = {
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
return (function()o:internalObjetCall()end)
end
else
return self:getBaseFrame():getVariable(str)
end
return self
end
object = {
name = name,
getType = function(self) getType = function(self)
return objectType return objectType
end;
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
setValuesByXMLData = function(self, data)
local f
if(xmlValue("thread", data)~=nil)then f = generateXMLEventFunction(self, xmlValue("thread", data)) end
if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))and(f~=nil)then self:start(f) end end
return self
end, end,
start = function(self, f) start = function(self, f)
@@ -62,36 +28,36 @@ return function(name)
error("Thread Error Occurred - " .. result) error("Thread Error Occurred - " .. result)
end end
end end
self.parent:addEvent("mouse_click", self) self:listenEvent("mouse_click")
self.parent:addEvent("mouse_up", self) self:listenEvent("mouse_up")
self.parent:addEvent("mouse_scroll", self) self:listenEvent("mouse_scroll")
self.parent:addEvent("mouse_drag", self) self:listenEvent("mouse_drag")
self.parent:addEvent("key", self) self:listenEvent("key")
self.parent:addEvent("key_up", self) self:listenEvent("key_up")
self.parent:addEvent("char", self) self:listenEvent("char")
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
return self return self
end; end,
getStatus = function(self, f) getStatus = function(self, f)
if (cRoutine ~= nil) then if (cRoutine ~= nil) then
return coroutine.status(cRoutine) return coroutine.status(cRoutine)
end end
return nil return nil
end; end,
stop = function(self, f) stop = function(self, f)
isActive = false isActive = false
self.parent:removeEvent("mouse_click", self) self:listenEvent("mouse_click", false)
self.parent:removeEvent("mouse_up", self) self:listenEvent("mouse_up", false)
self.parent:removeEvent("mouse_scroll", self) self:listenEvent("mouse_scroll", false)
self.parent:removeEvent("mouse_drag", self) self:listenEvent("mouse_drag", false)
self.parent:removeEvent("key", self) self:listenEvent("key", false)
self.parent:removeEvent("key_up", self) self:listenEvent("key_up", false)
self.parent:removeEvent("char", self) self:listenEvent("char", false)
self.parent:removeEvent("other_event", self) self:listenEvent("other_event", false)
return self return self
end; end,
mouseHandler = function(self, ...) mouseHandler = function(self, ...)
self:eventHandler("mouse_click", ...) self:eventHandler("mouse_click", ...)
@@ -119,6 +85,7 @@ return function(name)
end, end,
eventHandler = function(self, event, ...) eventHandler = function(self, event, ...)
base.eventHandler(self, event, ...)
if (isActive) then if (isActive) then
if (coroutine.status(cRoutine) == "suspended") then if (coroutine.status(cRoutine) == "suspended") then
if(filter~=nil)then if(filter~=nil)then
@@ -136,11 +103,10 @@ return function(name)
self:stop() self:stop()
end end
end end
end; end,
} }
object.__index = object object.__index = object
return setmetatable(object, base)
return object
end end

View File

@@ -1,71 +1,23 @@
local basaltEvent = require("basaltEvent") return function(name, basalt)
local xmlValue = require("utils").getValueFromXML local base = basalt.getObject("Object")(name, basalt)
return function(name)
local objectType = "Timer" local objectType = "Timer"
local timer = 0 local timer = 0
local savedRepeats = 0 local savedRepeats = 0
local repeats = 0 local repeats = 0
local timerObj local timerObj
local eventSystem = basaltEvent()
local timerIsActive = false local timerIsActive = false
local generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
local o = self:getBaseFrame():getDeepObject(str:sub(2,str:len()))
if(o~=nil)and(o.internalObjetCall~=nil)then
func(self,function()o:internalObjetCall()end)
end
else
func(self,self:getBaseFrame():getVariable(str))
end
end
if(type(val)=="string")then
createF(val)
elseif(type(val)=="table")then
for k,v in pairs(val)do
createF(v)
end
end
return self
end
local object = { local object = {
name = name,
getType = function(self) getType = function(self)
return objectType return objectType
end;
setValuesByXMLData = function(self, data)
if(xmlValue("time", data)~=nil)then timer = xmlValue("time", data) end
if(xmlValue("repeat", data)~=nil)then savedRepeats = xmlValue("repeat", data) end
if(xmlValue("start", data)~=nil)then if(xmlValue("start", data))then self:start() end end
if(xmlValue("onCall", data)~=nil)then generateXMLEventFunction(self, self.onCall, xmlValue("onCall", data)) end
return self
end, end,
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
getZIndex = function(self)
return 1
end;
getName = function(self)
return self.name
end;
setTime = function(self, _timer, _repeats) setTime = function(self, _timer, _repeats)
timer = _timer or 0 timer = _timer or 0
savedRepeats = _repeats or 1 savedRepeats = _repeats or 1
return self return self
end; end,
start = function(self) start = function(self)
if(timerIsActive)then if(timerIsActive)then
@@ -74,31 +26,32 @@ return function(name)
repeats = savedRepeats repeats = savedRepeats
timerObj = os.startTimer(timer) timerObj = os.startTimer(timer)
timerIsActive = true timerIsActive = true
self.parent:addEvent("other_event", self) self:listenEvent("other_event")
return self return self
end; end,
isActive = function(self) isActive = function(self)
return timerIsActive return timerIsActive
end; end,
cancel = function(self) cancel = function(self)
if (timerObj ~= nil) then if (timerObj ~= nil) then
os.cancelTimer(timerObj) os.cancelTimer(timerObj)
end end
timerIsActive = false timerIsActive = false
self.parent:removeEvent("other_event", self) self:removeEvent("other_event")
return self return self
end; end,
onCall = function(self, func) onCall = function(self, func)
eventSystem:registerEvent("timed_event", func) self:registerEvent("timed_event", func)
return self return self
end; end,
eventHandler = function(self, event, tObj) eventHandler = function(self, event, ...)
base.eventHandler(self, event, ...)
if event == "timer" and tObj == timerObj and timerIsActive then if event == "timer" and tObj == timerObj and timerIsActive then
eventSystem:sendEvent("timed_event", self) self:sendEvent("timed_event")
if (repeats >= 1) then if (repeats >= 1) then
repeats = repeats - 1 repeats = repeats - 1
if (repeats >= 1) then if (repeats >= 1) then
@@ -108,9 +61,9 @@ return function(name)
timerObj = os.startTimer(timer) timerObj = os.startTimer(timer)
end end
end end
end; end,
} }
object.__index = object
return object object.__index = object
return setmetatable(object, base)
end end

320
Basalt/objects/Treeview.lua Normal file
View File

@@ -0,0 +1,320 @@
local utils = require("utils")
local tHex = require("tHex")
return function(name, basalt)
local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "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:setSize(16, 8)
base:setZIndex(5)
local function newNode(text, expandable)
text = text or ""
expandable = expandable or false
local expanded = false
local parent = nil
local children = {}
local node = {}
local onSelect
node = {
getChildren = function()
return children
end,
setParent = function(p)
if(parent~=nil)then
parent.removeChild(parent.findChildrenByText(node.getText()))
end
parent = p
base:updateDraw()
return node
end,
getParent = function()
return parent
end,
addChild = function(text, expandable)
local childNode = newNode(text, expandable)
childNode.setParent(node)
table.insert(children, childNode)
base:updateDraw()
return childNode
end,
setExpanded = function(exp)
if(expandable)then
expanded = exp
end
base:updateDraw()
return node
end,
isExpanded = function()
return expanded
end,
onSelect = function(...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
onSelect = v
end
end
return node
end,
callOnSelect = function()
if(onSelect~=nil)then
onSelect(node)
end
end,
setExpandable = function(expandable)
expandable = expandable
base:updateDraw()
return node
end,
isExpandable = function()
return expandable
end,
removeChild = function(index)
if(type(index)=="table")then
for k,v in pairs(index)do
if(v==index)then
index = k
break
end
end
end
table.remove(children, index)
base:updateDraw()
return node
end,
findChildrenByText = function(searchText)
local foundNodes = {}
for _, child in ipairs(children) do
if string.find(child.getText(), searchText) then
table.insert(foundNodes, child)
end
end
return foundNodes
end,
getText = function()
return text
end,
setText = function(t)
text = t
base:updateDraw()
return node
end
}
return node
end
local root = newNode("Root", true)
root.setExpanded(true)
local object = {
init = function(self)
local parent = self:getParent()
self:listenEvent("mouse_click")
self:listenEvent("mouse_scroll")
return base.init(self)
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,
setOffset = function(self, x, y)
xOffset = x
yOffset = y
return self
end,
getOffset = function(self)
return xOffset, yOffset
end,
setScrollable = function(self, scroll)
scrollable = scroll
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,
getSelectionColor = function(self)
return itemSelectedBG, 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
self:registerEvent("treeview_select", v)
end
end
return self
end,
selectionHandler = function(self, node)
node.callOnSelect(node)
self:sendEvent("treeview_select", node)
return self
end,
mouseHandler = function(self, button, x, y)
if base.mouseHandler(self, button, x, y) then
local currentLine = 1 - yOffset
local obx, oby = self:getAbsolutePosition()
local w, h = self:getSize()
local function checkNodeClick(node, level)
if y == oby+currentLine-1 then
if x >= obx and x < obx + w then
node.setExpanded(not node.isExpanded())
self:selectionHandler(node)
self:setValue(node)
self:updateDraw()
return true
end
end
currentLine = currentLine + 1
if node.isExpanded() then
for _, child in ipairs(node.getChildren()) do
if checkNodeClick(child, level + 1) then
return true
end
end
end
return false
end
for _, item in ipairs(root.getChildren()) do
if checkNodeClick(item, 1) then
return true
end
end
end
end,
scrollHandler = function(self, dir, x, y)
if base.scrollHandler(self, dir, x, y) then
if scrollable then
local _, h = self:getSize()
yOffset = yOffset + dir
if yOffset < 0 then
yOffset = 0
end
if dir >= 1 then
local visibleLines = 0
local function countVisibleLines(node, level)
visibleLines = visibleLines + 1
if node.isExpanded() then
for _, child in ipairs(node.getChildren()) do
countVisibleLines(child, level + 1)
end
end
end
for _, item in ipairs(root.getChildren()) do
countVisibleLines(item, 1)
end
if visibleLines > h then
if yOffset > visibleLines - h then
yOffset = visibleLines - h
end
else
yOffset = yOffset - 1
end
end
self:updateDraw()
end
return true
end
return false
end,
draw = function(self)
base.draw(self)
self:addDraw("treeview", function()
local currentLine = 1 - yOffset
local lastClickedNode = self:getValue()
local function drawNode(node, level)
local w, h = self:getSize()
if currentLine >= 1 and currentLine <= h then
local bg = (node == lastClickedNode) and itemSelectedBG or self:getBackground()
local fg = (node == lastClickedNode) and itemSelectedFG or self:getForeground()
local text = node.getText()
self:addBlit(1 + level + xOffset, currentLine, text, tHex[fg]:rep(#text), tHex[bg]:rep(#text))
end
currentLine = currentLine + 1
if node.isExpanded() then
for _, child in ipairs(node.getChildren()) do
drawNode(child, level + 1)
end
end
end
for _, item in ipairs(root.getChildren()) do
drawNode(item, 1)
end
end)
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -0,0 +1,630 @@
local utils = require("utils")
local tHex = require("tHex")
local sub, find, insert = string.sub, string.find, table.insert
return function(name, basalt)
local base = basalt.getObject("Object")(name, basalt)
-- Base object
local objectType = "VisualObject" -- not changeable
local isVisible,ignOffset,isHovered,isClicked,isDragging = true,false,false,false,false
local zIndex = 1
local x, y, width, height = 1,1,1,1
local dragStartX, dragStartY, dragXOffset, dragYOffset = 0, 0, 0, 0
local bgColor,fgColor, transparency = colors.black, colors.white, false
local parent
local preDrawQueue = {}
local drawQueue = {}
local postDrawQueue = {}
local renderObject = {}
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
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)
return basalt
end,
show = function(self)
isVisible = true
self:updateDraw()
return self
end,
hide = function(self)
isVisible = false
self:updateDraw()
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
end,
setParent = function(self, newParent, noRemove)
base.setParent(self, newParent, noRemove)
parent = newParent
return self
end,
setFocus = function(self)
if (parent ~= nil) then
parent:setFocusedObject(self)
end
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()
end
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,
getY = function(self)
return y
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,
getWidth = function(self)
return width
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
if (parent ~= nil) then
local fx, fy = parent:getAbsolutePosition()
x = fx + x - 1
y = fy + y - 1
end
return x, y
end,
ignoreOffset = function(self, ignore)
ignOffset = ignore
if(ignore==nil)then ignOffset = true end
return self
end,
getIgnoreOffset = function(self)
return ignOffset
end,
isCoordsInObject = function(self, x, y)
if(isVisible)and(self:isEnabled())then
if(x==nil)or(y==nil)then return false end
local objX, objY = self:getAbsolutePosition()
local w, h = self:getSize()
if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) then
return true
end
end
return false
end,
onGetFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("get_focus", v)
end
end
return self
end,
onLoseFocus = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("lose_focus", v)
end
end
return self
end,
isFocused = function(self)
if (parent ~= nil) then
return parent:getFocusedObject() == self
end
return true
end,
resizeHandler = function(self, ...)
if(self:isEnabled())then
local val = self:sendEvent("basalt_resize", ...)
if(val==false)then return false end
end
return true
end,
repositionHandler = function(self, ...)
if(self:isEnabled())then
local val = self:sendEvent("basalt_reposition", ...)
if(val==false)then return false end
end
return true
end,
onResize = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("basalt_resize", v)
end
end
return self
end,
onReposition = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("basalt_reposition", v)
end
end
return self
end,
mouseHandler = function(self, button, x, y, isMon)
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
local val = self:sendEvent("mouse_click", button, x - (objX-1), y - (objY-1), x, y, isMon)
if(val==false)then return false end
if(parent~=nil)then
parent:setFocusedObject(self)
end
isClicked = true
isDragging = true
dragStartX, dragStartY = x, y
return true
end
end,
mouseUpHandler = function(self, button, x, y)
isDragging = false
if(isClicked)then
local objX, objY = self:getAbsolutePosition()
local val = self:sendEvent("mouse_release", button, x - (objX-1), y - (objY-1), x, y)
isClicked = false
end
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
local val = self:sendEvent("mouse_up", button, x - (objX-1), y - (objY-1), x, y)
if(val==false)then return false end
return true
end
end,
dragHandler = function(self, button, x, y)
if(isDragging)then
local objX, objY = self:getAbsolutePosition()
local val = self:sendEvent("mouse_drag", button, x - (objX-1), y - (objY-1), dragStartX-x, dragStartY-y, x, y)
dragStartX, dragStartY = x, y
if(val~=nil)then return val end
if(parent~=nil)then
parent:setFocusedObject(self)
end
return true
end
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
dragStartX, dragStartY = x, y
dragXOffset, dragYOffset = objX - x, objY - y
end
end,
scrollHandler = function(self, dir, x, y)
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
local val = self:sendEvent("mouse_scroll", dir, x - (objX-1), y - (objY-1))
if(val==false)then return false end
if(parent~=nil)then
parent:setFocusedObject(self)
end
return true
end
end,
hoverHandler = function(self, x, y, stopped)
if(self:isCoordsInObject(x, y))then
local val = self:sendEvent("mouse_hover", x, y, stopped)
if(val==false)then return false end
isHovered = 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
end
end,
keyHandler = function(self, key, isHolding)
if(self:isEnabled())and(isVisible)then
if (self:isFocused()) then
local val = self:sendEvent("key", key, isHolding)
if(val==false)then return false end
return true
end
end
end,
keyUpHandler = function(self, key)
if(self:isEnabled())and(isVisible)then
if (self:isFocused()) then
local val = self:sendEvent("key_up", key)
if(val==false)then return false end
return true
end
end
end,
charHandler = function(self, char)
if(self:isEnabled())and(isVisible)then
if(self:isFocused())then
local val = self:sendEvent("char", char)
if(val==false)then return false end
return true
end
end
end,
getFocusHandler = function(self)
local val = self:sendEvent("get_focus")
if(val~=nil)then return val end
return true
end,
loseFocusHandler = function(self)
isDragging = false
local val = self:sendEvent("lose_focus")
if(val~=nil)then return val end
return true
end,
addDraw = function(self, name, f, pos, typ, active)
local queue = (typ==nil or typ==1) and drawQueue or typ==2 and preDrawQueue or typ==3 and postDrawQueue
pos = pos or #queue+1
if(name~=nil)then
for k,v in pairs(queue)do
if(v.name==name)then
table.remove(queue, k)
break
end
end
local t = {name=name, f=f, pos=pos, active=active~=nil and active or true}
table.insert(queue, pos, t)
end
self:updateDraw()
return self
end,
addPreDraw = function(self, name, f, pos, typ)
self:addDraw(name, f, pos, 2)
return self
end,
addPostDraw = function(self, name, f, pos, typ)
self:addDraw(name, f, pos, 3)
return self
end,
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
v.active = state
break
end
end
self:updateDraw()
return self
end,
getDrawId = function(self, name, typ)
local queue = typ==1 and drawQueue or typ==2 and preDrawQueue or typ==3 and postDrawQueue or drawQueue
for k,v in pairs(queue)do
if(v.name==name)then
return k
end
end
end,
addText = function(self, x, y, text)
local obj = self:getParent() or self
local xPos,yPos = self:getPosition()
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:setText(x+xPos-1, y+yPos-1, text)
return
end
local t = split(text, "\0")
for k,v in pairs(t)do
if(v.value~="")and(v.value~="\0")then
obj:setText(x+v.x+xPos-2, y+yPos-1, v.value)
end
end
end,
addBG = function(self, x, y, bg, noText)
local obj = parent or self
local xPos,yPos = self:getPosition()
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)
return
end
local t = split(bg)
for k,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)
else
table.insert(renderObject, {x=x+v.x-1,y=y,bg=v.value})
obj:setBG(x+xPos-1, y+yPos-1, fg)
end
end
end
end,
addFG = function(self, x, y, fg)
local obj = parent or self
local xPos,yPos = self:getPosition()
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)
return
end
local t = split(fg)
for k,v in pairs(t)do
if(v.value~="")and(v.value~=" ")then
obj:setFG(x+v.x+xPos-2, y+yPos-1, v.value)
end
end
end,
addBlit = function(self, x, y, t, fg, bg)
local obj = parent or self
local xPos,yPos = self:getPosition()
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: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
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
if(v.value~="")or(v.value~=" ")then
obj:setBG(x+v.x+xPos-2, y+yPos-1, v.value)
end
end
for k,v in pairs(_fg)do
if(v.value~="")or(v.value~=" ")then
obj:setFG(x+v.x+xPos-2, y+yPos-1, v.value)
end
end
end,
addTextBox = function(self, x, y, w, h, text)
local obj = parent or self
local xPos,yPos = self:getPosition()
if(parent~=nil)then
local xO, yO = parent:getOffset()
xPos = ignOffset and xPos or xPos - xO
yPos = ignOffset and yPos or yPos - yO
end
obj:drawTextBox(x+xPos-1, y+yPos-1, w, h, text)
end,
addForegroundBox = function(self, x, y, w, h, col)
local obj = parent or self
local xPos,yPos = self:getPosition()
if(parent~=nil)then
local xO, yO = parent:getOffset()
xPos = ignOffset and xPos or xPos - xO
yPos = ignOffset and yPos or yPos - yO
end
obj:drawForegroundBox(x+xPos-1, y+yPos-1, w, h, col)
end,
addBackgroundBox = function(self, x, y, w, h, col)
local obj = parent or self
local xPos,yPos = self:getPosition()
if(parent~=nil)then
local xO, yO = parent:getOffset()
xPos = ignOffset and xPos or xPos - xO
yPos = ignOffset and yPos or yPos - yO
end
obj:drawBackgroundBox(x+xPos-1, y+yPos-1, w, h, col)
end,
render = function(self)
if (isVisible)then
self:redraw()
end
end,
redraw = function(self)
for k,v in pairs(preDrawQueue)do
if (v.active)then
v.f(self)
end
end
for k,v in pairs(drawQueue)do
if (v.active)then
v.f(self)
end
end
for k,v in pairs(postDrawQueue)do
if (v.active)then
v.f(self)
end
end
return true
end,
draw = function(self)
self:addDraw("base", function()
local w,h = self:getSize()
if(bgColor~=false)then
self:addTextBox(1, 1, w, h, " ")
self:addBackgroundBox(1, 1, w, h, bgColor)
end
if(fgColor~=false)then
self:addForegroundBox(1, 1, w, h, fgColor)
end
end, 1)
end,
}
object.__index = object
return setmetatable(object, base)
end

56
Basalt/plugin.lua Normal file
View File

@@ -0,0 +1,56 @@
local args = {...}
local plugins = {}
local dir = fs.getDir(args[2] or "Basalt")
local pluginDir = fs.combine(dir, "plugins")
if(packaged)then
for k,v in pairs(getProject("plugins"))do
local newPlugin = v()
if(type(newPlugin)=="table")then
for a,b in pairs(newPlugin)do
if(type(a)=="string")then
if(plugins[a]==nil)then plugins[a] = {} end
table.insert(plugins[a], b)
end
end
end
end
end
if(fs.exists(pluginDir))then
for _,v in pairs(fs.list(pluginDir))do
local newPlugin = require(v:gsub(".lua", ""))
if(type(newPlugin)=="table")then
for a,b in pairs(newPlugin)do
if(type(a)=="string")then
if(plugins[a]==nil)then plugins[a] = {} end
table.insert(plugins[a], b)
end
end
end
end
end
local function get(name)
return plugins[name]
end
return {
get = get,
addPlugins = function(objects, basalt)
for k,v in pairs(objects)do
local plugList = plugins[k]
if(plugList~=nil)then
objects[k] = function(...)
local moddedObject = v(...)
for a,b in pairs(plugList)do
local ext = b(moddedObject, basalt, ...)
ext.__index = ext
moddedObject = setmetatable(ext, moddedObject)
end
return moddedObject
end
end
end
return objects
end
}

View File

@@ -0,0 +1,54 @@
local utils = require("utils")
local xmlValue = utils.xmlValue
return {
VisualObject = function(base)
local bgSymbol = false
local bgSymbolColor = colors.black
local object = {
setBackground = function(self, bg, symbol, symbolCol)
base.setBackground(self, bg)
bgSymbol = symbol or bgSymbol
bgSymbolColor = symbolCol or bgSymbolColor
return self
end,
setBackgroundSymbol = function(self, symbol, symbolCol)
bgSymbol = symbol
bgSymbolColor = symbolCol or bgSymbolColor
self:updateDraw()
return self
end,
getBackgroundSymbol = function(self)
return bgSymbol
end,
getBackgroundSymbolColor = function(self)
return bgSymbolColor
end,
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("background-symbol", data)~=nil)then self:setBackgroundSymbol(xmlValue("background-symbol", data), xmlValue("background-symbol-color", data)) end
return self
end,
draw = function(self)
base.draw(self)
self:addDraw("advanced-bg", function()
local w, h = self:getSize()
if(bgSymbol~=false)then
self:addTextBox(1, 1, w, h, bgSymbol:sub(1,1))
if(bgSymbol~=" ")then
self:addForegroundBox(1, 1, w, h, bgSymbolColor)
end
end
end, 2)
end,
}
return object
end
}

View File

@@ -0,0 +1,362 @@
local floor,sin,cos,pi,sqrt,pow = math.floor,math.sin,math.cos,math.pi,math.sqrt,math.pow
-- You can find the easing curves here https://easings.net
local function lerp(s, e, pct)
return s + (e - s) * pct
end
local function linear(t)
return t
end
local function flip(t)
return 1 - t
end
local function easeIn(t)
return t * t * t
end
local function easeOut(t)
return flip(easeIn(flip(t)))
end
local function easeInOut(t)
return lerp(easeIn(t), easeOut(t), t)
end
local function easeOutSine(t)
return sin((t * pi) / 2);
end
local function easeInSine(t)
return flip(cos((t * pi) / 2))
end
local function easeInOutSine(t)
return -(cos(pi * x) - 1) / 2
end
local function easeInBack(t)
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
local function easeInCubic(t)
return t^3
end
local function easeInElastic(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (
-2^(10*t-10)*sin((t*10-10.75)*c4)
))
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInOutBack(t)
local c1 = 1.70158;
local c2 = c1 * 1.525;
return t < 0.5 and ((2*t)^2*((c2+1)*2*t-c2))/2 or ((2*t-2)^2*((c2+1)*(t*2-2)+c2)+2)/2
end
local function easeInOutCubic(t)
return t < 0.5 and 4 * t^3 or 1-(-2*t+2)^3 / 2
end
local function easeInOutElastic(t)
local c5 = (2*pi) / 4.5
return t==0 and 0 or (t == 1 and 1 or (t < 0.5 and -(2^(20*t-10) * sin((20*t - 11.125) * c5))/2 or (2^(-20*t+10) * sin((20*t - 11.125) * c5))/2 + 1))
end
local function easeInOutExpo(t)
return t == 0 and 0 or (t == 1 and 1 or (t < 0.5 and 2^(20*t-10)/2 or (2-2^(-20*t+10)) /2))
end
local function easeInOutQuad(t)
return t < 0.5 and 2*t^2 or 1-(-2*t+2)^2/2
end
local function easeInOutQuart(t)
return t < 0.5 and 8*t^4 or 1 - (-2*t+2)^4 / 2
end
local function easeInOutQuint(t)
return t < 0.5 and 16*t^5 or 1-(-2*t+2)^5 / 2
end
local function easeInQuad(t)
return t^2
end
local function easeInQuart(t)
return t^4
end
local function easeInQuint(t)
return t^5
end
local function easeOutBack(t)
local c1 = 1.70158;
local c3 = c1 + 1
return 1+c3*(t-1)^3+c1*(t-1)^2
end
local function easeOutCubic(t)
return 1 - (1-t)^3
end
local function easeOutElastic(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (2^(-10*t)*sin((t*10-0.75)*c4)+1))
end
local function easeOutExpo(t)
return t == 1 and 1 or 1-2^(-10*t)
end
local function easeOutQuad(t)
return 1 - (1 - t) * (1 - t)
end
local function easeOutQuart(t)
return 1 - (1-t)^4
end
local function easeOutQuint(t)
return 1 - (1 - t)^5
end
local function easeInCirc(t)
return 1 - sqrt(1 - pow(t, 2))
end
local function easeOutCirc(t)
return sqrt(1 - pow(t - 1, 2))
end
local function easeInOutCirc(t)
return t < 0.5 and (1 - sqrt(1 - pow(2 * t, 2))) / 2 or (sqrt(1 - pow(-2 * t + 2, 2)) + 1) / 2;
end
local function easeOutBounce(t)
local n1 = 7.5625;
local d1 = 2.75;
if (t < 1 / d1)then
return n1 * t * t
elseif (t < 2 / d1)then
local a = t - 1.5 / d1
return n1 * a * a + 0.75;
elseif (t < 2.5 / d1)then
local a = t - 2.25 / d1
return n1 * a * a + 0.9375;
else
local a = t - 2.625 / d1
return n1 * a * a + 0.984375;
end
end
local function easeInBounce(t)
return 1 - easeOutBounce(1 - t)
end
local function easeInOutBounce(t)
return x < 0.5 and (1 - easeOutBounce(1 - 2 * t)) / 2 or (1 + easeOutBounce(2 * t - 1)) / 2;
end
local lerp = {
linear = linear,
lerp = lerp,
flip=flip,
easeIn=easeIn,
easeInSine = easeInSine,
easeInBack=easeInBack,
easeInCubic=easeInCubic,
easeInElastic=easeInElastic,
easeInExpo=easeInExpo,
easeInQuad=easeInQuad,
easeInQuart=easeInQuart,
easeInQuint=easeInQuint,
easeInCirc=easeInCirc,
easeInBounce=easeInBounce,
easeOut=easeOut,
easeOutSine = easeOutSine,
easeOutBack=easeOutBack,
easeOutCubic=easeOutCubic,
easeOutElastic=easeOutElastic,
easeOutExpo=easeOutExpo,
easeOutQuad=easeOutQuad,
easeOutQuart=easeOutQuart,
easeOutQuint=easeOutQuint,
easeOutCirc=easeOutCirc,
easeOutBounce=easeOutBounce,
easeInOut=easeInOut,
easeInOutSine = easeInOutSine,
easeInOutBack=easeInOutBack,
easeInOutCubic=easeInOutCubic,
easeInOutElastic=easeInOutElastic,
easeInOutExpo=easeInOutExpo,
easeInOutQuad=easeInOutQuad,
easeInOutQuart=easeInOutQuart,
easeInOutQuint=easeInOutQuint,
easeInOutCirc=easeInOutCirc,
easeInOutBounce=easeInOutBounce,
}
local utils = require("utils")
local xmlValue = utils.xmlValue
return {
VisualObject = function(base, basalt)
local activeAnimations = {}
local defaultMode = "linear"
local function getAnimation(self, timerId)
for k,v in pairs(activeAnimations)do
if(v.timerId==timerId)then
return v
end
end
end
local function createAnimation(self, v1, v2, duration, timeOffset, mode, typ, f, get, set)
local v1Val, v2Val = get(self)
if(activeAnimations[typ]~=nil)then
os.cancelTimer(activeAnimations[typ].timerId)
end
activeAnimations[typ] = {}
activeAnimations[typ].call = function()
local progress = activeAnimations[typ].progress
local _v1 = math.floor(lerp.lerp(v1Val, v1, lerp[mode](progress / duration))+0.5)
local _v2 = math.floor(lerp.lerp(v2Val, v2, lerp[mode](progress / duration))+0.5)
set(self, _v1, _v2)
end
activeAnimations[typ].finished = function()
set(self, v1, v2)
if(f~=nil)then f(self) end
end
activeAnimations[typ].timerId=os.startTimer(0.05+timeOffset)
activeAnimations[typ].progress=0
activeAnimations[typ].duration=duration
activeAnimations[typ].mode=mode
self:listenEvent("other_event")
end
local function createColorAnimation(self, duration, timeOffset, typ, set, ...)
local newColors = {...}
if(activeAnimations[typ]~=nil)then
os.cancelTimer(activeAnimations[typ].timerId)
end
activeAnimations[typ] = {}
local colorIndex = 1
activeAnimations[typ].call = function()
local color = newColors[colorIndex]
set(self, color)
end
end
local object = {
animatePosition = function(self, x, y, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
x = math.floor(x+0.5)
y = math.floor(y+0.5)
createAnimation(self, x, y, duration, timeOffset, mode, "position", f, self.getPosition, self.setPosition)
return self
end,
animateSize = function(self, w, h, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createAnimation(self, w, h, duration, timeOffset, mode, "size", f, self.getSize, self.setSize)
return self
end,
animateOffset = function(self, x, y, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createAnimation(self, x, y, duration, timeOffset, mode, "offset", f, self.getOffset, self.setOffset)
return self
end,
animateBackground = function(self, color, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createColorAnimation(self, color, nil, duration, timeOffset, mode, "background", f, self.getBackground, self.setBackground)
return self
end,
doneHandler = function(self, timerId, ...)
for k,v in pairs(activeAnimations)do
if(v.timerId==timerId)then
activeAnimations[k] = nil
self:sendEvent("animation_done", self, "animation_done", k)
end
end
end,
onAnimationDone = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("animation_done", v)
end
end
return self
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
local animation = getAnimation(self, timerId)
if(animation~=nil)then
if(animation.progress<animation.duration)then
animation.call()
animation.progress = animation.progress+0.05
animation.timerId=os.startTimer(0.05)
else
animation.finished()
self:doneHandler(timerId)
end
end
end
end,
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local animX, animY, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateX", data), xmlValue("animateY", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
local animW, animH, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateW", data), xmlValue("animateH", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
local animXOffset, animYOffset, animateDuration, animeteTimeOffset, animateMode = xmlValue("animateXOffset", data), xmlValue("animateYOffset", data), xmlValue("animateDuration", data), xmlValue("animateTimeOffset", data), xmlValue("animateMode", data)
if(animX~=nil and animY~=nil)then
self:animatePosition(animX, animY, animateDuration, animeteTimeOffset, animateMode)
end
if(animW~=nil and animH~=nil)then
self:animateSize(animW, animH, animateDuration, animeteTimeOffset, animateMode)
end
if(animXOffset~=nil and animYOffset~=nil)then
self:animateOffset(animXOffset, animYOffset, animateDuration, animeteTimeOffset, animateMode)
end
return self
end,
}
return object
end
}

View File

@@ -0,0 +1,10 @@
return {
basalt = function()
return {
cool = function()
print("ello")
sleep(2)
end
}
end
}

View File

@@ -0,0 +1,42 @@
local utils = require("utils")
local wrapText = utils.wrapText
return {
basalt = function(basalt)
local frame
local errorList
return {
getBasaltErrorFrame = function()
return frame
end,
basaltError = function(err)
if(frame==nil)then
local mainFrame = basalt.getMainFrame()
local w, h = mainFrame:getSize()
frame = mainFrame:addMovableFrame("basaltErrorFrame"):setSize(w-10, h-4):setBackground(colors.lightGray):setForeground(colors.white):setZIndex(500)
frame:addPane("titleBackground"):setSize(w, 1):setPosition(1, 1):setBackground(colors.black):setForeground(colors.white)
frame:setPosition(w/2-frame:getWidth()/2, h/2-frame:getHeight()/2):setBorder(colors.black)
frame:addLabel("title"):setText("Basalt Unexpected Error"):setPosition(2, 1):setBackground(colors.black):setForeground(colors.white)
errorList = frame:addList("errorList"):setSize(frame:getWidth()-2, frame:getHeight()-6):setPosition(2, 3):setBackground(colors.lightGray):setForeground(colors.white):setSelectionColor(colors.lightGray, colors.gray)
frame:addButton("xButton"):setText("x"):setPosition(frame:getWidth(), 1):setSize(1, 1):setBackground(colors.black):setForeground(colors.red):onClick(function()
frame:hide()
end)
frame:addButton("Clear"):setText("Clear"):setPosition(frame:getWidth()-19, frame:getHeight()-1):setSize(9, 1):setBackground(colors.black):setForeground(colors.white):onClick(function()
errorList:clear()
end)
frame:addButton("Close"):setText("Close"):setPosition(frame:getWidth()-9, frame:getHeight()-1):setSize(9, 1):setBackground(colors.black):setForeground(colors.white):onClick(function()
basalt.autoUpdate(false)
term.clear()
term.setCursorPos(1, 1)
end)
end
frame:show()
errorList:addItem(("-"):rep(frame:getWidth()-2))
local err = wrapText(err, frame:getWidth()-2)
for i=1, #err do
errorList:addItem(err[i])
end
end
}
end
}

File diff suppressed because one or more lines are too long

105
Basalt/plugins/border.lua Normal file
View File

@@ -0,0 +1,105 @@
local utils = require("utils")
local xmlValue = utils.xmlValue
return {
VisualObject = function(base)
local inline = true
local borderColors = {top = false, bottom = false, left = false, right = false}
local object = {
setBorder = function(self, ...)
local t = {...}
if(t~=nil)then
for k,v in pairs(t)do
if(v=="left")or(#t==1)then
borderColors["left"] = t[1]
end
if(v=="top")or(#t==1)then
borderColors["top"] = t[1]
end
if(v=="right")or(#t==1)then
borderColors["right"] = t[1]
end
if(v=="bottom")or(#t==1)then
borderColors["bottom"] = t[1]
end
end
end
self:updateDraw()
return self
end,
draw = function(self)
base.draw(self)
self:addDraw("border", function()
local x, y = self:getPosition()
local w,h = self:getSize()
local bgCol = self:getBackground()
if(inline)then
if(borderColors["left"]~=false)then
self:addTextBox(1, 1, 1, h, "\149")
if(bgCol~=false)then self:addBackgroundBox(1, 1, 1, h, bgCol) end
self:addForegroundBox(1, 1, 1, h, borderColors["left"])
end
if(borderColors["top"]~=false)then
self:addTextBox(1, 1, w, 1, "\131")
if(bgCol~=false)then self:addBackgroundBox(1, 1, w, 1, bgCol) end
self:addForegroundBox(1, 1, w, 1, borderColors["top"])
end
if(borderColors["left"]~=false)and(borderColors["top"]~=false)then
self:addTextBox(1, 1, 1, 1, "\151")
if(bgCol~=false)then self:addBackgroundBox(1, 1, 1, 1, bgCol) end
self:addForegroundBox(1, 1, 1, 1, borderColors["left"])
end
if(borderColors["right"]~=false)then
self:addTextBox(w, 1, 1, h, "\149")
if(bgCol~=false)then self:addForegroundBox(w, 1, 1, h, bgCol) end
self:addBackgroundBox(w, 1, 1, h, borderColors["right"])
end
if(borderColors["bottom"]~=false)then
self:addTextBox(1, h, w, 1, "\143")
if(bgCol~=false)then self:addForegroundBox(1, h, w, 1, bgCol) end
self:addBackgroundBox(1, h, w, 1, borderColors["bottom"])
end
if(borderColors["top"]~=false)and(borderColors["right"]~=false)then
self:addTextBox(w, 1, 1, 1, "\148")
if(bgCol~=false)then self:addForegroundBox(w, 1, 1, 1, bgCol) end
self:addBackgroundBox(w, 1, 1, 1, borderColors["right"])
end
if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then
self:addTextBox(w, h, 1, 1, "\133")
if(bgCol~=false)then self:addForegroundBox(w, h, 1, 1, bgCol) end
self:addBackgroundBox(w, h, 1, 1, borderColors["right"])
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
self:addBackgroundBox(1, h, 1, 1, borderColors["left"])
end
end
end)
end,
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data)
local borders = {}
if(xmlValue("border", data)~=nil)then
borders["top"] = colors[xmlValue("border", data)]
borders["bottom"] = colors[xmlValue("border", data)]
borders["left"] = colors[xmlValue("border", data)]
borders["right"] = colors[xmlValue("border", data)]
end
if(xmlValue("borderTop", data)~=nil)then borders["top"] = colors[xmlValue("borderTop", data)] end
if(xmlValue("borderBottom", data)~=nil)then borders["bottom"] = colors[xmlValue("borderBottom", data)] end
if(xmlValue("borderLeft", data)~=nil)then borders["left"] = colors[xmlValue("borderLeft", data)] end
if(xmlValue("borderRight", data)~=nil)then borders["right"] = colors[xmlValue("borderRight", data)] end
self:setBorder(borders["top"], borders["bottom"], borders["left"], borders["right"])
return self
end
}
return object
end
}

97
Basalt/plugins/debug.lua Normal file
View File

@@ -0,0 +1,97 @@
local utils = require("utils")
local wrapText = utils.wrapText
return {
basalt = function(basalt)
local mainFrame = basalt.getMainFrame()
local debugFrame
local debugList
local debugLabel
local debugExitButton
local function createDebuggingFrame()
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)
local resizeButton = debugFrame:addButton()
:setPosition("parent.w", "parent.h")
:setSize(1, 1)
:setText("\133")
:setForeground(colors.gray)
:setBackground(colors.black)
:onClick(function() end)
:onDrag(function(self, event, btn, xOffset, yOffset)
local w, h = debugFrame:getSize()
local wOff, hOff = w, h
if(w+xOffset-1>=minW)and(w+xOffset-1<=maxW)then
wOff = w+xOffset-1
end
if(h+yOffset-1>=minH)and(h+yOffset-1<=maxH)then
hOff = h+yOffset-1
end
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()
debugFrame:animatePosition(-w, h/2-debugFrame:getHeight()/2, 0.5)
end)
debugList = debugFrame:addList()
:setSize("parent.w - 2", "parent.h - 3")
:setPosition(2, 3)
:setBackground(colors.gray)
:setForeground(colors.white)
:setSelectionColor(colors.gray, colors.white)
if(debugLabel==nil)then
debugLabel = mainFrame:addLabel()
:setPosition(1, "parent.h")
:setBackground(colors.black)
:setForeground(colors.white)
:setZIndex(100)
:onClick(function()
debugFrame:show()
debugFrame:animatePosition(w/2-debugFrame:getWidth()/2, h/2-debugFrame:getHeight()/2, 0.5)
end)
end
end
return {
debug = function(...)
local args = { ... }
if(mainFrame==nil)then
mainFrame = basalt.getMainFrame()
if(mainFrame~=nil)then
createDebuggingFrame()
else
print(...) return
end
end
if (mainFrame:getName() ~= "basaltDebuggingFrame") then
if (mainFrame ~= debugFrame) then
debugLabel:setParent(mainFrame)
end
end
local str = ""
for key, value in pairs(args) do
str = str .. tostring(value) .. (#args ~= key and ", " or "")
end
debugLabel:setText("[Debug] " .. str)
for k,v in pairs(wrapText(str, debugList:getWidth()))do
debugList:addItem(v)
end
if (debugList:getItemCount() > 50) then
debugList:removeItem(1)
end
debugList:setValue(debugList:getItem(debugList:getItemCount()))
if(debugList.getItemCount() > debugList:getHeight())then
debugList:setOffset(debugList:getItemCount() - debugList:getHeight())
end
debugLabel:show()
end
}
end
}

View File

@@ -0,0 +1,125 @@
local utils = require("utils")
local count = utils.tableCount
local xmlValue = utils.xmlValue
return {
VisualObject = function(base, basalt)
local dynObjects = {}
local curProperties = {}
local properties = {x="getX", y="getY", w="getWidth", h="getHeight"}
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
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)
end
end
end
local parent = self:getParent()
local objects = {}
for k,v in pairs(objectGroup)do
objects[v] = parent:getObject(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
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)
end
end,
}
return object
end
}

221
Basalt/plugins/pixelbox.lua Normal file
View File

@@ -0,0 +1,221 @@
-- Most of this is made by Dev9551, you can find his awesome work here: https://github.com/9551-Dev/apis/blob/main/pixelbox_lite.lua
-- Slighly modified by NyoriE to work with Basalt
--[[
The MIT License (MIT)
Copyright © 2022 Oliver Caha (9551Dev)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local t_sort,t_cat,s_char = table.sort,table.concat,string.char
local function sort(a,b) return a[2] > b[2] end
local distances = {
{5,256,16,8,64,32},
{4,16,16384,256,128},
[4] = {4,64,1024,256,128},
[8] = {4,512,2048,256,1},
[16] = {4,2,16384,256,1},
[32] = {4,8192,4096,256,1},
[64] = {4,4,1024,256,1},
[128] = {6,32768,256,1024,2048,4096,16384},
[256] = {6,1,128,2,512,4,8192},
[512] = {4,8,2048,256,128},
[1024] = {4,4,64,128,32768},
[2048] = {4,512,8,128,32768},
[4096] = {4,8192,32,128,32768},
[8192] = {3,32,4096,256128},
[16384] = {4,2,16,128,32768},
[32768] = {5,128,1024,2048,4096,16384}
}
local to_colors = {}
for i = 0, 15 do
to_colors[("%x"):format(i)] = 2^i
end
local to_blit = {}
for i = 0, 15 do
to_blit[2^i] = ("%x"):format(i)
end
local function pixelbox(colTable, defaultCol)
defaultCol = defaultCol or "f"
local width, height = #colTable[1], #colTable
local cache = {}
local canv = {}
local cached = false
local function generateCanvas()
for y = 1, height * 3 do
for x = 1, width * 2 do
if not canv[y] then canv[y] = {} end
canv[y][x] = defaultCol
end
end
for k, v in ipairs(colTable) do
for x = 1, #v do
local col = v:sub(x, x)
canv[k][x] = to_colors[col]
end
end
end
generateCanvas()
local function setSize(w,h)
width, height = w, h
canv = {}
cached = false
generateCanvas()
end
local function generateChar(a,b,c,d,e,f)
local arr = {a,b,c,d,e,f}
local c_types = {}
local sortable = {}
local ind = 0
for i=1,6 do
local c = arr[i]
if not c_types[c] then
ind = ind + 1
c_types[c] = {0,ind}
end
local t = c_types[c]
local t1 = t[1] + 1
t[1] = t1
sortable[t[2]] = {c,t1}
end
local n = #sortable
while n > 2 do
t_sort(sortable,sort)
local bit6 = distances[sortable[n][1]]
local index,run = 1,false
local nm1 = n - 1
for i=2,bit6[1] do
if run then break end
local tab = bit6[i]
for j=1,nm1 do
if sortable[j][1] == tab then
index = j
run = true
break
end
end
end
local from,to = sortable[n][1],sortable[index][1]
for i=1,6 do
if arr[i] == from then
arr[i] = to
local sindex = sortable[index]
sindex[2] = sindex[2] + 1
end
end
sortable[n] = nil
n = n - 1
end
local n = 128
local a6 = arr[6]
if arr[1] ~= a6 then n = n + 1 end
if arr[2] ~= a6 then n = n + 2 end
if arr[3] ~= a6 then n = n + 4 end
if arr[4] ~= a6 then n = n + 8 end
if arr[5] ~= a6 then n = n + 16 end
if sortable[1][1] == arr[6] then
return s_char(n),sortable[2][1],arr[6]
else
return s_char(n),sortable[1][1],arr[6]
end
end
local function convert()
local w_double = width * 2
local sy = 0
for y = 1, height * 3, 3 do
sy = sy + 1
local layer_1 = canv[y]
local layer_2 = canv[y + 1]
local layer_3 = canv[y + 2]
local char_line, fg_line, bg_line = {}, {}, {}
local n = 0
for x = 1, w_double, 2 do
local xp1 = x + 1
local b11, b21, b12, b22, b13, b23 = layer_1[x], layer_1[xp1], layer_2[x], layer_2[xp1], layer_3[x], layer_3[xp1]
local char, fg, bg = " ", 1, b11
if not (b21 == b11 and b12 == b11 and b22 == b11 and b13 == b11 and b23 == b11) then
char, fg, bg = generateChar(b11, b21, b12, b22, b13, b23)
end
n = n + 1
char_line[n] = char
fg_line[n] = to_blit[fg]
bg_line[n] = to_blit[bg]
end
cache[sy] = {t_cat(char_line), t_cat(fg_line), t_cat(bg_line)}
end
cached = true
end
return {
convert = convert,
generateCanvas = generateCanvas,
setSize = setSize,
getSize = function()
return width, height
end,
set = function(colTab, defCol)
colTable = colTab
defaultCol = defCol or defaultCol
canv = {}
cached = false
generateCanvas()
end,
get = function(y)
if not cached then convert() end
return y~= nil and cache[y] or cache
end
}
end
return {
Image = function(base, basalt)
return {
shrink = function(self)
local bimg = self:getImageFrame(1)
local img = {}
for k,v in pairs(bimg)do
if(type(k)=="number")then
table.insert(img,v[3])
end
end
local shrinkedImg = pixelbox(img, self:getBackground()).get()
self:setImage(shrinkedImg)
return self
end,
getShrinkedImage = function(self)
local bimg = self:getImageFrame(1)
local img = {}
for k,v in pairs(bimg)do
if(type(k)=="number")then
table.insert(img, v[3])
end
end
return pixelbox(img, self:getBackground()).get()
end,
}
end,
}

43
Basalt/plugins/shadow.lua Normal file
View File

@@ -0,0 +1,43 @@
local utils = require("utils")
local xmlValue = utils.xmlValue
return {
VisualObject = function(base)
local shadow = false
local object = {
setShadow = function(self, color)
shadow = color
self:updateDraw()
return self
end,
getShadow = function(self)
return shadow
end,
draw = function(self)
base.draw(self)
self:addDraw("shadow", function()
if(shadow~=false)then
local w,h = self:getSize()
if(shadow)then
self:addBackgroundBox(w+1, 2, 1, h, shadow)
self:addBackgroundBox(2, h+1, w, 1, shadow)
self:addForegroundBox(w+1, 2, 1, h, shadow)
self:addForegroundBox(2, h+1, w, 1, shadow)
end
end
end)
end,
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("shadow", data)~=nil)then self:setShadow(xmlValue("shadow", data)) end
return self
end
}
return object
end
}

123
Basalt/plugins/textures.lua Normal file
View File

@@ -0,0 +1,123 @@
local images = require("images")
local utils = require("utils")
local xmlValue = utils.xmlValue
return {
VisualObject = function(base)
local textureId, infinitePlay = 1, true
local bimg, texture, textureTimerId
local textureMode = "default"
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)
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
self:updateDraw()
return self
end,
setInfinitePlay = function(self, state)
infinitePlay = state
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()
end
end
end
end
end,
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))
end
end
end, 1)
self:setDrawState("texture-base", false)
end,
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("texture", data)~=nil)then self:addTexture(xmlValue("texture", data), xmlValue("animate", data)) end
if(xmlValue("textureMode", data)~=nil)then self:setTextureMode(xmlValue("textureMode", data)) end
if(xmlValue("infinitePlay", data)~=nil)then self:setInfinitePlay(xmlValue("infinitePlay", data)) end
return self
end
}
return object
end
}

99
Basalt/plugins/themes.lua Normal file
View File

@@ -0,0 +1,99 @@
local baseTheme = { -- The default main theme for basalt!
BaseFrameBG = colors.lightGray,
BaseFrameText = colors.black,
FrameBG = colors.gray,
FrameText = colors.black,
ButtonBG = colors.gray,
ButtonText = colors.black,
CheckboxBG = colors.lightGray,
CheckboxText = colors.black,
InputBG = colors.black,
InputText = colors.lightGray,
TextfieldBG = colors.black,
TextfieldText = colors.white,
ListBG = colors.gray,
ListText = colors.black,
MenubarBG = colors.gray,
MenubarText = colors.black,
DropdownBG = colors.gray,
DropdownText = colors.black,
RadioBG = colors.gray,
RadioText = colors.black,
SelectionBG = colors.black,
SelectionText = colors.lightGray,
GraphicBG = colors.black,
ImageBG = colors.black,
PaneBG = colors.black,
ProgramBG = colors.black,
ProgressbarBG = colors.gray,
ProgressbarText = colors.black,
ProgressbarActiveBG = colors.black,
ScrollbarBG = colors.lightGray,
ScrollbarText = colors.gray,
ScrollbarSymbolColor = colors.black,
SliderBG = false,
SliderText = colors.gray,
SliderSymbolColor = colors.black,
SwitchBG = colors.lightGray,
SwitchText = colors.gray,
LabelBG = false,
LabelText = colors.black,
GraphBG = colors.gray,
GraphText = colors.black
}
local plugin = {
Container = function(base, name, basalt)
local theme = {}
local object = {
getTheme = function(self, name)
local parent = self:getParent()
return theme[name] or (parent~=nil and parent:getTheme(name) or baseTheme[name])
end,
setTheme = function(self, _theme, col)
if(type(_theme)=="table")then
theme = _theme
elseif(type(_theme)=="string")then
theme[_theme] = col
end
self:updateDraw()
return self
end,
}
return object
end,
basalt = function()
return {
getTheme = function(name)
return baseTheme[name]
end,
setTheme = function(_theme, col)
if(type(_theme)=="table")then
baseTheme = _theme
elseif(type(_theme)=="string")then
baseTheme[_theme] = col
end
end
}
end
}
for k,v in pairs({"BaseFrame", "Frame", "ScrollableFrame", "MovableFrame", "Button", "Checkbox", "Dropdown", "Graph", "Graphic", "Input", "Label", "List", "Menubar", "Pane", "Program", "Progressbar", "Radio", "Scrollbar", "Slider", "Switch", "Textfield"})do
plugin[v] = function(base, name, basalt)
local object = {
init = function(self)
if(base.init(self))then
local parent = self:getParent() or self
self:setBackground(parent:getTheme(v.."BG"))
self:setForeground(parent:getTheme(v.."Text"))
end
end
}
return object
end
end
return plugin

1185
Basalt/plugins/xml.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +0,0 @@
return { -- The default main theme for basalt!
BasaltBG = colors.lightGray,
BasaltText = colors.black,
FrameBG = colors.gray,
FrameText = colors.black,
ButtonBG = colors.gray,
ButtonText = colors.black,
CheckboxBG = colors.gray,
CheckboxText = colors.black,
InputBG = colors.gray,
InputText = colors.black,
TextfieldBG = colors.gray,
TextfieldText = colors.black,
ListBG = colors.gray,
ListText = colors.black,
MenubarBG = colors.gray,
MenubarText = colors.black,
DropdownBG = colors.gray,
DropdownText = colors.black,
RadioBG = colors.gray,
RadioText = colors.black,
SelectionBG = colors.black,
SelectionText = colors.lightGray,
GraphicBG = colors.black,
ImageBG = colors.black,
PaneBG = colors.black,
ProgramBG = colors.black,
ProgressbarBG = colors.gray,
ProgressbarText = colors.black,
ProgressbarActiveBG = colors.black,
ScrollbarBG = colors.lightGray,
ScrollbarText = colors.gray,
ScrollbarSymbolColor = colors.black,
SliderBG = false,
SliderText = colors.gray,
SliderSymbolColor = colors.black,
SwitchBG = colors.lightGray,
SwitchText = colors.gray,
SwitchBGSymbol = colors.black,
SwitchInactive = colors.red,
SwitchActive = colors.green,
LabelBG = false,
LabelText = colors.black,
GraphBG = colors.gray,
GraphText = colors.black
}

View File

@@ -2,11 +2,19 @@
*Note: The Basalt Wiki is a work in progress. Please treat wiki errors the same as bugs and report them accordingly.* *Note: The Basalt Wiki is a work in progress. Please treat wiki errors the same as bugs and report them accordingly.*
Here you can find information about how to use Basalt as well as examples of functional Basalt code. The aim of Basalt is to improve user interaction through visual display. Basalt is a user-friendly UI framework for CC:Tweaked (also known as "ComputerCraft: Tweaked") - a popular Minecraft mod. It was developed to enhance user interaction through visual displays. In this wiki, you'll find information on how to use Basalt as well as examples of functional Basalt code.
This Website is made with the help of ChatGPT.
## About Basalt ## About Basalt
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also known as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://modrinth.com/mod/cc-tweaked). Basalt is an easy-to-understand UI framework designed to improve user interaction with CC:Tweaked. Some of its key features include:
- A set of pre-built UI components for creating interfaces quickly and easily.
- A flexible layout system that allows users to create custom designs.
- A powerful event handling system for managing user input and interaction.
- Support for multiple screen resolutions and aspect ratios.
- Extensive documentation and examples to help users get started quickly.
## Quick Demo ## Quick Demo

View File

@@ -1,32 +1,41 @@
[1.6 Docs](https://basalt.madefor.cc/docs1_6)
- About - About
- [Home](home) - [Home](/)
- [How To](home/How-To) - [How To](home/How-To)
- [Download](home/download) - [Download](home/download)
- Objects - Objects
- [Basalt](objects/Basalt.md) - [Basalt](objects/Basalt.md)
- [Object](objects/Object.md) - [Object](objects/Object.md)
- [VisualObject](objects/VisualObject.md)
- [ChangeableObject](objects/ChangeableObject.md)
- [Container](objects/Container.md)
- [BaseFrame](objects/BaseFrame.md)
- [MonitorFrame](objects/MonitorFrame.md)
- [Frame](objects/Frame.md)
- [Flexbox](objects/Flexbox.md)
- [MovableFrame](objects/MovableFrame.md)
- [ScrollableFrame](objects/ScrollableFrame.md)
- [Button](objects/Button.md) - [Button](objects/Button.md)
- [Checkbox](objects/Checkbox.md) - [Checkbox](objects/Checkbox.md)
- [Dropdown](objects/Dropdown.md) - [Graph](objects/Graph.md)
- [Frame](objects/Frame.md)
- [Image](objects/Image.md) - [Image](objects/Image.md)
- [Input](objects/Input.md) - [Input](objects/Input.md)
- [Label](objects/Label.md) - [Label](objects/Label.md)
- [List](objects/List.md) - [List](objects/List.md)
- [Menubar](objects/Menubar.md) - [Dropdown](objects/Dropdown.md)
- [Menubar](objects/Menubar.md)
- [Radio](objects/Radio.md)
- [Pane](objects/Pane.md) - [Pane](objects/Pane.md)
- [Program](objects/Program.md) - [Program](objects/Program.md)
- [Progressbar](objects/Progressbar.md) - [Progressbar](objects/Progressbar.md)
- [Radio](objects/Radio.md)
- [Scrollbar](objects/Scrollbar.md) - [Scrollbar](objects/Scrollbar.md)
- [Slider](objects/Slider.md) - [Slider](objects/Slider.md)
- [Textfield](objects/Textfield.md) - [Textfield](objects/Textfield.md)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread.md) - [Thread](objects/Thread.md)
- [Treeview](objects/Treeview.md)
- [Timer](objects/Timer.md) - [Timer](objects/Timer.md)
- Tips & Tricks - Guides
- [Your Logic](tips/logic.md) - [Introduction to Basalt](guides/introduction.md)
- [Button coloring](tips/buttonColoring.md) - [Dynamic Values](guides/dynamicvalues.md)
- [Designing/Animating](tips/design.md) - [XML](guides/xml.md)
- [Dynamic Values](tips/dynamicvalues.md)
- [XML](tips/xml.md)

0
docs/docs1_6/.nojekyll Normal file
View File

1
docs/docs1_6/CNAME Normal file
View File

@@ -0,0 +1 @@
basalt.madefor.cc

19
docs/docs1_6/Home.md Normal file
View File

@@ -0,0 +1,19 @@
# Welcome to The Basalt Wiki
*Note: The Basalt Wiki is a work in progress. Please treat wiki errors the same as bugs and report them accordingly.*
Here you can find information about how to use Basalt as well as examples of functional Basalt code. The aim of Basalt is to improve user interaction through visual display.
## About Basalt
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also known as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://modrinth.com/mod/cc-tweaked).
## Quick Demo
![Basalt Demo GIF](https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/basaltPreview2.gif)
## Questions & Bugs
Obviously NyoriE has implemented some easter eggs, *some people* call them "bugs". If you happen to discover one of these just make a new [Github Issue](https://github.com/Pyroxenium/Basalt/issues)
Additionally, if you have questions about Basalt or how to make use of it, feel free to create a new discussion on [Basalt's Discussion Board (Github)](https://github.com/Pyroxenium/Basalt/discussions), or ask in our [discord](https://discord.gg/yNNnmBVBpE).

3
docs/docs1_6/_footer.md Normal file
View File

@@ -0,0 +1,3 @@
---
Thanks for checking out our wiki, join our discord for more help: [discord.gg/yM7kndJdJJ](discord.gg/yNNnmBVBpE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Binary file not shown.

4
docs/docs1_6/_navbar.md Normal file
View File

@@ -0,0 +1,4 @@
- Getting Started
- [Home](Home)
- [How To](home/How-To)
- [Download](home/download)

32
docs/docs1_6/_sidebar.md Normal file
View File

@@ -0,0 +1,32 @@
- About
- [Home](home)
- [How To](home/How-To)
- [Download](home/download)
- Objects
- [Basalt](objects/Basalt.md)
- [Object](objects/Object.md)
- [Button](objects/Button.md)
- [Checkbox](objects/Checkbox.md)
- [Dropdown](objects/Dropdown.md)
- [Frame](objects/Frame.md)
- [Image](objects/Image.md)
- [Input](objects/Input.md)
- [Label](objects/Label.md)
- [List](objects/List.md)
- [Menubar](objects/Menubar.md)
- [Pane](objects/Pane.md)
- [Program](objects/Program.md)
- [Progressbar](objects/Progressbar.md)
- [Radio](objects/Radio.md)
- [Scrollbar](objects/Scrollbar.md)
- [Slider](objects/Slider.md)
- [Textfield](objects/Textfield.md)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread.md)
- [Timer](objects/Timer.md)
- Tips & Tricks
- [Your Logic](tips/logic.md)
- [Button coloring](tips/buttonColoring.md)
- [Designing/Animating](tips/design.md)
- [Dynamic Values](tips/dynamicvalues.md)
- [XML](tips/xml.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
docs/docs1_6/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,61 @@
# How-To
After downloading the project you can finally start creating your own program and use basalt. The first thing you want to use in your program is always:
```lua
local basalt = require("basalt")
```
It doesn't matter if you're using the source folder or the minified/packed version of basalt. Both can be found by using require("basalt") without .lua.
Also to really run basalt you should use
```lua
basalt.autoUpdate()
```
somewhere on the bottom of your program. basalt.autoUpdate() starts the event listener and the draw handler.
## Example
Here is a fully working example of how a program could look like:
```lua
local basalt = require("basalt") --> Load the basalt framework into the variable called "basalt"
--> Now we want to create a base frame, we call the variable "main" - by default everything you create is visible. (you don't need to use :show())
local main = basalt.createFrame()
local button = main:addButton() --> Here we add our first button
button:setPosition(4, 4) -- of course we want to change the default position of our button
button:setSize(16, 3) -- and the default size.
button:setText("Click me!") --> This method displays what the text of our button should look like
local function buttonClick() --> Let us create a function we want to call when the button gets clicked
basalt.debug("I got clicked!")
end
-- Now we just need to register the function to the buttons onClick event handlers, this is how we can achieve that:
button:onClick(buttonClick)
basalt.autoUpdate() -- As soon as we call basalt.autoUpdate, the event and draw handlers will listen to any incomming events (and draw if necessary)
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local button = main --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton() --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
basalt.autoUpdate()
```

View File

@@ -0,0 +1,36 @@
Basalt provides multiple unique versions. A source version, a minified version and a web version.
## Source
This version is, like the name already says, the source code of basalt. If you want to dig into the code, add additional content or just prefer to use the source, then you should aim for the source-version.
The following command allows you to download the source-version on your computer:
`wget run https://basalt.madefor.cc/install.lua source [foldername] [branch]`
The first optional argument is the folder name you wish that basalt should be installed into, by default the folder is called basalt.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Minified / Packed
This version is the minified version, i also call it the packed version. There are 2 changes, the first one is that the code will be shown minified which makes the size much smaller, the second change is that you will recieve a file instead of a folder.
The following command allows you to download the packed-version on your computer:
`wget run https://basalt.madefor.cc/install.lua packed [filename] [branch]`
The first optional argument is the file name you wish that the installer should use, by default the file is called basalt.lua.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Web
The web version is a special version, used if your goal is to keep your project's size as small as possible. I suggest you to use the web version only if you don't restart your program over and over again. For example if you designed your program to reboot after the user made a bad choice (leads into a error or something like that) it is better to use the minified/source version.
The following command allows you to download the web-version on your computer:
`wget run https://basalt.madefor.cc/install.lua web [version] [filename]`
By default the first argument is the latest version of basalt's releases. [Here](https://github.com/Pyroxenium/Basalt/tree/master/docs/versions) you can see which versions are available to use.
For example: wget run https://basalt.madefor.cc/install.lua web basalt-1.6.3.lua - the second argument is just the file name, default is basaltWeb.lua.
Remember to rename `local basalt = require("basalt")` into `local basalt = require("basaltWeb")` if you want to use the web-version

71
docs/docs1_6/index.html Normal file
View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Basalt Documentation</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Basalt is an easy-to-understand UI Framework designed for CC:Tweaked - a popular minecraft mod. ">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<!-- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism-tomorrow.min.css">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<style>
:root {
--theme-color: #16CC27;
--mono-hue: 120;
--mono-saturation: 1%;
--mono-shade3: hsl(var(--mono-hue), var(--mono-saturation), 5%);
--mono-shade2: hsl(var(--mono-hue), var(--mono-saturation), 6%);
--mono-shade1: hsl(var(--mono-hue), var(--mono-saturation), 7%);
--mono-base: hsl(var(--mono-hue), var(--mono-saturation), 20%);
--mono-tint1: hsl(var(--mono-hue), var(--mono-saturation), 25%);
--mono-tint2: hsl(var(--mono-hue), var(--mono-saturation), 30%);
--mono-tint3: hsl(var(--mono-hue), var(--mono-saturation), 35%);
--base-background-color: hsl(var(--mono-hue), var(--mono-saturation), 10%);
--sidebar-nav-pagelink-background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='11.2' viewBox='0 0 7 11.2'%3E%3Cpath d='M1.5 1.5l4 4.1 -4 4.1' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--active: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11.2' height='7' viewBox='0 0 11.2 7'%3E%3Cpath d='M1.5 1.5l4.1 4 4.1-4' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--collapse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='11.2' viewBox='0 0 7 11.2'%3E%3Cpath d='M1.5 1.5l4 4.1 -4 4.1' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
--sidebar-nav-pagelink-background-image--loaded: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11.2' height='7' viewBox='0 0 11.2 7'%3E%3Cpath d='M1.5 1.5l4.1 4 4.1-4' stroke-width='1.5' stroke='%23575d5e' fill='none' stroke-linecap='square' stroke-linejoin='miter' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
}
</style>
</head>
<body>
<div id="app">Did you know: Basalt is a Pyroxene?></div>
<script src="//cdn.jsdelivr.net/npm/docsify-edit-on-github"></script>
<script>
window.$docsify = {
logo: '/_media/logo.png',
loadNavbar: true,
loadSidebar: true,
loadFooter: '_footer.md',
autoHeader: true,
homepage: 'Home.md',
name: 'Basalt',
repo: 'https://github.com/Pyroxenium/Basalt',
auto2top: true,
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: 'auto',
placeholder: 'Type to search',
noData: 'No Results!',
// Headline depth, 1 - 6
depth: 2,
hideOtherSidebarContent: false, // whether or not to hide other sidebar content
},
plugins: [
EditOnGithubPlugin.create("https://github.com/Pyroxenium/Basalt/blob/master/docs/", null, "Edit on Github")
]
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.28.0/components/prism-lua.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/@alertbox/docsify-footer/dist/docsify-footer.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,32 @@
With animations, you can create a beautiful experience for users while interacting with your program.
There are 2 types of animations, predefined animations and custom animations. By using add and wait you can create custom
animations (calls). Pre-defined methods are for example move, offset, size, changeText,...
:setObject always sets the object on what pre-defined methods should apply on.
When calling a pre-defined animation it will check what is safed as object (:setObject) and will calculate the animation methods based on that which means you won't
be able to change the object on the fly - you will always have to recreate the animation itself
| | |
|---|---|
|[add](objects/Animation/add.md)|Adds a new custom function to call at the current time
|[wait](objects/Animation/wait.md)|Adds a amount to the animation time
|[play](objects/Animation/play.md)|Plays the animation
|[cancel](objects/Animation/cancel.md)|Cancels the animation
|[addMode](objects/Animation/addMode.md)|Adds custom easings
|[setMode](objects/Animation/setMode.md)|Changes the current easing-calculation
|[setObject](objects/Animation/setObject.md)|Sets an object on which predefined animations should work on
|[move](objects/Animation/move.md)|Predefined animation: moves the object to a new position
|[offset](objects/Animation/offset.md)|Predefined animation: Changes the offset of that object
|[size](objects/Animation/size.md)|Predefined animation: Changes the size on a object
|[changeText](objects/Animation/changeText.md)|Predefined animation: Changes the text (object needs a setText method)
|[changeTextColor](objects/Animation/changeTextColor.md)|Predefined animation: changes the foreground/textcolor on a object
|[changeBackground](objects/Animation/changeBackground.md)|Predefined animation: changes the background on a object
# Events
| | |
|---|---|
|[onStart](objects/Animation/onStart.md)|Gets called as soon as the animation is started
|[onDone](objects/Animation/onDone.md)|Gets called as soon as the animation has finished

View File

@@ -0,0 +1,17 @@
## add
Adds a new function to an animation
#### Parameters:
1. `function` The function containing animation logic
#### Returns:
1. `animation` Animation in use
#### Usage:
* This will set the button position to 3,3, waits 1 second, then sets position to 4,4, waits 2 seconds, and then sets the position to 5,5
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setPosition(3,3) end):wait(1):add(function() testButton:setPosition(1,1,"r") end):wait(2):add(function() testButton:setPosition(1,1,"r") end)
aAnimation:play()
```

View File

@@ -0,0 +1,30 @@
## addMode
Adds a new easing curve into the available easing list. Checkout the animation object if you want to know how this works.
#### Parameters:
1. `string` - The name of the curve you want to use.
2. `functon` - The function to call
#### Returns:
1. `animation` Animation in use
#### Usage:
* Creates a new curve
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton)
local function easeInBack(t) -- t is the time from 0 to 1
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
aAnimation:addMode("coolEaseInBack", easeInBack)
aAnimation:setMode("coolEaseInBack"):move(15,3,2):play()
```

View File

@@ -0,0 +1,15 @@
## cancel
Cancels the animation
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() aAnimation:cancel() end):wait(1):add(function() testButton:setBackground(colors.lightGray) end)
aAnimation:play()
```

View File

@@ -0,0 +1,28 @@
## changeBackground
Changes the background color while the animation is running
#### Parameters:
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
3. `...` multiple color numbers - example: colors.red, colors.yellow, colors.green
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<background>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</background>
</animation>
```

View File

@@ -0,0 +1,30 @@
## changeText
Changes the text while animation is running
#### Parameters:
1. `table` multiple text strings - example: {"i", "am", "groot"}
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
3. `...` multiple text strings - example: "i", "am", "groot"
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText(2, 0, "i", "am", "groot"):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<text>
<text>i</text>
<text>am</text>
<text>groot</text>
<duration>2</duration>
</text>
</animation>
```

View File

@@ -0,0 +1,28 @@
## changeTextColor
Changes the text color while the animation is running
#### Parameters:
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
1. `...` multiple color numbers - example: colors.red, colors.yellow, colors.green
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<textColor>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</textColor>
</animation>
```

View File

@@ -0,0 +1,25 @@
## move
Moves the object which got defined by setObject
#### Parameters:
1. `number` x coordinate
2. `number` y coordinate
3. `number` duration in seconds
4. `number` time - time when this part should begin (offset to when the animation starts - default 0)
5. `table` object - optional, you could also define the object here
#### Returns:
1. `animation` Animation in use
#### Usage:
* Takes 2 seconds to move the object from its current position to x15 y3
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):move(15,3,2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<move><x>15</x><y>6</y><duration>2</duration></move>
</animation>
```

View File

@@ -0,0 +1,25 @@
## offset
Changes the offset on the object which got defined by setObject
#### Parameters:
1. `number` x offset
2. `number` y offset
3. `number` duration in seconds
4. `number` time - time when this part should begin (offset to when the animation starts - default 0)
5. `table` object - optional, you could also define the object here
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame("frameToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(subFrame):offset(1,12,1):play()
```
```xml
<animation object="frameToAnimate" play="true">
<offset><x>1</x><y>12</y><duration>1</duration></offset>
</animation>
```

View File

@@ -0,0 +1,35 @@
## onDone
`onDone(self)`<br>
This is a event which gets fired as soon as the animation has finished.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
aAnimation:onDone(function()
basalt.debug("The animation is done")
end)
```
In XML you are also able to queue multiple animations, like this:
```xml
<animation id="anim2" object="buttonToAnimate">
<textColor>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</textColor>
</animation>
<animation onDone="#anim2" object="buttonToAnimate" play="true">
<background>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</background>
</animation>
```

View File

@@ -0,0 +1,16 @@
## onStart
`onStart(self)`<br>
This is a event which gets fired as soon as the animation is started.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2)
aAnimation:onStart(function()
basalt.debug("The animation is started")
end)
aAnimation:play()
```

View File

@@ -0,0 +1,16 @@
## play
Plays the animation
#### Parameters:
1. `boolean` Whether it will loop forever, will most likely be replaced with a count in the future
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():add(function() testButton:setBackground(colors.black) end):wait(1):add(function() testButton:setBackground(colors.gray) end):wait(1):add(function() testButton:setBackground(colors.lightGray) end)
aAnimation:play() -- changes the background color of that button from black to gray and then to lightGray
```

View File

@@ -0,0 +1,36 @@
## setMode
Changes the easing curve. If you want to test them, here is a interesting website: https://easings.co
#### Parameters:
1. `string` - The name of the curve you want to use.
#### Returns:
1. `animation` Animation in use
#### Usage:
* Takes 2 seconds to move the object from its current position to x15 y3
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):setMode("easeInBounce"):move(15,3,2):play()
```
## Easing Curve List
Here is a list of all available easing curves:
| | | |
|---|---|---|
|linear||
|easIn|easeOut|easeInOut
|easeInSine|easeOutSine|easeInOutSine
|easeInBack|easeOutBack|easeInOutBack
|easeInCubic|easeOutCubic|easeInOutCubic
|easeInElastic|easeOutElastic|easeInOutElastic
|easeInExpo|easeOutExpo|easeInOutExpo
|easeInBack|easeOutBack|easeInOutBack
|easeInQuad|easeOutQuad|easeInOutQuad
|easeInQuint|easeOutQuint|easeInOutQuint
|easeInQuart|easeOutQuart|easeInOutQuart
|easeInCirc|easeOutCirc|easeInOutCirc
|easeInBounce|easeOutBounce|easeInOutBounce

Some files were not shown because too many files have changed in this diff Show More