16 Commits

Author SHA1 Message Date
Robert Jelic
859303e7a1 documentated multi-monitor support 2022-09-08 20:36:36 +02:00
Robert Jelic
51f6ebe7ce docs updates 2022-09-06 17:43:03 +02:00
Robert Jelic
4d227af9d9 fixed removeObject 2022-09-06 16:21:54 +02:00
Robert Jelic
cf4f15e659 added multimonitor support
- cursor fix @input
- now you are able to add bigger monitors - still in beta
Some features are still missing: checking if monitors are connected/disconnected,
resizing by destroying the blocks
2022-09-05 23:00:38 +02:00
Robert Jelic
a3291544ac small input fixed
Used the old way of receiving x position
2022-09-04 17:44:06 +02:00
Robert Jelic
0503aa1274 Update process.lua 2022-09-03 20:41:16 +02:00
Robert Jelic
299b23a6c2 Border fix
fixed the way borders are drawn
2022-09-02 19:38:38 +02:00
Robert Jelic
8b3b6f3490 Update Frame.lua
fixed small focus issue
2022-09-01 21:05:13 +02:00
Robert Jelic
d1792ac537 Merge pull request #27 from Erb3/patch-2
Fix typo in Animations - changeBackground.md
2022-09-01 19:43:53 +02:00
Erlend
709cf66ce8 Fix typo in Animations - changeBackground.md 2022-09-01 18:57:39 +02:00
Robert Jelic
ae14d85a6b Input fix
fixed a bug in input fields while drag event is happening - now the input object loses the focus when dragging outside of its position+size
2022-08-30 22:51:26 +02:00
Robert Jelic
896e8179a6 oops 2022-08-30 20:52:28 +02:00
Robert Jelic
2dd3bf648b Some docs updates 2022-08-30 20:49:25 +02:00
Robert Jelic
c977410a41 Small bugfix
Fixed a bug where frames incorrectly remove their own events in parent frames
2022-08-30 20:17:00 +02:00
Robert Jelic
23b94d076b Frame drag fix
Fixed a dragging bug on frames
2022-08-29 18:50:18 +02:00
Robert Jelic
b10ec1770c fixed wrong links for labels 2022-08-29 18:26:59 +02:00
47 changed files with 1217 additions and 218 deletions

View File

@@ -3,6 +3,7 @@ local _OBJECTS = require("loadObjects")
local BasaltDraw = require("basaltDraw") local BasaltDraw = require("basaltDraw")
local utils = require("utils") local utils = require("utils")
local layout = require("layout") local layout = require("layout")
local basaltMon = require("basaltMon")
local uuid = utils.uuid local uuid = utils.uuid
local rpairs = utils.rpairs local rpairs = utils.rpairs
local xmlValue = utils.getValueFromXML local xmlValue = utils.getValueFromXML
@@ -27,6 +28,7 @@ return function(name, parent, pTerm, basalt)
local monSide = "" local monSide = ""
local isMonitor = false local isMonitor = false
local isGroupedMonitor = false
local monitorAttached = false local monitorAttached = false
local dragXOffset = 0 local dragXOffset = 0
local dragYOffset = 0 local dragYOffset = 0
@@ -138,7 +140,7 @@ return function(name, parent, pTerm, basalt)
if (value == obj) then if (value == obj) then
table.remove(events[a][c], key) table.remove(events[a][c], key)
if(self.parent~=nil)then if(self.parent~=nil)then
if(tableCount(events[event])<=0)then if(tableCount(events[a])<=0)then
self.parent:removeEvent(a, self) self.parent:removeEvent(a, self)
end end
end end
@@ -148,13 +150,23 @@ return function(name, parent, pTerm, basalt)
end end
end end
local function removeObject(obj) local function removeObject(self, obj)
for a, b in pairs(objects) do for a, b in pairs(objects) do
for key, value in pairs(b) do for key, value in pairs(b) do
if (value == obj) then if(type(obj)=="string")then
table.remove(objects[a], key) if (value:getName() == obj) then
removeEvents(object, obj) table.remove(objects[a], key)
return true; removeEvents(object, value)
self:updateDraw()
return true;
end
else
if (value == obj) then
table.remove(objects[a], key)
removeEvents(object, value)
self:updateDraw()
return true;
end
end end
end end
end end
@@ -375,6 +387,7 @@ return function(name, parent, pTerm, basalt)
setFocusedObject = function(self, obj) setFocusedObject = function(self, obj)
focusedObjectCache = obj focusedObjectCache = obj
focusSystem(self)
return self return self
end; end;
@@ -451,6 +464,7 @@ return function(name, parent, pTerm, basalt)
removeFocusedObject = function(self) removeFocusedObject = function(self)
focusedObjectCache = nil focusedObjectCache = nil
focusSystem(self)
return self return self
end; end;
@@ -520,8 +534,10 @@ return function(name, parent, pTerm, basalt)
base.show(self) base.show(self)
if(self.parent==nil)then if(self.parent==nil)then
basalt.setActiveFrame(self) basalt.setActiveFrame(self)
if(isMonitor)then if(isMonitor)and not(isGroupedMonitor)then
basalt.setMonitorFrame(monSide, self) basalt.setMonitorFrame(monSide, self)
elseif(isGroupedMonitor)then
basalt.setMonitorFrame(self:getName(), self, monSide)
else else
basalt.setMainFrame(self) basalt.setMainFrame(self)
end end
@@ -532,11 +548,15 @@ return function(name, parent, pTerm, basalt)
hide = function (self) hide = function (self)
base.hide(self) base.hide(self)
if(self.parent==nil)then if(self.parent==nil)then
if(activeFrame == self)then activeFrame = nil end if(activeFrame == self)then activeFrame = nil end -- bug activeFrame always nil
if(isMonitor)then if(isMonitor)and not(isGroupedMonitor)then
if(basalt.getMonitorFrame(monSide) == self)then if(basalt.getMonitorFrame(monSide) == self)then
basalt.setActiveFrame(nil) basalt.setActiveFrame(nil)
end end
elseif(isGroupedMonitor)then
if(basalt.getMonitorFrame(self:getName()) == self)then
basalt.setActiveFrame(nil)
end
else else
if(basalt.getMainFrame() == self)then if(basalt.getMainFrame() == self)then
basalt.setMainFrame(nil) basalt.setMainFrame(nil)
@@ -640,25 +660,47 @@ return function(name, parent, pTerm, basalt)
return self return self
end, end,
setMonitor = function(self, side) setMonitorScale = function(self, scale)
if(isMonitor)then
termObject.setTextScale(scale)
end
return self
end,
setMonitor = function(self, side, scale)
if(side~=nil)and(side~=false)then if(side~=nil)and(side~=false)then
if(peripheral.getType(side)=="monitor")then if(type(side)=="string")then
termObject = peripheral.wrap(side) if(peripheral.getType(side)=="monitor")then
termObject = peripheral.wrap(side)
monitorAttached = true
end
if(self.parent~=nil)then
self.parent:removeObject(self)
end
isMonitor = true
basalt.setMonitorFrame(side, self)
elseif(type(side)=="table")then
termObject = basaltMon(side)
monitorAttached = true monitorAttached = true
isMonitor = true
isGroupedMonitor = true
basalt.setMonitorFrame(self:getName(), self, true)
end end
if(self.parent~=nil)then
self.parent:removeObject(self)
end
isMonitor = true
basalt.setMonitorFrame(side, self)
else else
termObject = parentTerminal termObject = parentTerminal
isMonitor = false isMonitor = false
if(basalt.getMonitorFrame(monSide)==self)then isGroupedMonitor = false
basalt.setMonitorFrame(monSide, nil) if(type(monSide)=="string")then
if(basalt.getMonitorFrame(monSide)==self)then
basalt.setMonitorFrame(monSide, nil)
end
else
if(basalt.getMonitorFrame(self:getName())==self)then
basalt.setMonitorFrame(self:getName(), nil)
end
end end
end end
if(scale~=nil)then termObject.setTextScale(scale) end
basaltDraw = BasaltDraw(termObject) basaltDraw = BasaltDraw(termObject)
self:setSize(termObject.getSize()) self:setSize(termObject.getSize())
autoSize = true autoSize = true
@@ -715,8 +757,18 @@ return function(name, parent, pTerm, basalt)
end end
if(isMonitor)then if(isMonitor)then
if(autoSize)then if(autoSize)then
if(event=="monitor_resize")and(p1==monSide)then if(event=="monitor_resize")then
self:setSize(termObject.getSize()) if(type(monSide)=="string")then
self:setSize(termObject.getSize())
elseif(type(monSide)=="table")then
for k,v in pairs(monSide)do
for a,b in pairs(v)do
if(p1==b)then
self:setSize(termObject.getSize())
end
end
end
end
autoSize = true autoSize = true
self:updateDraw() self:updateDraw()
end end
@@ -750,7 +802,12 @@ return function(name, parent, pTerm, basalt)
end end
end, end,
mouseHandler = function(self, button, x, y) mouseHandler = function(self, button, x, y, _, side)
if(isGroupedMonitor)then
if(termObject.calculateClick~=nil)then
x, y = termObject.calculateClick(side, x, y)
end
end
if(base.mouseHandler(self, button, x, y))then if(base.mouseHandler(self, button, x, y))then
if(events["mouse_click"]~=nil)then if(events["mouse_click"]~=nil)then
self:setCursor(false) self:setCursor(false)
@@ -776,7 +833,6 @@ return function(name, parent, pTerm, basalt)
end end
end end
self:removeFocusedObject() self:removeFocusedObject()
focusSystem(self)
return true return true
end end
return false return false
@@ -832,7 +888,6 @@ return function(name, parent, pTerm, basalt)
end end
end end
self:removeFocusedObject() self:removeFocusedObject()
focusSystem(self)
if(yOffset==cache)then return false end if(yOffset==cache)then return false end
return true return true
end end
@@ -853,14 +908,16 @@ return function(name, parent, pTerm, basalt)
self:updateDraw() self:updateDraw()
return true return true
end end
if(events["mouse_drag"]~=nil)then if(self:isVisible())and(self:isEnabled())then
for _, index in ipairs(eventZIndex["mouse_drag"]) do if(events["mouse_drag"]~=nil)then
if (events["mouse_drag"][index] ~= nil) then for _, index in ipairs(eventZIndex["mouse_drag"]) do
for _, value in rpairs(events["mouse_drag"][index]) do if (events["mouse_drag"][index] ~= nil) then
if (value.dragHandler ~= nil) then for _, value in rpairs(events["mouse_drag"][index]) do
if (value:dragHandler(button, x, y)) then if (value.dragHandler ~= nil) then
focusSystem(self) if (value:dragHandler(button, x, y)) then
return true focusSystem(self)
return true
end
end end
end end
end end
@@ -1069,9 +1126,7 @@ return function(name, parent, pTerm, basalt)
return addObject(obj) return addObject(obj)
end; end;
removeObject = function(self, obj) removeObject = removeObject,
return removeObject(obj)
end;
getObject = function(self, obj) getObject = function(self, obj)
return getObject(obj) return getObject(obj)

