Basalt 1.7 Update

- New Objects (Flexbox, Graph, Treeview)
- Pluginsystem to add/remove functionality
- Reworked the entire Object system, instead of one big Object Class we have multiple classes: Object, VisualObject, ChangeableObject
- Instead of one big Frame Class we have multiple Frame Classes: BaseFrame, Frame, MovableFrame, ScrollableFrame, MonitorFrame, Flexbox
- Removed the Animation Object, and added a animation plugin instead
- Removed the Graphic Object and merged it's functionality with the image object
- Updated currently existing objects
This commit is contained in:
Robert Jelic
2023-04-30 17:05:34 +02:00
parent e086c1abb2
commit bb1b1beb79
341 changed files with 15541 additions and 3862 deletions

View File

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

View File

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

View File

@@ -1,21 +1,41 @@
return function()
local events = {}
local index = {}
local event = {
registerEvent = function(self, _event, func)
if (events[_event] == nil) then
events[_event] = {}
index[_event] = 1
end
events[_event][index[_event]] = func
index[_event] = index[_event] + 1
return index[_event] - 1
end;
table.insert(events[_event], func)
end,
removeEvent = function(self, _event, index)
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, ...)
local returnValue
@@ -28,7 +48,7 @@ return function()
end
end
return returnValue
end;
end,
}
event.__index = event
return event

View File

@@ -10,7 +10,7 @@ local mt = {
if(text==nil)then return end
local dirStr = logDir~="" and logDir.."/"..logFileName or logFileName
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()
end,
}

View File

