Clean up the README #67

Merged
piprett merged 2 commits from erb3-path-7 into master 2023-05-08 23:01:40 +08:00
613 changed files with 23908 additions and 8133 deletions
Showing only changes of commit 32e972e103 - Show all commits

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 blit(x, y, t, fg, bg)
if #t == #fg and #t == #bg then
if y >= 1 and y <= height then
if x + #t > 0 and x <= width then
local newCacheT, newCacheFG, newCacheBG
local oldCacheT, oldCacheFG, oldCacheBG = cacheT[y], cacheFG[y], cacheBG[y]
local startN, endN = 1, #t
if x < 1 then
startN = 1 - x + 1
endN = width - x + 1
elseif x + #t > width then
endN = width - x + 1
end
newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN)
newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN)
if x + #t <= width then
newCacheT = newCacheT .. sub(oldCacheT, x + #t, width)
newCacheFG = newCacheFG .. sub(oldCacheFG, x + #t, width)
newCacheBG = newCacheBG .. sub(oldCacheBG, x + #t, width)
end
cacheT[y], cacheFG[y], cacheBG[y] = newCacheT,newCacheFG,newCacheBG
end
end
end
end
local function setText(x, y, t)
if y >= 1 and y <= height then
if x + #t > 0 and x <= width then
local newCacheT
local oldCacheT = cacheT[y]
local startN, endN = 1, #t
if x < 1 then
startN = 1 - x + 1
endN = width - x + 1
elseif x + #t > width then
endN = width - x + 1
end
newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
if x + #t <= width then
newCacheT = newCacheT .. sub(oldCacheT, x + #t, width)
end
cacheT[y] = newCacheT
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) local function setText(x, y, text)
if (y >= 1) and (y <= height) then if (y >= 1) and (y <= height) then
if (x + text:len() > 0) and (x <= width) then local emptyLine = rep(" ", #text)
local oldCache = cacheT[y] blit(x, y, text, emptyLine, emptyLine)
local newCache
local nEnd = x + #text - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
text = sub(text, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
text = sub(text, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCache = sub(oldCache, 1, endN) .. text
else
newCache = text
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheT[y] = newCache
end
end
end
local function setBG(x, y, colorStr)
if (y >= 1) and (y <= height) then
if (x + colorStr:len() > 0) and (x <= width) then
local oldCache = cacheBG[y]
local newCache
local nEnd = x + #colorStr - 1
if (x < 1) then
colorStr = sub(colorStr, 1 - x + 1, width - x + 1)
elseif (nEnd > width) then
colorStr = sub(colorStr, 1, width - x + 1)
end
if (x > 1) then
newCache = sub(oldCache, 1, x - 1) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
cacheBG[y] = newCache
end
end end
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
if (x + t:len() > 0) and (x <= width) then local w = #colorStr
local oldCacheT = cacheT[y] local emptyLine = rep(" ", w)
local oldCacheFG = cacheFG[y] local text = sub(cacheT[y], x, w)
local oldCacheBG = cacheBG[y] blit(x, y, text, emptyLine, colorStr)
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,10 +80,12 @@ local function frame(base, manager)
end end
if(base~=nil)then if(base~=nil)then
if(#base>0)then
w = #base[1][1] w = #base[1][1]
h = #base h = #base
setFrame(base) setFrame(base)
end end
end
return { return {
recalculateSize = recalculateSize, recalculateSize = recalculateSize,
@@ -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,21 +27,18 @@ 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) return loadNFP(path, binaryMode)
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
@@ -56,7 +47,6 @@ local function loadImageAsBimg(path, f)
return loadNFPAsBimg(path) return loadNFPAsBimg(path)
end end
end end
end
local function resizeBIMG(source, w, h) local function resizeBIMG(source, w, h)
local oW, oH = source.width or #source[1][1][1], source.height or #source[1] local oW, oH = source.width or #source[1][1][1], source.height or #source[1]

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,4 +1,5 @@
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 = {}
@@ -8,93 +9,219 @@ local function splitString(str, delimiter)
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
return {""}
end end
local uniqueLines = splitString(str, "\n")
return 1 local result = {}
end for k, v in pairs(uniqueLines) do
if #v == 0 then
local function colsToChar(pattern, totals) table.insert(result, "")
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function (a, b) return a[2] > b[2] end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else else
-- Solid colour character: while #v > width do
return "\128", colourChar[pattern[1]], colourChar[pattern[1]] local last_space = width
for i = width, 1, -1 do
if sub(v, i, i) == " " then
last_space = i
break
end end
end end
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
--- Coonverts a string with special tags to a table with colors and text
-- @param input The string to convert
-- @return A table with the following structure: { {text = "Hello", color = colors.red}, {text = "World", color = colors.blue} }
local function convertRichText(input)
local parsedResult = {}
local currentPosition = 1
local rawPosition = 1
while currentPosition <= #input do
local closestColor, closestBgColor
local color, bgColor
local colorEnd, bgColorEnd
for colorName, _ in pairs(colors) do
local fgPattern = "{fg:" .. colorName.."}"
local bgColorPattern = "{bg:" .. colorName.."}"
local colorStart, colorEndCandidate = input:find(fgPattern, currentPosition)
local bgColorStart, bgColorEndCandidate = input:find(bgColorPattern, currentPosition)
if colorStart and (not closestColor or colorStart < closestColor) then
closestColor = colorStart
color = colorName
colorEnd = colorEndCandidate
end
if bgColorStart and (not closestBgColor or bgColorStart < closestBgColor) then
closestBgColor = bgColorStart
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
--- 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)()
--- Writes text with special color tags
--- @param obj object The object to write to
--- @param x number X-Position
--- @param y number Y-Position
--- @param text string The text to write
writeRichText = function(obj, x, y, text)
local richText = convertRichText(text)
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, end,
wrapRichText = wrapRichText,
--- 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,
--- Returns a random UUID.
--- @return string UUID.
uuid = function() uuid = function()
local random = math.random 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')
local function uuid()
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function (c)
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
return string.format('%x', v)
end)
end
return uuid()
end,
array = function(arraysize, hashsize)
return load("return {" .. ("nil,"):rep(arraysize) .. ("[0]=nil,"):rep(hashsize) .. "}")()
end,
shrink = function(image, bgCol)
local results, width, height, bgCol = {{}, {}, {}}, 0, #image + #image % 3, bgCol or colours.black
for i = 1, #image do if #image[i] > width then width = #image[i] end end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do for xx = 1, 2 do
pattern[#pattern + 1] = (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 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
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then if not(ok)then
basaltError(result) basalt.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 end
handleSchedules(event, ...) handleSchedules(event, ...)
drawFrames() renderingUpdateEvent()
end
end
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
while updaterActive do
local ok, err = xpcall(f, debug.traceback) local ok, err = xpcall(f, debug.traceback)
if not(ok)then if not(ok)then
basaltError(err) basalt.basaltError(err)
return 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
xOffset = math.floor((w - text:len()) / 2)
elseif(textHorizontalAlign=="right")then
xOffset = w - text:len()
end
for n = 1, h do self:addText(xOffset + 1, verticalAlign, text)
if (n == verticalAlign) then self:addFG(xOffset + 1, verticalAlign, tHex[self:getForeground() or colors.white]:rep(text:len()))
local val = self:getValue() end)
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,
} }
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
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(symbol, w, "center"), self.bgColor, self.fgColor)
else else
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", w, "center"), self.bgColor, self.fgColor) self:addBlit(1, verticalAlign, utils.getTextHorizontalAlign(inactiveSymbol, w, "center"), tHex[fg], tHex[bg])
end end
if(text~="")then
local align = textPos=="left" and -text:len() or 3
self:addText(align, verticalAlign, text)
end end
end end)
end
end
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
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
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
local val = self:getValue() local val = self:getValue()
local list = self:getAll()
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
self:addTextBox(1, 2, dropdownW, dropdownH, " ")
self:addBackgroundBox(1, 2, dropdownW, dropdownH, bgCol)
self:addForegroundBox(1, 2, dropdownW, dropdownH, fgCol)
for n = 1, dropdownH do for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then if (list[n + yOffset] ~= nil) then
local t =utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align)
if (list[n + yOffset] == val) then if (list[n + yOffset] == val) then
if (selectionColorActive) then if (selectionColorActive) then
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG) 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 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
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 end
if(originalImage.palette~=nil)then local globalPalette = bimgLibrary.getMetadata("palette")
for k,v in pairs(originalImage.palette)do if(globalPalette~=nil)then
for k,v in pairs(globalPalette)do
p[k] = tonumber(v) p[k] = tonumber(v)
end end
end end
if(originalImage[id]~=nil)and(originalImage[id].palette~=nil)then local localPalette = bimgLibrary.getFrameData("palette")
for k,v in pairs(originalImage[id].palette)do basalt.log(localPalette)
if(localPalette~=nil)then
for k,v in pairs(localPalette)do
p[k] = tonumber(v) p[k] = tonumber(v)
end end
end end
return p return p
end end
local function checkAutoSize()
if(autoSize)then
if(bimgLibrary~=nil)then
base:setSize(bimgLibrary.getSize())
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
curFrame = fr
if(animTimer~=nil)then
os.cancelTimer(animTimer) os.cancelTimer(animTimer)
end animTimer = nil
self:updateDraw() infinitePlay = false
end return self
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
self:getBaseFrame():setThemeColor(getPalette(curFrame))
end
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize() local w,h = self:getSize()
for y,v in ipairs(image[curFrame])do local x, y = self:getPosition()
local t, f, b = unpack(v) local wParent, hParent = self:getParent():getSize()
t = sub(t, 1,w) local parentXOffset, parentYOffset = self:getParent():getOffset()
f = sub(f, 1,w)
b = sub(b, 1,w) if(x - parentXOffset > wParent)or(y - parentYOffset > hParent)or(x - parentXOffset + w < 1)or(y - parentYOffset + h < 1)then
self.parent:blit(obx, oby+y-1, t, f, b) return
if(y==h)then break end end
if(usePalette)then
self:getParent():setPalette(getPalette(activeFrame))
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 end
self.parent:setCursor(false) parent:setCursor(false)
end end,
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
end
if (wIndex > 1) then
if (textX < wIndex) then if (textX < wIndex) then
wIndex = wIndex - 1 wIndex = math.max(wIndex - 1, 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 end
if (wIndex < 1) then local obx, oby = self:getPosition()
wIndex = 1
end
end
local obx, oby = self:getAnchorPosition()
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,64 +254,22 @@ 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 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, textVerticalAlign)
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor) end
for n = 1, h do
if (n == verticalAlign) then
local val = tostring(base.getValue()) local val = tostring(base.getValue())
local bCol = self.bgColor local bCol = self:getBackground()
local fCol = self.fgColor local fCol = self:getForeground()
local text local text
if (val:len() <= 0) then if (val:len() <= 0) then
text = showingText text = showingText
@@ -343,31 +289,16 @@ return function(name)
if (inputType == "password") and (val ~= "") then if (inputType == "password") and (val ~= "") then
text = string.rep("*", text:len()) text = string.rep("*", text:len())
end end
text = text .. string.rep(self.bgSymbol, space) text = text .. string.rep(" ", space)
self.parent:writeText(obx, oby + (n - 1), text, bCol, fCol) self:addBlit(1, verticalAlign, text, tHex[fCol]:rep(text:len()), tHex[bCol]:rep(text:len()))
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,
init = function(self) if(self:isFocused())then
if(self.parent~=nil)then parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self:getForeground())
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("key", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
self.parent:addEvent("mouse_drag", self)
end
if(base.init(self))then
self.bgColor = self.parent:getTheme("InputBG")
self.fgColor = self.parent:getTheme("InputText")
end 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)
return base
end,
--- Changes the label's text.
--- @param newText string The new text of the label.
--- @return object
setText = function(self, newText)
text = tostring(newText)
if(autoSize)then if(autoSize)then
local xOffset = self.parent:getOffset() local t = wrapText(text, #text)
if(text:len()+self:getX()>self.parent:getWidth()+xOffset)then local newW, newH = 1,1
local newW = self.parent:getWidth()+xOffset - self:getX() for k,v in pairs(t)do
base.setSize(self, newW, #createText(text, newW)) newH = newH+1
else newW = math.max(newW, v:len())
base.setSize(self, text:len(), 1)
end end
self:setSize(newW, newH)
autoSize = true
end end
self:updateDraw() self:updateDraw()
return self return self
end;
setBackground = function(self, col)
base.setBackground(self, col)
bgColChanged = true
self:updateDraw()
return self
end, end,
setForeground = function(self, col) --- Returns the label's autoSize property.
base.setForeground(self, col) --- @return boolean
fgColChanged = 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,
setTextAlign = function(self, hor, vert) --- Returns the label's text.
textHorizontalAlign = hor or textHorizontalAlign --- @return string
textVerticalAlign = vert or textVerticalAlign getText = function(self)
self:updateDraw() return text
return self
end;
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, end,
setSize = function(self, width, height, rel) --- Sets the size of the label.
base.setSize(self, width, height, rel) --- @param width number The width of the label.
--- @param height number The height of the label.
--- @return object
setSize = function(self, width, height)
base.setSize(self, width, height)
autoSize = false 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 verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign) local align = textAlign=="center" and math.floor(w/2-text:len()/2+0.5) or textAlign=="right" and w-(text:len()-1) or 1
if(fontsize==0)then writeWrappedText(self, align, 1, text, w, h)
if not(autoSize)then end)
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 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
for n = 1, h do for n = 1, h do
if (list[n + yOffset] ~= nil) then if list[n + yOffset] then
if (list[n + yOffset] == self:getValue()) then local t = list[n + yOffset].text
if (selectionColorActive) then local fg, bg = list[n + yOffset].fgCol, list[n + yOffset].bgCol
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), itemSelectedBG, itemSelectedFG) if list[n + yOffset] == self:getValue() and selectionColorActive then
else fg, bg = itemSelectedFG, itemSelectedBG
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
else self:addBlit(1, n, t, tHex[fg]:rep(#t), tHex[bg]:rep(#t))
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 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
if(xPos < w)then
mScroll = mScroll + (list[n].text:len() + space * 2-(w - xPos))
else
mScroll = mScroll + list[n].text:len() + space * 2 mScroll = mScroll + list[n].text:len() + space * 2
end end
end return math.max(mScroll - w, 0)
xPos = xPos + list[n].text:len() + space * 2
end
return mScroll
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
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
local text = "" local text = ""
local textBGCol = "" local textBGCol = ""
local textFGCol = "" local textFGCol = ""
for _, v in pairs(list) do local itemSelectedBG, itemSelectedFG = self:getSelectionColor()
for _, v in pairs(self:getAll()) do
local newItem = (" "):rep(space) .. v.text .. (" "):rep(space) local newItem = (" "):rep(space) .. v.text .. (" "):rep(space)
text = text .. newItem text = text .. newItem
if(v == self:getValue())then if(v == self:getValue())then
textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self.bgColor]:rep(newItem:len()) textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self:getBackground()]:rep(newItem:len())
textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self.fgColor]:rep(newItem:len()) textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self:getForeground()]:rep(newItem:len())
else else
textBGCol = textBGCol .. tHex[v.bgCol or self.bgColor]:rep(newItem:len()) textBGCol = textBGCol .. tHex[v.bgCol or self:getBackground()]:rep(newItem:len())
textFGCol = textFGCol .. tHex[v.FgCol or self.fgColor]:rep(newItem:len()) textFGCol = textFGCol .. tHex[v.FgCol or self:getForeground()]:rep(newItem:len())
end end
end end
self.parent:setText(obx, oby, text:sub(itemOffset+1, w+itemOffset)) self:addBlit(1, 1, text:sub(itemOffset+1, w+itemOffset), textFGCol:sub(itemOffset+1, w+itemOffset), textBGCol:sub(itemOffset+1, w+itemOffset))
self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, w+itemOffset)) end)
self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, w+itemOffset))
end
end
end,
init = function(self)
self.parent:addEvent("mouse_click", self)
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 end
cacheT[yCursor] = sub(cacheT[yCursor], 1, xCursor - 1) .. sText .. sub(cacheT[yCursor], xCursor + #sText, width)
local sOldText = cacheT[yCursor] cacheFG[yCursor] = sub(cacheFG[yCursor], 1, xCursor - 1) .. sTextColor .. sub(cacheFG[yCursor], xCursor + #sText, width)
local sOldTextColor = cacheFG[yCursor] cacheBG[yCursor] = sub(cacheBG[yCursor], 1, xCursor - 1) .. sBackgroundColor .. sub(cacheBG[yCursor], xCursor + #sText, width)
local sOldBackgroundColor = cacheBG[yCursor] xCursor = xCursor + #sText
local sNewText, sNewTextColor, sNewBackgroundColor if visible then
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() updateCursor()
end end
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
parent:setText(x, y + (n - 1), cacheT[n]) object:addBlit(1, n, cacheT[n], cacheFG[n], cacheBG[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
local sEmptyTextColor = emptyColorLines[fgColor]
local sEmptyBackgroundColor = emptyColorLines[bgColor]
for newY = 1, height do for newY = 1, height do
local y = newY + offset local y = newY + offset
if y >= 1 and y <= height then if y < 1 or y > height then
cacheT[newY] = emptySpaceLine
cacheFG[newY] = emptyColorLines[fgColor]
cacheBG[newY] = emptyColorLines[bgColor]
else
cacheT[newY] = cacheT[y] cacheT[newY] = cacheT[y]
cacheBG[newY] = cacheBG[y] cacheBG[newY] = cacheBG[y]
cacheFG[newY] = cacheFG[y] cacheFG[newY] = cacheFG[y]
else
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 parent:removeEvents(self)
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
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
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 obx, oby = self:getPosition()
local xCur, yCur = pWindow.getCursorPos() local xCur, yCur = pWindow.getCursorPos()
local w,h = self:getSize() local w,h = self:getSize()
pWindow.basalt_reposition(obx, oby)
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(fgCol~=false)then self:addForegroundBox(1, 1, w, h, fgCol) end
if (direction == 1) then if (direction == 1) then
self.parent:drawBackgroundBox(obx, oby, w, h / 100 * progress, activeBarColor) self:addBackgroundBox(1, 1, w, h / 100 * progress, activeBarColor)
self.parent:drawForegroundBox(obx, oby, w, h / 100 * progress, activeBarSymbolCol) self:addForegroundBox(1, 1, w, h / 100 * progress, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby, w, h / 100 * progress, activeBarSymbol) self:addTextBox(1, 1, w, h / 100 * progress, activeBarSymbol)
elseif (direction == 2) then
self.parent:drawBackgroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor)
self.parent:drawForegroundBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol)
elseif (direction == 3) then elseif (direction == 3) then
self.parent:drawBackgroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarColor) self:addBackgroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarColor)
self.parent:drawForegroundBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbolCol) self:addForegroundBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbolCol)
self.parent:drawTextBox(obx + math.ceil(w - w / 100 * progress), oby, w / 100 * progress, h, activeBarSymbol) self:addTextBox(1, 1 + math.ceil(h - h / 100 * progress), w, h / 100 * progress, activeBarSymbol)
elseif (direction == 2) then
self:addBackgroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarColor)
self:addForegroundBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbolCol)
self:addTextBox(1 + math.ceil(w - w / 100 * progress), 1, w / 100 * progress, h, activeBarSymbol)
else else
self.parent:drawBackgroundBox(obx, oby, w / 100 * progress, h, activeBarColor) self:addBackgroundBox(1, 1, math.ceil( w / 100 * progress), h, activeBarColor)
self.parent:drawForegroundBox(obx, oby, w / 100 * progress, h, activeBarSymbolCol) self:addForegroundBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbolCol)
self.parent:drawTextBox(obx, oby, w / 100 * progress, h, activeBarSymbol) self:addTextBox(1, 1, math.ceil(w / 100 * progress), h, activeBarSymbol)
end
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 return self
end; end,
getAll = function(self)
return list
end;
removeItem = function(self, index) removeItem = function(self, index)
base.removeItem(self, index)
table.remove(list, index) table.remove(list, index)
self:updateDraw()
return self return self
end; 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) clear = function(self)
base.clear(self)
list = {} list = {}
self:setValue({}, false)
self:updateDraw()
return self return self
end; end,
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, x, y, bgCol, fgCol, ...) editItem = function(self, index, text, x, y, bgCol, fgCol, ...)
base.editItem(self, index, text, bgCol, fgCol, ...)
table.remove(list, index) 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 = { ... } }) table.insert(list, index, { x = x or 1, y = y or 1 })
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) setBoxSelectionColor = function(self, bg, fg)
itemSelectedBG = bgCol or itemSelectedBG boxSelectedBG = bg
itemSelectedFG = fgCol or itemSelectedFG boxSelectedFG = fg
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) 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,66 +1,65 @@
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:scrollbarMoveHandler()
self:updateDraw() self:updateDraw()
end end
end 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
local object = { local object = {
getType = function(self) getType = function(self)
return objectType return objectType
end; end,
setSymbol = function(self, _symbol) load = function(self)
base.load(self)
local parent = self:getParent()
self:listenEvent("mouse_click")
self:listenEvent("mouse_up")
self:listenEvent("mouse_scroll")
self:listenEvent("mouse_drag")
end,
setSymbol = function(self, _symbol, bg, fg)
symbol = _symbol:sub(1,1) 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()
if (barType == "horizontal") then
self.parent:writeText(obx, oby, bgSymbol:rep(index - 1), self.bgColor, self.fgColor)
self.parent:writeText(obx + index - 1, oby, symbol:rep(symbolSize), symbolColor, symbolColor)
self.parent:writeText(obx + index + symbolSize - 1, oby, bgSymbol:rep(w - (index + symbolSize - 1)), self.bgColor, self.fgColor)
end end
end
return self
end,
if (barType == "vertical") then
scrollbarMoveHandler = function(self)
self:sendEvent("scrollbar_moved", self:getIndex())
end,
customEventHandler = function(self, event, ...)
base.customEventHandler(self, event, ...)
if(event=="basalt_FrameResize")then
updateSymbolSize()
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 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, index + curIndexOffset, symbol:rep(math.max(#symbol, w)), tHex[symbolFG]:rep(math.max(#symbol, w)), tHex[symbolBG]:rep(math.max(#symbol, w)))
end
else
if (n + 1 < index) or (n + 1 > index - 1 + symbolSize) then
self.parent:writeText(obx, oby + n, bgSymbol, self.bgColor, self.fgColor)
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("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 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
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)
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, 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,56 +28,55 @@ 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
ex = endSelX
if startSelY < endSelY then
sy = startSelY
ey = endSelY
else else
sx,ex = startSelX,endSelX sy = endSelY
ey = startSelY
end end
if(startSelY>endSelY)then elseif startSelX > endSelX and startSelY >= endSelY then
sy,ey = endSelY,startSelY sx = endSelX
ex = startSelX
if startSelY > endSelY then
sy = endSelY
ey = startSelY
else else
sy,ey = startSelY,endSelY sy = startSelY
ey = endSelY
end end
elseif startSelY > endSelY then
sx = endSelX
ex = startSelX
sy = endSelY
ey = startSelY
end end
return sx, ex, sy, ey return sx, ex, sy, ey
end 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
textX, textY = sx, sy
startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil 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,35 +272,44 @@ 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(isSelected())then
removeSelection(self)
else
if (lines[textY] == "") then if (lines[textY] == "") then
if (textY > 1) then if (textY > 1) then
table.remove(lines, textY) table.remove(lines, textY)
@@ -377,11 +353,10 @@ return function(name)
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)
elseif (key == keys.enter) then
if(isSelected())then
removeSelection(self)
end end
if (key == keys.enter) then
-- 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 obx, oby = self:getPosition()
local w, h = self:getSize() local w, h = self:getSize()
local bgColor = tHex[self:getBackground()]
local fgColor = tHex[self:getForeground()]
for n = 1, h do for n = 1, h do
local text = "" local text = ""
local bg = "" local bg = ""
local fg = "" local fg = ""
if (lines[n + hIndex - 1] ~= nil) then if lines[n + hIndex - 1] then
text = lines[n + hIndex - 1] text = lines[n + hIndex - 1]
fg = fgLines[n + hIndex - 1] fg = fgLines[n + hIndex - 1]
bg = bgLines[n + hIndex - 1] bg = bgLines[n + hIndex - 1]
end end
text = text:sub(wIndex, w + wIndex - 1)
bg = bg:sub(wIndex, w + wIndex - 1) text = sub(text, wIndex, w + wIndex - 1)
fg = fg:sub(wIndex, w + wIndex - 1) bg = rep(bgColor, w)
local space = w - text:len() fg = rep(fgColor, w)
if (space < 0) then
space = 0 self:addText(1, n, text)
self:addBG(1, n, bg)
self:addFG(1, n, fg)
self:addBlit(1, n, text, fg, bg)
end end
text = text .. rep(self.bgSymbol, space)
bg = bg .. rep(tHex[self.bgColor], space) if startSelX and endSelX and startSelY and endSelY then
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
--[[
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
local sx, ex, sy, ey = getSelectionCoordinates(self) local sx, ex, sy, ey = getSelectionCoordinates(self)
for n = sy, ey do for n = sy, ey do
local line = lines[n]:len() local line = #lines[n]
local xOffset = 0 local xOffset = 0
if(n==sy)and(n==ey)then if n == sy and n == ey then
xOffset = sx - 1 xOffset = sx - 1
line = line - (sx - 1) - (line - ex) line = line - (sx - 1) - (line - ex)
elseif(n==ey)then elseif n == ey then
line = line - (line - ex) line = line - (line - ex)
elseif(n==sy)then elseif n == sy then
line = line - (sx - 1) line = line - (sx - 1)
xOffset = sx - 1 xOffset = sx - 1
end end
self.parent:setBG(obx + xOffset, oby + n - 1, rep(tHex[selectionBG], line)) self:addBG(1 + xOffset, n, rep(tHex[selectionBG], line))
self.parent:setFG(obx + xOffset, oby + n - 1, rep(tHex[selectionFG], line)) self:addFG(1 + xOffset, n, rep(tHex[selectionFG], line))
end
end]]
if(self:isFocused())then
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)
- [Dropdown](objects/Dropdown.md)
- [Menubar](objects/Menubar.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