View File

@@ -56,17 +56,21 @@ return function(name)
isVisible = false isVisible = false
self:updateDraw() self:updateDraw()
return self return self
end; end,
enable = function(self) enable = function(self)
isEnabled = true isEnabled = true
return self return self
end; end,
disable = function(self) disable = function(self)
isEnabled = false isEnabled = false
return self return self
end; end,
isEnabled = function(self)
return isEnabled
end,
generateXMLEventFunction = function(self, func, val) generateXMLEventFunction = function(self, func, val)
local createF = function(str) local createF = function(str)
@@ -415,39 +419,44 @@ return function(name)
end end
if(borderColors["left"]~=false)then if(borderColors["left"]~=false)then
self.parent:drawTextBox(x-1, y, 1, h, "\149") self.parent:drawTextBox(x-1, y, 1, h, "\149")
self.parent:drawBackgroundBox(x-1, y, 1, h, borderColors["left"]) self.parent:drawBackgroundBox(x-1, y, 1, h, self.bgColor)
self.parent:drawForegroundBox(x-1, y, 1, h, self.parent.bgColor) self.parent:drawForegroundBox(x-1, y, 1, h, borderColors["left"])
end end
if(borderColors["left"]~=false)and(borderColors["top"]~=false)then if(borderColors["left"]~=false)and(borderColors["top"]~=false)then
self.parent:drawTextBox(x-1, y-1, 1, 1, "\151") self.parent:drawTextBox(x-1, y-1, 1, 1, "\151")
self.parent:drawBackgroundBox(x-1, y-1, 1, 1, borderColors["left"]) self.parent:drawBackgroundBox(x-1, y-1, 1, 1, self.bgColor)
self.parent:drawForegroundBox(x-1, y-1, 1, 1, self.parent.bgColor) self.parent:drawForegroundBox(x-1, y-1, 1, 1, borderColors["left"])
end end
if(borderColors["top"]~=false)then if(borderColors["top"]~=false)then
self.parent:drawTextBox(x, y-1, w, 1, "\131") self.parent:drawTextBox(x, y-1, w, 1, "\131")
self.parent:drawBackgroundBox(x, y-1, w, 1, borderColors["top"]) self.parent:drawBackgroundBox(x, y-1, w, 1, self.bgColor)
self.parent:drawForegroundBox(x, y-1, w, 1, self.parent.bgColor) self.parent:drawForegroundBox(x, y-1, w, 1, borderColors["top"])
end end
if(borderColors["top"]~=false)and(borderColors["right"]~=false)then if(borderColors["top"]~=false)and(borderColors["right"]~=false)then
self.parent:drawTextBox(x+w, y-1, 1, 1, "\148") self.parent:drawTextBox(x+w, y-1, 1, 1, "\148")
self.parent:drawForegroundBox(x+w, y-1, 1, 1, borderColors["right"]) self.parent:drawForegroundBox(x+w, y-1, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x+w, y-1, 1, 1, borderColors["right"])
end end
if(borderColors["right"]~=false)then if(borderColors["right"]~=false)then
self.parent:drawTextBox(x+w, y, 1, h, "\149") self.parent:drawTextBox(x+w, y, 1, h, "\149")
self.parent:drawForegroundBox(x+w, y, 1, h, borderColors["right"]) self.parent:drawForegroundBox(x+w, y, 1, h, self.bgColor)
self.parent:drawBackgroundBox(x+w, y, 1, h, borderColors["right"])
end end
if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then
self.parent:drawTextBox(x+w, y+h, 1, 1, "\129") self.parent:drawTextBox(x+w, y+h, 1, 1, "\133")
self.parent:drawForegroundBox(x+w, y+h, 1, 1, borderColors["right"]) self.parent:drawForegroundBox(x+w, y+h, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x+w, y+h, 1, 1, borderColors["right"])
end end
if(borderColors["bottom"]~=false)then if(borderColors["bottom"]~=false)then
self.parent:drawTextBox(x, y+h, w, 1, "\131") self.parent:drawTextBox(x, y+h, w, 1, "\143")
self.parent:drawForegroundBox(x, y+h, w, 1, borderColors["bottom"]) self.parent:drawForegroundBox(x, y+h, w, 1, self.bgColor)
self.parent:drawBackgroundBox(x, y+h, w, 1, borderColors["bottom"])
end end
if(borderColors["bottom"]~=false)and(borderColors["left"]~=false)then if(borderColors["bottom"]~=false)and(borderColors["left"]~=false)then
self.parent:drawTextBox(x-1, y+h, 1, 1, "\130") self.parent:drawTextBox(x-1, y+h, 1, 1, "\138")
self.parent:drawForegroundBox(x-1, y+h, 1, 1, borderColors["left"]) self.parent:drawForegroundBox(x-1, y+h, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x-1, y+h, 1, 1, borderColors["left"])
end end
end end
draw = false draw = false