@@ -80,9 +80,11 @@ local function frame(base, manager)
end
if(base~=nil)then
w = #base[1][1]
h = #base
setFrame(base)
if(#base>0)then
w = #base[1][1]
h = #base
setFrame(base)
end
end
return {
@@ -134,7 +136,11 @@ local function frame(base, manager)
end,
getFrameData = function(key)
return (key~= nil and data[key] or data)
if(key~=nil)then
return data[key]
else
return data
end
end,
blit = function(text, fgCol, bgCol, x, y)
@@ -185,10 +191,12 @@ return function(img)
local function addFrame(id, data)
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
frames[id].setSize(width, height)
end
return f
end
local function removeFrame(id)
@@ -283,7 +291,6 @@ return function(img)
end,
addFrame = function(id)
local f = frame()
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
@@ -292,21 +299,10 @@ return function(img)
metadata.secondsPerFrame = 0.2
end
end
addFrame(id)
return f
return addFrame(id)
end,
removeFrame = function(id)
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,
removeFrame = removeFrame,
moveFrame = moveFrame,
@@ -317,7 +313,9 @@ return function(img)
end,
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,
getSize = function()
@@ -339,7 +337,11 @@ return function(img)
end,
getMetadata = function(key)
return key~=nil and metadata[key] or metadata
if(key~=nil)then
return metadata[key]
else
return metadata
end
end,
createBimg = function()

View File

@@ -1,23 +1,16 @@
local sub,floor,rep = string.sub,math.floor,string.rep
local sub,floor = string.sub,math.floor
local function loadNFPAsBimg(path)
local 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
return {[1]={{}, {}, paintutils.loadImage(path)}}, "bimg"
end
local function loadNFP(path)
return paintutils.loadImage(path), "nfp"
end
local function loadBIMG(path)
local f = fs.open(path, "rb")
local function loadBIMG(path, binaryMode)
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())
f.close()
if(content~=nil)then
@@ -33,28 +26,24 @@ local function loadBBFAsBimg(path)
end
local function loadImage(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBF(path)
else
return loadNFP(path)
end
local function loadImage(path, f, binaryMode)
if(sub(path, -4) == ".bimg")then
return loadBIMG(path, binaryMode)
elseif(sub(path, -3) == ".bbf")then
return loadBBF(path, binaryMode)
else
return loadNFP(path, binaryMode)
end
-- ...
end
local function loadImageAsBimg(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBFAsBimg(path)
else
return loadNFPAsBimg(path)
end
local function loadImageAsBimg(path)
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBFAsBimg(path)
else
return loadNFPAsBimg(path)
end
end
@@ -94,4 +83,4 @@ return {
resizeBIMG = resizeBIMG,
loadImageAsBimg = loadImageAsBimg,
}
}

View File

@@ -17,6 +17,7 @@ function process:new(path, window, newEnv, ...)
local env = setmetatable(newEnv, {__index=_ENV})
env.shell = shell
env.basaltProgram=true
env.arg = {[0]=path, table.unpack(args)}
env.require, env.package = newPackage(env, fs.getDir(pPath))
if(fs.exists(pPath))then
local file = fs.open(pPath, "r")
@@ -24,7 +25,7 @@ function process:new(path, window, newEnv, ...)
file.close()
local program = load(content, path, "bt", env)
if(program~=nil)then
return program(table.unpack(args))
return program()
end
end
end)
@@ -81,4 +82,4 @@ function process:start()
coroutine.resume(self.coroutine)
end
return process
return process

View File

@@ -1,18 +1,6 @@
return { -- copy paste is a very important feature
[colors.white] = "0",
[colors.orange] = "1",
[colors.magenta] = "2",
[colors.lightBlue] = "3",
[colors.yellow] = "4",
[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",
}
local cols = {}
for i = 0, 15 do
cols[2^i] = ("%x"):format(i)
end
return cols

View File

@@ -1,100 +1,32 @@
local sub,find,reverse = string.sub,string.find,string.reverse
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 result = {}
if str == "" or delimiter == "" then
return result
end
end
local start = 1
local delim_start, delim_end = find(str, delimiter, start)
while delim_start do
table.insert(result, sub(str, start, delim_start - 1))
start = delim_end + 1
delim_start, delim_end = find(str, delimiter, start)
end
table.insert(result, sub(str, start))
while delim_start do
insert(result, sub(str, start, delim_start - 1))
start = delim_end + 1
delim_start, delim_end = find(str, delimiter, start)
end
insert(result, sub(str, start))
return result
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},
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}}
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do exponents[2^i] = i end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function (a, b) return a[2] > b[2] end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
return {
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
text = sub(text, 1, width)
local offset = width - string.len(text)
local offset = width - len(text)
if (textAlign == "right") then
text = string.rep(replaceChar or " ", offset) .. text
text = rep(replaceChar or " ", offset) .. text
elseif (textAlign == "center") then
text = string.rep(replaceChar or " ", math.floor(offset / 2)) .. text .. string.rep(replaceChar or " ", math.floor(offset / 2))
text = text .. (string.len(text) < width and (replaceChar or " ") or "")
text = rep(replaceChar or " ", math.floor(offset / 2)) .. text .. rep(replaceChar or " ", math.floor(offset / 2))
text = text .. (len(text) < width and (replaceChar or " ") or "")
else
text = text .. string.rep(replaceChar or " ", offset)
text = text .. rep(replaceChar or " ", offset)
end
return text
end,
@@ -114,6 +46,14 @@ getTextVerticalAlign = function(h, textAlign)
return offset
end,
orderedTable = function(t)
local newTable = {}
for _, v in pairs(t) do
newTable[#newTable+1] = v
end
return newTable
end,
rpairs = function(t)
return function(t, i)
i = i - 1
@@ -135,7 +75,7 @@ end,
splitString = splitString,
createText = function(str, width)
wrapText = function(str, width)
local uniqueLines = splitString(str, "\n")
local result = {}
for k,v in pairs(uniqueLines)do
@@ -145,7 +85,7 @@ createText = function(str, width)
if not last_space then
last_space = width
else
last_space = width - last_space + 1
last_space = width - last_space --+ 1
end
local line = sub(v, 1, last_space)
table.insert(result, line)
@@ -158,73 +98,8 @@ createText = function(str, width)
return result
end,
getValueFromXML = function(name, tab)
local var
if(type(tab)~="table")then return end
if(tab[name]~=nil)then
if(type(tab[name])=="table")then
if(tab[name].value~=nil)then
var = tab[name]:value()
end
end
end
if(var==nil)then var = tab["@"..name] end
if(var=="true")then
var = true
elseif(var=="false")then
var = false
elseif(tonumber(var)~=nil)then
var = tonumber(var)
end
return var
end,
numberFromString = function(str)
return load("return " .. str)()
end,
uuid = function()
local random = math.random
local function uuid()
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
return string.gsub(template, '[xy]', function (c)
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
return string.format('%x', v)
end)
end
return uuid()
end,
return string.gsub(string.format('%x-%x-%x-%x-%x', math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0x0fff) + 0x4000, math.random(0, 0x3fff) + 0x8000), ' ', '0')
end
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
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 = {}
if(packaged)then
for k,v in pairs(getProject("objects"))do
_OBJECTS[k] = v()
@@ -13,7 +14,7 @@ if(dir==nil)then
end
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", "")
_OBJECTS[name] = require(name)
end

View File

@@ -1,16 +1,17 @@
local basaltEvent = require("basaltEvent")()
local Frame = require("Frame")
local theme = require("theme")
local _OBJECTS = require("loadObjects")
local pluginSystem = require("plugin")
local utils = require("utils")
local log = require("basaltLogs")
local uuid = utils.uuid
local createText = utils.createText
local wrapText = utils.wrapText
local count = utils.tableCount
local moveThrottle = 300
local dragThrottle = 50
local dragThrottle = 0
local renderingThrottle = 0
local baseTerm = term.current()
local version = "1.6.4"
local version = "1.7.0"
local projectDirectory = fs.getDir(table.pack(...)[2] or "")
@@ -42,7 +43,7 @@ local function stop()
end
end
local function basaltError(errMsg)
function basalt.basaltError(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
@@ -51,7 +52,7 @@ local function basaltError(errMsg)
log(errMsg, "Error")
end
local text = createText("Basalt error: "..errMsg, w)
local text = wrapText("Basalt error: "..errMsg, w)
local yPos = 1
for k,v in pairs(text)do
baseTerm.setCursorPos(1,yPos)
@@ -68,13 +69,17 @@ return function(...)
local co = coroutine.create(f)
local ok, result = coroutine.resume(co, ...)
if(ok)then
table.insert(schedules, {co, result})
table.insert(schedules, co)
else
basaltError(result)
basalt.basaltError(result)
end
end
end
basalt.log = function(...)
log(...)
end
local setVariable = function(name, var)
variables[name] = var
end
@@ -83,14 +88,6 @@ local getVariable = function(name)
return variables[name]
end
local setTheme = function(_theme)
theme = _theme
end
local getTheme = function(name)
return theme[name]
end
local bInstance = {
getDynamicValueEventSetting = function()
return basalt.dynamicValueEvents
@@ -102,7 +99,6 @@ local bInstance = {
setVariable = setVariable,
getVariable = getVariable,
getTheme = getTheme,
setMainFrame = function(mFrame)
mainFrame = mFrame
@@ -140,7 +136,7 @@ local bInstance = {
end
end,
getBaseTerm = function()
getTerm = function()
return baseTerm
end,
@@ -148,32 +144,31 @@ local bInstance = {
stop = stop,
newFrame = Frame,
debug = basalt.debug,
log = basalt.log,
getObjects = function()
return _OBJECTS
end,
getObject = function(id)
return _OBJECTS[id]
end,
getDirectory = function()
return projectDirectory
end
}
local function handleSchedules(event, ...)
local function handleSchedules(event, p1, p2, p3, p4)
if(#schedules>0)then
local finished = {}
for n=1,#schedules do
if(schedules[n]~=nil)then
if (coroutine.status(schedules[n][1]) == "suspended")then
if(schedules[n][2]~=nil)then
if(schedules[n][2]==event)then
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
end
else
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
if (coroutine.status(schedules[n]) == "suspended")then
local ok, result = coroutine.resume(schedules[n], event, p1, p2, p3, p4)
if not(ok)then
basalt.basaltError(result)
end
else
table.insert(finished, n)
@@ -189,15 +184,15 @@ end
local function drawFrames()
if(updaterActive==false)then return end
if(mainFrame~=nil)then
mainFrame:draw()
mainFrame:render()
mainFrame:updateTerm()
end
for _,v in pairs(monFrames)do
v:draw()
v:render()
v:updateTerm()
end
for _,v in pairs(monGroups)do
v[1]:draw()
v[1]:render()
v[1]:updateTerm()
end
end
@@ -236,6 +231,23 @@ local function mouseDragEvent(_, b, x, y)
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 a = {...}
if(basaltEvent:sendEvent("basaltEventCycle", event, ...)==false)then return end
@@ -252,15 +264,15 @@ local function basaltUpdateEvent(event, ...)
if(mouseEvent~=nil)then
mouseEvent(mainFrame, ...)
handleSchedules(event, ...)
drawFrames()
renderingUpdateEvent()
return
end
end
if(event == "monitor_touch") then
if(monFrames[a[1]]~=nil)then
monFrames[a[1]]:mouseHandler(1, a[2], a[3], true)
activeFrame = monFrames[a[1]]
if(monFrames[a[2]]~=nil)then
monFrames[a[2]]:mouseHandler(1, a[2], a[3], true)
activeFrame = monFrames[a[2]]
end
if(count(monGroups)>0)then
for k,v in pairs(monGroups)do
@@ -268,7 +280,7 @@ local function basaltUpdateEvent(event, ...)
end
end
handleSchedules(event, ...)
drawFrames()
renderingUpdateEvent()
return
end
@@ -287,7 +299,7 @@ local function basaltUpdateEvent(event, ...)
end
keyEvent(activeFrame, ...)
handleSchedules(event, ...)
drawFrames()
renderingUpdateEvent()
return
end
end
@@ -296,13 +308,15 @@ local function basaltUpdateEvent(event, ...)
moveHandlerTimer()
elseif(event=="timer")and(a[1]==dragTimer)then
dragHandlerTimer()
elseif(event=="timer")and(a[1]==renderingTimer)then
renderingUpdateTimer()
else
for k, v in pairs(frames) do
v:eventHandler(event, ...)
end
handleSchedules(event, ...)
renderingUpdateEvent()
end
handleSchedules(event, ...)
drawFrames()
end
basalt = {
@@ -311,10 +325,15 @@ basalt = {
setTheme = setTheme,
getTheme = getTheme,
drawFrames = drawFrames,
log = log,
getVersion = function()
return version
end,
memory = function()
return math.floor(collectgarbage("count")+0.5).."KB"
end,
setVariable = setVariable,
getVariable = getVariable,
@@ -322,8 +341,12 @@ basalt = {
baseTerm = _baseTerm
end,
log = function(...)
log(...)
resetPalette = function()
for k,v in pairs(colors)do
if(type(v)=="number")then
--baseTerm.setPaletteColor(v, colors.packRGB(table.unpack(defaultColors[k])))
end
end
end,
setMouseMoveThrottle = function(amount)
@@ -339,6 +362,15 @@ basalt = {
return false
end,
setRenderingThrottle = function(amount)
if(amount<=0)then
renderingThrottle = 0
else
renderingTimer = nil
renderingThrottle = amount
end
end,
setMouseDragThrottle = function(amount)
if(amount<=0)then
dragThrottle = 0
@@ -357,10 +389,11 @@ basalt = {
basaltUpdateEvent(os.pullEventRaw())
end
end
local ok, err = xpcall(f, debug.traceback)
if not(ok)then
basaltError(err)
return
while updaterActive do
local ok, err = xpcall(f, debug.traceback)
if not(ok)then
basalt.basaltError(err)
end
end
end,
@@ -368,7 +401,7 @@ basalt = {
if (event ~= nil) then
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, ...)
if not(ok)then
basaltError(err)
basalt.basaltError(err)
return
end
end
@@ -395,12 +428,16 @@ basalt = {
end,
setActiveFrame = function(frame)
if (frame:getType() == "Frame") then
if (frame:getType() == "Container") then
activeFrame = frame
return true
end
return false
end,
getMainFrame = function()
return mainFrame
end,
onEvent = function(...)
for _,v in pairs(table.pack(...))do
@@ -413,14 +450,15 @@ basalt = {
schedule = schedule,
createFrame = function(name)
name = name or uuid()
for _, v in pairs(frames) do
if (v.name == name) then
if (v:getName() == name) then
return nil
end
end
local newFrame = Frame(name,nil,nil,bInstance)
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()
@@ -435,41 +473,26 @@ basalt = {
setProjectDir = function(dir)
projectDirectory = dir
end,
forceRenderUpdate = function()
drawFrames()
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)
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()
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()
_OBJECTS = pluginSystem.addPlugins(_OBJECTS, bInstance)
local basaltPlugins = pluginSystem.get("basalt")
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

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
-- You can find the easing curves here https://easings.net
@@ -222,7 +219,8 @@ local lerp = {
local activeAnimations = {}
return function(name)
return function(name, basalt)
local base = basalt.getObject("Object")(name, basalt)
local object = {}
local objectType = "Animation"
@@ -234,8 +232,6 @@ return function(name)
local index = 1
local infinitePlay = false
local eventSystem = basaltEvent()
local nextWaitTimer = 0
local lastFunc
local loop=false
@@ -306,7 +302,7 @@ return function(name)
local obj = _OBJ
local x,y
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()
addAnimationPart(t+0.05, function()
if(typ~=nil)then
@@ -340,14 +336,7 @@ return function(name)
name = name,
getType = function(self)
return objectType
end;
getBaseFrame = function(self)
if(self.parent~=nil)then
return self.parent:getBaseFrame()
end
return self
end;
end,
setMode = function(self, newMode)
mode = newMode
@@ -359,124 +348,6 @@ return function(name)
return self
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)
_OBJ = obj
return self
@@ -557,12 +428,12 @@ return function(name)
end;
onDone = function(self, f)
eventSystem:registerEvent("animation_done", f)
self:registerEvent("animation_done", f)
return self
end,
onStart = function(self, f)
eventSystem:registerEvent("animation_start", f)
self:registerEvent("animation_start", f)
return self
end,
@@ -572,16 +443,16 @@ return function(name)
end,
animationDoneHandler = function(self)
eventSystem:sendEvent("animation_done", self)
self.parent:removeEvent("other_event", self)
self:sendEvent("animation_done", self)
self:listenEvent("other_event", false)
if(autoDestroy)then
self.parent:removeObject(self)
self:getParent():removeObject(self)
self = nil
end
end;
animationStartHandler = function(self)
eventSystem:sendEvent("animation_start", self)
self:sendEvent("animation_start", self)
end;
clear = function(self)
@@ -609,7 +480,7 @@ return function(name)
else
self:animationDoneHandler()
end
self.parent:addEvent("other_event", self)
self:listenEvent("other_event")
return self
end;
@@ -619,7 +490,7 @@ return function(name)
infinitePlay = false
end
animationActive = false
self.parent:removeEvent("other_event", self)
self:listenEvent("other_event", false)
return self
end;
@@ -639,7 +510,7 @@ return function(name)
end
end;
}
object.__index = object
return object
object.__index = object
return setmetatable(object, base)
end

View File

@@ -0,0 +1,213 @@
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,
show = function(self)
base.show(self)
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,
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)
basaltDraw.update()
end,
setTerm = function(self, newTerm)
termObject = newTerm
basaltDraw = drawSystem(termObject)
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()
cursorBlink = _blink or false
if (_xCursor ~= nil) then
xCursor = obx + _xCursor - 1
end
if (_yCursor ~= nil) then
yCursor = oby + _yCursor - 1
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({"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 xmlValue = utils.getValueFromXML
local tHex = require("tHex")
return function(name)
return function(name, basalt)
-- Button
local base = Object(name)
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Button"
local textHorizontalAlign = "center"
local textVerticalAlign = "center"
local text = "Button"
base:setSize(12, 3)
base:setZIndex(5)
base:setValue("Button")
base.width = 12
base.height = 3
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)
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)
textHorizontalAlign = pos
self:updateDraw()
return self
end;
end,
setVerticalAlign = function(self, pos)
textVerticalAlign = pos
self:updateDraw()
return self
end;
end,
setText = function(self, text)
base:setValue(tostring(text))
setText = function(self, newText)
text = newText
self:updateDraw()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("horizontalAlign", data)~=nil)then textHorizontalAlign = xmlValue("horizontalAlign", data) end
if(xmlValue("verticalAlign", data)~=nil)then textVerticalAlign = xmlValue("verticalAlign", data) end
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
for n = 1, h do
if (n == verticalAlign) then
local val = self:getValue()
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
base.draw(self)
self:addDraw("button", function()
local w,h = self:getSize()
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
end
end,
self:addText(xOffset + 1, verticalAlign, text)
self:addFG(xOffset + 1, verticalAlign, tHex[self:getForeground() or colors.white]:rep(text:len()))
end)
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

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

View File

@@ -0,0 +1,388 @@
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 activeEvents = {}
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 k,v in pairs(elements)do
if(v.element==element)then
v.zIndex = newZ
v.objId = objId
break
end
end
for k,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
activeEvents[a] = false
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)
local parent = self:getParent()
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
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,
getEvent = getEvent,
addEvent = addEvent,
removeEvent = removeEvent,
updateZIndex = updateZIndex,
listenEvent = function(self, event, active)
base.listenEvent(self, event, active)
activeEvents[event] = active~=nil and active or true
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[v[1]](obj.element, btn, x+xO, y+yO, ...)) then
return true
end
end
end
if(v[2])then
self:removeFocusedObject()
end
return true
end
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,17 +1,15 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = require("utils").getValueFromXML
local tHex = require("tHex")
return function(name)
local base = Object(name)
return function(name, basalt)
local base = basalt.getObject("List")(name, basalt)
local objectType = "Dropdown"
base.width = 12
base.height = 1
base:setSize(12, 1)
base:setZIndex(6)
local list = {}
local itemSelectedBG
local itemSelectedFG
local itemSelectedBG = colors.black
local itemSelectedFG = colors.lightGray
local selectionColorActive = true
local align = "left"
local yOffset = 0
@@ -25,94 +23,28 @@ return function(name)
local object = {
getType = function(self)
return objectType
end;
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("dropdownWidth", data)~=nil)then dropdownW = xmlValue("dropdownWidth", data) end
if(xmlValue("dropdownHeight", data)~=nil)then dropdownH = xmlValue("dropdownHeight", data) end
if(xmlValue("offset", data)~=nil)then yOffset = xmlValue("offset", data) end
if(data["item"]~=nil)then
local tab = data["item"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
isType = function(self, t)
return objectType==t or base.isType~=nil and base.isType(t) or false
end,
load = function(self)
self:listenEvent("mouse_click", self)
self:listenEvent("mouse_up", self)
self:listenEvent("mouse_scroll", self)
self:listenEvent("mouse_drag", self)
end,
setOffset = function(self, yOff)
yOffset = yOff
self:updateDraw()
return self
end;
end,
getOffset = function(self)
return yOffset
end;
addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
self:updateDraw()
return self
end;
getAll = function(self)
return list
end;
removeItem = function(self, index)
table.remove(list, index)
self:updateDraw()
return self
end;
getItem = function(self, index)
return list[index]
end;
getItemIndex = function(self)
local selected = self:getValue()
for key, value in pairs(list) do
if (value == selected) then
return key
end
end
end;
clear = function(self)
list = {}
self:setValue({}, false)
self:updateDraw()
return self
end;
getItemCount = function(self)
return #list
end;
editItem = function(self, index, text, 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;
end,
setDropdownSize = function(self, width, height)
dropdownW, dropdownH = width, height
@@ -124,20 +56,18 @@ return function(name)
return dropdownW, dropdownH
end,
mouseHandler = function(self, button, x, y, touch)
mouseHandler = function(self, button, x, y)
if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local obx, oby = self:getAbsolutePosition()
if(button==1)then
local list = self:getAll()
if (#list > 0) then
for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then
self:setValue(list[n + yOffset])
self:updateDraw()
local val = self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", dir, x, y)
if(touch)then
self:mouseUpHandler(button, x, y)
end
local val = self:sendEvent("mouse_click", self, "mouse_click", dir, x, y)
if(val==false)then return val end
return true
end
@@ -146,8 +76,9 @@ return function(name)
end
end
end
local base = base:getBase()
if (base.mouseHandler(self, button, x, y)) then
isOpened = (not isOpened)
isOpened = true
self:updateDraw()
return true
else
@@ -161,15 +92,16 @@ return function(name)
mouseUpHandler = function(self, button, x, y)
if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local obx, oby = self:getAbsolutePosition()
if(button==1)then
local list = self:getAll()
if (#list > 0) then
for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then
if (obx <= x) and (obx + dropdownW > x) and (oby + n == y) then
isOpened = false
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
return true
end
@@ -182,6 +114,7 @@ return function(name)
scrollHandler = function(self, dir, x, y)
if (isOpened)and(self:isFocused()) then
local list = self:getAll()
yOffset = yOffset + dir
if (yOffset < 0) then
yOffset = 0
@@ -195,7 +128,7 @@ return function(name)
yOffset = math.min(#list - 1, 0)
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
self:updateDraw()
return true
@@ -203,46 +136,40 @@ return function(name)
end,
draw = function(self)
if (base.draw(self)) then
local obx, oby = self:getAnchorPosition()
base.draw(self)
self:setDrawState("list", false)
self:addDraw("dropdown", function()
local obx, oby = self:getPosition()
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 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)
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)
self:addBlit(1, 1, text, tHex[fgCol]:rep(#text), tHex[bgCol]:rep(#text))
if (isOpened) then
for n = 1, dropdownH do
if (list[n + yOffset] ~= nil) then
if (list[n + yOffset] == val) then
if (selectionColorActive) then
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG)
else
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
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
if (list[n + yOffset] ~= nil) then
local t =utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align)
if (list[n + yOffset] == val) then
if (selectionColorActive) then
self:addBlit(1, n+1, t, tHex[itemSelectedFG]:rep(#t), tHex[itemSelectedBG]:rep(#t))
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
else
self:addBlit(1, n+1, t, tHex[list[n + yOffset].fgCol]:rep(#t), tHex[list[n + yOffset].bgCol]:rep(#t))
end
end
end
end
end
end,
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)
end

View File

@@ -0,0 +1,95 @@
return function(name, basalt)
local base = basalt.getObject("Frame")(name, basalt)
local objectType = "Flexbox"
local flexDirection = "row" -- "row" oder "column"
local justifyContent = "flex-start" -- "flex-start", "flex-end", "center", "space-between", "space-around"
local spacing = 1
local function applyLayout(self)
local objects = self:getObjects()
local totalElements = #objects
local _, _ = self:getPosition()
local width, height = self:getSize()
local totalChildSize = 0
for _, obj in ipairs(objects) do
if flexDirection == "row" then
local objWidth, _ = obj.element:getSize()
totalChildSize = totalChildSize + objWidth
else
local _, objHeight = obj.element:getSize()
totalChildSize = totalChildSize + objHeight
end
end
local availableSpace = (flexDirection == "row" and width or height) - totalChildSize - (spacing * (totalElements - 1))
local currentOffset = 0
if justifyContent == "center" then
currentOffset = availableSpace / 2
elseif justifyContent == "flex-end" then
currentOffset = availableSpace
end
for _, obj in ipairs(objects) do
if flexDirection == "row" then
obj.element:setPosition(currentOffset, 1) -- Ändere den y-Wert auf 1
local objWidth, _ = obj.element:getSize()
currentOffset = currentOffset + objWidth + spacing
else
obj.element:setPosition(1, math.floor(currentOffset+0.5)) -- Ändere den x-Wert auf 1
local _, objHeight = obj.element:getSize()
currentOffset = currentOffset + 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,
}
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

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

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

View File

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

View File

@@ -1,170 +1,94 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
local createText = utils.createText
local wrapText = utils.wrapText
local tHex = require("tHex")
local bigFont = require("bigfont")
return function(name)
return function(name, basalt)
-- Label
local base = Object(name)
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Label"
base:setZIndex(3)
local autoSize = true
base:setValue("Label")
base.width = 5
local textHorizontalAlign = "left"
local textVerticalAlign = "top"
local fontsize = 0
local fgColChanged,bgColChanged = false,false
local text, textAlign = "Label", "left"
local object = {
getType = function(self)
return objectType
end;
end,
getBase = function(self)
return base
end,
setText = function(self, text)
text = tostring(text)
base:setValue(text)
if (autoSize) then
local xOffset = self.parent:getOffset()
if(text:len()+self:getX()>self.parent:getWidth()+xOffset)then
local newW = self.parent:getWidth()+xOffset - self:getX()
base.setSize(self, newW, #createText(text, newW))
else
base.setSize(self, text:len(), 1)
end
setText = function(self, newText)
text = tostring(newText)
if(autoSize)then
self:setSize(#text, 1)
autoSize = true
end
self:updateDraw()
return self
end;
end,
getText = function(self)
return text
end,
setBackground = function(self, col)
base.setBackground(self, col)
bgColChanged = true
self:updateDraw()
return self
end,
setForeground = function(self, col)
base.setForeground(self, col)
fgColChanged = true
self:updateDraw()
return self
end,
setTextAlign = function(self, hor, vert)
textHorizontalAlign = hor or textHorizontalAlign
textVerticalAlign = vert or textVerticalAlign
self:updateDraw()
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,
setSize = function(self, width, height, rel)
base.setSize(self, width, height, rel)
setSize = function(self, ...)
base.setSize(self, ...)
autoSize = false
self:updateDraw()
return self
end;
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
setTextAlign = function(self, align)
textAlign = align or textAlign
return self;
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
local verticalAlign = utils.getTextVerticalAlign(h, textVerticalAlign)
if(fontsize==0)then
if not(autoSize)then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
if(#self:getValue()+obx>self.parent:getWidth())then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
self.parent:writeText(obx, oby, self:getValue(), self.bgColor, self.fgColor)
end
base.draw(self)
self:addDraw("label", function()
local parent = self:getParent()
local obx, oby = self:getPosition()
local w,h = self:getSize()
local bgCol,fgCol = self:getBackground(), self:getForeground()
if not(autoSize)then
local text = wrapText(text, w)
for k,v in pairs(text)do
if(k<=h)then
local align = textAlign=="center" and math.floor(w/2-v:len()/2+0.5) or textAlign=="right" and w-(v:len()-1) or 1
self:addText(align, k, v)
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
else
self:addText(1, 1, text:sub(1,w))
end
end
end)
end,
init = function(self)
self.parent:addEvent("other_event", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("LabelBG")
self.fgColor = self.parent:getTheme("LabelText")
if(self.parent.bgColor==colors.black)and(self.fgColor==colors.black)then
self.fgColor = colors.lightGray
end
end
base.init(self)
local parent = self:getParent()
self:setForeground(parent:getForeground())
self:setBackground(parent:getBackground())
end
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,59 +1,87 @@
local Object = require("Object")
local utils = require("utils")
local xmlValue = utils.getValueFromXML
local tHex = require("tHex")
return function(name)
local base = Object(name)
return function(name, basalt)
local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "List"
base.width = 16
base.height = 6
base:setZIndex(5)
local list = {}
local itemSelectedBG
local itemSelectedFG
local itemSelectedBG = colors.black
local itemSelectedFG = colors.lightGray
local selectionColorActive = true
local align = "left"
local textAlign = "left"
local yOffset = 0
local scrollable = true
base:setSize(16, 8)
base:setZIndex(5)
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)
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, ...)
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
self:setValue(list[1], false)
end
self:updateDraw()
return self
end;
end,
setOffset = function(self, yOff)
yOffset = yOff
self:updateDraw()
return self
end;
end,
getOffset = function(self)
return yOffset
end;
end,
removeItem = function(self, index)
table.remove(list, index)
self:updateDraw()
return self
end;
end,
getItem = function(self, index)
return list[index]
end;
end,
getAll = function(self)
return list
end;
end,
getItemIndex = function(self)
local selected = self:getValue()
@@ -62,61 +90,53 @@ return function(name)
return key
end
end
end;
end,
clear = function(self)
list = {}
self:setValue({}, false)
self:updateDraw()
return self
end;
end,
getItemCount = function(self)
return #list
end;
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 = { ... } })
table.insert(list, index, { text = text, bgCol = bgCol or self:getBackground(), fgCol = fgCol or self:getForeground(), args = { ... } })
self:updateDraw()
return self
end;
end,
selectItem = function(self, index)
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
end,
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
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;
end,
getSelectionColor = function(self)
return itemSelectedBG, itemSelectedFG
end,
isSelectionColorActive = function(self)
return selectionColorActive
end,
setScrollable = function(self, scroll)
scrollable = scroll
if(scroll==nil)then scrollable = true end
self:updateDraw()
return self
end;
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,
scrollHandler = function(self, dir, x, y)
@@ -148,7 +168,7 @@ return function(name)
mouseHandler = function(self, button, x, y)
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()
if (#list > 0) then
for n = 1, h do
@@ -174,42 +194,25 @@ return function(name)
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(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
for n = 1, h do
if (list[n + yOffset] ~= nil) then
if (list[n + yOffset] == self:getValue()) then
if (selectionColorActive) then
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), itemSelectedBG, itemSelectedFG)
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
else
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, w, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
end
base.draw(self)
self:addDraw("list", function()
local parent = self:getParent()
local obx, oby = self:getPosition()
local w, h = self:getSize()
for n = 1, h do
if list[n + yOffset] then
local t = list[n + yOffset].text
local fg, bg = list[n + yOffset].fgCol, list[n + yOffset].bgCol
if list[n + yOffset] == self:getValue() and selectionColorActive then
fg, bg = itemSelectedFG, itemSelectedBG
end
self:addBlit(1, n, t, tHex[fg]:rep(#t), tHex[bg]:rep(#t))
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)
end

View File

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

View File

@@ -0,0 +1,40 @@
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:hide()
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, name)
local mon = peripheral.wrap(name)
if(mon~=nil)then
self:setTerm(mon)
end
return self
end,
show = function(self)
if(basalt.getTerm()~=self:getTerm())then
base.show()
end
return self
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

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

@@ -0,0 +1,240 @@
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)
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,
sendEvent = function(self, event, ...)
return eventSystem:sendEvent(event, self, ...)
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")
local log = require("basaltLogs")
return function(name)
return function(name, basalt)
-- Pane
local base = Object(name)
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Pane"
base:setSize(25, 10)
local object = {
getType = function(self)
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,
}
object.__index = object
return setmetatable(object, base)
end

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,85 @@
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 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 h, y = b.element:getWidth(), b.element:getX()
local width = self:getWidth()
if (h + y - width >= amount) then
amount = max(h + y - 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 (h + y - height >= amount) then
amount = max(h + y - height, 0)
end
end
end
return amount
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,
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.scrollHandler(self, dir, x, y))then
local xO, yO = self:getOffset()
if(direction==1)then
self:setOffset(min(getHorizontalScrollAmount(self), max(0, xO + dir)), yO)
elseif(direction==0)then
self:setOffset(xO, min(getVerticalScrollAmount(self), max(0, yO + dir)))
end
self:updateDraw()
return true
end
end,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,42 +1,39 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
local tHex = require("tHex")
return function(name)
local base = Object(name)
return function(name, basalt)
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Scrollbar"
base.width = 1
base.height = 8
base:setValue(1)
base:setZIndex(2)
base:setSize(1, 8)
base:setBackground(colors.lightGray, "\127", colors.gray)
local barType = "vertical"
local symbol = " "
local symbolColor
local bgSymbol = "\127"
local maxValue = base.height
local symbolBG = colors.yellow
local symbolFG = colors.black
local scrollAmount = 3
local index = 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
local function mouseEvent(self, button, x, y)
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local obx, oby = self:getPosition()
local w,h = self:getSize()
if (barType == "horizontal") then
for _index = 0, w do
if (obx + _index == x) and (oby <= y) and (oby + h > y) then
index = math.min(_index + 1, w - (symbolSize - 1))
self:setValue(maxValue / w * (index))
self:updateDraw()
end
end
end
if (barType == "vertical") then
for _index = 0, h do
if (oby + _index == y) and (obx <= x) and (obx + w > x) then
index = math.min(_index + 1, h - (symbolSize - 1))
self:setValue(maxValue / h * (index))
self:updateDraw()
end
updateSymbolSize()
local size = barType == "vertical" and h or w
for i = 0, size do
if ((barType == "vertical" and oby + i == y) or (barType == "horizontal" and obx + i == x)) and (obx <= x) and (obx + w > x) and (oby <= y) and (oby + h > y) then
index = math.min(i + 1, size - (#symbol + symbolSize - 2))
self:scrollbarMoveHandler()
self:updateDraw()
end
end
end
@@ -44,23 +41,24 @@ return function(name)
local object = {
getType = function(self)
return objectType
end;
end,
setSymbol = function(self, _symbol)
symbol = _symbol:sub(1, 1)
load = function(self)
base.load(self)
local parent = self:getParent()
self:listenEvent("mouse_click")
self:listenEvent("mouse_up")
self:listenEvent("mouse_scroll")
self:listenEvent("mouse_drag")
end,
setSymbol = function(self, _symbol, bg, fg)
symbol = _symbol:sub(1,1)
symbolBG = bg or symbolBG
symbolFG = fg or symbolFG
updateSymbolSize()
self:updateDraw()
return self
end;
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("maxValue", data)~=nil)then maxValue = xmlValue("maxValue", data) end
if(xmlValue("backgroundSymbol", data)~=nil)then bgSymbol = xmlValue("backgroundSymbol", data):sub(1,1) end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data):sub(1,1) end
if(xmlValue("barType", data)~=nil)then barType = xmlValue("barType", data):lower() end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("symbolColor", data)~=nil)then symbolColor = colors[xmlValue("symbolColor", data)] end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
end,
setIndex = function(self, _index)
@@ -70,50 +68,37 @@ return function(name)
end
local w,h = self:getSize()
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
updateSymbolSize()
self:updateDraw()
return self
end,
setScrollAmount = function(self, amount)
scrollAmount = amount
updateSymbolSize()
self:updateDraw()
return self
end,
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,
setSymbolSize = function(self, size)
symbolSize = tonumber(size) or 1
local w,h = self:getSize()
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
symbolAutoSize = size~=false and false or true
updateSymbolSize()
self:updateDraw()
return self
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;
end,
setBarType = function(self, _typ)
barType = _typ:lower()
updateSymbolSize()
self:updateDraw()
return self
end;
end,
mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then
@@ -131,58 +116,69 @@ return function(name)
return false
end,
setSize = function(self, ...)
base.setSize(self, ...)
updateSymbolSize()
return self
end,
scrollHandler = function(self, dir, x, y)
if(base.scrollHandler(self, dir, x, y))then
local w,h = self:getSize()
updateSymbolSize()
index = index + dir
if (index < 1) then
index = 1
end
index = math.min(index, (barType == "vertical" and h or w) - (symbolSize - 1))
self:setValue(maxValue / (barType == "vertical" and h or w) * index)
index = math.min(index, (barType == "vertical" and h or w) - (barType == "vertical" and symbolSize - 1 or #symbol+symbolSize-2))
self:scrollbarMoveHandler()
self:updateDraw()
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()
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
onChange = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("scrollbar_moved", v)
end
end
return self
end,
if (barType == "vertical") then
for n = 0, h - 1 do
if (index == n + 1) then
for curIndexOffset = 0, math.min(symbolSize - 1, h) do
self.parent:writeText(obx, oby + n + curIndexOffset, symbol, symbolColor, symbolColor)
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
scrollbarMoveHandler = function(self)
self:sendEvent("scrollbar_moved", self, 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
if (index == n + 1) then
for curIndexOffset = 0, math.min(symbolSize - 1, h) do
self:blit(1, index + curIndexOffset, symbol:rep(math.max(#symbol, w)), tHex[symbolFG]:rep(math.max(#symbol, w)), tHex[symbolBG]:rep(math.max(#symbol, w)))
end
end
end
end
end
end,
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)
end

View File

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

View File

@@ -1,14 +1,8 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
return function(name)
local base = Object(name)
return function(name, basalt)
local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Switch"
base.width = 2
base.height = 1
base.bgColor = colors.lightGray
base.fgColor = colors.gray
base:setSize(4, 1)
base:setValue(false)
base:setZIndex(5)
@@ -19,71 +13,53 @@ return function(name)
local object = {
getType = function(self)
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,
mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
setSymbol = function(self, col)
bgSymbol = col
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:updateDraw()
return true
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,
init = function(self)
self.parent:addEvent("mouse_click", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("SwitchBG")
self.fgColor = self.parent:getTheme("SwitchText")
bgSymbol = self.parent:getTheme("SwitchBGSymbol")
inactiveBG = self.parent:getTheme("SwitchInactive")
activeBG = self.parent:getTheme("SwitchActive")
end
draw = function(self)
base.draw(self)
self:addDraw("switch", function()
local parent = self:getParent()
local bgCol,fgCol = self:getBackground(), self:getForeground()
local w,h = self:getSize()
if(self:getValue())then
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,
}
object.__index = object
return setmetatable(object, base)
end

View File

@@ -1,12 +1,9 @@
local Object = require("Object")
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
return function(name)
local base = Object(name)
return function(name, basalt)
local base = basalt.getObject("ChangeableObject")(name, basalt)
local objectType = "Textfield"
local hIndex, wIndex, textX, textY = 1, 1, 1, 1
@@ -20,8 +17,7 @@ return function(name)
local selectionBG,selectionFG = colors.lightBlue,colors.black
base.width = 30
base.height = 12
base:setSize(30, 12)
base:setZIndex(5)
local function isSelected()
@@ -32,57 +28,56 @@ return function(name)
end
local function getSelectionCoordinates()
local sx,ex,sy,ey
if(isSelected())then
if(startSelX>endSelX)then
sx,ex = endSelX,startSelX
else
sx,ex = startSelX,endSelX
end
if(startSelY>endSelY)then
sy,ey = endSelY,startSelY
else
sy,ey = startSelY,endSelY
local sx, ex, sy, ey = startSelX, endSelX, startSelY, endSelY
if isSelected() then
if startSelX < endSelX and startSelY <= endSelY then
sx = startSelX
ex = endSelX
if startSelY < endSelY then
sy = startSelY
ey = endSelY
else
sy = endSelY
ey = startSelY
end
elseif startSelX > endSelX and startSelY >= endSelY then
sx = endSelX
ex = startSelX
if startSelY > endSelY then
sy = endSelY
ey = startSelY
else
sy = startSelY
ey = endSelY
end
elseif startSelY > endSelY then
sx = endSelX
ex = startSelX
sy = endSelY
ey = startSelY
end
return sx, ex, sy, ey
end
return sx,ex,sy,ey
end
local function getSelection()
end
local function removeSelection(self)
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=ey,sy,-1 do
if(n==sy)or(n==ey)then
local l = lines[n]
local b = bgLines[n]
local f = fgLines[n]
if(n==sy)and(n==ey)then
l = l:sub(1,sx-1)..l:sub(ex+1,l:len())
b = b:sub(1,sx-1)..b:sub(ex+1,b:len())
f = f:sub(1,sx-1)..f:sub(ex+1,f:len())
elseif(n==sx)then
l = l:sub(1, sx)
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)
local sx, ex, sy, ey = getSelectionCoordinates(self)
local startLine = lines[sy]
local endLine = lines[ey]
lines[sy] = startLine:sub(1, sx - 1) .. endLine:sub(ex + 1, endLine:len())
bgLines[sy] = bgLines[sy]:sub(1, sx - 1) .. bgLines[ey]:sub(ex + 1, bgLines[ey]:len())
fgLines[sy] = fgLines[sy]:sub(1, sx - 1) .. fgLines[ey]:sub(ex + 1, fgLines[ey]:len())
for i = ey, sy + 1, -1 do
if i ~= sy then
table.remove(lines, i)
table.remove(bgLines, i)
table.remove(fgLines, i)
end
end
textX,textY = startSelX,startSelY
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil
textX, textY = sx, sy
startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil
return self
end
@@ -105,8 +100,8 @@ return function(name)
local function updateColors(self, l)
l = l or textY
local fgLine = tHex[self.fgColor]:rep(fgLines[l]:len())
local bgLine = tHex[self.bgColor]:rep(bgLines[l]:len())
local fgLine = tHex[self:getForeground()]:rep(fgLines[l]:len())
local bgLine = tHex[self:getBackground()]:rep(bgLines[l]:len())
for k,v in pairs(rules)do
local pos = stringGetPositions(lines[l], v[1])
if(#pos>0)then
@@ -160,60 +155,30 @@ return function(name)
return self
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(data["lines"]~=nil)then
local l = data["lines"]["line"]
if(l.properties~=nil)then l = {l} 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
setSelection = function(self, fg, bg)
selectionFG = fg or selectionFG
selectionBG = bg or selectionBG
return self
end,
if(xmlValue("pattern", v)~=nil)then
self:addRule(xmlValue("pattern", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)])
end
end
end
end
getSelection = function(self)
return selectionFG, selectionBG
end,
getLines = function(self)
return lines
end;
end,
getLine = function(self, index)
return lines[index]
end;
end,
editLine = function(self, index, text)
lines[index] = text or lines[index]
updateColors(self, index)
self:updateDraw()
return self
end;
end,
clear = function(self)
lines = {""}
@@ -227,21 +192,23 @@ return function(name)
addLine = function(self, text, index)
if(text~=nil)then
local bgColor = self:getBackground()
local fgColor = self:getForeground()
if(#lines==1)and(lines[1]=="")then
lines[1] = text
bgLines[1] = tHex[self.bgColor]:rep(text:len())
fgLines[1] = tHex[self.fgColor]:rep(text:len())
bgLines[1] = tHex[bgColor]:rep(text:len())
fgLines[1] = tHex[fgColor]:rep(text:len())
updateColors(self, 1)
return self
end
if (index ~= nil) then
table.insert(lines, index, text)
table.insert(bgLines, index, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, index, tHex[self.fgColor]:rep(text:len()))
table.insert(bgLines, index, tHex[bgColor]:rep(text:len()))
table.insert(fgLines, index, tHex[fgColor]:rep(text:len()))
else
table.insert(lines, text)
table.insert(bgLines, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len()))
table.insert(bgLines, tHex[bgColor]:rep(text:len()))
table.insert(fgLines, tHex[fgColor]:rep(text:len()))
end
end
updateColors(self, index or #lines)
@@ -285,13 +252,13 @@ return function(name)
end
self:updateDraw()
return self
end;
end,
setKeywords = function(self, color, tab)
keyWords[color] = tab
self:updateDraw()
return self
end;
end,
removeLine = function(self, index)
if(#lines>1)then
@@ -305,83 +272,91 @@ return function(name)
end
self:updateDraw()
return self
end;
end,
getTextCursor = function(self)
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)
base.getFocusHandler(self)
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self.fgColor)
end
end
end;
local obx, oby = self:getPosition()
self:getParent():setCursor(true, obx + textX - wIndex, oby + textY - hIndex, self:getForeground())
end,
loseFocusHandler = function(self)
base.loseFocusHandler(self)
if (self.parent ~= nil) then
self.parent:setCursor(false)
end
end;
self:getParent():setCursor(false)
end,
keyHandler = function(self, key)
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()
if (key == keys.backspace) then
-- on backspace
if (lines[textY] == "") then
if (textY > 1) then
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
textY = textY - 1
end
elseif (textX <= 1) then
if (textY > 1) then
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
lines[textY - 1] = lines[textY - 1] .. lines[textY]
fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY]
bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY]
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textY = textY - 1
end
if(isSelected())then
removeSelection(self)
else
lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
if (textX > 1) then
textX = textX - 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
if (lines[textY] == "") then
if (textY > 1) then
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
textY = textY - 1
end
elseif (textX <= 1) then
if (textY > 1) then
textX = lines[textY - 1]:len() + 1
wIndex = textX - w + 1
if (wIndex < 1) then
wIndex = 1
end
lines[textY - 1] = lines[textY - 1] .. lines[textY]
fgLines[textY - 1] = fgLines[textY - 1] .. fgLines[textY]
bgLines[textY - 1] = bgLines[textY - 1] .. bgLines[textY]
table.remove(lines, textY)
table.remove(fgLines, textY)
table.remove(bgLines, textY)
textY = textY - 1
end
else
lines[textY] = lines[textY]:sub(1, textX - 2) .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 2) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 2) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
if (textX > 1) then
textX = textX - 1
end
if (wIndex > 1) then
if (textX < wIndex) then
wIndex = wIndex - 1
end
end
end
end
if (textY < hIndex) then
hIndex = hIndex - 1
if (textY < hIndex) then
hIndex = hIndex - 1
end
end
updateColors(self)
self:setValue("")
end
if (key == keys.delete) then
elseif (key == keys.delete) then
-- on delete
if(isSelected())then
removeSelection(self)
@@ -400,9 +375,10 @@ return function(name)
end
end
updateColors(self)
end
if (key == keys.enter) then
elseif (key == keys.enter) then
if(isSelected())then
removeSelection(self)
end
-- on enter
table.insert(lines, textY + 1, lines[textY]:sub(textX, lines[textY]:len()))
table.insert(fgLines, textY + 1, fgLines[textY]:sub(textX, fgLines[textY]:len()))
@@ -417,9 +393,8 @@ return function(name)
hIndex = hIndex + 1
end
self:setValue("")
end
if (key == keys.up) then
elseif (key == keys.up) then
startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow up
if (textY > 1) then
textY = textY - 1
@@ -440,8 +415,8 @@ return function(name)
end
end
end
end
if (key == keys.down) then
elseif (key == keys.down) then
startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow down
if (textY < #lines) then
textY = textY + 1
@@ -460,8 +435,8 @@ return function(name)
hIndex = hIndex + 1
end
end
end
if (key == keys.right) then
elseif (key == keys.right) then
startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow right
textX = textX + 1
if (textY < #lines) then
@@ -482,8 +457,8 @@ return function(name)
wIndex = 1
end
end
if (key == keys.left) then
elseif (key == keys.left) then
startSelX, startSelY, endSelX, endSelY = nil, nil, nil, nil
-- arrow left
textX = textX - 1
if (textX >= 1) then
@@ -504,6 +479,19 @@ return function(name)
if (wIndex < 1) then
wIndex = 1
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
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
cursorX = 0
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground())
self:updateDraw()
return true
end
@@ -527,11 +515,15 @@ return function(name)
charHandler = function(self, char)
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()
if(isSelected())then
removeSelection(self)
end
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())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor] .. bgLines[textY]:sub(textX, bgLines[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
if (textX >= w + wIndex) then
wIndex = wIndex + 1
@@ -552,10 +544,7 @@ return function(name)
if (cursorX < 1) then
cursorX = 0
end
if(isSelected())then
removeSelection(self)
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
parent:setCursor(true, obx + cursorX, oby + cursorY, self:getForeground())
self:updateDraw()
return true
end
@@ -563,30 +552,31 @@ return function(name)
dragHandler = function(self, button, x, y)
if (base.dragHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local parent = self:getParent()
local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
local w,h = self:getSize()
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
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
endSelX = textX
end
if (textX < wIndex) then
endSelX = textX
endSelY = textY
if textX < wIndex then
wIndex = textX - 1
if (wIndex < 1) then
if wIndex < 1 then
wIndex = 1
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()
end
end
end
return true
end
@@ -594,8 +584,9 @@ return function(name)
scrollHandler = function(self, dir, x, y)
if (base.scrollHandler(self, dir, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local parent = self:getParent()
local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
local w,h = self:getSize()
hIndex = hIndex + dir
if (hIndex > #lines - (h - 1)) then
@@ -607,9 +598,9 @@ return function(name)
end
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
self.parent:setCursor(false)
parent:setCursor(false)
end
self:updateDraw()
return true
@@ -618,8 +609,9 @@ return function(name)
mouseHandler = function(self, button, x, y)
if (base.mouseHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local parent = self:getParent()
local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex
textY = y - oby + hIndex
@@ -639,17 +631,15 @@ return function(name)
end
self:updateDraw()
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self:getForeground())
return true
end
end,
mouseUpHandler = function(self, button, x, y)
if (base.mouseUpHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
local obx, oby = self:getAbsolutePosition()
local anchx, anchy = self:getPosition()
if (lines[y - oby + hIndex] ~= nil) then
endSelX = x - obx + wIndex
endSelY = y - oby + hIndex
@@ -666,100 +656,89 @@ return function(name)
end,
eventHandler = function(self, event, paste, p2, p3, p4)
base.eventHandler(self, event, paste, p2, p3, p4)
if(event=="paste")then
if(self:isFocused())then
local w, h = self:getSize()
lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self.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())
textX = textX + paste:len()
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then
if(self:isFocused())then
local parent = self:getParent()
local fgColor, bgColor = self:getForeground(), self:getBackground()
local w, h = self:getSize()
lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[bgColor]:rep(paste:len()) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + paste:len()
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
end
local anchx, anchy = self:getPosition()
parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, fgColor)
updateColors(self)
self:updateDraw()
end
local anchx, anchy = self:getAnchorPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
updateColors(self)
self:updateDraw()
end
end
end,
setSelectionColor = function(self, bg, fg)
selectionBG = bg or selectionBG
selectionFG = fg or selectionFG
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
for n = 1, h do
local text = ""
local bg = ""
local fg = ""
if (lines[n + hIndex - 1] ~= nil) then
text = lines[n + hIndex - 1]
fg = fgLines[n + hIndex - 1]
bg = bgLines[n + hIndex - 1]
end
text = text:sub(wIndex, w + wIndex - 1)
bg = bg:sub(wIndex, w + wIndex - 1)
fg = fg:sub(wIndex, w + wIndex - 1)
local space = w - text:len()
if (space < 0) then
space = 0
end
text = text .. rep(self.bgSymbol, space)
bg = bg .. rep(tHex[self.bgColor], space)
fg = fg .. rep(tHex[self.fgColor], space)
self.parent:setText(obx, oby + n - 1, text)
self.parent:setBG(obx, oby + n - 1, bg)
self.parent:setFG(obx, oby + n - 1, fg)
base.draw(self)
self:addDraw("textfield", function()
local parent = self:getParent()
local obx, oby = self:getPosition()
local w, h = self:getSize()
local bgColor = tHex[self:getBackground()]
local fgColor = tHex[self:getForeground()]
for n = 1, h do
local text = ""
local bg = ""
local fg = ""
if lines[n + hIndex - 1] then
text = lines[n + hIndex - 1]
fg = fgLines[n + hIndex - 1]
bg = bgLines[n + hIndex - 1]
end
--[[
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=sy,ey do
local line = lines[n]:len()
local xOffset = 0
if(n==sy)and(n==ey)then
xOffset = sx-1
line = line - (sx-1) - (line - ex)
elseif(n==ey)then
line = line - (line - ex)
elseif(n==sy)then
line = line-(sx-1)
xOffset = sx-1
end
self.parent:setBG(obx + xOffset, oby + n - 1, rep(tHex[selectionBG], line))
self.parent:setFG(obx + xOffset, oby + n - 1, rep(tHex[selectionFG], line))
text = sub(text, wIndex, w + wIndex - 1)
bg = rep(bgColor, w)
fg = rep(fgColor, w)
self:addText(1, n, text)
self:addBG(1, n, bg)
self:addFG(1, n, fg)
self:addBlit(1, n, text, fg, bg)
end
if startSelX and endSelX and startSelY and endSelY then
local sx, ex, sy, ey = getSelectionCoordinates(self)
for n = sy, ey do
local line = #lines[n]
local xOffset = 0
if n == sy and n == ey then
xOffset = sx - 1
line = line - (sx - 1) - (line - ex)
elseif n == ey then
line = line - (line - ex)
elseif n == sy then
line = line - (sx - 1)
xOffset = sx - 1
end
end]]
if(self:isFocused())then
local anchx, anchy = self:getAnchorPosition()
--self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
self:addBG(1 + xOffset, n, rep(tHex[selectionBG], line))
self:addFG(1 + xOffset, n, rep(tHex[selectionFG], line))
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)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("TextfieldBG")
self.fgColor = self.parent:getTheme("TextfieldText")
end
load = function(self)
self:listenEvent("mouse_click")
self:listenEvent("mouse_up")
self:listenEvent("mouse_scroll")
self:listenEvent("mouse_drag")
self:listenEvent("key")
self:listenEvent("char")
self:listenEvent("other_event")
end,
}
object.__index = object
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 func
@@ -9,42 +8,9 @@ return function(name)
local isActive = false
local filter
local generateXMLEventFunction = function(self, 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
return (function()o:internalObjetCall()end)
end
else
return self:getBaseFrame():getVariable(str)
end
return self
end
object = {
name = name,
local object = {
getType = function(self)
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,
start = function(self, f)
@@ -62,36 +28,36 @@ return function(name)
error("Thread Error Occurred - " .. result)
end
end
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)
self.parent:addEvent("key_up", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
self:listenEvent("mouse_click")
self:listenEvent("mouse_up")
self:listenEvent("mouse_scroll")
self:listenEvent("mouse_drag")
self:listenEvent("key")
self:listenEvent("key_up")
self:listenEvent("char")
self:listenEvent("other_event")
return self
end;
end,
getStatus = function(self, f)
if (cRoutine ~= nil) then
return coroutine.status(cRoutine)
end
return nil
end;
end,
stop = function(self, f)
isActive = false
self.parent:removeEvent("mouse_click", self)
self.parent:removeEvent("mouse_up", self)
self.parent:removeEvent("mouse_scroll", self)
self.parent:removeEvent("mouse_drag", self)
self.parent:removeEvent("key", self)
self.parent:removeEvent("key_up", self)
self.parent:removeEvent("char", self)
self.parent:removeEvent("other_event", self)
self:listenEvent("mouse_click", false)
self:listenEvent("mouse_up", false)
self:listenEvent("mouse_scroll", false)
self:listenEvent("mouse_drag", false)
self:listenEvent("key", false)
self:listenEvent("key_up", false)
self:listenEvent("char", false)
self:listenEvent("other_event", false)
return self
end;
end,
mouseHandler = function(self, ...)
self:eventHandler("mouse_click", ...)
@@ -136,11 +102,10 @@ return function(name)
self:stop()
end
end
end;
end,
}
object.__index = object
return object
return setmetatable(object, base)
end

View File

@@ -1,6 +1,3 @@
local basaltEvent = require("basaltEvent")
local xmlValue = require("utils").getValueFromXML
return function(name)
local objectType = "Timer"
@@ -8,64 +5,18 @@ return function(name)
local savedRepeats = 0
local repeats = 0
local timerObj
local eventSystem = basaltEvent()
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 = {
name = name,
getType = function(self)
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,
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)
timer = _timer or 0
savedRepeats = _repeats or 1
return self
end;
end,
start = function(self)
if(timerIsActive)then
@@ -74,31 +25,31 @@ return function(name)
repeats = savedRepeats
timerObj = os.startTimer(timer)
timerIsActive = true
self.parent:addEvent("other_event", self)
self:listenEvent("other_event")
return self
end;
end,
isActive = function(self)
return timerIsActive
end;
end,
cancel = function(self)
if (timerObj ~= nil) then
os.cancelTimer(timerObj)
end
timerIsActive = false
self.parent:removeEvent("other_event", self)
self:removeEvent("other_event")
return self
end;
end,
onCall = function(self, func)
eventSystem:registerEvent("timed_event", func)
self:registerEvent("timed_event", func)
return self
end;
end,
eventHandler = function(self, event, tObj)
if event == "timer" and tObj == timerObj and timerIsActive then
eventSystem:sendEvent("timed_event", self)
self:sendEvent("timed_event")
if (repeats >= 1) then
repeats = repeats - 1
if (repeats >= 1) then
@@ -108,7 +59,7 @@ return function(name)
timerObj = os.startTimer(timer)
end
end
end;
end,
}
object.__index = object

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

@@ -0,0 +1,262 @@
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 = {}
node = {
getChildren = function()
return children
end,
setParent = function(p)
parent = p
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()
end,
isExpanded = function()
return expanded
end,
setExpandable = function(expandable)
expandable = expandable
base:updateDraw()
end,
isExpandable = function()
return expandable
end,
removeChild = function(index)
table.remove(children, index)
end,
findChildrenByText = function(searchText)
local foundNodes = {}
for _, child in ipairs(children) do
if child.getText() == searchText then
table.insert(foundNodes, child)
end
end
return foundNodes
end,
getText = function()
return text
end,
setText = function(t)
text = t
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,
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: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,618 @@
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
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()
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)
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: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,
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,
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", self, 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", self, "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", self, 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", self, 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", self, "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", self, "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", self, "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", self, "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", self, "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", self, "char", char)
if(val==false)then return false end
return true
end
end
end,
eventHandler = function(self, event, ...)
local val = self:sendEvent("other_event", self, event, ...)
if(val~=nil)then return val end
end,
customEventHandler = function(self, event, ...)
local val = self:sendEvent("custom_event", self, event, ...)
if(val~=nil)then return val end
return true
end,
getFocusHandler = function(self)
local val = self:sendEvent("get_focus", self)
if(val~=nil)then return val end
return true
end,
loseFocusHandler = function(self)
isDragging = false
local val = self:sendEvent("lose_focus", self)
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

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

43
Basalt/plugin.lua Normal file
View File

@@ -0,0 +1,43 @@
local args = {...}
local plugins = {}
local dir = fs.getDir(args[2] or "Basalt")
local pluginDir = fs.combine(dir, "plugins")
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,51 @@
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)
base.setValuesByXMLData(self, data)
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,338 @@
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,
}
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 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,
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-20, h-10):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("--------------------------------------------")
local err = wrapText(err, frame:getWidth()-2)
for i=1, #err do
errorList:addItem(err[i])
end
end
}
end
}

206
Basalt/plugins/bigfonts.lua Normal file

File diff suppressed because one or more lines are too long

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

@@ -0,0 +1,102 @@
return {
VisualObject = function(base)
local inline = true
local borderColors = {top = false, bottom = false, left = false, right = false}
local object = {
setBorder = function(self, ...)
if(...~=nil)then
local t = {...}
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()
if(border~=false)then
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:drawForegroundBox(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)
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
}

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

@@ -0,0 +1,92 @@
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.lightGray):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.lightGray)
:setBackground(colors.black)
:onClick(function(self, event, btn, xOffset, yOffset)
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("Exit"):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.lightGray):setForeground(colors.white):setSelectionColor(colors.lightGray, colors.gray)
if(debugLabel==nil)then
debugLabel = mainFrame:addLabel()
:setPosition(1, "parent.h")
:setBackground(colors.black)
:setForeground(colors.white)
: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,123 @@
local count = require("utils").tableCount
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,
}

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

@@ -0,0 +1,40 @@
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)
base.setValuesByXMLData(self, data)
if(xmlValue("shadow", data)~=nil)then self:setShadow(xmlValue("shadow", data)) end
return self
end
}
return object
end
}

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

@@ -0,0 +1,122 @@
local images = require("images")
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)
base.setValuesByXMLData(self, data)
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,
basaltInternal = function()
return {
getTheme = function(name)
return baseTheme[name]
end,
setTheme = function(_theme, col)
if(type(_theme)=="table")then
theme = _theme
elseif(type(_theme)=="string")then
theme[_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

762
Basalt/plugins/xml.lua Normal file
View File

@@ -0,0 +1,762 @@
local utils = require("utils")
local uuid = utils.uuid
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 = ""
end
local path = fs.combine(base, xmlFilename)
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
local function xmlValue(name, tab)
local var
if(type(tab)~="table")then return end
if(tab[name]~=nil)then
if(type(tab[name])=="table")then
if(tab[name].value~=nil)then
var = tab[name]:value()
end
end
end
if(var==nil)then var = tab["@"..name] end
if(var=="true")then
var = true
elseif(var=="false")then
var = false
elseif(tonumber(var)~=nil)then
var = tonumber(var)
end
return var
end
local function executeScript(scripts)
for k,v in pairs(scripts)do
if(k~="env")then
for a,b in pairs(v)do
load(b, nil, "t", scripts.env)()
end
end
end
end
local function registerFunctionEvent(self, data, event, scripts)
if(data:sub(1,1)=="$")then
local data = data:sub(2)
event(self, self:getBasalt():getVariable(data))
else
event(self, load(data, nil, "t", scripts.env))
end
end
return {
VisualObject = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
local x, y = self:getPosition()
local w, h = self:getSize()
if(xmlValue("x", data)~=nil)then x = xmlValue("x", data) end
if(xmlValue("y", data)~=nil)then y = xmlValue("y", data) end
if(xmlValue("width", data)~=nil)then w = xmlValue("width", data) end
if(xmlValue("height", data)~=nil)then h = xmlValue("height", data) end
if(xmlValue("background", data)~=nil)then self:setBackground(colors[xmlValue("background", data)]) end
if(xmlValue("script", data)~=nil)then
if(scripts[1]==nil)then
scripts[1] = {}
end
table.insert(scripts[1], xmlValue("script", data))
end
local events = {"onClick", "onClickUp", "onHover", "onScroll", "onDrag", "onKey", "onKeyUp", "onRelease", "onChar", "onGetFocus", "onLoseFocus", "onResize", "onReposition", "onEvent", "onLeave"}
for k,v in pairs(events)do
if(xmlValue(v, data)~=nil)then
registerFunctionEvent(self, xmlValue(v, data), self[v], scripts)
end
end
self:setPosition(x, y)
self:setSize(w, h)
return self
end,
}
return object
end,
ChangeableObject = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("value", data)~=nil)then self:setValue(xmlValue("value", data)) end
if(xmlValue("onChange", data)~=nil)then
registerFunctionEvent(self, xmlValue("onChange", data), self.onChange, scripts)
end
return self
end,
}
return object
end,
BaseFrame = function(base, basalt)
local lastXMLReferences = {}
local function xmlDefaultValues(data, obj, scripts)
if(obj~=nil)then
obj:setValuesByXMLData(data, scripts)
end
end
local function addXMLObjectType(tab, f, self, scripts)
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local obj = f(self, v["@id"] or uuid())
table.insert(lastXMLReferences, obj)
xmlDefaultValues(v, obj, scripts)
end
end
end
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local xOffset, yOffset = self:getOffset()
if(xmlValue("layout", data)~=nil)then self:addLayout(xmlValue("layout", data)) end
if(xmlValue("xOffset", data)~=nil)then xOffset = xmlValue("xOffset", data) end
self:setOffset(xOffset, yOffset)
local objectList = data:children()
local _OBJECTS = basalt.getObjects()
for k,v in pairs(objectList)do
if(v.___name~="animation")then
local name = v.___name:gsub("^%l", string.upper)
if(_OBJECTS[name]~=nil)then
addXMLObjectType(v, self["add"..name], self, scripts)
end
end
end
addXMLObjectType(data["animation"], self.addAnimation, self, scripts)
return self
end,
loadLayout = function(self, path)
if(fs.exists(path))then
local scripts = {}
scripts.env = _ENV
scripts.env.basalt = basalt
scripts.env.main = self
scripts.env.shared = {}
local f = fs.open(path, "r")
local data = XmlParser:ParseXmlText(f.readAll())
f.close()
lastXMLReferences = {}
self:setValuesByXMLData(data, scripts)
executeScript(scripts)
end
return self
end,
}
return object
end,
Frame = function(base, basalt)
local lastXMLReferences = {}
local function xmlDefaultValues(data, obj, scripts)
if(obj~=nil)then
obj:setValuesByXMLData(data, scripts)
end
end
local function addXMLObjectType(tab, f, self, scripts)
if(tab~=nil)then
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local obj = f(self, v["@id"] or uuid())
table.insert(lastXMLReferences, obj)
xmlDefaultValues(v, obj, scripts)
end
end
end
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local xOffset, yOffset = self:getOffset()
if(xmlValue("layout", data)~=nil)then self:addLayout(xmlValue("layout", data)) end
if(xmlValue("xOffset", data)~=nil)then xOffset = xmlValue("xOffset", data) end
if(xmlValue("yOffset", data)~=nil)then yOffset = xmlValue("yOffset", data) end
self:setOffset(xOffset, yOffset)
local objectList = data:children()
local _OBJECTS = basalt.getObjects()
for k,v in pairs(objectList)do
if(v.___name~="animation")then
local name = v.___name:gsub("^%l", string.upper)
if(_OBJECTS[name]~=nil)then
addXMLObjectType(v, self["add"..name], self, scripts)
end
end
end
addXMLObjectType(data["animation"], self.addAnimation, self, scripts)
return self
end,
loadLayout = function(self, path)
if(fs.exists(path))then
local scripts = {}
scripts.env = _ENV
scripts.env.basalt = basalt
scripts.env.main = self
scripts.env.shared = {}
local f = fs.open(path, "r")
local data = XmlParser:ParseXmlText(f.readAll())
f.close()
lastXMLReferences = {}
self:setValuesByXMLData(data, scripts)
executeScript(scripts)
end
return self
end,
}
return object
end,
Button = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("horizontalAlign", data)~=nil)then self:setHorizontalAlign(xmlValue("horizontalAlign", data)) end
if(xmlValue("verticalAlign", data)~=nil)then self:setText(xmlValue("verticalAlign", data)) end
return self
end,
}
return object
end,
Label = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("align", data)~=nil)then self:setTextAlign(xmlValue("align", data)) end
return self
end,
}
return object
end,
Input = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local defaultText, defaultFG, defaultBG = self:getDefaultText()
if(xmlValue("defaultText", data)~=nil)then defaultText = xmlValue("defaultText", data) end
if(xmlValue("defaultFG", data)~=nil)then defaultFG = xmlValue("defaultFG", data) end
if(xmlValue("defaultBG", data)~=nil)then defaultBG = xmlValue("defaultBG", data) end
self:setDefaultText(defaultText, defaultFG, defaultBG)
if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end
if(xmlValue("textOffset", data)~=nil)then self:setTextOffset(xmlValue("textOffset", data)) end
if(xmlValue("text", data)~=nil)then self:setValue(xmlValue("text", data)) end
if(xmlValue("inputLimit", data)~=nil)then self:setInputLimit(xmlValue("inputLimit", data)) end
return self
end,
}
return object
end,
Image = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local xOffset, yOffset = self:getOffset()
if(xmlValue("xOffset", data)~=nil)then xOffset = xmlValue("xOffset", data) end
if(xmlValue("yOffset", data)~=nil)then yOffset = xmlValue("yOffset", data) end
self:setOffset(xOffset, yOffset)
if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end
if(xmlValue("usePalette", data)~=nil)then self:usePalette(xmlValue("usePalette", data)) end
if(xmlValue("play", data)~=nil)then self:play(xmlValue("play", data)) end
return self
end,
}
return object
end,
Checkbox = function(base, basalt)
local object = {
setValuesByXMLData = function(self, dat, scriptsa)
base.setValuesByXMLData(self, data, scripts)
local activeSymbol, inactiveSymbol = self:getSymbol()
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("checked", data)~=nil)then self:setChecked(xmlValue("checked", data)) end
if(xmlValue("textPosition", data)~=nil)then self:setTextPosition(xmlValue("textPosition", data)) end
if(xmlValue("activeSymbol", data)~=nil)then activeSymbol = xmlValue("activeSymbol", data) end
if(xmlValue("inactiveSymbol", data)~=nil)then inactiveSymbol = xmlValue("inactiveSymbol", data) end
self:setSymbol(activeSymbol, inactiveSymbol)
return self
end,
}
return object
end,
Program = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("execute", data)~=nil)then self:execute(xmlValue("execute", data)) end
return self
end,
}
return object
end,
Progressbar = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local activeBarColor, activeBarSymbol, activeBarSymbolCol = self:getProgressBar()
if(xmlValue("direction", data)~=nil)then self:setDirection(xmlValue("direction", data)) end
if(xmlValue("activeBarColor", data)~=nil)then activeBarColor = colors[xmlValue("activeBarColor", data)] end
if(xmlValue("activeBarSymbol", data)~=nil)then activeBarSymbol = xmlValue("activeBarSymbol", data) end
if(xmlValue("activeBarSymbolColor", data)~=nil)then activeBarSymbolCol = colors[xmlValue("activeBarSymbolColor", data)] end
if(xmlValue("backgroundSymbol", data)~=nil)then self:setBackgroundSymbol(xmlValue("backgroundSymbol", data)) end
if(xmlValue("progress", data)~=nil)then self:setProgress(xmlValue("progress", data)) end
return self
end,
}
return object
end,
Slider = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("symbol", data)~=nil)then self:setSymbol(xmlValue("symbol", data)) end
if(xmlValue("symbolColor", data)~=nil)then self:setSymbolColor(xmlValue("symbolColor", data)) end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
if(xmlValue("maxValue", data)~=nil)then self:setIndex(xmlValue("maxValue", data)) end
if(xmlValue("barType", data)~=nil)then self:setBarType(xmlValue("barType", data)) end
return self
end,
}
return object
end,
Scrollbar = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("symbol", data)~=nil)then self:setSymbol(xmlValue("symbol", data)) end
if(xmlValue("symbolColor", data)~=nil)then self:setSymbolColor(xmlValue("symbolColor", data)) end
if(xmlValue("symbolSize", data)~=nil)then self:setSymbolSize(xmlValue("symbolSize", data)) end
if(xmlValue("scrollAmount", data)~=nil)then self:setScrollAmount(xmlValue("scrollAmount", data)) end
if(xmlValue("index", data)~=nil)then self:setIndex(xmlValue("index", data)) end
if(xmlValue("maxValue", data)~=nil)then self:setIndex(xmlValue("maxValue", data)) end
if(xmlValue("barType", data)~=nil)then self:setBarType(xmlValue("barType", data)) end
return self
end,
}
return object
end,
MonitorFrame = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("monitor", data)~=nil)then self:setSymbol(xmlValue("monitor", data)) end
return self
end,
}
return object
end,
Switch = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("symbol", data)~=nil)then self:setSymbol(xmlValue("symbol", data)) end
if(xmlValue("activeBackground", data)~=nil)then self:setActiveBackground(xmlValue("activeBackground", data)) end
if(xmlValue("inactiveBackground", data)~=nil)then self:setInactiveBackground(xmlValue("inactiveBackground", data)) end
return self
end,
}
return object
end,
Textfield = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local bgSel, fgSel = self:getSelection()
local xOffset, yOffset = self:getOffset()
if(xmlValue("bgSelection", data)~=nil)then bgSel = xmlValue("bgSelection", data) end
if(xmlValue("fgSelection", data)~=nil)then fgSel = xmlValue("fgSelection", data) end
if(xmlValue("xOffset", data)~=nil)then xOffset = xmlValue("xOffset", data) end
if(xmlValue("yOffset", data)~=nil)then yOffset = xmlValue("yOffset", data) end
self:setSelection(fgSel, bgSel)
self:setOffset(xOffset, yOffset)
if(data["lines"]~=nil)then
local l = data["lines"]["line"]
if(l.properties~=nil)then l = {l} 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
self:addRule(xmlValue("pattern", v), colors[xmlValue("fg", v)], colors[xmlValue("bg", v)])
end
end
end
end
return self
end,
}
return object
end,
Thread = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("start", data)~=nil)then self:start(load(xmlValue("start", data), nil, "t", scripts.env)) end
return self
end,
}
return object
end,
Timer = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("start", data)~=nil)then self:start(xmlValue("start", data)) end
if(xmlValue("time", data)~=nil)then self:setTime(xmlValue("time", data)) end
if(xmlValue("onCall", data)~=nil)then
registerFunctionEvent(self, xmlValue("onCall", data), self.onCall, scripts)
end
return self
end,
}
return object
end,
List = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local selBg, selFg = self:getSelectionColor()
if(xmlValue("align", data)~=nil)then self:setTextAlign(xmlValue("align", data)) end
if(xmlValue("offset", data)~=nil)then self:setOffset(xmlValue("offset", data)) end
if(xmlValue("selectionBg", data)~=nil)then selBg = xmlValue("selectionBg", data) end
if(xmlValue("selectionFg", data)~=nil)then selFg = xmlValue("selectionFg", data) end
self:setSelectionColor(selBg, selFg)
if(xmlValue("scrollable", data)~=nil)then self:setScrollable(xmlValue("scrollable", 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
if(self:getType()~="Radio")then
self:addItem(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
end
end
end
return self
end,
}
return object
end,
Dropdown = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local w, h = self:getDropdownSize()
if(xmlValue("dropdownWidth", data)~=nil)then w = xmlValue("dropdownWidth", data) end
if(xmlValue("dropdownHeight", data)~=nil)then h = xmlValue("dropdownHeight", data) end
self:setDropdownSize(w, h)
return self
end,
}
return object
end,
Radio = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local selBg, selFg = self:getBoxSelectionColor()
local defBg, defFg = self:setBoxDefaultColor()
if(xmlValue("selectionBg", data)~=nil)then selBg = xmlValue("selectionBg", data) end
if(xmlValue("selectionFg", data)~=nil)then selFg = xmlValue("selectionFg", data) end
self:setBoxSelectionColor(selBg, selFg)
if(xmlValue("defaultBg", data)~=nil)then defBg = xmlValue("defaultBg", data) end
if(xmlValue("defaultFg", data)~=nil)then defFg = xmlValue("defaultFg", data) end
self:setBoxDefaultColor(defBg, defFg)
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,
}
return object
end,
Menubar = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
if(xmlValue("space", data)~=nil)then self:setSpace(xmlValue("space", data)) end
if(xmlValue("scrollable", data)~=nil)then self:setScrollable(xmlValue("scrollable", data)) end
return self
end,
}
return object
end,
Graph = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local symbol, symbolCol = self:getGraphSymbol()
if(xmlValue("maxEntries", data)~=nil)then self:setMaxEntries(xmlValue("maxEntries", data)) end
if(xmlValue("type", data)~=nil)then self:setGraphType(xmlValue("type", data)) end
if(xmlValue("minValue", data)~=nil)then self:setMinValue(xmlValue("minValue", data)) end
if(xmlValue("maxValue", data)~=nil)then self:setMaxValue(xmlValue("maxValue", data)) end
if(xmlValue("symbol", data)~=nil)then symbol = xmlValue("symbol", data) end
if(xmlValue("symbolColor", data)~=nil)then symbolCol = xmlValue("symbolColor", data) end
self:setGraphSymbol(symbol, symbolCol)
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:addDataPoint(xmlValue("value"))
end
end
return self
end,
}
return object
end,
Treeview = function(base, basalt)
local object = {
setValuesByXMLData = function(self, data, scripts)
base.setValuesByXMLData(self, data, scripts)
local selBg, selFg = self:getSelectionColor()
local xOffset, yOffset = self:getOffset()
if(xmlValue("space", data)~=nil)then self:setSpace(xmlValue("space", data)) end
if(xmlValue("scrollable", data)~=nil)then self:setScrollable(xmlValue("scrollable", data)) end
if(xmlValue("selectionBg", data)~=nil)then selBg = xmlValue("selectionBg", data) end
if(xmlValue("selectionFg", data)~=nil)then selFg = xmlValue("selectionFg", data) end
self:setSelectionColor(selBg, selFg)
if(xmlValue("xOffset", data)~=nil)then xOffset = xmlValue("xOffset", data) end
if(xmlValue("yOffset", data)~=nil)then yOffset = xmlValue("yOffset", data) end
self:setOffset(xOffset, yOffset)
local function addNode(node, data)
if(data["node"]~=nil)then
local tab = data["node"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local n = node:addNode(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
addNode(n, v)
end
end
end
if(data["node"]~=nil)then
local tab = data["node"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local n = self:addNode(xmlValue("text", v), colors[xmlValue("bg", v)], colors[xmlValue("fg", v)])
addNode(n, v)
end
end
return self
end,
}
return object
end,
}

View File

@@ -2,11 +2,18 @@
*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.
## 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

View File

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

View File

@@ -2,29 +2,38 @@
- [Home](home)
- [How To](home/How-To)
- [Download](home/download)
- [1.6 Docs](docs1_6)
- Objects
- [Basalt](objects/Basalt.md)
- [Object](objects/Object.md)
- [VisualObject](objects/VisualObject.md)
- [ChangeableObject](objects/ChangeableObject.md)
- [Container](objects/Container.md)
- [BaseFrame](objects/BaseFrame.md)
- [Frame](objects/Frame.md)
- [Flexbox](objects/Flexbox.md)
- [MovableFrame](objects/MovableFrame.md)
- [ScrollableFrame](objects/ScrollableFrame.md)
- [Button](objects/Button.md)
- [Checkbox](objects/Checkbox.md)
- [Dropdown](objects/Dropdown.md)
- [Frame](objects/Frame.md)
- [Graph](objects/Graph.md)
- [Image](objects/Image.md)
- [Input](objects/Input.md)
- [Label](objects/Label.md)
- [List](objects/List.md)
- [Menubar](objects/Menubar.md)
- [Dropdown](objects/Dropdown.md)
- [Menubar](objects/Menubar.md)
- [Radio](objects/Radio.md)
- [Pane](objects/Pane.md)
- [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)
- [Treeview](objects/Treeview.md)
- [Timer](objects/Timer.md)
- Tips & Tricks
- Tutorials
- [Your Logic](tips/logic.md)
- [Button coloring](tips/buttonColoring.md)
- [Designing/Animating](tips/design.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

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

@@ -0,0 +1,26 @@
# Welcome to The old Basalt Wiki!
This Basalt Wiki is outdated!
*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 know as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://www.curseforge.com/minecraft/mc-mods/cc-tweaked).
## Quick Demo
<img src="https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/basaltPreview2.gif" width="600">
## 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 <a href="https://github.com/Pyroxenium/Basalt/issues">issue</a>.
Additionally, if you have questions about Basalt or how to make use of it, feel free to create a new discussion on <a href="https://github.com/Pyroxenium/Basalt/discussions">Basalt's Discussion Board</a>, or ask in our [discord](https://discord.gg/yNNnmBVBpE).
---
Feel free to join our [discord](https://discord.gg/yNNnmBVBpE)!
<br><br>

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

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

@@ -0,0 +1,4 @@
- Getting Started
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)

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

@@ -0,0 +1,35 @@
- About
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)
- Objects
- [Basalt](objects/Basalt)
- [Object](objects/Object)
- [Button](objects/Button)
- [Checkbox](objects/Checkbox)
- [Dropdown](objects/Dropdown)
- [Frame](objects/Frame)
- [Image](objects/Image)
- [Input](objects/Input)
- [Label](objects/Label)
- [List](objects/List)
- [Menubar](objects/Menubar)
- [Pane](objects/Pane)
- [Program](objects/Program)
- [Progressbar](objects/Progressbar)
- [Radio](objects/Radio)
- [Scrollbar](objects/Scrollbar)
- [Slider](objects/Slider)
- [Textfield](objects/Textfield)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread)
- [Timer](objects/Timer)
- Events
- [Mouse Events](events/mouseEvents.md)
- [Keyboard Events](events/keyEvents.md)
- [Other Events](events/otherEvents.md)
- Tips & Tricks
- [Component Logic](tips/logic)
- [Changing Button Color](tips/buttons)
- [Advanced usage of Events](tips/events.md)
- [Example Designs](tips/design.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,92 @@
## HowTo Use
To load the framework into your project, make use of the following code on top of your code.
```lua
local basalt = require("basalt")
```
It does not matter if you have installed the single file version or the full folder project. <br>
Both versions can be loaded by using `require("Basalt")`, you dont need to add `.lua`.
## Download
### Download the folder version
This version is for people who'd like to work with Basalt, change something in Basalt or checkout the project.<br>
But you are also able to just use it to create your own UI.<br>
To install the full project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P`
This will download the project as a folder called "Basalt". You are immediatly after the download is done able to use it in your projects.
### Download the single file version
This is the version you should use if you're done with programming. It is a little bit faster and it is also minified, which makes the project smaller.
To install the single filed project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P packed`
This will download the project as a single file called "basalt.lua". You are immediatly after the download is done able to use it in your projects.
### Basalt Package Manager
The Basalt Package Manager is still in alpha!<br><br>
The Basalt Package Manager is a visual installer, you are able to change some settings, also to choose which objects are necessary for your projects and which are not.
To install the BPM (Basalt Package Manager) use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P bpm true`
The true keyword in the end is optional and would simply start BPM immediately.
## Example
Here is a fully functioning example of Basalt code
```lua
local basalt = require("basalt") --> Load the Basalt framework
--> Create the first frame. Please note that Basalt needs at least one active "non-parent" frame to properly supply events
--> When Basalt#createFrame makes use of unique identifiers (commonly referred to as UIDs), meaning that the supplied value must be UNIQUE
local mainFrame = basalt.createFrame("mainFrame")
--> Show the frame to the user
mainFrame:show()
local button = mainFrame:addButton("clickableButton") --> Add a button to the mainFrame (With a unique identifier)
--> Set the position of the button, Button#setPosition follows an x, y pattern.
--> The x value is how far right the object should be from its anchor (negative values from an anchor will travel left)
--> The y value is how far down the object should be from its anchor (negative values from an anchor will travel up)
button:setPosition(4, 4)
button:setText("Click me!") --> Set the text of our button
local function buttonClick() --> This function serves as our click logic
basalt.debug("I got clicked!")
end
--> Remember! You cannot supply buttonClick(), that will only supply the result of the function
--> Make sure the button knows which function to call when it's clicked
button:onClick(buttonClick)
button:show() --> Make the button visible, so the user can click it
basalt.autoUpdate() --> Basalt#autoUpdate starts the event listener to detect user input
```
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 mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton("clickableButton") --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
:show()
basalt.autoUpdate()
```

View File

@@ -0,0 +1,74 @@
# Installer
This is just a script which helps you to setup your program to automatically install the Basalt UI Framework, if it doesn't exists. Means, you create your program (which requires basalt) and add this on the top of your program. Now, everytime you execute your program it checks if basalt.lua (or your custom filepath) exists or not, if not it installs it, or if you are using the advanced installer, it asks the user if the program is allowed to install basalt for you.
## Basic Installer
Here is a very basic one which just installs basalt.lua if don't exist:
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", "")) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
```
## Advanced Installer
This is a visual version, it asks the user if he wants to install basalt.lua (if not found)<br>
![](https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/installer.png)
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
local w,h = term.getSize()
term.clear()
local _installerWindow = window.create(term.current(),w/2-8,h/2-3,18,6)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.setTextColor(colors.black)
_installerWindow.write(" Basalt Installer ")
_installerWindow.setBackgroundColor(colors.lightGray)
for line=2,6,1 do
_installerWindow.setCursorPos(1,line)
if(line==3)then
_installerWindow.write(" No Basalt found! ")
elseif(line==4)then
_installerWindow.write(" Install it? ")
elseif(line==6)then
_installerWindow.setTextColor(colors.black)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.write("Install")
_installerWindow.setBackgroundColor(colors.lightGray)
_installerWindow.write(string.rep(" ",5))
_installerWindow.setBackgroundColor(colors.red)
_installerWindow.write("Cancel")
else
_installerWindow.write(string.rep(" ",18))
end
end
_installerWindow.setVisible(true)
_installerWindow.redraw()
while(not(fs.exists(filePath))) do
local event, p1,p2,p3,p4 = os.pullEvent()
if(event=="mouse_click")then
if(p3==math.floor(h/2+2))and(p2>=w/2-8)and(p2<=w/2-2)then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", ""))
_installerWindow.setVisible(false)
term.clear()
break
end
if(p3==math.floor(h/2+2))and(p2<=w/2+9)and(p2>=w/2+4)then
_installerWindow.clear()
_installerWindow.setVisible(false)
term.setCursorPos(1,1)
term.clear()
return
end
end
end
term.setCursorPos(1,1)
term.clear()
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
------------------------------
```

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

@@ -0,0 +1,54 @@
<!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>
window.$docsify = {
logo: '/_media/logo.png',
loadNavbar: true,
loadSidebar: true,
autoHeader: true,
subMaxLevel: 1,
homepage: 'Home.md',
name: 'Basalt',
repo: 'https://github.com/Pyroxenium/Basalt',
auto2top: true
}
</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>
</body>
</html>

View File

@@ -0,0 +1,303 @@
With animations, you can create a beautiful experience for users while interacting with objects.<br>
For now the animation class is very basic, it will be expanded in the future, but we have to say you can already do almost everything you can imagine!
Right now animation is a class which makes use of the timer event.<br>
You can find more information below:
`The animation object is still a WIP and the way you use it right now could change in the future!`
## add
Adds a new function to an animation
#### Parameters:
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()
```
## wait
Sets a wait timer for the next function after the previous function got executed, no wait timer calls the next function immediately
#### Parameters:
1. `number` The length of delay between the functions _(in seconds)_
#### Returns:
1. `animation` Animation in use
#### Usage:
```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()
```
## 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
```
## 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()
```
## setObject
Sets the object which the animation should reposition/resize
#### Parameters:
1. `table` object
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton()
local aAnimation = mainFrame:addAnimation():setObject(testButton)
```
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
```
```xml
<animation object="buttonToAnimate" />
```
## 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>
```
## 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>
```
## size
Changes the size on the object which got defined by setObject
#### Parameters:
1. `number` width
2. `number` height
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 testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):size(15,3,1):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<offset><w>15</w><h>3</h><duration>1</duration></offset>
</animation>
```
## changeText
Changes the text while animation is running
#### Parameters:
1. `table` multiple text strings - example: {"i", "am", "groot"}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText({"i", "am", "groot"}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<text>
<text>i</text>
<text>am</text>
<text>groot</text>
<duration>2</duration>
</text>
</animation>
```
## changeTextColor
Changes the text color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<textColor>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</textColor>
</animation>
```
## changeBackground
Changes the background color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
#### Returns:
1. `animation` Animation in use
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play()
```
```xml
<animation object="buttonToAnimate" play="true">
<background>
<color>red</color>
<color>yellow</color>
<color>green</color>
<duration>2</duration>
</background>
</animation>
```
# Events
## 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,201 @@
Before you can access Basalt, you need to add the following code on top of your file:
`local basalt = require("Basalt")`
Now you are able to access the following methods:
## basalt.createFrame
Create a base-frame (main frame)
#### Parameters:
1. `string` name
#### Returns:
1. `frame` object
#### Usage:
* Create and show a frame with id "myFirstFrame"
```lua
local mainFrame = basalt.createFrame("myFirstFrame")
```
## basalt.removeFrame
Removes a base frame
#### Parameters:
1. `string` name
#### Usage:
* Removes the previously created frame with id "myFirstFrame"
```lua
local mainFrame = basalt.createFrame("myFirstFrame")
basalt.removeFrame("myFirstFrame")
```
## basalt.getFrame
Returns a base frame with the given name
#### Parameters:
1. `string` name
#### Returns:
1. `frame` object
#### Usage:
* Creates, fetches and shows the "myFirstFrame" object
```lua
basalt.createFrame("myFirstFrame"):hide()
basalt.getFrame("myFirstFrame"):show()
```
## basalt.getActiveFrame
Returns the currently active base frame
#### Returns:
1. `frame` The current frame
#### Usage:
* Displays the active frame name in the debug console
```lua
basalt.createFrame()
basalt.debug(basalt.getActiveFrame():getName()) -- returns the uuid
```
## basalt.autoUpdate
Starts the draw and event handler until basalt.stopUpdate() is called
#### Usage:
* Enable the basalt updates, otherwise the screen will not continue to update
```lua
local mainFrame = basalt.createFrame()
basalt.autoUpdate()
```
## basalt.update
Calls the draw and event handler once - this gives more flexibility about which events basalt should process. For example you could filter the terminate event.
#### Parameters:
1. `string` The event to be received
2. `...` Additional event variables to capture
#### Usage:
* Creates and starts a custom update cycle
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2)
while true do
basalt.update(os.pullEventRaw())
end
```
## basalt.stopUpdate
Stops the automatic draw and event handler which got started by basalt.autoUpdate()
#### Usage:
* When the quit button is clicked, the button stops basalt auto updates
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2):setText("Stop Basalt!")
aButton:onClick(function()
basalt.stopUpdate()
end)
basalt.autoUpdate()
```
## basalt.isKeyDown
Checks if the user is currently holding a key
#### Parameters:
1. `number` key code (use the keys table for that)
#### Returns:
1. `boolean` true or false
#### Usage:
* Shows a debug message with true or false if the left ctrl key is down, as soon as you click on the button.
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2):setText("Check Ctrl")
aButton:onClick(function()
basalt.debug(basalt.isKeyDown(keys.leftCtrl))
end)
basalt.autoUpdate()
```
## basalt.debug
creates a label with some information on the main frame on the bottom left, if you click on that label it will open a log view for you. See it as the new print for debugging
You can also edit the default debug Label (change position, change color or whatever you want) by accessing the variable basalt.debugLabel
which returns the debug Label.
Also basalt.debugFrame and basalt.debugList are available.
#### Parameters:
1. `...` (multiple parameters are possible, like print does)
#### Usage:
* Prints "Hello! ^-^" to the debug console
```lua
basalt.debug("Hello! ", "^-^")
```
## basalt.setTheme
Sets the base theme of the project! Make sure to cover all existing objects, otherwise it will result in errors. A good example is [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua)
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Usage:
* Sets the default theme of basalt.
```lua
basalt.setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
...,
})
```
## basalt.setVariable
This stores a variable which you're able to access via xml. You are also able to add a function, which then gets called by object events created in XML.
#### Parameters:
1. `string` a key name
1. `any` any variable
#### Usage:
* Adds a function to basalt.
```lua
basalt.setVariable("clickMe", function()
basalt.debug("I got clicked")
end)
```
```xml
<button onClick="clickMe" text="Click me" />
```
## basalt.schedule
Schedules a function which gets called in a coroutine. After the coroutine is finished it will get destroyed immediatly. It's something like threads, but with some limits.
#### Parameters:
1. `function` a function which should get executed
#### Returns:
1. `function` it returns the function which you have to execute in order to start the coroutine
#### Usage:
* Creates a schedule which switches the color between red and gray
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setText("Click me")
aButton:onClick(basalt.schedule(function(self)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
os.sleep(0.1)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
os.sleep(0.1)
self:setBackground(colors.red)
os.sleep(0.1)
self:setBackground(colors.gray)
end))
```

View File

@@ -0,0 +1,91 @@
Buttons are objects, which execute something by clicking on them.<br>
Remember button also inherits from [Object](objects/Object.md)
## setText
Sets the displayed button text
#### Parameters:
1. `string` the text the button should show
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a button with "Click me!" as text.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Click me!")
```
```xml
<button text="Click me!" />
```
## setHorizontalAlign
Sets the horizontal align of the button text
#### Parameters:
1. `string` the position as string ("left", "center", "right") - default is center.
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button's horizontal text align to right.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
:setText("Click me!")
:setHorizontalAlign("right")
```
```xml
<button text="Click me!" horizontalAlign="right" />
```
## setVerticalAlign
Sets the vertical align of the button text
#### Parameters:
1. `string` the position as string ("top", "center", "bottom") - default is center.
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button's horizontal text align to right and the vertical text align to bottom.
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
:setText("Click me!")
:setHorizontalAlign("right")
:setVerticalAlign("bottom")
```
```xml
<button text="Click me!" horizontalAlign="right" verticalAlign="bottom" />
```
# Example
This is a example on how you would create a fully working button:
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setText("Click")
aButton:onClick(function(self,event,button,x,y)
if(event=="mouse_click")and(button==1)then
basalt.debug("Left mousebutton got clicked!")
end
end)
```
and this would be the xml way to do it:
```lua
local mainFrame = basalt.createFrame():addLayout("example.xml")
basalt.setVariable("buttonClick", function(self,event,button,x,y)
if(event=="mouse_click")and(button==1)then
basalt.debug("Left mousebutton got clicked!")
end
end)
```
```xml
<button onClick="buttonClick" text="Click" />
```

View File

@@ -0,0 +1,33 @@
With checkbox objects the user can set a bool to true or false
Remember checkbox also inherits from [Object](objects/Object.md)
A checkbox does not have any custom methods. All required methods are provided by the base [object](objects/Object.md) class.
# Example
This is how you would create a event which gets fired as soon as the value gets changed:
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox()
local function checkboxChange(self)
local checked = self:getValue()
basalt.debug("The value got changed into ", checked)
end
aCheckbox:onChange(checkboxChange)
```
also possible via xml:
```lua
local mainFrame = basalt.createFrame():addLayout("example.xml")
basalt.setVariable("checkboxChange", function(self)
local checked = self:getValue()
basalt.debug("The value got changed into ", checked)
end)
```
```xml
<checkbox onChange="checkboxChange" />
```

View File

@@ -0,0 +1,307 @@
Dropdowns are objects where the user can click on a button, this will open a list where the user can choose from.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Dropdown also inherits from [Object](objects/Object.md)
## addItem
Adds a item into the dropdown
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<dropdown>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</dropdown>
```
## removeItem
Removes a item from the dropdown
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:removeItem(2)
```
## editItem
Edits a item from the dropdown
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default dropdown with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default dropdown with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aDropdown:getAll())
```
## selectItem
selects a item in the dropdown (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default dropdown with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:selectItem(2)
basalt.debug(aDropdown:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry",colors.yellow)
aDropdown:addItem("3. Entry",colors.yellow,colors.green)
aDropdown:addItem("4. Entry")
aDropdown:setSelectedItem(colors.green, colors.red)
```
```xml
<dropdown selectionBG="green" selectionFG="red">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>2. Entry</text><bg>yellow</bg><fg>green</fg></item>
</dropdown>
```
## setOffset
Sets the offset of the dropdown (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
```
```xml
<dropdown offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</dropdown>
```
## getOffset
Returns the current index offset
#### Returns:
1. `number` offset value
#### Usage:
* Creates a default dropdown with 6 entries and sets the offset to 3, also prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
basalt.debug(aDropdown:getOffset())
```
## setDropdownSize
Sets the size of the opened dropdown
#### Parameters:
1. `number` The width value
2. `number` The height value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default dropdown, adds 3 entries and sets the dropdown size to 15w, 8h
```lua
local mainFrame = basalt.createFrame()
local aDropdown = mainFrame:addDropdown():setDropdownSize(15,8)
aDropdown:addItem("1. Entry")
aDropdown:addItem("2. Entry")
aDropdown:addItem("3. Entry")
```
```xml
<dropdown dropdownWidth="15" dropdownHeight="8">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
</dropdown>
```

View File

@@ -0,0 +1,409 @@
<a href="https://i.imgur.com/aikc0K1.png"><img src="https://i.imgur.com/aikc0K1.png" height="500" /></a>
Frames are like containers, but are also normal objects.
In other words, you can add other objects _(even frames)_ to a frame; if the frame itself is visible
all sub-objects _(if they are set as visible)_ are also visible. A better description will follow.
## basalt.createFrame
Creates a new non-parent frame - in most cases it is the first thing you'll need.
#### Parameters:
1. `string` name (should be unique)
#### Returns:
1. `frame | nil` The frame created by createFrame, or `nil` if there is already a frame with the given name.
#### Usage:
* Create a frame with an id "myFirstFrame", stored in a variable named frame
```lua
local myFrame = basalt.createFrame("myFirstFrame")
```
## addFrame
Creates a child frame on the frame, the same as [basalt.createFrame](https://github.com/Pyroxenium/Basalt/wiki/Frame#basaltcreateframe) except the frames are given a parent-child relationship automatically
#### Parameters:
1. `string` name (should be unique)
#### Returns:
1. `frame | nil` The frame created by addFrame, or `nil` if there is already a child frame with the given name.<br>
#### Usage:
* Create a new main frame and adds a child frame to it
```lua
local mainFrame = basalt.createFrame()
local myFrame = mainFrame:addFrame()
```
```xml
<frame></frame>
```
## setBar
Sets the text, background, and foreground of the upper bar of the frame, accordingly.
#### Parameters:
1. `string` The title text to set the bar to
2. `number` The background color
2. `number` The foreground color
#### Returns:
1. `frame` The frame being used
#### Usage:
* Set the title to "My first frame!", with a background of black and a foreground of light gray.
```lua
frame:setBar("My first Frame!", colors.black, colors.lightGray)
```
* Store the frame, use the named frame variable after assigning.
```lua
local mainFrame = basalt.createFrame()
local myFrame = MainFrame:addFrame()
myFrame:setBar("My first Frame!")
```
* This abuses the call-chaining that Basalt uses.
```lua
local mainFrame = basalt.createFrame()
local myFrame = mainFrame:addFrame():setBar("My first Frame!")
```
```xml
<frame barText="My first Frame!" barBG="black" barFG="lightGray"></frame>
```
## setBarTextAlign
Sets the frame's bar-text alignment
#### Parameters:
1. `string` Can be supplied with "left", "center", or "right"
#### Returns:
1. `frame` The frame being used
#### Usage:
* Set the title of myFrame to "My first frame!", and align it to the right.
```lua
myFrame:setBar("My first Frame!"):setBarTextAlign("right")
```
```xml
<frame barAlign="right"></frame>
```
## showBar
Toggles the frame's upper bar
#### Parameters:
1. `boolean | nil` Whether the frame's bar is visible or if supplied `nil`, is automatically visible
#### Returns:
1. `frame` The frame being used
#### Usage:
* Sets myFrame to have a bar titled "Hello World!" and subsequently displays it.
```lua
myFrame:setBar("Hello World!"):showBar()
```
```xml
<frame bar="true"></frame>
```
## setMonitor
Sets this frame as a monitor frame
#### Parameters:
1. `string` The monitor name ("right", "left",... "monitor_1", "monitor_2",...)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new monitor frame, you can use to show objects on a monitor.
```lua
local mainFrame = basalt.createFrame()
local monitorFrame = basalt.createFrame():setMonitor("right")
monitorFrame:setBar("Monitor 1"):showBar()
```
```xml
<frame monitor="right"></frame>
```
## setMirror
mirrors this frame to another peripheral monitor object.
#### Parameters:
1. `string` The monitor name ("right", "left",... "monitor_1", "monitor_2",...)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates mirror of your main frame to a monitor on the left side.
```lua
local mainFrame = basalt.createFrame():setMirror("left")
```
```xml
<frame mirror="left"></frame>
```
## getObject
Returns a child object of the frame
#### Parameters:
1. `string` The name of the child object
#### Returns:
1. `object | nil` The object with the supplied name, or `nil` if there is no object present with the given name
#### Usage:
* Adds a button with id "myFirstButton", then retrieves it again through the frame object
```lua
myFrame:addButton("myFirstButton")
local aButton = myFrame:getObject("myFirstButton")
```
## removeObject
Removes a child object from the frame
#### Parameters:
1. `string` The name of the child object
#### Returns:
1. `boolean` Whether the object with the given name was properly removed
#### Usage:
* Adds a button with the id "myFirstButton", then removes it with the aforementioned id
```lua
myFrame:addButton("myFirstButton")
myFrame:removeObject("myFirstButton")
```
## setFocusedObject
Sets the currently focused object
#### Parameters:
1. `object` The child object to focus on
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new button, sets the focused object to the previously mentioned button
```lua
local aButton = myFrame:addButton()
myFrame:setFocusedObject(aButton)
```
## removeFocusedObject
Removes the focus of the supplied object
#### Parameters:
1. `object` The child object to remove focus from
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new button then removes the focus from that button when clicking on it
```lua
local aButton = myFrame:addButton():setFocus():onClick(function()
myFrame:removeFocusedObject(aButton)
end)
```
## getFocusedObject
Gets the currently focused object
#### Returns:
1. `object` The currently focused object
#### Usage:
* Gets the currently focused object from the frame, storing it in a variable
```lua
local focusedObject = myFrame:getFocusedObject()
```
## setMovable
Sets whether the frame can be moved. _In order to move the frame click and drag the upper bar of the frame_
#### Parameters:
1. `boolean` Whether the object is movable
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a frame with id "myFirstFrame" and makes it movable
```lua
local myFrame = basalt.createFrame():setMovable(true)
```
```xml
<frame moveable="true"></frame>
```
## setOffset
Sets the frame's coordinate offset. The frame's child objects will receive the frame's coordinate offset. For example, when using a scrollbar, if you use its value to add an offset to a frame, you will get a scrollable frame.
Objects are also able to ignore the offset by using :ignoreOffset() (For example, you may want to ignore the offset on the scrollbar itself)
The function can also be supplied with negative values
#### Parameters:
1. `number` The x direction offset (+/-)
2. `number` The y direction offset (+/-)
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame with x offset of 5 and a y offset of 3
```lua
local myFrame = basalt.createFrame():setOffset(5, 3)
```
* Creates with x offset of 5 and a y offset of -5 (Meaning if you added a button with y position 5, it would be at y position 0)
```lua
local myFrame = basalt.createFrame():setOffset(5, -5)
```
```xml
<frame xOffset="5" yOffset="-5"></frame>
```
## addLayout
Adds a new XML Layout into your frame.
#### Parameters:
1. `string` Path to your layout
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds the mainframe.xml layout
```lua
local myFrame = basalt.createFrame():addLayout("mainframe.xml")
```
```xml
<frame layout="mainframe.xml"></frame>
```
## addLayoutFromString
Adds a new XML Layout as string into your frame.
#### Parameters:
1. `string` xml
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds the mainframe.xml layout
```lua
local myFrame = basalt.createFrame():addLayoutFromString("<button x='12' y='5' bg='black' />")
```
## getLastLayout
returns a table of all objects this frame has created via xml (useful if you'd like to access all of them for some reason)
#### Returns:
1. `table` table with objects
## setTheme
Sets the default theme of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt managers theme - which is sotred in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds a new theme which only changes the default color of buttons.
```lua
local myFrame = basalt.createFrame():setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
})
```
## setScrollable
Makes the frame scrollable with mousewheel.
#### Parameters:
1. `bool` scrollable or not
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable
```lua
local myFrame = basalt.createFrame():setScrollable()
```
```xml
<frame scrollable="true"></frame>
```
## setMinScroll
Sets the minimum offset it is allowed to scroll (default 0)
#### Parameters:
1. `number` minimum y offset
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and sets the minimum amount to -5
```lua
local myFrame = basalt.createFrame():setScrollable():setMinScroll(-5)
```
```xml
<frame minScroll="-5"></frame>
```
## setMaxScroll
Sets the maximum offset it is allowed to scroll (default 10)
#### Parameters:
1. `number` maximum y offset
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and sets the maximum amount to 25
```lua
local myFrame = basalt.createFrame():setScrollable():setMaxScroll(25)
```
```xml
<frame maxScroll="25"></frame>
```
## setImportantScroll
By default if you hovering your mouse over children objects, you wont scroll the frame, if you set this to true the frame scrolling becomes more important
#### Parameters:
1. `bool` important or not
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and makes it scrollable and defines it as important
```lua
local myFrame = basalt.createFrame():setScrollable():setImportantScroll(true)
```
```xml
<frame importantScroll="true"></frame>
```
# XML Example
*This is how you would implement frames via xml:
```xml
<frame>
<frame width="parent.w * 0.5" bg="red">
<button x="2" y="2" width="17" text="Example Button!"/>
</frame>
<frame x="parent.w * 0.5 + 1" width="parent.w * 0.5 +1" bg="black">
<textfield bg="green" x="2" width="parent.w-2" />
</frame>
</frame>
```

View File

@@ -0,0 +1,41 @@
The image object is for adding more advanced backgrounds.
It also provides a :shrink() function, where you can shrink the images to smaller ones. This functionallity is fully provided by the blittle library created by Bomb Bloke. I did not ask for permission to add it into the framework. If the creator wants me to remove the blittle part, just text me on discord!
The image object is still not done. in the future i will provide more image formats.
Remember image inherits from [Object](objects/Object.md)
## loadImage
loads a default .nfp file into the object.
#### Parameters:
1. `string` the absolute file path
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame():show()
local aImage = mainFrame:addImage():loadImage("test.nfp")
```
```xml
<image path="test.nfp" />
```
## shrink
Shrinks the current image into a blittle image.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.nfp"):shrink()
```
```xml
<image path="test.nfp" shrink="true" />
```

View File

@@ -0,0 +1,91 @@
With input's you are able to create a object where the user can type something in.<br>
Here are all possible functions available for inputs:<br>
Remember Input inherits from [Object](objects/Object.md)
## setInputType
Changes the input type. default: text
#### Parameters:
1. `string` input type ("text", "password", "number")
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets it to numbers only.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputType("number")
```
```xml
<input type="number" />
```
## getInputType
Gets the current input type
#### Returns:
1. `string` input type
#### Usage:
* Creates a default input and sets it to numbers only. Also prints the current input type to log.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputType("number")
basalt.debug(aInput:getInputType())
```
## setDefaultText
Sets the default text. This will only be displayed if there is no input set by the user.
#### Parameters:
1. `string` input type ("text", "password", "number")
2. `number|color` default background color - optional
3. `number|color` default text color - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets the default text to "...".
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setDefaultText("...")
```
```xml
<input default="..." />
```
## setInputLimit
Sets a character limit to the input.
#### Parameters:
1. `number` character limit
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default input and sets the character limit to 8.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputLimit(8)
```
```xml
<input limit="8" />
```
## getInputLimit
Returns the input limit.
#### Returns:
1. `number` character limit
#### Usage:
* Creates a default input and sets the character limit to 8. Prints the current limit.
```lua
local mainFrame = basalt.createFrame()
local aInput = mainFrame:addInput():setInputLimit(8)
basalt.debug(aInput:getInputLimit())
```

View File

@@ -0,0 +1,77 @@
A label is for adding simple text.
By default label's width is auto sizing based on the length of the text. If you change the size with setSize it will automatically stop autosizing the width.
The fontsize feature is calculated by bigfonts, a library made by Wojbie (http://www.computercraft.info/forums2/index.php?/topic/25367-bigfont-api-write-bigger-letters-v10/)
Here are all possible functions available for labels.<br>
Remember Label inherits from [Object](objects/Object.md)
## setText
Sets the text which gets displayed.
#### Parameters:
1. `string` The text which should be displayed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default label with text "Some random text".
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Some random text")
```
```xml
<label text="Some random text" />
```
## setFontSize
Sets the font size, calculated by bigfonts. Default size is 1.
#### Parameters:
1. `number` The size (1, 2, 3, 4)
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default label, sets the text to "Basalt!" and its font size to 2.
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setFontSize(2)
```
```xml
<label font="2" />
```
## getFontSize
Returns the current font size
#### Returns:
1. `number` font size
#### Usage:
* Creates a default label, sets the text to "Basalt!" and its font size to 2. Also prints the current fontsize.
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setFontSize(2)
basalt.debug(aLabel:getFontSize())
```
## setTextAlign
Changes the text align
#### Returns:
1. `string` horizontal ("left", "center", "right")
1. `string` vertical ("top", "center", "bottom")
#### Usage:
* Creates a default label, sets the text to "Basalt!" changes the horizontal align to right
```lua
local mainFrame = basalt.createFrame()
local aLabel = mainFrame:addLabel():setText("Basalt!"):setTextAlign("right")
```
```xml
<label horizontalAlign="right" verticalAlign="center" />
```

View File

@@ -0,0 +1,279 @@
Lists are objects where you can create endless entries, and the user is able to select one of them
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Lists also inherits from [Object](objects/Object.md)
## addItem
Adds a item into the list
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<list>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</list>
```
## removeItem
Removes a item from the list
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:removeItem(2)
```
## editItem
Edits a item from the list
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and changes the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default list with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default list with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aList:getAll())
```
## selectItem
selects a item in the list (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default list with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:selectItem(2)
basalt.debug(aList:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
aList:addItem("1. Entry")
aList:addItem("2. Entry",colors.yellow)
aList:addItem("3. Entry",colors.yellow,colors.green)
aList:addItem("4. Entry")
aList:setSelectedItem(colors.green, colors.red)
```
```xml
<list selectionBG="green" selectionFG="red">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>2. Entry</text><bg>yellow</bg><fg>green</fg></item>
</list>
```
## setOffset
Sets the offset of the list (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default list with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
```
```xml
<list offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</list>
```
## getOffset
Returns the current index offset
#### Returns:
1. `number` offset value
#### Usage:
* Creates a default list with 6 entries and sets the offset to 3, also prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aList = mainFrame:addList()
:addItem("1. Entry")
:addItem("2. Entry")
:addItem("3. Entry")
:addItem("4. Entry")
:addItem("5. Entry")
:addItem("6. Entry")
:setOffset(3)
basalt.debug(aList:getOffset())
```

View File

@@ -0,0 +1,337 @@
Menubars are like lists but instead of being vertical, they are horizontal. Imagine you are creating a Operating System and you would like to add a taskbar, menubars would be exactly what you need, because they are also scrollable, which means they have endless entry possibility.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember menubar inherits from [Object](objects/Object.md)
## addItem
Adds a item into the menubar
#### Parameters:
1. `string` The entry name
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
```
```xml
<menubar>
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## removeItem
Removes a item from the menubar
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:removeItem(2)
```
## editItem
Edits a item from the menubar
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new item background color - optional
4. `number` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:editItem(2, "Still 2. Entry", colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default menubar with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item list count
#### Usage:
* Creates a default menubar with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
basalt.debug(aMenubar:getAll())
```
## setSpace
Sets the space between entries
#### Parameters:
1. `number` The space between each entry
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and changes the space to 3.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:setSpace(3)
```
```xml
<menubar space="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## setScrollable
Makes the menubar scrollable. The menubar will be scrollable as soon as the menubar is to small for all the entries.
#### Parameters:
1. `boolean` if this menubar should be scrollable or not
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and makes it scrollable.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:setScrollable(true)
```
```xml
<menubar scrollable="true">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text><bg>yellow</bg></item>
<item><text>3. Entry</text><bg>yellow</bg><fg>green</fg></item>
</menubar>
```
## selectItem
selects a item in the list (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default menubar with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry",colors.yellow)
aMenubar:addItem("3. Entry",colors.yellow,colors.green)
aMenubar:selectItem(2)
basalt.debug(aMenubar:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:setSelectedItem(colors.green, colors.yellow)
```
```xml
<menubar selectionBG="green" selectionFG="yellow">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
</menubar>
```
## setOffset
Sets the offset of the menubar (the same as you would scroll) - default is 0
#### Parameters:
1. `number` The offset value
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:addItem("5. Entry")
aMenubar:addItem("6. Entry")
aMenubar:setOffset(3)
```
```xml
<menubar offset="3">
<item><text>1. Entry</text></item>
<item><text>2. Entry</text></item>
<item><text>3. Entry</text></item>
<item><text>4. Entry</text></item>
<item><text>5. Entry</text></item>
<item><text>6. Entry</text></item>
</menubar>
```
## getOffset
returns the current offset
#### Returns:
1. `number` Current offset
#### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3, prints the current offset.
```lua
local mainFrame = basalt.createFrame()
local aMenubar = mainFrame:addMenubar()
aMenubar:addItem("1. Entry")
aMenubar:addItem("2. Entry")
aMenubar:addItem("3. Entry")
aMenubar:addItem("4. Entry")
aMenubar:addItem("5. Entry")
aMenubar:addItem("6. Entry")
aMenubar:getOffset(3)
basalt.debug(aMenubar:getOffset())
```

View File

@@ -0,0 +1,395 @@
This is the base class for all visual objects. Which means, if you create a button, label, frame or something else (no timers, threads or animations) the following methods apply:
## show
Shows the object (only if the parent frame is already visible)
#### Returns:
1. `object` The object in use
#### Usage:
* Shows a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
button:show()
```
```xml
<button visible="true" />
```
## hide
Hides the object
#### Returns:
1. `object` The object in use
#### Usage:
* Hides a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Close"):onClick(function() mainFrame:hide() end)
```
```xml
<button visible="false" />
```
## setPosition
Changes the position relative to its parent frame
#### Parameters:
1. `number` x coordinate
2. `number` y coordinate
3. `boolean` Whether it will add/remove to the current coordinates instead of setting them
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the Buttons position to an x coordinate of 2 with a y coordinate of 3
```lua
local mainFrame = basalt.createFrame()
mainFrame:addButton():setPosition(2,3)
```
```xml
<button x="2" y="3" />
```
## setBackground
Changes the object background color, if you set the value to false the background wont be visible. For example you could see trough a frame.
#### Parameters:
1. `number|color` Background color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame, and sets its background color to `colors.gray`
```lua
local mainFrame = basalt.createFrame():setBackground(colors.gray)
```
```xml
<button bg="gray" />
```
## setForeground
Changes the object text color
#### Parameters:
1. `number|color` Foreground color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame, and sets its foreground color to `colors.green`
```lua
local mainFrame = basalt.createFrame():setForeground(colors.green)
```
```xml
<button fg="green" />
```
## setSize
Changes the object size
#### Parameters:
1. `number` width
2. `number` height
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the frame to have a width of 15 and a height of 12
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame():setSize(15,12)
```
```xml
<frame width="15" height="12" />
```
## setFocus
Sets the object to be the focused object.
If you click on an object, it's normally automatically the focused object. For example, if you call :show() on a frame, and you want this particular frame to be in
the foreground, you should also use :setFocus()
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button to the focused object
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setFocus()
```
## setZIndex
Sets the z-index. Higher value means higher draw/event priority. You can also add multiple objects to the same z-index, if so the last added object will have the highest priority.
#### Parameters:
1. `number` z-index
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the buttons z-index to `1` and the labels z-index to `2`
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setZIndex(1):setPosition(2,2)
local aLabel = mainFrame:addButton():setZIndex(2):setPosition(2,2):setText("I am a label!")
```
```xml
<button x="2" y="2" zIndex="1" />
<label x="2" y="2" text="I am a label!" zIndex="2" />
```
## setParent
Sets the parent frame of the object
#### Parameters:
1. `frame` The to-be parent frame
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the parent frame of the random frame, adding it to the main frame when the button is clicked"
```lua
local mainFrame = basalt.createFrame()
local aRandomFrame = basalt.createFrame()
local aButton = mainFrame:addButton():onClick(
function()
aRandomFrame:setParent(mainFrame)
end
)
```
## isFocused
Returns if the object is currently the focused object of the parent frame
#### Returns:
1. `boolean` Whether the object is focused
#### Usage:
* Prints whether the button is focused to the debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton()
basalt.debug(aButton:isFocused()) -- shows true or false as a debug message
```
## getAnchorPosition
Converts the x and y coordinates into the anchor coordinates of the object
#### Parameters:
1. `number|nil` x
2. `number|nil` y, if nothing it uses the object's x, y
#### Returns:
1. `number` x
2. `number` y
#### Usage:
* Prints the anchor position to the debug console
```lua
local mainFrame = basalt.createFrame():setSize(15,15)
local aButton = mainFrame:addButton()
:setAnchor("bottomRight")
:setSize(8,1)
:setPosition(1,1)
basalt.debug(aButton:getAnchorPosition()) -- returns 7,14 (framesize - own size) instead of 1,1
```
## setAnchor
Sets the anchor of the object
#### Parameters:
1. `string` Anchor sides `("topLeft" "top", "topRight", "right", "bottomRight", "bottom", "bottomLeft", "left", "center")`
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the button to have an anchor of `bottomRight`
```lua
local mainFrame = basalt.createFrame():show()
local aButton = mainFrame:addButton()
:setAnchor("bottomRight")
:setSize(8,1)
:setPosition(-8,1)
```
```xml
<button anchor="bottomRight" />
```
## getAbsolutePosition
Converts the relative coordinates into absolute coordinates
#### Parameters:
1. `number|nil` x
2. `number|nil` y
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame and a button and prints the button's absolute position to the debug console
```lua
local mainFrame = basalt.createFrame():setPosition(3,3)
local aButton = mainFrame:addButton():setSize(8,1):setPosition(4,2)
basalt.debug(aButton:getAbsolutePosition()) -- returns 7,5 (frame coords + own coords) instead of 4,2
```
## setValue
Sets the value of that object (input, label, checkbox, textfield, scrollbar,...)
#### Parameters:
1. `any` Value to set the object to
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a checkbox and ticks it
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
```
```xml
<checkbox value="true" />
```
## getValue
Returns the currently saved value
#### Returns:
1. `any` Object's value
#### Usage:
* Prints the value of the checkbox to the debug console
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
basalt.debug(aCheckbox:getValue()) -- returns true
```
## getHeight/getWidth
Returns the respective height/width of the object
#### Returns:
1. `number` height/width
#### Usage:
* Prints the height of the object to the debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setSize(5,8)
basalt.debug(aButton:getHeight()) -- returns 8
```
## isVisible
Returns if the object is currently visible
#### Returns:
1. `boolean`
#### Usage:
* Prints boolean visibility of object to debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setSize(5,8)
basalt.debug(aButton:isVisible()) -- returns true
```
## getName
Returns the given name of the object
#### Returns:
1. `string` name
#### Usage:
* Prints name of object to debug window
```lua
local mainFrame = basalt.createFrame()
basalt.debug(mainFrame:getName()) -- returns myFirstFrame
```
## setShadow
Sets the shadow color - default: colors.black
#### Parameters:
1. `number|color` Shadow color
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the shadow to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:setShadow(colors.green)
:showShadow(true)
```
```xml
<frame width="18" height="6" shadow="true" shadowColor="green" moveable="true" />
```
## showShadow
Shows or hides the shadow
#### Parameters:
1. `boolean` Whether it should show or hide the shadow
#### Returns:
1. `object` The object in use
#### Usage:
* Shows the shadow:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:showShadow(true)
```
```xml
<frame width="18" height="6" shadow="true" moveable="true" />
```
## setBorder
Sets the border color - default: colors.black
#### Parameters:
1. `number|color` Border color
#### Returns:
1. `object` The object in use
#### Usage:
* Sets the border to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:setBorder(colors.green)
:showBorder("left", "top", "right", "bottom")
```
```xml
<frame width="18" height="6" border="true" borderColor="green" moveable="true" />
```
## showBorder
Shows or hides the border
#### Parameters:
1. `strings` Whether it should show or hide the border on the specific sides ("left", "top", "right", "bottom")
#### Returns:
1. `object` The object in use
#### Usage:
* Shows the border:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
:setMoveable()
:setSize(18,6)
:showBorder("left", "top", "bottom")
```
```xml
<frame width="18" height="6" border="true" borderColor="green" borderRight="false" moveable="true" />
```

View File

@@ -0,0 +1,19 @@
Panes are very simple sizeable background objects.
The following list is only available to panes: <br>
Remember Pane also inherits from [Object](objects/Object.md)
Pane doesn't have any custom functionallity. If you want to change the color/position or size, just check out the [object](https://github.com/NoryiE/basalt/wiki/Object) wikipage.
## Example:
```lua
local mainFrame = basalt.createFrame()
local aPane = mainFrame:addPane()
aPane:setSize(30, 10)
aPane:setBackground(colors.yellow)
aPane:show()
```
```xml
<pane width="30" height="10" bg="yellow" />
```

View File

@@ -0,0 +1,167 @@
Program objects are here for opening other executable programs in your main program. You can execute worms, shell or any custom program you've made.
<br>
Remember Program inherits from [Object](objects/Object.md)
## getStatus
returns the current process status
#### Returns:
1. `string` current status ("running", "normal, "suspended", or "dead")
#### Usage:
* Prints current status
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
basalt.debug(aProgram:getStatus())
```
## execute
Executes the given path or program
#### Parameters:
1. `string|function` the path to your file as string, or function which should be called
#### Returns:
1. `object` The object in use
#### Usage:
* Executes worm
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
aProgram:execute("rom/programs/fun/worm.lua") -- executes worm
```
```xml
<program path="rom/programs/fun/worm.lua" execute="true" />
```
## stop
Stops a currently running program
#### Returns:
1. `object` The object in use
#### Usage:
* Stops worm by clicking a button
```lua
local mainFrame = basalt.createFrame()
local aProgram = mainFrame:addProgram()
aProgram:execute("rom/programs/fun/worm.lua") -- executes worm
mainFrame:addButton():setText("Pause"):onClick(function() aProgram:stop() end):show()
```
## pause
pauses the current program (prevents the program from receiving events)
#### Parameters:
1. `boolean` true, false or nothing
#### Returns:
1. `object` The object in use
#### Usage:
* Pauses worm by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("Pause"):onClick(function() aProgram:pause(true) end):show()
```
## isPaused
returns if the program is paused
#### Returns:
1. `boolean` pause status
#### Usage:
* Prints the pause status of the program
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
basalt.debug(aProgram:isPaused())
```
## injectEvent
injects a event into the program manually. For example you could inject w a s and d for worm, by clicking buttons.
#### Parameters:
1. `string` event
2. `any` parameter
3. `any` parameter
4. `any` parameter
5. `any` parameter
6. `boolean` if this is true, the injected event will be executed even if the program is paused
#### Returns:
1. `object` The object in use
#### Usage:
* injects a event by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function() aProgram:injectEvent("char", "w") end):show()
```
## injectEvents
Injects multiple events
#### Parameters:
1. `table` a table, items should be {event="event", args={para1, para2, para3, para4}}
#### Returns:
1. `object` The object in use
#### Usage:
* injects a multiple char events by clicking a button
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
local events = {
{event="char", args={"h"}},
{event="char", args={"e"}},
{event="char", args={"y"}}
}
mainFrame:addButton():setText("inject"):onClick(function() aProgram:injectEvents(events) end):show()
```
## getQueuedEvents
If the program is paused, incomming events will be inserted into a queued events table. As soon as the program is unpaused, the queued events table will be empty
#### Returns:
1. `table` a table - {event="event", args={"a", "b",...}}
#### Usage:
* prints the queued events table
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function() basalt.debug(aProgram:getQueuedEvents()) end):show()
```
## updateQueuedEvents
Here you can manipulate the queued events table
#### Parameters:
1. `table` a table, items should be {event="event", args={para1, para2, para3, para4}}
#### Returns:
1. `object` The object in use
```lua
local mainFrame = basalt.createFrame():show()
local aProgram = mainFrame:addProgram():execute("rom/programs/shell.lua"):show()
mainFrame:addButton():setText("inject"):onClick(function()
local events = aProgram:getQueuedEvents()
table.insert(events,1,{event="char", args={"w"}}
aProgram:updateQueuedEvents(events)
end):show()
```

View File

@@ -0,0 +1,134 @@
Progressbars are objects to visually display the current state of your progression. They always go from 0 to 100 (%) - no matter how big they are. which means if you
want to add some energy progress you have to do simple maths: currentValue / maxValue * 100
Here are all possible functions available for progessbars. Remember progressbar inherits from [Object](objects/Object.md)
## setDirection
Sets the direction in which the bar should be expanding.
#### Parameters:
1. `number` x direction (0 = left to right, 1 = top to bottom, 2 = right to left and 3 = bottom to top)
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the direction from bottom to top
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setDirection(3)
```
```xml
<frame direction="3"></frame>
```
## setProgress
This is the function you need to call if you want the progression to change.
#### Parameters:
1. `number` a number from 0 to 100
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the current progress to 50
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgress(50)
```
## getProgress
Returns the current progress status
#### Returns:
1. `number` progress (0-100)
#### Usage:
* Creates a progressbar, sets the current progress to 50 and prints the current progress
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgress(50)
basalt.debug(aProgressbar:getProgress())
```
## setProgressBar
This function will change the visual display of your progress bar
#### Parameters:
1. `number|color` the expanding progress bar color
2. `char` optional - the bar symbol - default is " " (space)
3. `number|color` optional - the bar symbol color
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the progressbar color to green
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setProgressBar(colors.green, colors.yellow, colors.red)
```
```xml
<progressbar progressColor="green" progressSymbol="yellow" progressSymbolColor="red" />
```
## setBackgroundSymbol
Will change the default background symbol (default is " " - space)
#### Parameters:
1. `char` the background symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a progressbar and sets the progressbar background symbol to X
```lua
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
aProgressbar:setBackgroundSymbol("X")
```
```xml
<progressbar backgroundSymbol="X" />
```
# Events
## onProgressDone
`onProgressDone(self)`<br>
A custom event which gets triggered as soon as the progress reaches 100.
Here is a example on how to add a onProgressDone event to your progressbar:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local aProgressbar = mainFrame:addProgressbar()
function progressDone()
basalt.debug("The Progressbar reached 100%!")
end
aProgressbar:onProgressDone(progressDone)
```
Here is also a example how this is done with xml:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
basalt.setVariable("progressDone", function()
basalt.debug("The Progressbar reached 100%!")
end)
```
```xml
<progressbar onDone="progressDone" />
```

View File

@@ -0,0 +1,229 @@
Radios are objects which you can freely place, and the user is then able to select a single item.
If you want to access values inside items this is how the table for single items is made (just a example):
```lua
item = {
text="1. Entry",
bgCol=colors.black,
fgCol=colors.white
args = {}
}
```
Remember Radios also inherits from [Object](objects/Object.md)
## addItem
Adds a item to the radio
#### Parameters:
1. `string` The entry name
2. `number` x position
3. `number` y position
2. `number|color` unique default background color - optional
3. `number|color` unique default text color - optional
4. `any` any value - you could access this later in a :onChange() event (you need to use :getValue()) - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
```
```xml
<radio>
<item><text>1. Entry</text><x>5</x><y>2</y></item>
<item><text>2. Entry</text><x>5</x><y>4</y><bg>yellow</bg></item>
<item><text>3. Entry</text><x>5</x><y>6</y><bg>yellow</bg><fg>green</fg></item>
</radio>
```
## removeItem
Removes a item from the radio
#### Parameters:
1. `number` The index which should get removed
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and removes the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:removeItem(2)
```
## editItem
Edits a item from the radio
#### Parameters:
1. `number` The index which should be edited
2. `string` The new item name
3. `number` the new x position
4. `number` the new y position
3. `number|color` the new item background color - optional
4. `number|color` The new item text color - optional
5. `any` New additional information - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and changes the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:editItem(2, "Still 2. Entry", 5, 4, colors.red)
```
## getItem
Returns a item by index
#### Parameters:
1. `number` The index which should be returned
#### Returns:
1. `table` The item table example: {text="1. Entry", bgCol=colors.black, fgCol=colors.white}
#### Usage:
* Creates a default radio with 3 entries and edits the second one.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getItem(2).text)
```
## getItemCount
Returns the current item count
#### Returns:
1. `number` The item radio count
#### Usage:
* Creates a default radio with 3 entries and prints the current item count.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getItemCount())
```
## getAll
Returns all items as table
#### Returns:
1. `table` All items
#### Usage:
* Creates a default menubar with 3 entries and prints a table.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
basalt.debug(aRadio:getAll())
```
## selectItem
selects a item in the radio (same as a player would click on a item)
#### Parameters:
1. `number` The index which should get selected
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and selects the second entry.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:selectItem(2)
```
## clear
Removes all items.
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 3 entries and removes them immediatley. Which makes no sense.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:clear()
```
## getItemIndex
returns the item index of the currently selected item
#### Returns:
1. `number` The current index
#### Usage:
* Creates a default radio with 3 entries selects the second entry and prints the currently selected index.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:selectItem(2)
basalt.debug(aRadio:getItemIndex())
```
## setSelectedItem
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number|color` The background color which should be used
2. `number|color` The text color which should be used
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default radio with 4 entries and sets the selection background color to green.
```lua
local mainFrame = basalt.createFrame()
local aRadio = mainFrame:addRadio()
aRadio:addItem("1. Entry",5,2)
aRadio:addItem("2. Entry",5,4,colors.yellow)
aRadio:addItem("3. Entry",5,6,colors.yellow,colors.green)
aRadio:addItem("4. Entry",5,8)
aRadio:setSelectedItem(colors.green, colors.red)
```
```xml
<radio selectionBG="green" selectionFG="red">
<item><text>1. Entry</text><x>5</x><y>2</y></item>
<item><text>2. Entry</text><x>5</x><y>4</y><bg>yellow</bg></item>
<item><text>3. Entry</text><x>5</x><y>6</y><bg>yellow</bg><fg>green</fg></item>
</radio>
```

View File

@@ -0,0 +1,108 @@
Scrollbars are objects, the user can scroll vertically or horizontally, this will change a value, which you can access by :getValue().<br>
Remember scrollbar also inherits from [Object](objects/Object.md)
## setSymbol
Changes the scrollbar symbol, default is " "
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the symbol to X
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setSymbol("X")
```
```xml
<scrollbar symbol="X" />
```
## setBackgroundSymbol
Changes the symbol in the background, default is "\127"
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the background symbol to X
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setBackgroundSymbol("X")
```
```xml
<scrollbar backgroundSymbol="X" />
```
## setBarType
Changes the scrollbar to be vertical or horizontal, default is vertical
#### Parameters:
1. `string` vertical or horizontal
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the bar type to horizontal
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setBarType("horizontal")
```
```xml
<scrollbar barType="horizontal" />
```
## setMaxValue
the default max value is always the width (if horizontal) or height (if vertical), if you change the max value the bar will always calculate the value based on its width or height - example: you set the max value to 100, the height is 10 and it is a vertical bar, this means if the bar is on top, the value is 10, if the bar goes one below, it is 20 and so on.
#### Parameters:
1. `number` maximum
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the max value to 20
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setMaxValue(20)
```
```xml
<scrollbar maxValue="20" />
```
## setIndex
Changes the current index to your choice, for example you could create a button which scrolls up to 1 by using :setIndex(1)
#### Parameters:
1. `number` the index
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new scrollbar and changes the index to 1 as soon as the button got clicked
```lua
local mainFrame = basalt.createFrame()
local scrollbar = mainFrame:addScrollbar():setMaxValue(20)
local button = mainFrame:addButton(function()
scrollbar:setIndex(1)
end)
```
```xml
<scrollbar index="2" />
```
## getIndex
Returns the current index
#### Returns:
1. `number` index

View File

@@ -0,0 +1,108 @@
Sliders are objects, the user can scroll vertically or horizontally, this will change a value, which you can access by :getValue().<br>
Remember slider also inherits from [Object](objects/Object.md)
## setSymbol
Changes the slider symbol, default is " "
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the symbol to X
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setSymbol("X")
```
```xml
<slider symbol="X" />
```
## setBackgroundSymbol
Changes the symbol in the background, default is "\140"
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the background symbol to X
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setBackgroundSymbol("X")
```
```xml
<slider backgroundSymbol="X" />
```
## setBarType
Changes the slider to be vertical or horizontal, default is horizontal
#### Parameters:
1. `string` vertical or horizontal
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the bar type to horizontal
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setBarType("vertical")
```
```xml
<slider barType="vertical" />
```
## setMaxValue
the default max value is always the width (if horizontal) or height (if vertical), if you change the max value the bar will always calculate the value based on its width or height - example: you set the max value to 100, the height is 10 and it is a vertical bar, this means if the bar is on top, the value is 10, if the bar goes one below, it is 20 and so on.
#### Parameters:
1. `number` maximum
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the max value to 20
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setMaxValue(20)
```
```xml
<slider maxValue="20" />
```
## setIndex
Changes the current index to your choice, for example you could create a button which scrolls up to 1 by using :setIndex(1)
#### Parameters:
1. `number` the index
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new slider and changes the index to 1 as soon as the button got clicked
```lua
local mainFrame = basalt.createFrame()
local slider = mainFrame:addSlider():setMaxValue(20)
local button = mainFrame:addButton(function()
slider:setIndex(1)
end)
```
```xml
<slider index="2" />
```
## getIndex
Returns the current index
#### Returns:
1. `number` index

View File

@@ -0,0 +1,161 @@
Textfields are objects, where the user can write something on multiple lines. it act's like the default edit script (without coloring)<br>
Remember textfield inherits from [Object](objects/Object.md)
## getLines
Returns all lines
#### Returns:
1. `table` lines
#### Usage:
* Prints all lines
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:getLines())
```
## getLine
Returns the line on index position
#### Parameteres:
1. `number` index
#### Returns:
1. `string` line
#### Usage:
* Prints one line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:getLine(1))
```
## editLine
Edits the line on index position
#### Parameteres:
1. `number` index
2. `string` text
#### Returns:
1. `object` The object in use
#### Usage:
* Edits the line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:editLine(1, "Hello!"))
```
## addLine
Adds a line on index position
#### Parameteres:
1. `string` text
2. `number` index
#### Returns:
1. `object` The object in use
#### Usage:
* Adds a line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:addLine("Hello!", 1))
```
```xml
<textfield>
<lines>
<line>Hello!</line>
</lines>
</textfield>
```
## removeLine
Removes the line on index position
#### Parameteres:
1. `number` index
2. `string` text
#### Returns:
1. `object` The object in use
#### Usage:
* Removes a line
```lua
local mainFrame = basalt.createFrame("myFirstFrame"):show()
local aTextfield = mainFrame:addTextfield("myFirstTextfield"):show()
basalt.debug(aTextfield:removeLine())
```
## getTextCursor
Gets text cursor position
#### Returns:
1. `number` x position
2. `number` y position
## addKeywords
Adds keywords for special coloring
#### Parameteres:
1. `number|color` color of your choice
2. `table` a list of keywords which should be colored example: {"if", "else", "then", "while", "do"}
#### Returns:
1. `object` The object in use
#### Usage:
* Changes the color of some words to purple
```lua
local mainFrame = basalt.createFrame()
local aTextfield = mainFrame:addTextfield():addKeywords(colors.purple, {"if", "else", "then", "while", "do", "hello"})
```
```xml
<textfield>
<keywords>
<purple>
<keyword>if</keyword>
<keyword>else</keyword>
<keyword>then</keyword>
<keyword>while</keyword>
<keyword>do</keyword>
<keyword>hello</keyword>
</purple>
</keywords>
</textfield>
```
## addRule
Adds a new rule for special coloring
#### Parameteres:
1. `string` a pattern - check out this page: (https://riptutorial.com/lua/example/20315/lua-pattern-matching)
2. `number|color` text color
3. `number|color` background color - optional
#### Returns:
1. `object` The object in use
#### Usage:
* Changes the color of all numbers
```lua
local mainFrame = basalt.createFrame()
local aTextfield = mainFrame:addTextfield():addRule("%d", colors.lightBlue)
```
```xml
<textfield>
<rules>
<rule>
<pattern>%d</pattern>
<fg>lightBlue</fg>
</rule>
</rules>
</textfield>
```

View File

@@ -0,0 +1,65 @@
Threads are being executed simultaneously.
<br>
## start
starts a new thread and executes the function
#### Parameters:
1. `function` the function which should be executed
#### Returns:
1. `object` The object in use
#### Usage:
* Starts a new thread
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
local function randomThreadFunction()
while true do
basalt.debug("Thread is active")
os.sleep(1) -- a sleep/coroutine.yield() or pullEvent is required otherwise we will never come back to the main program (error)
end
end
aThread:start(randomThreadfunction)
```
you are also able to start threads via xml:
```lua
basalt.setVariable("myThread", function() while true do os.sleep(1) end end)
```
```xml
<thread thread="myThread" start="true"/>
```
## stop
stops the thread
#### Returns:
1. `object` The object in use
#### Usage:
* Stops the current running thread by clicking on a button
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
local function randomThreadFunction()
while true do
basalt.debug("Thread is active")
os.sleep(1) -- a sleep/coroutine.yield() or pullEvent is required otherwise we will never come back to the main program (error)
end
end
aThread:start(randomThreadfunction)
local aButton = mainFrame:addButton():setText("Stop Thread"):onClick(function() aThread:stop() end)
```
## getStatus
gets the current thread status
#### Returns:
1. `string` current status - ("running", "normal", "suspended", "dead")
#### Usage:
```lua
local mainFrame = basalt.createFrame()
local aThread = mainFrame:addThread()
basalt.debug(aThread:getStatus())
```

View File

@@ -0,0 +1,84 @@
Timers can call your functions delay and repeat it as often as you wish
<br>
## setTime
sets the time the timer should wait after calling your function
#### Parameters:
1. `number` the time to delay
2. `number` how often it should be repeated -1 is infinite
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2)
```
```xml
<timer time="2" repeat="1"/>
```
## start
Starts the timer
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2):start()
```
```xml
<timer time="2" start="true"/>
```
## cancel
Cancels the timer
#### Returns:
1. `object` The object
```lua
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
aTimer:setTime(2):start()
aTimer:cancel()
```
# Events
## onCall
`onCall(self)`<br>
A custom event which gets triggered as soon as the current timer has finished
Here is a example on how to add a onCall event to your timer:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local aTimer = mainFrame:addTimer()
function call()
basalt.debug("The timer has finished!")
end
aTimer:onCall(call)
```
Here is also a example how this is done with xml:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
basalt.setVariable("call", function()
basalt.debug("The timer has finished!")
end)
```
```xml
<progressbar onDone="call" />
```

View File

@@ -0,0 +1,41 @@
Here I want to explain to you how you would create a button with the default color gray, and as long as the user is clicking on the button it will change its color to black (the default frame-background is lightGray).
To make this possible the button needs 1 onClick event, 1 onClickUp event and 1 onLoseFocus event.
Very interesting sidetip: events can hold multiple functions!<br>
**Example snippet:**
```lua
local function buttonColoring()
-- here you can add some coloring for your button
end
local function buttonLogic()
-- here you can add some logic for your button
end
local button = mainFrame:addButton("ExampleButton"):show()
button:onClick(buttonColoring):onClick(buttonLogic) -- yes this would work, if not its a bug!
```
This means you can create a function wich handles only the coloring side of your button, and if your button also needs some logic you just create your own unique function for that and add it to your button.
With this knowledge we create now a function where we pass a button-object as parameter and this will setup the coloring of our button:
**Example snippet:**
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame:addButton("firstButton"):setPosition(3,3):setSize(12,3):setText("Click me"):setBackground(colors.gray):setForeground(colors.black):show()
local button2 = mainFrame:addButton("secondButton"):setPosition(25,3):setSize(16,3):setText("Another Btn"):setBackground(colors.gray):setForeground(colors.black):show()
local function setupButtonColoring(btn)
btn:onClick(function() btn:setBackground(colors.black) btn:setForeground(colors.lightGray) end)
btn:onClickUp(function() btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
btn:onLoseFocus(function() btn:setBackground(colors.gray) btn:setForeground(colors.black) end)
end
setupButtonColoring(button)
setupButtonColoring(button2)
basalt.autoUpdate()
```
Now you've got a function which sets your buttons up.

View File

@@ -0,0 +1,82 @@
Hello! This page contains some tips on how to create cool designs with Basalt
To understand this page, it is recommended to familiarize yourself with [Animations](../objects/Animation.md) as animations are important for creating complex designs
Let us begin with simple things:
## Recolor objects
Let's create a Button:
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame():setBackground(colors.black):show()
local aButton = mainFrame:addButton():setSize(10, 3):setText("Beautiful"):setBackground(colors.gray):show()
```
Here lets make use of the event system:<br>
```lua
local function changeButtonColor(self,event,typ,x,y)
if(event=="mouse_click")then
self:setBackground(colors.lightGray)
end
if(event=="mouse_up")then
self:setBackground(colors.gray)
end
end
local function buttonLogic()
-- here you can do some logic when button gets the mouse_up event
end
aButton:onClick(changeButtonColor) -- button color change on click
aButton:onClickUp(changeButtonColor) -- button color change on click up
aButton:onClickUp(buttonLogic) -- button logic on click up
aButton:onLoseFocus(function(self) self:setBackground(colors.gray) end) -- if user is clicking on the button and dragging out of button size this event will change the bg color back to gray
```
## Fade In/Out Objects
instead of recoloring we are also able to slowly reposition the button, something like fade in:<br>
```lua
local buttonAnimation = mainFrame:addAnimation()
local function fadeButtonIn(btn)
if(btn.x < 5)then
btn:setPosition(1,0,"r")
else
buttonAnimation:cancel() -- here you cancel the loop
end
end
buttonAnimation:wait(0.1):add(function() fadeButtonIn(aButton) end):play(true) -- with play(true) you will create a infinite loop
```
This is also possible with entire frames and its children objects. So keep that in mind if you want to create something like a bigger panel to the right or a menu bar
## How To use XML
Here is a example on how to create a cool looking frame by using xml:
```xml
<frame width="parent.w/2" bg="gray" scrollable="true" importantScroll="true">
<button x="2" y="2" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 1!"/>
<button x="2" y="6" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 2!"/>
<button x="2" y="10" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 3!"/>
<button x="2" y="14" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 4!"/>
<button x="2" y="18" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 5!"/>
<button x="2" y="22" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 6!"/>
<button x="2" y="26" width="parent.w-2" bg="black" fg="lightGray" text="Example Button 7!"/>
</frame>
<frame x="parent.w/2+1" width="parent.w/2+1" bg="black">
<textfield bg="gray" x="2" y="2" width="parent.w-2">
<lines>
<line>This is line 1.</line>
<line>And this is line 2.</line>
</lines>
</textfield>
<label anchor="bottomLeft" x="2" y="0" text="I love labels!" fg="lightGray"/>
</frame>
```
in your lua code you just have to add this layout to your frame:
```lua
local basalt = require("Basalt")
basalt.createFrame():addLayout("example.xml")
basalt.autoUpdate()
```

View File

@@ -0,0 +1,34 @@
## Short way of adding functions to events
Not everyone knows that a function (or in other words a method) does not need to have a name. Instead of a function name you are also able to add the function itself as a argument.
Both do the exact same thing:
```lua
local function clickButton()
basalt.debug("I got clicked!")
end
button:onClick(clickButton)
```
```lua
button:onClick(function()
basalt.debug("I got clicked!")
end)
```
## Using isKeyDown for shortcuts
there is also a function with which you can check if the user is holding a key down, it is called `basalt.isKeyDown()`. It's especially useful for click events.
Let us say you want a button to execute something, but if you are holding ctrl down, something in the execution should get changed. This is how you would
achieve that:
```lua
button:onClick(function()
if(basalt.isKeyDown(keys.leftCtrl)then
basalt.debug("Ctrl is down!")
else
basalt.debug("Ctrl is up!")
end
end)
```
Make sure to always use the available `keys` table: https://computercraft.info/wiki/Keys_(API)

View File

@@ -0,0 +1,56 @@
You question yourself how you can execute your own logic while basalt is also active? There are multiple ways of doing that:
## Method 1:
Using parallel.waitForAll
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame and a button without functionality
mainFrame:addButton("aButton"):onClick(function() end):show()
local function yourCustomHandler()
while true do
-- add your logic here
os.sleep(1) -- you need something which calls coroutine.yield(), yes os.sleep does that os.pullEvent() aswell
end
end
parallel.waitForAll(basalt.autoUpdate, yourCustomHandler) -- here it will handle your function (yourCustomHandler) and basalts handlers at the time
```
You can read [here (tweaked.cc)](https://tweaked.cc/module/parallel.html) what exactly parallel.waitForAll() does
## Method 2:
Using threads
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame, a button without functionality and a thread
mainFrame:addButton("aButton"):onClick(function() end):show()
local thread = mainFrame:addThread("customHandlerExecutingThread")
local function yourCustomHandler()
while true do
-- add your logic here
os.sleep(1) -- you need something which calls coroutine.yield(), yes os.sleep does that os.pullEvent() aswell
end
end
thread:start(yourCustomHandler) -- this will create a coroutine and starts the coroutine, os.sleep does the rest, so you just have to call start once.
```
## Method 3:
Using timers
```lua
local basalt = dofile("basalt.lua")
local mainFrame = basalt.createFrame("mainFrame"):show()-- lets create a frame, a button without functionality and a timer
mainFrame:addButton("aButton"):onClick(function() end):show()
local timer = mainFrame:addTimer("customHandlerExecutingTimer")
local function yourCustomHandler()
-- add your logic here
end
timer:onCall(yourCustomHandler):setTime(1, -1):start() -- this will call your function every second until you :cancel() the timer
```

View File

@@ -1,48 +1,47 @@
# 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:
After downloading the project, you can start creating your own program and use Basalt. The first thing you want to include 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.
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
To 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.
This should be placed at 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:
Here's 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"
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
button:setPosition(4, 4) -- We want to change the default position of our button
button:setSize(16, 3) -- And the default size.
button:setText("Click me!") --> This method sets the text displayed on our button
local function buttonClick() --> Let us create a function we want to call when the button gets clicked
local function buttonClick() --> 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:
-- Now we just need to register the function to the button's 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)
basalt.autoUpdate() -- As soon as we call basalt.autoUpdate, the event and draw handlers will listen to any incoming 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:
If you strive for succinct and beautiful code, here's a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
@@ -50,11 +49,11 @@ 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)
:setPosition(4, 4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
function()
basalt.debug("I got clicked!")
end)
basalt.autoUpdate()

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