View File

@@ -181,7 +181,7 @@ return function(drawTerm)
isBlinking = terminal.getCursorBlink() isBlinking = terminal.getCursorBlink()
end end
terminal.setCursorBlink(false) terminal.setCursorBlink(false)
if(mirrorTerm~=nil)then terminal.setCursorBlink(false) end if(mirrorTerm~=nil)then mirrorTerm.setCursorBlink(false) end
for n = 1, height do for n = 1, height do
terminal.setCursorPos(1, n) terminal.setCursorPos(1, n)
terminal.blit(cacheT[n], cacheFG[n], cacheBG[n]) terminal.blit(cacheT[n], cacheFG[n], cacheBG[n])

View File

@@ -0,0 +1,199 @@
-- Right now this doesn't support scroll(n)
-- Because this lbirary is mainly made for basalt - it doesn't need scroll support, maybe i will add it in the future
local tHex = {
[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 type,len,rep,sub = type,string.len,string.rep,string.sub
return function (monitorNames)
local monitors = {}
for k,v in pairs(monitorNames)do
monitors[k] = {}
for a,b in pairs(v)do
local mon = peripheral.wrap(b)
if(mon==nil)then
error("Unable to find monitor "..b)
end
monitors[k][a] = mon
monitors[k][a].name = b
end
end
local x,y,monX,monY,monW,monH,w,h = 1,1,1,1,0,0,0,0
local blink,scale = false,1
local fg,bg = colors.white,colors.black
local function calcSize()
local maxW,maxH = 0,0
for k,v in pairs(monitors)do
local _maxW,_maxH = 0,0
for a,b in pairs(v)do
local nw,nh = b.getSize()
_maxW = _maxW + nw
_maxH = nh > _maxH and nh or _maxH
end
maxW = maxW > _maxW and maxW or _maxW
maxH = maxH + _maxH
end
w,h = maxW,maxH
end
calcSize()
local function calcPosition()
local relY = 0
local mX,mY = 0,0
for k,v in pairs(monitors)do
local relX = 0
local _mh = 0
for a,b in pairs(v)do
local mw,mh = b.getSize()
if(x-relX>=1)and(x-relX<=mw)then
mX = a
end
b.setCursorPos(x-relX, y-relY)
relX = relX + mw
if(_mh<mh)then _mh = mh end
end
if(y-relY>=1)and(y-relY<=_mh)then
mY = k
end
relY = relY + _mh
end
monX,monY = mX,mY
end
calcPosition()
local function call(f, ...)
local t = {...}
return function()
for k,v in pairs(monitors)do
for a,b in pairs(v)do
b[f](table.unpack(t))
end
end
end
end
local function cursorBlink()
call("setCursorBlink", false)()
if not(blink)then return end
if(monitors[monY]==nil)then return end
local mon = monitors[monY][monX]
if(mon==nil)then return end
mon.setCursorBlink(blink)
end
local function blit(text, tCol, bCol)
if(monitors[monY]==nil)then return end
local mon = monitors[monY][monX]
if(mon==nil)then return end
mon.blit(text, tCol, bCol)
local mW, mH = mon.getSize()
if(len(text)+x>mW)then
local monRight = monitors[monY][monX+1]
if(monRight~=nil)then
monRight.blit(text, tCol, bCol)
monX = monX + 1
x = x + len(text)
end
end
calcPosition()
end
return {
clear = call("clear"),
setCursorBlink = function(_blink)
blink = _blink
cursorBlink()
end,
getCursorBlink = function()
return blink
end,
getCursorPos = function()
return x, y
end,
setCursorPos = function(newX,newY)
x, y = newX, newY
calcPosition()
cursorBlink()
end,
setTextScale = function(_scale)
call("setTextScale", _scale)()
calcSize()
calcPosition()
scale = _scale
end,
getTextScale = function()
return scale
end,
blit = function(text,fgCol,bgCol)
blit(text,fgCol,bgCol)
end,
write = function(text)
text = tostring(text)
local l = len(text)
blit(text, rep(tHex[fg], l), rep(tHex[bg], l))
end,
getSize = function()
return w,h
end,
setBackgroundColor = function(col)
call("setBackgroundColor", col)()
bg = col
end,
setTextColor = function(col)
call("setTextColor", col)()
fg = col
end,
calculateClick = function(name, xClick, yClick)
local relY = 0
for k,v in pairs(monitors)do
local relX = 0
local maxY = 0
for a,b in pairs(v)do
local wM,hM = b.getSize()
if(b.name==name)then
return xClick + relX, yClick + relY
end
relX = relX + wM
if(hM > maxY)then maxY = hM end
end
relY = relY + maxY
end
return xClick, yClick
end,
}
end

View File

@@ -7,9 +7,17 @@ function process:new(path, window, ...)
local newP = setmetatable({ path = path }, { __index = self }) local newP = setmetatable({ path = path }, { __index = self })
newP.window = window newP.window = window
newP.processId = processId newP.processId = processId
if(type(path)=="string")then
newP.coroutine = coroutine.create(function() newP.coroutine = coroutine.create(function()
shell.execute(path, table.unpack(args)) shell.execute(path, table.unpack(args))
end) end)
elseif(type(path)=="function")then
newP.coroutine = coroutine.create(function()
path(table.unpack(args))
end)
else
return
end
processes[processId] = newP processes[processId] = newP
processId = processId + 1 processId = processId + 1
return newP return newP
@@ -22,7 +30,6 @@ function process:resume(event, ...)
self.filter=nil self.filter=nil
end end
local ok, result = coroutine.resume(self.coroutine, event, ...) local ok, result = coroutine.resume(self.coroutine, event, ...)
self.window = term.current()
if ok then if ok then
self.filter = result self.filter = result
else else

View File

@@ -5,15 +5,16 @@ local utils = require("utils")
local log = require("basaltLogs") local log = require("basaltLogs")
local uuid = utils.uuid local uuid = utils.uuid
local createText = utils.createText local createText = utils.createText
local count = utils.tableCount
local baseTerm = term.current() local baseTerm = term.current()
local version = "1.6.0" local version = "1.6.2"
local debugger = true local debugger = true
local projectDirectory = fs.getDir(table.pack(...)[2] or "") local projectDirectory = fs.getDir(table.pack(...)[2] or "")
local activeKey, frames, monFrames, variables, schedules = {}, {}, {}, {}, {} local activeKey, frames, monFrames, monGroups, variables, schedules = {}, {}, {}, {}, {}, {}
local mainFrame, activeFrame, focusedObject, updaterActive local mainFrame, activeFrame, focusedObject, updaterActive
local basalt = {} local basalt = {}
@@ -74,12 +75,19 @@ local bInstance = {
end, end,
getMonitorFrame = function(name) getMonitorFrame = function(name)
return monFrames[name] return monFrames[name] or monGroups[name][1]
end, end,
setMonitorFrame = function(name, frame) setMonitorFrame = function(name, frame, isGroupedMon)
if(mainFrame == frame)then mainFrame = nil end if(mainFrame == frame)then mainFrame = nil end
monFrames[name] = frame if(isGroupedMon)then
monGroups[name] = {frame, sides}
else
monFrames[name] = frame
end
if(frame==nil)then
monGroups[name] = nil
end
end, end,
getBaseTerm = function() getBaseTerm = function()
@@ -145,6 +153,10 @@ local function drawFrames()
v:draw() v:draw()
v:updateTerm() v:updateTerm()
end end
for _,v in pairs(monGroups)do
v[1]:draw()
v[1]:updateTerm()
end
end end
local function basaltUpdateEvent(event, p1, p2, p3, p4) local function basaltUpdateEvent(event, p1, p2, p3, p4)
@@ -169,8 +181,15 @@ local function basaltUpdateEvent(event, p1, p2, p3, p4)
monFrames[p1]:mouseHandler(1, p2, p3, true) monFrames[p1]:mouseHandler(1, p2, p3, true)
activeFrame = monFrames[p1] activeFrame = monFrames[p1]
end end
if(count(monGroups)>0)then
for k,v in pairs(monGroups)do
v[1]:mouseHandler(1, p2, p3, true, p1)
end
end
end end
if(event == "char")then if(event == "char")then
if(activeFrame~=nil)then if(activeFrame~=nil)then
activeFrame:charHandler(p1) activeFrame:charHandler(p1)

View File

@@ -61,7 +61,7 @@ return function(name)
textX = tostring(val):len() + 1 textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1) wIndex = math.max(1, textX-self:getWidth()+1)
local obx, oby = self:getAnchorPosition() local obx, oby = self:getAnchorPosition()
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self.height/2), self.fgColor) self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor)
end end
end end
self:updateDraw() self:updateDraw()
@@ -179,13 +179,15 @@ return function(name)
local obx, oby = self:getAnchorPosition() local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue()) local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1) local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then local inpX = self:getX()
cursorX = self.x + w - 1 if (cursorX > inpX + w - 1) then
cursorX = inpX + w - 1
end end
if (self.parent ~= nil) then if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor) self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end end
self:updateDraw()
internalValueChange = false internalValueChange = false
return true return true
end end
@@ -249,11 +251,22 @@ return function(name)
wIndex = 1 wIndex = 1
end end
end end
self.parent:setCursor(true, obx + textX-1, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor) self.parent:setCursor(true, ax + textX - wIndex, ay+math.max(math.ceil(h/2-1, 1)), self.fgColor)
return true return true
end end
end, end,
dragHandler = function(self, btn, x, y, xOffset, yOffset)
if(self:isFocused())then
if(self:isCoordsInObject(x, y))then
if(base.dragHandler(self, btn, x, y, xOffset, yOffset))then
return true
end
end
self.parent:removeFocusedObject()
end
end,
eventHandler = function(self, event, paste, p2, p3, p4) eventHandler = function(self, event, paste, p2, p3, p4)
if(base.eventHandler(self, event, paste, p2, p3, p4))then if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then if(event=="paste")then
@@ -333,7 +346,7 @@ return function(name)
end end
end end
if(self:isFocused())then if(self:isFocused())then
self.parent:setCursor(true, obx + textX - wIndex, oby+math.max(math.ceil(self:getHeight()/2-1, 1)), self.fgColor) self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor)
end end
end end
end end
@@ -347,6 +360,7 @@ return function(name)
self.parent:addEvent("key", self) self.parent:addEvent("key", self)
self.parent:addEvent("char", self) self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self) self.parent:addEvent("other_event", self)
self.parent:addEvent("mouse_drag", self)
end end
end, end,
} }

View File

@@ -29,3 +29,4 @@
- [Button coloring](tips/buttonColoring.md) - [Button coloring](tips/buttonColoring.md)
- [Designing/Animating](tips/design.md) - [Designing/Animating](tips/design.md)
- [Dynamic Values](tips/dynamicvalues.md) - [Dynamic Values](tips/dynamicvalues.md)
- [XML](tips/xml.md)

487
docs/installer.lua Normal file
View File

@@ -0,0 +1,487 @@
--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
local maxCoWorker = 3
local recipeList = {}
local craftingQueue = {}
local bridge = peripheral.find("rsBridge")
local w, h = term.getSize()
local main = basalt.createFrame()
local home = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-2)
local recipes = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide()
local log = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide()
local menuBar = main:addMenubar():addItem("Home"):addItem("Recipes"):addItem("Log"):setBackground(colors.gray):setSize(w, 1):setSpace(6):setScrollable():show()
menuBar:onChange(function(self)
home:hide()
recipes:hide()
log:hide()
if(self:getValue().text=="Home")then
home:show()
elseif(self:getValue().text=="Recipes")then
recipes:show()
elseif(self:getValue().text=="Log")then
log:show()
end
end)
local function buttonVisuals(btn)
btn:onClick(basalt.schedule(function() btn:setBackground(colors.black) btn:setForeground(colors.lightGray) os.sleep(0.1) btn:setBackground(colors.gray) btn:setForeground(colors.black) end))
end
local coworkerCount = home:addLabel():setText(maxCoWorker):setPosition(45,2):show()
home:addLabel():setText("Co-Worker:"):setPosition(32,2):show()
buttonVisuals(home:addButton():setText(">"):setSize(1,1):setPosition(47,2):onClick(function() if(maxCoWorker<100)then maxCoWorker = maxCoWorker+1 end coworkerCount:setText(maxCoWorker) end):show())
buttonVisuals(home:addButton():setText("<"):setSize(1,1):setPosition(43,2):onClick(function() if(maxCoWorker>1)then maxCoWorker = maxCoWorker-1 end coworkerCount:setText(maxCoWorker) end):show())
local logList = log:addList():setPosition(2,2):setSize(w-2,h-3):setScrollable(false):show()
local jobList = home:addList():setPosition(20,4):setSize(30,10):show()
local rList = recipes:addList():setPosition(13,2):setSize(38,16):show()
local function logging(text)
logList:addItem(text)
if(logList:getItemCount()>h-3)then
logList:removeItem(1)
end
end
logging("Loading autocrafter...")
function SaveToFile()
local file = io.open("recipes", "wb")
local sel = rList:getItemIndex()
rList:clear()
for _,v in pairs(recipeList)do
if(v.useDmg)then
file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|true|", "\n")
else
file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|false|", "\n")
end
rList:addItem(v.minAmount.."x "..v.name..":"..v.damage, nil, nil, v)
end
rList:selectItem(sel)
file:close()
end
buttonVisuals(recipes:addButton():setPosition(2,2):setText("Remove"):setSize(8,1):onClick(function()
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
table.remove(recipeList, k)
logging("Removed recipe: "..v.name..":"..v.damage)
SaveToFile()
end
end
end
end))
local changeAmn = recipes:addInput():setPosition(4,4):setSize(5,1):setInputType("number"):setForeground(colors.black):setDefaultText("32", colors.black):onChange(function(self)
local val = tonumber(self:getValue()) or 32
if(val<0)then
self:setValue(0)
end
end)
buttonVisuals(recipes:addButton():setPosition(2,4):setSize(1,1):setText("-"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = v.minAmount - val
if(v.minAmount < 0)then v.minAmount = 0 end
SaveToFile()
end
end
end
end
end))
buttonVisuals(recipes:addButton():setPosition(10,4):setSize(1,1):setText("+"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = v.minAmount + val
SaveToFile()
end
end
end
end
end))
buttonVisuals(recipes:addButton():setPosition(2,6):setSize(8,1):setText("Set"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = val
SaveToFile()
end
end
end
end
end))
local rItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,6):setMoveable(true):setBar("Remove Item", colors.black, colors.lightGray):showBar():hide()
rItemFrame:addButton():setPosition(1,1):setAnchor("topRight"):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() rItemFrame:hide() end):show()
rItemFrame:addLabel():setText("Item ID:"):setPosition(2,3):show()
local ritemId = rItemFrame:addInput("itemid"):setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray):show()
rItemFrame:addButton():setPosition(-7,0):setAnchor("bottomRight"):setSize(8,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Remove"):onClick(function()
local id = ritemId:getValue()
for k,v in pairs(recipeList)do
if(v.name==id)then
table.remove(recipeList, k)
logging("Removed recipe: "..v.name..":"..v.damage)
end
end
SaveToFile()
end)
local aItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,12):setMoveable(true):setBar("Add Item", colors.black, colors.lightGray):showBar():hide()
aItemFrame:addLabel():setText("Item ID:"):setPosition(2,3)
aItemFrame:addLabel():setText("Damage:"):setPosition(2,5)
aItemFrame:addLabel():setText("Count:"):setPosition(2,7)
aItemFrame:addLabel():setText("Max:"):setPosition(2,9)
aItemFrame:addLabel():setText("Use Damage:"):setAnchor("bottomLeft"):setPosition(4,0)
local itemId = aItemFrame:addInput():setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray)
local itemDamage = aItemFrame:addInput():setPosition(12,5):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray)
local itemCount = aItemFrame:addInput():setPosition(12,7):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("64", colors.gray)
local itemMaxCount = aItemFrame:addInput():setPosition(12,9):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray)
local useDamage = aItemFrame:addCheckbox():setAnchor("bottomLeft"):setPosition(2,0):setBackground(colors.black):setForeground(colors.lightGray):setValue(true)
aItemFrame:addButton():setAnchor("topRight"):setPosition(1,1):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() aItemFrame:hide() end)
aItemFrame:addButton():setAnchor("bottomRight"):setPosition(-4,0):setSize(5,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Add"):onClick(function()
local id = itemId:getValue()
local dmg = itemDamage:getValue() == "" and 0 or itemDamage:getValue()
local count = itemCount:getValue() == "" and 64 or itemCount:getValue()
local maxCount = itemMaxCount:getValue() == "" and 0 or itemMaxCount:getValue()
local usedamage = useDamage:getValue() or true
if(id~="")then
local itemExist = false
for k,v in pairs(recipeList)do
if(v.name==id)then
if(usedamage)then
if(v.damage==dmg)then
itemExist = true
v.minAmount = count or 64
v.maxCraftAmount = maxCount or 0
logging("Edited recipe: "..(count).."x "..id..":"..dmg)
end
else
itemExist = true
v.minAmount = count or 64
v.maxCraftAmount = maxCount or 0
logging("Edited recipe: "..(count).."x "..id..":"..dmg)
end
end
end
if(itemExist == false)then
table.insert(recipeList, {name = id, damage = dmg or 0, minAmount = count, maxCraftAmount = maxCount or 0, useDmg = usedamage, fails = 0, timer = 0})
logging("Added recipe: "..(count).."x "..id..":"..dmg)
end
SaveToFile()
else
logging("Please set a ID.")
end
end)
buttonVisuals(home:addButton():setText("Add Item"):setSize(12,3):setPosition(2,6):onClick(function() aItemFrame:show() aItemFrame:setFocus() end):show())
buttonVisuals(home:addButton():setText("Remove Item"):setSize(12,3):setPosition(2,10):onClick(function() rItemFrame:show() rItemFrame:setFocus() end):show())
local function StringSeperate(str, seperator)
local words = {}
local word = ""
if(string.sub(str, str:len(), str:len())~=seperator)then
str = str..""..seperator
end
for x=1,str:len() do
local s = string.sub(str,x,x)
if(s==seperator)then
table.insert(words, word)
word = ""
else
word = word..s
end
end
return words
end
if not(fs.exists("recipes"))then
fs.open("recipes","w").close()
end
local f = fs.open("recipes", "r")
for line in f.readLine do
local tab = StringSeperate(line, "|")
if(tab[1]~=nil)and(tab[2]~=nil)and(tab[3]~=nil)and(tab[4]~=nil)and(tab[5]~=nil)then
logging("Registered recipe: "..tab[3].."x "..tab[1]..":"..tab[2])
local recipe = {name=tab[1],damage=tonumber(tab[2]),minAmount=tonumber(tab[3]),maxCraftAmount=tonumber(tab[4]),fails=0,timer=0}
if(tab[5]=="true")then
recipe.useDmg=true
else
recipe.useDmg=false
end
rList:addItem(recipe.minAmount.."x "..recipe.name..":"..recipe.damage, nil, nil, recipe)
table.insert(recipeList, recipe)
end
end
f.close()
local function findKeyWithItemName(table, itemname, damage)
for k,v in pairs(table)do
if(v.name==itemname)and(v.damage == damage)then
return k
end
end
return nil
end
local scanChestBtn = home:addButton("scanChest"):setText("Scan Chest"):setSize(12,3):setPosition(2,2):show()
local function checkChestForNewEntrys()
scanChestBtn:setText("Scanning..")
local inventory = peripheral.find("minecraft:chest")
local items = {}
local itemAmounts = {}
local somethingChanged = false
if(inventory~=nil)then
for x=1,inventory.size(), 1 do
local item = inventory.getItemDetail(x)
if(item~=nil)then
if(item.damage==nil)then item.damage = 0 end
table.insert(items, item)
end
os.sleep(0.1)
end
else
logging("No chest available!")
end
if(#items > 0)then
for _,v in pairs(items)do
local key = findKeyWithItemName(itemAmounts, v.name, v.damage)
if(key~=nil)then
itemAmounts[key].count = itemAmounts[key].count + v.count
else
table.insert( itemAmounts, {name=v.name, damage=v.damage, count = v.count})
end
end
end
if(#itemAmounts > 0)then
for _,v in pairs(itemAmounts)do
local key = findKeyWithItemName(recipeList, v.name, v.damage)
if(key~=nil)then
if(recipeList[key].minAmount ~= v.count)then
logging("Edited recipe: "..v.name.. ":"..v.damage.." new count: "..v.count)
end
somethingChanged = true
recipeList[key].minAmount = v.count
else
table.insert( recipeList, {name=v.name, damage=v.damage, minAmount = v.count, maxCraftAmount = 0, useDmg = true, fails = 0, timer = 0})
somethingChanged = true
logging("Registered recipe: "..v.count.."x "..v.name.. ":"..v.damage)
end
end
if(somethingChanged)then
SaveToFile()
end
end
scanChestBtn:setText("Scan Chest")
logging("Scanning chest done.")
end
local chestScanThread = main:addThread("chestScanThread")
buttonVisuals(scanChestBtn:onClick(function() chestScanThread:start(checkChestForNewEntrys) end))
local function GetAmount(itemAmount, recipe)
local amount = 0
if(itemAmount < recipe.minAmount)then
if(recipe.maxCraftAmount > 0)then
if(recipe.minAmount-itemAmount > recipe.maxCraftAmount)then
amount = recipe.maxCraftAmount
else
amount = recipe.minAmount-itemAmount
end
else
amount = recipe.minAmount-itemAmount
end
end
return amount
end
function GetRecipeKey(pattern)
for k,v in pairs(recipeList)do
if(v.name == pattern.name)then
if(pattern.damage==nil)then return k end
if(v.useDmg)then
if(v.damage == pattern.damage)then
return k
end
else
return k
end
end
end
return nil
end
local function CheckCraftingRecipe(recipe)
local pattern = bridge.getItem({name=recipe.name})
local item = {pattern=pattern, amount=0}
if(pattern~=nil)then
local storedAmount = pattern.amount
local neededItemAmount = GetAmount(storedAmount, recipe)
if(neededItemAmount > 0)then
item.amount = neededItemAmount
table.insert(craftingQueue, item)
return true
end
end
return false
end
function RemoveRecipe(item)
local key = -1
for k,v in pairs(recipeList)do
if(v.name == item.name)and(v.damage== item.damage)then
key = k
end
end
if(key>=0)then
table.remove(recipeList, key)
end
SaveToFile()
end
local function FindKeyInTable(table, item)
for k,v in pairs(table)do
if(v==item)then
return k
end
end
return nil
end
local function CheckAllRecipes()
for _,v in pairs(recipeList)do
if(type(v)=="table")then
CheckCraftingRecipe(v)
end
end
end
local function jobCrafting(coworker, item)
if(jobList:getItem(coworker)~=nil)then
jobList:editItem(coworker, "Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", ""))
else
jobList:addItem("Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", ""))
end
end
local function jobDone(coworker)
if(jobList:getItem(coworker)~=nil)then
jobList:editItem(coworker, "Co-Worker "..coworker..": waiting...")
else
jobList:addItem("Co-Worker "..coworker..": waiting...")
end
end
local coWorkerId = 1
local function UpdateCraftingQueue()
while(#craftingQueue > 0)do
local activeCoWorkers = {}
local craftingQueuesToRemove = {}
for _,v in pairs(craftingQueue)do
if(#activeCoWorkers+1 <= maxCoWorker)then
local stack = v.pattern
local recipeKey = GetRecipeKey(stack)
local waittimer = 0
local multiplier = 1
if(recipeList[recipeKey].fails > 0)and(recipeList[recipeKey].fails <=10)then
multiplier = recipeList[recipeKey].fails
elseif(recipeList[recipeKey].fails > 10)then
multiplier = 20
end
waittimer = multiplier * 30
if(os.clock()>=recipeList[recipeKey].timer+waittimer)then
if not(bridge.isItemCrafting(stack.name))then
local currentItemState = {item=stack, curAmount = stack.count, amountToCraft = v.amount}
if(bridge.isItemCraftable({name=stack.name}))then
local task, errormsg = bridge.craftItem({name=stack.name, count = v.amount})
if(task)then
logging("Sheduled Task: "..v.amount.." ("..stack.name..") "..stack.displayName:gsub(" ", ""))
jobCrafting(coWorkerId, currentItemState)
currentItemState.coWorker = coWorkerId
coWorkerId = coWorkerId + 1
if(coWorkerId > maxCoWorker)then coWorkerId = 1 end
table.insert(activeCoWorkers, currentItemState)
recipeList[recipeKey].fails = 0
else
logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", ""))
logging("Not enough materials!")
recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1
recipeList[recipeKey].timer = os.clock()
end
else
logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", ""))
logging("No pattern available!")
recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1
recipeList[recipeKey].timer = os.clock()
end
end
end
table.insert(craftingQueuesToRemove, v)
end
end
if(#craftingQueuesToRemove > 0)then
for _,v in pairs(craftingQueuesToRemove)do
local id = FindKeyInTable(craftingQueue, v)
table.remove(craftingQueue, id)
end
end
while(#activeCoWorkers > 0)do
local finishedCoworker = {}
for _,v in pairs(activeCoWorkers)do
if not(bridge.isItemCrafting(v.item.name))then
logging("Task done: "..v.amountToCraft.."x ("..v.item.name..") "..v.item.displayName:gsub(" ", ""))
table.insert(finishedCoworker, v)
end
end
if(#finishedCoworker>0)then
for _,v in pairs(finishedCoworker)do
local id = FindKeyInTable(activeCoWorkers, v)
table.remove(activeCoWorkers, id)
jobDone(v.coWorker)
end
end
os.sleep(0.75)
end
os.sleep(0.75)
end
end
main:addThread("craftingThread"):start(function() while true do CheckAllRecipes() os.sleep(1) UpdateCraftingQueue() os.sleep(1) end end)
logging("Autocrafter successfully loaded!")
basalt.autoUpdate()

View File

@@ -14,7 +14,7 @@ Changes the background color while the animation is running
```lua ```lua
local mainFrame = basalt.createFrame() local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate") local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play() local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play()
``` ```
```xml ```xml
<animation object="buttonToAnimate" play="true"> <animation object="buttonToAnimate" play="true">

View File

@@ -14,7 +14,7 @@ Changes the text while animation is running
```lua ```lua
local mainFrame = basalt.createFrame() local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate") local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText({"i", "am", "groot"}, 2):play() local aAnimation = mainFrame:addAnimation():setObject(testButton):changeText(2, 0, "i", "am", "groot"):play()
``` ```
```xml ```xml
<animation object="buttonToAnimate" play="true"> <animation object="buttonToAnimate" play="true">

View File

@@ -14,7 +14,7 @@ Changes the text color while the animation is running
```lua ```lua
local mainFrame = basalt.createFrame() local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate") local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2):play() local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor(2, 0, colors.red, colors.yellow, colors.green):play()
``` ```
```xml ```xml
<animation object="buttonToAnimate" play="true"> <animation object="buttonToAnimate" play="true">

View File

@@ -24,13 +24,13 @@ end)
and this would be the xml way: and this would be the xml way:
```lua ```lua
local main = basalt.createFrame():addLayout("example.xml")
basalt.setVariable("buttonClick", function(self,event,button,x,y) basalt.setVariable("buttonClick", function(self,event,button,x,y)
if(event=="mouse_click")and(button==1)then if(event=="mouse_click")and(button==1)then
basalt.debug("Left mousebutton got clicked!") basalt.debug("Left mousebutton got clicked!")
end end
end) end)
local main = basalt.createFrame():addLayout("example.xml")
``` ```
```xml ```xml
<button onClick="buttonClick" text="Click" /> <button onClick="buttonClick" text="Click" />

View File

@@ -0,0 +1,18 @@
## setSymbol
Changes the checkbox symbol, default is "\42"
#### Parameters:
1. `string` symbol
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new checkbox and changes the symbol to o
```lua
local main = basalt.createFrame()
local checkbox = main:addCheckbox():setSymbol("o")
```
```xml
<checkbox symbol="o" />
```

View File

@@ -10,6 +10,7 @@ some special functionality to create very advanced programs.
|[setBarTextAlign](objects/Frame/setBarTextAlign.md)|Sets the top bars text align - deprecated |[setBarTextAlign](objects/Frame/setBarTextAlign.md)|Sets the top bars text align - deprecated
|[showBar](objects/Frame/showBar.md)|Shows the top bar - deprecated |[showBar](objects/Frame/showBar.md)|Shows the top bar - deprecated
|[setMonitor](objects/Frame/setMonitor.md)|Sets the frame to be a monitor frame (only for base frames) |[setMonitor](objects/Frame/setMonitor.md)|Sets the frame to be a monitor frame (only for base frames)
|[setMonitorScale](objects/Frame/setMonitorScale.md)|Sets the monitor scale (same as monitor.setTextScale)
|[setMirror](objects/Frame/setMirror.md)|Sets the frame to mirror onto a monitor (only for base frames) |[setMirror](objects/Frame/setMirror.md)|Sets the frame to mirror onto a monitor (only for base frames)
|[getObject](objects/Frame/getObject.md)|Returns the object by its name (or id) |[getObject](objects/Frame/getObject.md)|Returns the object by its name (or id)
|[removeObject](objects/Frame/removeObject.md)|Removes the object by its name (or id) |[removeObject](objects/Frame/removeObject.md)|Removes the object by its name (or id)

View File

@@ -1,8 +1,5 @@
## removeFocusedObject ## removeFocusedObject
Removes the focus of the supplied object Removes the currently focused object of that frame
#### Parameters:
1. `object` The child object to remove focus from
#### Returns: #### Returns:
1. `frame` The frame being used 1. `frame` The frame being used
@@ -10,7 +7,9 @@ Removes the focus of the supplied object
#### Usage: #### Usage:
* Creates a new button then removes the focus from that button when clicking on it * Creates a new button then removes the focus from that button when clicking on it
```lua ```lua
local aButton = myFrame:addButton():setFocus():onClick(function() local main = basalt.createFrame()
myFrame:removeFocusedObject(aButton) local input = main:addInput():setFocus()
local aButton = main:addButton():onClick(function()
main:removeFocusedObject()
end) end)
``` ```

View File

@@ -2,7 +2,7 @@
Removes a child object from the frame Removes a child object from the frame
#### Parameters: #### Parameters:
1. `string` The name of the child object 1. `string|object` The name of the child object or the object itself
#### Returns: #### Returns:
1. `boolean` Whether the object with the given name was properly removed 1. `boolean` Whether the object with the given name was properly removed
@@ -10,6 +10,9 @@ Removes a child object from the frame
#### Usage: #### Usage:
* Adds a button with the id "myFirstButton", then removes it with the aforementioned id * Adds a button with the id "myFirstButton", then removes it with the aforementioned id
```lua ```lua
myFrame:addButton("myFirstButton") local main = basalt.createFrame()
myFrame:removeObject("myFirstButton") main:addButton("myFirstButton"):setText("Close")
:onClick(function(self)
main:removeObject("myFirstButton") -- or main:removeObject(self)
end)
``` ```

View File

@@ -1,8 +1,9 @@
## setMonitor ## setMonitor
Sets this frame as a monitor frame You can set base frames as monitor frames, don't try to use setMonitor on sub frames
#### Parameters: #### Parameters:
1. `string` The monitor name ("right", "left",... "monitor_1", "monitor_2",...) 1. `string|table` The monitor name ("right", "left",... "monitor_1", "monitor_2",...) OR a table to create multi-monitors (see example)
2. `number` optional - a number between 0.5 to 5 which sets the monitor scale
#### Returns: #### Returns:
1. `frame` The frame being used 1. `frame` The frame being used
@@ -12,8 +13,29 @@ Sets this frame as a monitor frame
```lua ```lua
local mainFrame = basalt.createFrame() local mainFrame = basalt.createFrame()
local monitorFrame = basalt.createFrame():setMonitor("right") local monitorFrame = basalt.createFrame():setMonitor("right")
monitorFrame:setBar("Monitor 1"):showBar() monitorFrame:addLabel():setText("Hellooo!")
``` ```
```xml ```xml
<frame monitor="right"></frame> <frame monitor="right"></frame>
```
* Here is a example on how to create mutlimonitors. You always have to start on the top left of your screen and go to the bottom right, which means in this example
monitor_1 is always your most top left monitor while monitor_6 is your most bottom right monitor.
Table structure:
local monitors = {
[y1] = {x1,x2,x3},
[y2] = {x1,x2,x3}
...
}
```lua
local monitors = {
{"monitor_1", "monitor_2", "monitor_3"},
{"monitor_4", "monitor_5", "monitor_6"}
}
local mainFrame = basalt.createFrame()
local monitorFrame = basalt.createFrame():setMonitor(monitors)
monitorFrame:addLabel():setText("Hellooo!")
``` ```

View File

@@ -0,0 +1,15 @@
## setMonitorScale
Changes the scale on the the monitor which the frame is attached to
#### Parameters:
1. `number` A number from 0.5 to 5
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame, sets the frame as a monitor frame and changes the monitor scale
```lua
local myFrame = basalt.createFrame()setMonitor("left"):setMonitorScale(2)
myFrame:addLabel("Monitor scale is bigger")
```

View File

@@ -10,7 +10,7 @@ loads a default .nfp file into the object.
#### Usage: #### Usage:
* Creates a default image and loads a test.nfp file * Creates a default image and loads a test.nfp file
```lua ```lua
local mainFrame = basalt.createFrame():show() local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.nfp") local aImage = mainFrame:addImage():loadImage("test.nfp")
``` ```
```xml ```xml

View File

@@ -8,6 +8,6 @@ The fontsize feature is calculated by bigfonts, a library made by Wojbie (http:/
| | | | | |
|---|---| |---|---|
|[setText](objects/Input/setInputType.md)|Sets the input type |[setText](objects/Label/setText.md)|Sets the input type
|[setFontSize](objects/Input/getInputType.md)|Returns the input type |[setFontSize](objects/Label/setFontSize.md)|Returns the input type
|[getFontSize](objects/Input/setDefaultText.md)|Sets the default text |[getFontSize](objects/Label/getFontSize.md)|Sets the default text

View File

@@ -13,8 +13,8 @@ Adds a item into the list
#### Usage: #### Usage:
* Creates a default menubar with 3 entries * Creates a default menubar with 3 entries
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -7,8 +7,8 @@ Removes all items.
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and removes them immediatley. Which makes no sense. * Creates a default menubar with 3 entries and removes them immediatley. Which makes no sense.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -14,8 +14,8 @@ Edits a item from the menubar
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and edits the second one. * Creates a default menubar with 3 entries and edits the second one.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -7,8 +7,8 @@ Returns all items as table
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and prints a table. * Creates a default menubar with 3 entries and prints a table.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -10,8 +10,8 @@ Returns a item by index
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and edits the second one. * Creates a default menubar with 3 entries and edits the second one.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMeubar() local aMenubar = main:addMeubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -7,8 +7,8 @@ Returns the current item count
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and prints the current item count. * Creates a default menubar with 3 entries and prints the current item count.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -7,8 +7,8 @@ returns the item index of the currently selected item
#### Usage: #### Usage:
* Creates a default menubar with 3 entries selects the second entry and prints the currently selected index. * Creates a default menubar with 3 entries selects the second entry and prints the currently selected index.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -7,8 +7,8 @@ Returns the current index offset
#### Usage: #### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3, also prints the current offset. * Creates a default menubar with 6 entries and sets the offset to 3, also prints the current offset.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry") :addItem("2. Entry")
:addItem("3. Entry") :addItem("3. Entry")

View File

@@ -10,8 +10,8 @@ Removes a item from the menubar
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and removes the second one. * Creates a default menubar with 3 entries and removes the second one.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -10,8 +10,8 @@ selects a item in the menubar (same as a player would click on a item)
#### Usage: #### Usage:
* Creates a default menubar with 3 entries and selects the second entry. * Creates a default menubar with 3 entries and selects the second entry.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -10,8 +10,8 @@ Sets the offset of the menubar (the same as you would scroll) - default is 0
#### Usage: #### Usage:
* Creates a default menubar with 6 entries and sets the offset to 3. * Creates a default menubar with 6 entries and sets the offset to 3.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry") :addItem("2. Entry")
:addItem("3. Entry") :addItem("3. Entry")

View File

@@ -10,8 +10,8 @@ Makes it possible to scroll while the mouse is over the menubar
#### Usage: #### Usage:
* Creates a new menubar and makes it scrollable * Creates a new menubar and makes it scrollable
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar():setScrollable(true) local aMenubar = main:addMenubar():setScrollable(true)
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry") :addItem("2. Entry")
:addItem("3. Entry") :addItem("3. Entry")

View File

@@ -11,8 +11,8 @@ Sets the background and the foreground of the item which is currently selected
#### Usage: #### Usage:
* Creates a default menubar with 4 entries and sets the selection background color to green. * Creates a default menubar with 4 entries and sets the selection background color to green.
```lua ```lua
local mainFrame = basalt.createFrame() local main = basalt.createFrame()
local aMenubar = mainFrame:addMenubar() local aMenubar = main:addMenubar()
:addItem("1. Entry") :addItem("1. Entry")
:addItem("2. Entry",colors.yellow) :addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green) :addItem("3. Entry",colors.yellow,colors.green)

View File

@@ -0,0 +1,27 @@
## setSpace
Sets the background and the foreground of the item which is currently selected
#### Parameters:
1. `number` The space you want between the entries
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default menubar with 4 entries and sets the space to 3.
```lua
local main = basalt.createFrame()
local aMenubar = main:addMenubar()
:addItem("1. Entry")
:addItem("2. Entry",colors.yellow)
:addItem("3. Entry",colors.yellow,colors.green)
:addItem("4. Entry")
:setSpace(3)
```
```xml
<menubar selectionBG="green" selectionFG="red" space="3">
<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>
</menubar>
```

View File

@@ -0,0 +1,5 @@
## getBackground
Returns the current background color
#### Returns:
1. `number` color

View File

@@ -0,0 +1,5 @@
## getForeground
Returns the current foreground color
#### Returns:
1. `number` color

View File

@@ -41,3 +41,24 @@ local button2 = main:addButton()
basalt.autoUpdate() basalt.autoUpdate()
``` ```
Also very interesting is a button where you are able to resize the frame just by dragging the button.
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local sub = main:addFrame():setSize(30,12):setMovable()
sub:addLabel():setText("Example Frame"):setSize("parent.w", 1):setBackground(colors.black):setForeground(colors.lightGray)
local dragButton = sub:addButton()
:setAnchor("bottomRight")
:setPosition(1,1)
:setSize(1,1)
:setText("/")
:onDrag(function(self, button, x, y, xOffset, yOffset)
sub:setSize(-xOffset, -yOffset, true)
end)
basalt.autoUpdate()
```

View File

@@ -0,0 +1,11 @@
## remove
Removes the object from it's parent frame. This won't 'destroy' the object, It will continue to exist as long as you still have pointers to it.
Here is a example on how a button will be fully removed from the memory:
```lua
local main = basalt.createFrame()
local button = main:addButton():setPosition(2,2):setText("Close")
button:remove()
button = nil
```

View File

@@ -1,108 +1,12 @@
Scrollbars are objects, the user can scroll vertically or horizontally, this will change a value, which you can access by :getValue().<br> 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) [Object](objects/Object.md) methods also apply for scrollbars.
## 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
| | |
|---|---|
|[setSymbol](objects/Slider/setSymbol.md)|Sets the slider symbol
|[setBackgroundSymbol](objects/Slider/setBackgroundSymbol.md)|Sets the background symbol
|[setBarType](objects/Slider/setBarType.md)|Sets the bar type (vertical or horizontal)
|[setMaxValue](objects/Slider/setMaxValue.md)|Sets the maximum value
|[setIndex](objects/Slider/setIndex.md)|Sets the current index
|[getIndex](objects/Slider/getIndex.md)|Returns the index

View File

@@ -0,0 +1,5 @@
## getIndex
Returns the current index
#### Returns:
1. `number` index

View File

@@ -0,0 +1,18 @@
## 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 main = basalt.createFrame()
local scrollbar = main:addScrollbar():setBackgroundSymbol("X")
```
```xml
<scrollbar backgroundSymbol="X" />
```

View File

@@ -0,0 +1,18 @@
## 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 main = basalt.createFrame()
local scrollbar = main:addScrollbar():setBarType("horizontal")
```
```xml
<scrollbar barType="horizontal" />
```

View File

@@ -0,0 +1,21 @@
## 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 main = basalt.createFrame()
local scrollbar = main:addScrollbar():setMaxValue(20)
local button = main:addButton(function()
scrollbar:setIndex(1)
end)
```
```xml
<scrollbar index="2" />
```

View File

@@ -0,0 +1,18 @@
## 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 main = basalt.createFrame()
local scrollbar = main:addScrollbar():setMaxValue(20)
```
```xml
<scrollbar maxValue="20" />
```

View File

@@ -0,0 +1,18 @@
## 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 main = basalt.createFrame()
local scrollbar = main:addScrollbar():setSymbol("X")
```
```xml
<scrollbar symbol="X" />
```

79
docs/tips/xml.md Normal file
View File

@@ -0,0 +1,79 @@
This is a basic guide on how to create a UI with XML.
In XML you are not able to create logic, but you could refer to logic - i will show you how.
But first i will show you how you are able to create some basic XML design.
First we will need a .lua file - we need to process the XML stuff, and this is only possible in lua.
So let's create a lua file:
```lua
local basalt = require("basalt") -- as always we will need basalt
local main = basalt.createFrame() -- and atleast 1 base frame is needed
basalt.autoUpdate() -- starting the event and draw handler is also needed
```
The code above you are just not able to do in XML, you are not able to create base frames and you are also not able to start the event/draw handlers.
This can only be done in Lua.
In Basalt XML Code will always be loaded into frames. Which means all the objects created in XML are always childrens of that particular frame. Here is a example to show what i mean:
Lua:
```lua
local basalt = require("basalt")
local main = basalt.createFrame():addLayout("example.xml")
basalt.autoUpdate()
```
XML:
```xml
<button x="5" y="3" text="Hello" />
```
This would be exactly the same like if you would use the following lua code:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
main:addButton():setPosition(5, 3):setText("Hello")
basalt.autoUpdate()
```
You can also add a layout multiple times, or create multiple frames and always use the same layout. For example a design layout for more frames and then you could also use
a unique layout for each frame. I wont show you a example, you just have to use :addLayout multiple times on different frames.
Another thing is, you could add/load XML files IN XML:
example.xml:
```xml
<frame layout="anotherExample.xml" />
```
anotherExample.xml:
```xml
<button x="2" y="3" width="parent.w - 2" text="Greetings" />
```
# Events
Using events in XML is also pretty simple. For that basalt has a function called basalt.setVariable. This is to store functions or other things which you can access via
XML. Obviously the logic you want to add has to be done in lua, here:
Lua:
```lua
local basalt = require("basalt")
basalt.setVariable("buttonClick", function()
basalt.debug("i got clicked!")
end)
local main = basalt.createFrame():addLayout("example.xml")
basalt.autoUpdate()
```
And then you just have to link your function in your XML file:
```xml
<button x="2" y="3" width="parent.w - 2" text="Greetings" onClick="buttonClick" />
```
This is pretty simple! BUT there is one thing you shouldn't forget: In Lua you always have to create the function's before you want to access it, which means
always use basalt.setVariable before you use frame:addLayout() - otherwise basalt is not able to find the function