3624 lines
119 KiB
Lua
3624 lines
119 KiB
Lua
local theme = {
|
|
basaltBG = colors.lightGray,
|
|
basaltFG = colors.black,
|
|
FrameBG = colors.gray,
|
|
FrameFG = colors.black,
|
|
ButtonBG = colors.gray,
|
|
ButtonFG = colors.black,
|
|
CheckboxBG = colors.gray,
|
|
CheckboxFG = colors.black,
|
|
InputBG = colors.gray,
|
|
InputFG = colors.black,
|
|
textfieldBG = colors.gray,
|
|
textfieldFG = colors.black,
|
|
listBG = colors.gray,
|
|
listFG = colors.black,
|
|
dropdownBG = colors.gray,
|
|
dropdownFG = colors.black,
|
|
radioBG = colors.gray,
|
|
radioFG = colors.black,
|
|
selectionBG = colors.black,
|
|
selectionFG = colors.lightGray,
|
|
}
|
|
|
|
local basalt = {debugger=true}
|
|
local activeFrame
|
|
local frames = {}
|
|
|
|
local keyModifier = {}
|
|
local parentTerminal = term.current()
|
|
|
|
local sub = string.sub
|
|
|
|
local function getTextHorizontalAlign(text, w, textAlign)
|
|
local text = string.sub(text, 1, w)
|
|
local n = w-string.len(text)
|
|
if(textAlign=="right")then
|
|
text = string.rep(" ", n)..text
|
|
elseif(textAlign=="center")then
|
|
text = string.rep(" ", math.floor(n/2))..text..string.rep(" ", math.floor(n/2))
|
|
text = text..(string.len(text) < w and " " or "")
|
|
else
|
|
text = text..string.rep(" ", n)
|
|
end
|
|
return text
|
|
end
|
|
|
|
local function getTextVerticalAlign(h,textAlign)
|
|
local offset = 0
|
|
if(textAlign=="center")then
|
|
offset = math.ceil(h / 2)
|
|
if(offset<1)then offset = 1 end
|
|
end
|
|
if(textAlign=="bottom")then
|
|
offset = h
|
|
end
|
|
return offset
|
|
end
|
|
|
|
local function rpairs(t)
|
|
return function(t, i)
|
|
i = i - 1
|
|
if i ~= 0 then
|
|
return i, t[i]
|
|
end
|
|
end, t, #t + 1
|
|
end
|
|
|
|
local tHex = { -- 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 function basaltDrawHelper()
|
|
local terminal = parentTerminal
|
|
local w,h = terminal.getSize()
|
|
local cacheT = {}
|
|
local cacheBG = {}
|
|
local cacheFG = {}
|
|
|
|
local _cacheT = {}
|
|
local _cacheBG = {}
|
|
local _cacheFG = {}
|
|
|
|
local emptySpaceLine
|
|
local emptyColorLines = {}
|
|
|
|
local function createEmptyLines()
|
|
emptySpaceLine = (" "):rep(w)
|
|
for n=0,15 do
|
|
local nColor = 2^n
|
|
local sHex = tHex[nColor]
|
|
emptyColorLines[nColor] = sHex:rep(w)
|
|
end
|
|
end
|
|
----
|
|
createEmptyLines()
|
|
|
|
local function recreateWindowArray()
|
|
local emptyText = emptySpaceLine
|
|
local emptyFG = emptyColorLines[colors.white]
|
|
local emptyBG = emptyColorLines[colors.black]
|
|
for n=1,h do
|
|
cacheT[n] = sub(cacheT[n] == nil and emptyText or cacheT[n]..emptyText:sub(1,w-cacheT[n]:len()),1,w)
|
|
cacheFG[n] = sub(cacheFG[n] == nil and emptyFG or cacheFG[n]..emptyFG:sub(1,w-cacheFG[n]:len()),1,w)
|
|
cacheBG[n] = sub(cacheBG[n] == nil and emptyBG or cacheBG[n]..emptyBG:sub(1,w-cacheBG[n]:len()),1,w)
|
|
end
|
|
end
|
|
recreateWindowArray()
|
|
|
|
local function setText(x,y,text)
|
|
if(y>=1)and(y<=h)then
|
|
if(x+text:len()>0)and(x<=w)then
|
|
local oldCache = cacheT[y]
|
|
local newCache
|
|
local nEnd = x + #text - 1
|
|
|
|
if(x < 1)then
|
|
local startN = 1 - x + 1
|
|
local endN = w - x + 1
|
|
text = sub(text, startN, endN)
|
|
elseif(nEnd > w)then
|
|
local endN = w - x + 1
|
|
text = sub(text, 1, endN)
|
|
end
|
|
|
|
if(x > 1)then
|
|
local endN = x - 1
|
|
newCache = sub( oldCache, 1, endN )..text
|
|
else
|
|
newCache = text
|
|
end
|
|
if nEnd < w then
|
|
newCache = newCache .. sub(oldCache, nEnd + 1, w)
|
|
end
|
|
cacheT[y] = newCache
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setBG(x,y,colorStr)
|
|
if(y>=1)and(y<=h)then
|
|
if(x+colorStr:len()>0)and(x<=w)then
|
|
local oldCache = cacheBG[y]
|
|
local newCache
|
|
local nEnd = x + #colorStr - 1
|
|
|
|
if(x < 1)then
|
|
colorStr = sub(colorStr, 1 - x + 1, w - x + 1)
|
|
elseif(nEnd > w)then
|
|
colorStr = sub(colorStr, 1, w - x + 1)
|
|
end
|
|
|
|
if(x > 1)then
|
|
newCache = sub( oldCache, 1, x - 1)..colorStr
|
|
else
|
|
newCache = colorStr
|
|
end
|
|
if nEnd < w then
|
|
newCache = newCache .. sub(oldCache, nEnd + 1, w)
|
|
end
|
|
cacheBG[y] = newCache
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setFG(x,y,colorStr)
|
|
if(y>=1)and(y<=h)then
|
|
if(x+colorStr:len()>0)and(x<=w)then
|
|
local oldCache = cacheFG[y]
|
|
local newCache
|
|
local nEnd = x + #colorStr - 1
|
|
|
|
if(x < 1)then
|
|
local startN = 1 - x + 1
|
|
local endN = w - x + 1
|
|
colorStr = sub(colorStr, startN, endN)
|
|
elseif(nEnd > w)then
|
|
local endN = w - 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 < w then
|
|
newCache = newCache .. sub( oldCache, nEnd + 1, w )
|
|
end
|
|
cacheFG[y] = newCache
|
|
end
|
|
end
|
|
end
|
|
|
|
local drawHelper = {
|
|
setBG = function(x,y,colorStr)
|
|
setBG(x,y,colorStr)
|
|
end;
|
|
|
|
setText = function(x,y,text)
|
|
setText(x,y,text)
|
|
end;
|
|
|
|
setFG = function(x,y,colorStr)
|
|
setFG(x,y,colorStr)
|
|
end;
|
|
|
|
drawBackgroundBox = function (x, y, w, h, bgCol)
|
|
for n = 1, h do
|
|
setBG(x, y + (n-1), tHex[bgCol]:rep(w))
|
|
end
|
|
end;
|
|
drawForegroundBox = function (x, y, w, h, fgCol)
|
|
for n = 1, h do
|
|
setFG(x, y + (n-1), tHex[fgCol]:rep(w))
|
|
end
|
|
end;
|
|
drawTextBox = function (x, y, w, h, symbol)
|
|
for n = 1, h do
|
|
setText(x, y + (n-1), symbol:rep(w))
|
|
end
|
|
end;
|
|
writeText = function (x, y, text, bgCol, fgCol)
|
|
bgCol = bgCol or terminal.getBackgroundColor()
|
|
fgCol = fgCol or terminal.getTextColor()
|
|
setText(x, y, text)
|
|
setBG(x, y, tHex[bgCol]:rep(text:len()))
|
|
setFG(x, y, tHex[fgCol]:rep(text:len()))
|
|
end;
|
|
|
|
update = function ()
|
|
local xC, yC = terminal.getCursorPos()
|
|
local isBlinking = terminal.getCursorBlink()
|
|
terminal.setCursorBlink(false)
|
|
for n=1, h do
|
|
terminal.setCursorPos(1, n)
|
|
terminal.blit(cacheT[n], cacheFG[n], cacheBG[n])
|
|
end
|
|
terminal.setCursorBlink(isBlinking)
|
|
terminal.setCursorPos(xC, yC)
|
|
end;
|
|
|
|
setTerm = function (newTerm)
|
|
terminal = newTerm;
|
|
end;
|
|
}
|
|
return drawHelper
|
|
end
|
|
local drawHelper = basaltDrawHelper()
|
|
|
|
local function BasaltEvents()
|
|
|
|
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;
|
|
|
|
removeEvent = function(self,_event,index)
|
|
events[_event][index[_event]] = nil
|
|
end;
|
|
|
|
sendEvent = function(self,_event,...)
|
|
if(events[_event]~=nil)then
|
|
for k,v in pairs(events[_event])do
|
|
v(...)
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
event.__index = event
|
|
return event
|
|
end
|
|
|
|
local processes = {}
|
|
local process = {}
|
|
local processId = 0
|
|
|
|
function process:new(path,window,...)
|
|
local args = table.pack( ... )
|
|
local newP = setmetatable({path=path},{__index = self})
|
|
newP.window = window
|
|
newP.processId = processId
|
|
newP.coroutine = coroutine.create(function()
|
|
os.run({basalt=basalt}, path, table.unpack(args))
|
|
end)
|
|
processes[processId] = newP
|
|
processId = processId + 1
|
|
return newP
|
|
end
|
|
|
|
function process:resume(event, ...)
|
|
term.redirect(self.window)
|
|
local ok, result = coroutine.resume( self.coroutine, event, ... )
|
|
self.window = term.current()
|
|
if ok then
|
|
self.filter = result
|
|
else
|
|
basalt.debug( result )
|
|
end
|
|
end
|
|
|
|
function process:isDead()
|
|
if(self.coroutine~=nil)then
|
|
if(coroutine.status(self.coroutine)=="dead")then
|
|
table.remove(processes, self.processId)
|
|
return true
|
|
end
|
|
else
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function process:getStatus()
|
|
if(self.coroutine~=nil)then
|
|
return coroutine.status(self.coroutine)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function process:start()
|
|
coroutine.resume(self.coroutine)
|
|
end
|
|
|
|
local function Object(name) -- Base object
|
|
local typ = "Object" -- not changeable
|
|
--[[
|
|
local horizontalAnchor = "left"
|
|
local verticalAnchor = "top"
|
|
local ignYOffset = false
|
|
local ignXOffset = false ]]
|
|
local value = nil
|
|
local zIndex = 1
|
|
local hanchor = "left"
|
|
local vanchor = "top"
|
|
local ignOffset = false
|
|
local isVisible = false
|
|
|
|
local visualsChanged = true
|
|
|
|
local eventSystem = BasaltEvents()
|
|
|
|
local object = {
|
|
x = 1,
|
|
y = 1,
|
|
w = 1,
|
|
h = 1,
|
|
bgcolor = colors.black,
|
|
fgcolor = colors.white,
|
|
name = name or "Object",
|
|
parent = nil,
|
|
|
|
show = function(self)
|
|
isVisible = true
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
hide = function(self)
|
|
isVisible = false
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
isVisible = function(self)
|
|
return isVisible
|
|
end;
|
|
|
|
getZIndex = function(self)
|
|
return zIndex;
|
|
end;
|
|
|
|
setFocus = function(self)
|
|
if(self.parent~=nil)then
|
|
self.parent:setFocusedObject(self)
|
|
end
|
|
end;
|
|
|
|
setZIndex = function(self, index)
|
|
zIndex = index
|
|
if(self.parent~=nil)then
|
|
self.parent:removeObject(self)
|
|
self.parent:addObject(self)
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
getName = function(self)
|
|
return self.name
|
|
end;
|
|
|
|
remove = function(self)
|
|
if(self.parent~=nil)then
|
|
self.parent:removeObject(self)
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setParent = function(self, frame)
|
|
if(frame.getType~=nil and frame:getType()=="Frame")then
|
|
self:remove()
|
|
frame:addObject(self)
|
|
if(self.draw)then
|
|
self:show()
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setValue = function(self, _value)
|
|
value = _value
|
|
visualsChanged = true
|
|
self:valueChangedHandler()
|
|
return self
|
|
end;
|
|
|
|
getValue = function(self)
|
|
return value
|
|
end;
|
|
|
|
getVisualChanged = function(self)
|
|
return visualsChanged
|
|
end;
|
|
|
|
setVisualChanged = function(self, change)
|
|
visualsChanged = change or true
|
|
return self
|
|
end;
|
|
|
|
|
|
getEventSystem = function(self)
|
|
return eventSystem
|
|
end;
|
|
|
|
|
|
getParent = function(self)
|
|
return self.parent
|
|
end;
|
|
|
|
setPosition = function(self, xPos, yPos, rel)
|
|
if(rel)then
|
|
self.x, self.y = self.x + xPos, self.y + yPos
|
|
else
|
|
self.x, self.y = xPos, yPos
|
|
end
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
getPosition = function(self)
|
|
return self.x,self.y
|
|
end;
|
|
|
|
getVisibility = function(self)
|
|
return isVisible
|
|
end;
|
|
|
|
setVisibility = function(self, _isVisible)
|
|
isVisible = _isVisible or not isVisible
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
setSize = function(self, w, h)
|
|
self.w, self.h = w, h
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
getHeight = function(self)
|
|
return self.h
|
|
end;
|
|
|
|
getWidth = function(self)
|
|
return self.w
|
|
end;
|
|
|
|
setBackground = function(self, color)
|
|
self.bgcolor = color
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
getBackground = function(self)
|
|
return self.bgcolor
|
|
end;
|
|
|
|
setForeground = function(self, color)
|
|
self.fgcolor = color
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
getForeground = function(self)
|
|
return self.fgcolor
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(isVisible)then
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
|
|
getAbsolutePosition = function(self, x,y) -- relative position
|
|
if(x==nil)then x = self.x end
|
|
if(y==nil)then y = self.y end
|
|
|
|
if(self.parent~=nil)then
|
|
local fx,fy = self.parent:getAbsolutePosition()
|
|
x=fx+x-1
|
|
y=fy+y-1
|
|
end
|
|
return x, y
|
|
end;
|
|
|
|
getAnchorPosition = function(self,x, y, ignOff)
|
|
if(x==nil)then x = self.x end
|
|
if(y==nil)then y = self.y end
|
|
if(hanchor=="right")then
|
|
x = self.parent.w-x-self.w+2
|
|
end
|
|
if(vanchor=="bottom")then
|
|
y = self.parent.h-y-self.h+2
|
|
end
|
|
local xO, yO = self:getOffset()
|
|
if(ignOffset or ignOff)then
|
|
return x, y
|
|
end
|
|
return x+xO, y+yO
|
|
end;
|
|
|
|
getOffset = function(self)
|
|
if(self.parent~=nil)and(ignOffset==false)then
|
|
return self.parent:getFrameOffset()
|
|
end
|
|
return 0, 0
|
|
end;
|
|
|
|
ignoreOffset = function(self, ignore)
|
|
ignOffset = ignore or true
|
|
return self
|
|
end;
|
|
|
|
setAnchor = function(self,...)
|
|
for _,v in pairs(table.pack(...))do
|
|
if(v=="right")or(v=="left")then
|
|
hanchor = v
|
|
end
|
|
if(v=="top")or(v=="bottom")then
|
|
vanchor = v
|
|
end
|
|
end
|
|
visualsChanged = true
|
|
return self
|
|
end;
|
|
|
|
getAnchor = function(self)
|
|
return hanchor, vanchor
|
|
end;
|
|
|
|
onChange = function(self, func)
|
|
self:registerEvent("value_changed", func)
|
|
return self
|
|
end;
|
|
|
|
onClick = function(self, func)
|
|
self:registerEvent("mouse_click", func)
|
|
return self
|
|
end;
|
|
|
|
onEvent = function(self, func)
|
|
self:registerEvent("custom_event_handler", func)
|
|
return self
|
|
end;
|
|
|
|
onClickUp = function(self, func)
|
|
self:registerEvent("mouse_up", func)
|
|
return self
|
|
end;
|
|
|
|
onKey = function(self, func)
|
|
self:registerEvent("key", func)
|
|
self:registerEvent("char", func)
|
|
return self
|
|
end;
|
|
|
|
onKeyUp = function(self, func)
|
|
self:registerEvent("key_up", func)
|
|
return self
|
|
end;
|
|
|
|
isFocused = function(self)
|
|
if(self.parent~=nil)then
|
|
return self.parent:getFocusedObject()==self
|
|
end
|
|
return false
|
|
end;
|
|
|
|
onGetFocus = function(self, func)
|
|
self:registerEvent("get_focus", func)
|
|
return self
|
|
end;
|
|
|
|
onLoseFocus = function(self, func)
|
|
self:registerEvent("lose_focus", func)
|
|
return self
|
|
end;
|
|
|
|
registerEvent = function(self,event, func)
|
|
return eventSystem:registerEvent(event, func)
|
|
end;
|
|
|
|
removeEvent = function(self,event, index)
|
|
return eventSystem:removeEvent(event, index)
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
local objX,objY = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(objX<=x)and(objX+self.w>x)and(objY<=y)and(objY+self.h>y)and(isVisible)then
|
|
if(self.parent~=nil)then self.parent:setFocusedObject(self) end
|
|
eventSystem:sendEvent(event, self, event, button, x, y)
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
keyHandler = function(self, event, key)
|
|
if(self:isFocused())then
|
|
eventSystem:sendEvent(event, self, event, key)
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
valueChangedHandler = function(self)
|
|
eventSystem:sendEvent("value_changed", self)
|
|
end;
|
|
|
|
eventHandler = function(self, event, p1, p2, p3, p4)
|
|
eventSystem:sendEvent("custom_event_handler", self, event, p1, p2, p3, p4)
|
|
end;
|
|
|
|
getFocusHandler = function(self)
|
|
eventSystem:sendEvent("get_focus", self)
|
|
end;
|
|
|
|
loseFocusHandler = function(self)
|
|
eventSystem:sendEvent("lose_focus", self)
|
|
end;
|
|
|
|
|
|
}
|
|
|
|
object.__index = object
|
|
return object
|
|
end
|
|
|
|
local function Button(name) -- Button
|
|
local base = Object(name)
|
|
local typ = "Button"
|
|
|
|
base:setValue("Button")
|
|
base:setZIndex(5)
|
|
base.w = 8
|
|
base.bgcolor = theme.ButtonBG
|
|
base.fgcolor = theme.ButtonFG
|
|
|
|
local textHorizontalAlign = "center"
|
|
local textVerticalAlign = "center"
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
setHorizontalAlign = function (self, pos)
|
|
textHorizontalAlign = pos
|
|
end;
|
|
|
|
setVerticalAlign = function (self, pos)
|
|
textVerticalAlign = pos
|
|
end;
|
|
|
|
setText = function(self,text)
|
|
base:setValue(text)
|
|
return self
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition(self.x,self.y)
|
|
local verticalAlign = getTextVerticalAlign(self.h, textVerticalAlign)
|
|
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
self.parent:drawForegroundBox(obx, oby, self.w, self.h, self.fgcolor)
|
|
self.parent:drawTextBox(obx, oby, self.w, self.h, " ")
|
|
for n=1,self.h do
|
|
if(n==verticalAlign)then
|
|
self.parent:setText(obx, oby+(n-1), getTextHorizontalAlign(self:getValue(), self.w, textHorizontalAlign))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Program(name)
|
|
local base = Object(name)
|
|
local typ = "Program"
|
|
base:setZIndex(5)
|
|
local object
|
|
|
|
local function basaltWindow(x, y, w, h)
|
|
local xCursor, yCursor = 1, 1
|
|
local bgcolor, fgcolor = colors.black, colors.white
|
|
local cursorBlink = false
|
|
local visible = false
|
|
|
|
local cacheT = {}
|
|
local cacheBG = {}
|
|
local cacheFG = {}
|
|
|
|
local tPalette = {}
|
|
|
|
local emptySpaceLine
|
|
local emptyColorLines = {}
|
|
|
|
for i=0,15 do
|
|
local c = 2 ^ i
|
|
tPalette[c] = { parentTerminal.getPaletteColour( c ) }
|
|
end
|
|
|
|
local function createEmptyLines()
|
|
emptySpaceLine = (" "):rep(w)
|
|
for n=0,15 do
|
|
local nColor = 2^n
|
|
local sHex = tHex[nColor]
|
|
emptyColorLines[nColor] = sHex:rep(w)
|
|
end
|
|
end
|
|
|
|
local function recreateWindowArray()
|
|
createEmptyLines()
|
|
local emptyText = emptySpaceLine
|
|
local emptyFG = emptyColorLines[colors.white]
|
|
local emptyBG = emptyColorLines[colors.black]
|
|
for n=1,h do
|
|
cacheT[n] = sub(cacheT[n] == nil and emptyText or cacheT[n]..emptyText:sub(1,w-cacheT[n]:len()),1,w)
|
|
cacheFG[n] = sub(cacheFG[n] == nil and emptyFG or cacheFG[n]..emptyFG:sub(1,w-cacheFG[n]:len()),1,w)
|
|
cacheBG[n] = sub(cacheBG[n] == nil and emptyBG or cacheBG[n]..emptyBG:sub(1,w-cacheBG[n]:len()),1,w)
|
|
end
|
|
end
|
|
recreateWindowArray()
|
|
|
|
local function updateCursor()
|
|
if xCursor >= 1 and yCursor >= 1 and xCursor <= w and yCursor <= h then
|
|
--parentTerminal.setCursorPos(xCursor + x - 1, yCursor + y - 1)
|
|
else
|
|
--parentTerminal.setCursorPos(0, 0)
|
|
end
|
|
--parentTerminal.setTextColor(fgcolor)
|
|
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 <= h then
|
|
if nStart <= w and nEnd >= 1 then
|
|
-- Modify line
|
|
if nStart == 1 and nEnd == w 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 = w - nStart + 1
|
|
sClippedText = sub( sText, nClipStart, nClipEnd )
|
|
sClippedTextColor = sub( sTextColor, nClipStart, nClipEnd )
|
|
sClippedBackgroundColor = sub( sBackgroundColor, nClipStart, nClipEnd )
|
|
elseif nEnd > w then
|
|
local nClipEnd = w - 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 < w then
|
|
local nOldStart = nEnd + 1
|
|
sNewText = sNewText .. sub( sOldText, nOldStart, w )
|
|
sNewTextColor = sNewTextColor .. sub( sOldTextColor, nOldStart, w )
|
|
sNewBackgroundColor = sNewBackgroundColor .. sub( sOldBackgroundColor, nOldStart, w )
|
|
end
|
|
|
|
cacheT[yCursor] = sNewText
|
|
cacheFG[yCursor] = sNewTextColor
|
|
cacheBG[yCursor] = sNewBackgroundColor
|
|
end
|
|
end
|
|
xCursor = nEnd + 1
|
|
if(visible)then
|
|
updateCursor()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setText(_x,_y,text)
|
|
if(text~=nil)then
|
|
local gText = cacheT[_y]
|
|
if(gText~=nil)then
|
|
cacheT[_y] = sub(gText:sub(1,_x-1)..text..gText:sub(_x+(text:len()),w),1,w)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setBG(_x,_y,colorStr)
|
|
if(colorStr~=nil)then
|
|
local gBG = cacheBG[_y]
|
|
if(gBG~=nil)then
|
|
cacheBG[_y] = sub(gBG:sub(1,_x-1)..colorStr..gBG:sub(_x+(colorStr:len()),w),1,w)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setFG(_x,_y,colorStr)
|
|
if(colorStr~=nil)then
|
|
local gFG = cacheFG[_y]
|
|
if(gFG~=nil)then
|
|
cacheFG[_y] = sub(gFG:sub(1,_x-1)..colorStr..gFG:sub(_x+(colorStr:len()),w),1,w)
|
|
end
|
|
end
|
|
end
|
|
|
|
local setTextColor = function(color)
|
|
if type( color ) ~= "number" then
|
|
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
|
|
elseif tHex[color] == nil then
|
|
error( "Invalid color (got " .. color .. ")" , 2 )
|
|
end
|
|
fgcolor = color
|
|
end
|
|
|
|
local setBackgroundColor = function(color)
|
|
if type( color ) ~= "number" then
|
|
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
|
|
elseif tHex[color] == nil then
|
|
error( "Invalid color (got " .. color .. ")" , 2 )
|
|
end
|
|
bgcolor = color
|
|
end
|
|
|
|
local setPaletteColor = function( colour, r, g, b ) -- have to work on
|
|
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
|
|
|
|
if tHex[colour] == nil then
|
|
error( "Invalid color (got " .. colour .. ")" , 2 )
|
|
end
|
|
|
|
local tCol
|
|
if type(r) == "number" and g == nil and b == nil then
|
|
tCol = { colours.rgb8( r ) }
|
|
tPalette[ colour ] = tCol
|
|
else
|
|
if type( r ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( r ) .. ")", 2 ) end
|
|
if type( g ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( g ) .. ")", 2 ) end
|
|
if type( b ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( b ) .. ")", 2 ) end
|
|
|
|
tCol = tPalette[ colour ]
|
|
tCol[1] = r
|
|
tCol[2] = g
|
|
tCol[3] = b
|
|
end
|
|
end
|
|
|
|
local getPaletteColor = function( colour )
|
|
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
|
|
if tHex[colour] == nil then
|
|
error( "Invalid color (got " .. colour .. ")" , 2 )
|
|
end
|
|
local tCol = tPalette[ colour ]
|
|
return tCol[1], tCol[2], tCol[3]
|
|
end
|
|
|
|
local basaltwindow = {
|
|
setCursorPos = function(_x, _y)
|
|
if type( _x ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( _x ) .. ")", 2 ) end
|
|
if type( _y ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( _y ) .. ")", 2 ) end
|
|
xCursor = math.floor(_x)
|
|
yCursor = math.floor(_y)
|
|
if(visible)then
|
|
updateCursor()
|
|
end
|
|
end;
|
|
|
|
getCursorPos = function()
|
|
return xCursor, yCursor
|
|
end;
|
|
|
|
setCursorBlink = function(blink)
|
|
if type( blink ) ~= "boolean" then error( "bad argument #1 (expected boolean, got " .. type( blink ) .. ")", 2 ) end
|
|
cursorBlink = blink
|
|
end;
|
|
|
|
getCursorBlink = function()
|
|
return cursorBlink
|
|
end;
|
|
|
|
|
|
getPaletteColor = getPaletteColor,
|
|
getPaletteColour = getPaletteColor,
|
|
|
|
setBackgroundColor = setBackgroundColor,
|
|
setBackgroundColour = setBackgroundColor,
|
|
|
|
setTextColor = setTextColor,
|
|
setTextColour = setTextColor,
|
|
|
|
setPaletteColor = setPaletteColor,
|
|
setPaletteColour = setPaletteColor,
|
|
|
|
getBackgroundColor = function()
|
|
return bgcolor
|
|
end;
|
|
getBackgroundColour = function()
|
|
return bgcolor
|
|
end;
|
|
|
|
getSize = function()
|
|
return w, h
|
|
end;
|
|
|
|
getTextColor = function()
|
|
return fgcolor
|
|
end;
|
|
getTextColour = function()
|
|
return fgcolor
|
|
end;
|
|
|
|
basalt_resize = function(_w, _h)
|
|
w, h = _w, _h
|
|
recreateWindowArray()
|
|
end;
|
|
|
|
basalt_reposition = function(_x, _y)
|
|
x, y = _x, _y
|
|
end;
|
|
|
|
basalt_setVisible = function(vis)
|
|
visible = vis
|
|
end;
|
|
|
|
drawBackgroundBox = function (_x, _y, _w, _h, bgCol)
|
|
for n = 1, _h do
|
|
setBG(_x, _y + (n-1), tHex[bgCol]:rep(_w))
|
|
end
|
|
end;
|
|
drawForegroundBox = function (_x, _y, _w, _h, fgCol)
|
|
for n = 1, _h do
|
|
setFG(_x, _y + (n-1), tHex[fgCol]:rep(_w))
|
|
end
|
|
end;
|
|
drawTextBox = function (_x, _y, _w, _h, symbol)
|
|
for n = 1, _h do
|
|
setText(_x, _y + (n-1), symbol:rep(_w))
|
|
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(object.parent~=nil)then
|
|
for n=1, h do
|
|
object.parent:setText(x, y + (n-1), cacheT[n])
|
|
object.parent:setBG(x, y + (n-1), cacheBG[n])
|
|
object.parent:setFG(x, y + (n-1), cacheFG[n])
|
|
end
|
|
end
|
|
end;
|
|
|
|
scroll = function (offset)
|
|
if type( offset ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( offset ) .. ")", 2 ) end
|
|
if offset ~= 0 then
|
|
local sEmptyText = emptySpaceLine
|
|
local sEmptyTextColor = emptyColorLines[ fgcolor ]
|
|
local sEmptyBackgroundColor = emptyColorLines[ bgcolor ]
|
|
for newY=1,h do
|
|
local y = newY + offset
|
|
if y >= 1 and y <= h then
|
|
cacheT[newY] = cacheT[y]
|
|
cacheBG[newY] = cacheBG[y]
|
|
cacheFG[newY] = cacheFG[y]
|
|
else
|
|
cacheT[newY] = sEmptyText
|
|
cacheFG[newY] = sEmptyTextColor
|
|
cacheBG[newY] = sEmptyBackgroundColor
|
|
end
|
|
end
|
|
end
|
|
if(visible)then
|
|
updateCursor()
|
|
end
|
|
end;
|
|
|
|
|
|
isColor = function()
|
|
return parentTerminal.isColor()
|
|
end;
|
|
|
|
isColour = function()
|
|
return parentTerminal.isColor()
|
|
end;
|
|
|
|
write = function(text)
|
|
text = tostring(text)
|
|
if(visible)then
|
|
internalBlit( text, tHex[fgcolor]:rep(text:len()), tHex[bgcolor]:rep(text:len()))
|
|
end
|
|
end;
|
|
|
|
clearLine = function()
|
|
if(visible)then
|
|
setText(1, yCursor, (" "):rep(w))
|
|
setBG(1, yCursor, tHex[bgcolor]:rep(w))
|
|
setFG(1, yCursor, tHex[fgcolor]:rep(w))
|
|
end
|
|
if(visible)then
|
|
updateCursor()
|
|
end
|
|
end;
|
|
|
|
clear = function()
|
|
for n=1,h do
|
|
setText(1, n, (" "):rep(w))
|
|
setBG(1, n, tHex[bgcolor]:rep(w))
|
|
setFG(1, n, tHex[fgcolor]:rep(w))
|
|
end
|
|
if(visible)then
|
|
updateCursor()
|
|
end
|
|
end;
|
|
|
|
blit = function(text, fgcol, bgcol)
|
|
if type( text ) ~= "string" then error( "bad argument #1 (expected string, got " .. type( text ) .. ")", 2 ) end
|
|
if type( fgcol ) ~= "string" then error( "bad argument #2 (expected string, got " .. type( fgcol ) .. ")", 2 ) end
|
|
if type( bgcol ) ~= "string" then error( "bad argument #3 (expected string, got " .. type( bgcol ) .. ")", 2 ) end
|
|
if #fgcol ~= #text or #bgcol ~= #text then
|
|
error( "Arguments must be the same length", 2 )
|
|
end
|
|
if(visible)then
|
|
--setText(xCursor, yCursor, text)
|
|
--setBG(xCursor, yCursor, bgcol)
|
|
--setFG(xCursor, yCursor, fgcol)
|
|
--xCursor = xCursor+text:len()
|
|
internalBlit(text, fgcol, bgcol)
|
|
end
|
|
end
|
|
|
|
|
|
}
|
|
|
|
return basaltwindow
|
|
end
|
|
|
|
base.w = 30
|
|
base.h = 12
|
|
local pWindow = basaltWindow(1, 1, base.w, base.h)
|
|
local curProcess
|
|
local paused = false
|
|
local queuedEvent = {}
|
|
|
|
object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
show = function(self)
|
|
base.show(self)
|
|
pWindow.setBackgroundColor(self.bgcolor)
|
|
pWindow.setTextColor(self.fgcolor)
|
|
pWindow.basalt_setVisible(true)
|
|
return self
|
|
end;
|
|
|
|
hide = function(self)
|
|
base.hide(self)
|
|
pWindow.basalt_setVisible(false)
|
|
return self
|
|
end;
|
|
|
|
setPosition = function(self, x, y, rel)
|
|
base.setPosition(self,x,y, rel)
|
|
pWindow.basalt_reposition(self:getAnchorPosition())
|
|
return self
|
|
end;
|
|
|
|
getBasaltWindow = function()
|
|
return pWindow
|
|
end;
|
|
|
|
getBasaltProcess = function()
|
|
return curProcess
|
|
end;
|
|
|
|
setSize = function(self, w, h)
|
|
base.setSize(self,w,h)
|
|
pWindow.basalt_resize(self.w, self.h)
|
|
return self
|
|
end;
|
|
|
|
getStatus = function(self)
|
|
if(curProcess~=nil)then
|
|
return curProcess:getStatus()
|
|
end
|
|
return "inactive"
|
|
end;
|
|
|
|
execute = function(self, path, ...)
|
|
curProcess = process:new(path, pWindow, ...)
|
|
pWindow.setBackgroundColor(colors.black)
|
|
pWindow.setTextColor(colors.white)
|
|
pWindow.clear()
|
|
pWindow.setCursorPos(1, 1)
|
|
curProcess:resume()
|
|
paused = false
|
|
return self
|
|
end;
|
|
|
|
stop = function(self)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
curProcess:resume("terminate")
|
|
if(curProcess:isDead())then
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
pause = function(self, p)
|
|
paused = p or (not paused)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
if not(paused)then
|
|
self:injectEvents(queuedEvent)
|
|
queuedEvent = {}
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
isPaused = function(self)
|
|
return paused
|
|
end;
|
|
|
|
injectEvent = function(self, event, p1, p2, p3, p4, ign)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
if (paused==false)or(ign)then
|
|
basalt.debug(event, p1)
|
|
curProcess:resume(event,p1,p2,p3,p4)
|
|
else
|
|
table.insert(queuedEvent, {event=event, args = {p1,p2,p3,p4}})
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getQueuedEvents = function(self)
|
|
return queuedEvent
|
|
end;
|
|
|
|
updateQueuedEvents = function(self, events)
|
|
queuedEvent = events or queuedEvent
|
|
return self
|
|
end;
|
|
|
|
injectEvents = function(self, events)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
for _,v in pairs(events)do
|
|
curProcess:resume(v.event, table.unpack(v.args))
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self,event,button,x,y))then
|
|
if(curProcess==nil)then return false end
|
|
if not(curProcess:isDead())then
|
|
if not(paused)then
|
|
local absX,absY = self:getAbsolutePosition(self:getAnchorPosition())
|
|
curProcess:resume(event, button, x-absX+1, y-absY+1)
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
end;
|
|
|
|
keyHandler = function(self, event, key)
|
|
if(self:isFocused())then
|
|
if(curProcess==nil)then return false end
|
|
if not(curProcess:isDead())then
|
|
if not(paused)then
|
|
base.keyHandler(self, event, key)
|
|
if(self.draw)then
|
|
curProcess:resume(event, key)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
getFocusHandler = function(self)
|
|
base.getFocusHandler(self)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
if not(paused)then
|
|
if(self.parent~=nil)then
|
|
local xCur, yCur = pWindow.getCursorPos()
|
|
local obx, oby = self:getAnchorPosition()
|
|
if(self.parent~=nil)then
|
|
if(obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + self.w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.h - 1)then
|
|
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
loseFocusHandler = function(self)
|
|
base.loseFocusHandler(self)
|
|
if(curProcess~=nil)then
|
|
if not(curProcess:isDead())then
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(false)
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
eventHandler = function(self, event, p1, p2, p3, p4)
|
|
if(curProcess==nil)then return end
|
|
if not(curProcess:isDead())then
|
|
if not(paused)then
|
|
if(event~="mouse_click")and(event~="mouse_up")and(event~="mouse_scroll")and(event~="mouse_drag")and(event~="key_up")and(event~="key")and(event~="char")and(event~="terminate")then
|
|
curProcess:resume(event,p1,p2,p3,p4)
|
|
end
|
|
if(self:isFocused())then
|
|
local obx, oby = self:getAnchorPosition()
|
|
local xCur, yCur = pWindow.getCursorPos()
|
|
if(self.parent~=nil)then
|
|
if(obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + self.w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.h - 1)then
|
|
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
|
|
end
|
|
end
|
|
|
|
if(event=="terminate")and(self:isFocused())then
|
|
self:stop()
|
|
end
|
|
end
|
|
else
|
|
if(event~="mouse_click")and(event~="mouse_up")and(event~="mouse_scroll")and(event~="mouse_drag")and(event~="key_up")and(event~="key")and(event~="char")and(event~="terminate")then
|
|
table.insert(queuedEvent, {event=event, args = {p1,p2,p3,p4}})
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
pWindow.basalt_reposition(obx,oby)
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
pWindow.basalt_update()
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Label(name) -- Label
|
|
local base = Object(name)
|
|
local typ = "Label"
|
|
|
|
local autoWidth = true
|
|
base:setValue("")
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
setText = function(self,text)
|
|
text = tostring(text)
|
|
base:setValue(text)
|
|
if(autoWidth)then
|
|
self.w = text:len()
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setSize = function(self,w,h)
|
|
self.w, self.h = w, h
|
|
autoWidth = false
|
|
return self
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
self.parent:writeText(obx, oby, self:getValue(), self.bgcolor, self.fgcolor)
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Checkbox(name) -- Checkbox
|
|
local base = Object(name)
|
|
local typ = "Checkbox"
|
|
|
|
base:setZIndex(5)
|
|
base:setValue(false)
|
|
base.w = 1
|
|
base.h = 1
|
|
base.bgcolor = theme.CheckboxBG
|
|
base.fgcolor = theme.CheckboxFG
|
|
|
|
local object = {
|
|
symbol = "\42",
|
|
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self, event, button, x, y))then
|
|
if(event == "mouse_click")and(button == 1)then
|
|
if(self:getValue()~=true)and(self:getValue()~=false)then
|
|
self:setValue(false)
|
|
else
|
|
self:setValue(not self:getValue())
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
local verticalAlign = getTextVerticalAlign(self.h, "center")
|
|
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
for n=1,self.h do
|
|
if(n==verticalAlign)then
|
|
if(self:getValue()==true)then
|
|
self.parent:writeText(obx, oby+(n-1), getTextHorizontalAlign(self.symbol, self.w, "center"), self.bgcolor, self.fgcolor)
|
|
else
|
|
self.parent:writeText(obx, oby+(n-1), getTextHorizontalAlign(" ", self.w, "center"), self.bgcolor, self.fgcolor)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Input(name) -- Input
|
|
local base = Object(name)
|
|
local typ = "Input"
|
|
|
|
local inputType = "text"
|
|
local inputLimit = 0
|
|
base:setZIndex(5)
|
|
base:setValue("")
|
|
base.w = 10
|
|
base.h = 1
|
|
base.bgcolor = theme.InputBG
|
|
base.fgcolor = theme.InputFG
|
|
|
|
local textX = 1
|
|
local wIndex = 1
|
|
|
|
local defaultText = ""
|
|
local defaultBGCol
|
|
local defaultFGCol
|
|
local showingText = defaultText
|
|
local internalValueChange = false
|
|
|
|
local object = {
|
|
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
setInputType = function(self, iType)
|
|
if(iType=="password")or(iType=="number")or(iType=="text")then
|
|
inputType = iType
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setDefaultText = function(self, text, fCol, bCol)
|
|
defaultText = text
|
|
defaultBGCol = bCol or defaultBGCol
|
|
defaultFGCol = fCol or defaultFGCol
|
|
if(self:isFocused())then
|
|
showingText = ""
|
|
else
|
|
showingText = defaultText
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getInputType = function(self)
|
|
return inputType
|
|
end;
|
|
|
|
setValue = function(self, val)
|
|
base.setValue(self, tostring(val))
|
|
if not(internalValueChange)then
|
|
textX = tostring(val):len()+1
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getValue = function(self)
|
|
local val = base.getValue(self)
|
|
return inputType == "number" and tonumber(val)or val
|
|
end;
|
|
|
|
setInputLimit = function(self, limit)
|
|
inputLimit = tonumber(limit) or inputLimit
|
|
return self
|
|
end;
|
|
|
|
getInputLimit = function(self)
|
|
return inputLimit
|
|
end;
|
|
|
|
getFocusHandler = function(self)
|
|
base.getFocusHandler(self)
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
showingText = ""
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(true, obx+textX-wIndex, oby, self.fgcolor)
|
|
end
|
|
end
|
|
end;
|
|
|
|
loseFocusHandler = function(self)
|
|
base.loseFocusHandler(self)
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(false)
|
|
showingText = defaultText
|
|
end
|
|
end;
|
|
|
|
keyHandler = function(self, event, key)
|
|
if(base.keyHandler(self, event, key))then
|
|
internalValueChange = true
|
|
if(event=="key")then
|
|
if(key==259)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
|
|
end
|
|
end
|
|
end
|
|
if(key==257)then -- on enter
|
|
if(self.parent~=nil)then
|
|
--self.parent:removeFocusedObject(self)
|
|
end
|
|
end
|
|
if(key==262)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
|
|
if(textX<wIndex)or(textX>=self.w+wIndex)then
|
|
wIndex = textX-self.w+1
|
|
end
|
|
if(wIndex<1)then wIndex = 1 end
|
|
end
|
|
|
|
if(key==263)then -- left arrow
|
|
textX = textX-1
|
|
if(textX>=1)then
|
|
if(textX<wIndex)or(textX>=self.w+wIndex)then
|
|
wIndex = textX
|
|
end
|
|
end
|
|
if(textX<1)then textX = 1 end
|
|
if(wIndex<1)then wIndex = 1 end
|
|
end
|
|
end
|
|
|
|
if(event=="char")then
|
|
local text = base.getValue()
|
|
if(text:len() < inputLimit or inputLimit <= 0)then
|
|
if(inputType=="number")then
|
|
local cache = text
|
|
if (key==".")or(tonumber(key)~=nil)then
|
|
self:setValue(text:sub(1,textX-1)..key..text:sub(textX,text:len()))
|
|
textX = textX + 1
|
|
end
|
|
if(tonumber(base.getValue())==nil)then
|
|
self:setValue(cache)
|
|
end
|
|
else
|
|
self:setValue(text:sub(1,textX-1)..key..text:sub(textX,text:len()))
|
|
textX = textX + 1
|
|
end
|
|
if(textX>=self.w+wIndex)then wIndex = wIndex+1 end
|
|
end
|
|
end
|
|
local obx,oby = self:getAnchorPosition()
|
|
local val = tostring(base.getValue())
|
|
local cursorX = (textX <= val:len() and textX-1 or val:len())-(wIndex-1)
|
|
|
|
if(cursorX>self.x+self.w-1)then cursorX = self.x+self.w-1 end
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(true, obx+cursorX, oby, self.fgcolor)
|
|
end
|
|
internalValueChange = false
|
|
end
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self, event, button, x, y))then
|
|
if(event == "mouse_click")and(button == 1)then
|
|
|
|
end
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
local verticalAlign = getTextVerticalAlign(self.h, "center")
|
|
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
for n=1,self.h do
|
|
if(n==verticalAlign)then
|
|
local val = tostring(base.getValue())
|
|
local text = inputType == "password" and ("*"):rep(val:len()) or val
|
|
if(text:len()>=self.w)then
|
|
if(inputType=="password")then
|
|
text = ("*"):rep(text:len()):sub(text:len()-self.w+2, text:len())
|
|
else
|
|
text = text:sub(text:len()-self.w+2, text:len())
|
|
end
|
|
end
|
|
local bCol = self.bgcolor
|
|
local fCol = self.fgcolor
|
|
if(text:len()<=0)then text = showingText bCol = defaultBGCol or bCol fCol = defaultFGCol or fCol end
|
|
|
|
local text = showingText
|
|
if(val~="")then
|
|
text = val
|
|
end
|
|
text = text:sub(wIndex, self.w+wIndex-1)
|
|
local space = self.w-text:len()
|
|
if(space<0)then space = 0 end
|
|
text = text..string.rep(" ", space)
|
|
self.parent:setText(obx, oby+n-1, text)
|
|
self.parent:writeText(obx, oby+(n-1), text, bCol, fCol)
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Textfield(name)
|
|
local base = Object(name)
|
|
local typ = "Textfield"
|
|
local hIndex, wIndex, textX, textY = 1, 1, 1, 1
|
|
|
|
local lines = {""}
|
|
local selection = {}
|
|
local selectionColor = colors.lightBlue
|
|
|
|
base.w = 20
|
|
base.h = 8
|
|
base.bgcolor = theme.textfieldBG
|
|
base.fgcolor = theme.textfieldFG
|
|
base:setZIndex(5)
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
getLines = function (self)
|
|
return lines
|
|
end;
|
|
|
|
getLine = function (self, index)
|
|
return lines[index] or ""
|
|
end;
|
|
|
|
editLine = function (self, index, text)
|
|
lines[index] = text or lines[index]
|
|
return self
|
|
end;
|
|
|
|
addLine = function (self, text, index)
|
|
if(index~=nil)then
|
|
table.insert(lines, index, text)
|
|
else
|
|
table.insert(lines, text)
|
|
end
|
|
return self
|
|
end;
|
|
|
|
removeLine = function(self, index)
|
|
table.remove(lines, index or #lines)
|
|
if(#lines <= 0)then
|
|
table.insert(lines, "")
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getTextCursor = function (self)
|
|
return textX, textY
|
|
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;
|
|
|
|
loseFocusHandler = function(self)
|
|
base.loseFocusHandler(self)
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(false)
|
|
end
|
|
end;
|
|
|
|
keyHandler = function(self, event, key)
|
|
if(base.keyHandler(self, event, key))then
|
|
local obx,oby = self:getAnchorPosition()
|
|
if(event=="key")then
|
|
if(key==259)then -- on backspace
|
|
if(lines[textY]=="")then
|
|
if(textY>1)then
|
|
table.remove(lines,textY)
|
|
textX = lines[textY-1]:len()+1
|
|
wIndex = textX-self.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-self.w+1
|
|
if(wIndex<1)then wIndex = 1 end
|
|
lines[textY-1] = lines[textY-1]..lines[textY]
|
|
table.remove(lines,textY)
|
|
textY = textY-1
|
|
end
|
|
else
|
|
lines[textY] = lines[textY]:sub(1,textX-2)..lines[textY]:sub(textX,lines[textY]:len())
|
|
if(textX>1)then textX = textX-1 end
|
|
if(wIndex>1)then
|
|
if(textX<wIndex)then
|
|
wIndex = wIndex-1
|
|
end
|
|
end
|
|
end
|
|
if(textY<hIndex)then
|
|
hIndex = hIndex-1
|
|
end
|
|
self:setValue("")
|
|
end
|
|
|
|
if(key==257)then -- on enter
|
|
table.insert(lines,textY+1,lines[textY]:sub(textX,lines[textY]:len()))
|
|
lines[textY] = lines[textY]:sub(1,textX-1)
|
|
textY = textY+1
|
|
textX = 1
|
|
wIndex = 1
|
|
if(textY-hIndex>=self.h)then
|
|
hIndex = hIndex+1
|
|
end
|
|
self:setValue("")
|
|
end
|
|
|
|
if(key==265)then -- arrow up
|
|
if(textY>1)then
|
|
textY = textY-1
|
|
if(textX>lines[textY]:len()+1)then textX = lines[textY]:len()+1 end
|
|
if(wIndex>1)then
|
|
if(textX<wIndex)then
|
|
wIndex = textX-self.w+1
|
|
if(wIndex<1)then wIndex = 1 end
|
|
end
|
|
end
|
|
if(hIndex>1)then
|
|
if(textY<hIndex)then
|
|
hIndex = hIndex-1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if(key==264)then -- arrow down
|
|
if(textY<#lines)then
|
|
textY = textY+1
|
|
if(textX>lines[textY]:len()+1)then textX = lines[textY]:len()+1 end
|
|
|
|
if(textY>=hIndex+self.h)then
|
|
hIndex = hIndex+1
|
|
end
|
|
end
|
|
end
|
|
if(key==262)then -- arrow right
|
|
textX = textX+1
|
|
if(textY<#lines)then
|
|
if(textX>lines[textY]:len()+1)then
|
|
textX = 1
|
|
textY = textY+1
|
|
end
|
|
elseif(textX > lines[textY]:len())then
|
|
textX = lines[textY]:len()+1
|
|
end
|
|
if(textX<1)then textX = 1 end
|
|
if(textX<wIndex)or(textX>=self.w+wIndex)then
|
|
wIndex = textX-self.w+1
|
|
end
|
|
if(wIndex<1)then wIndex = 1 end
|
|
|
|
end
|
|
if(key==263)then -- arrow left
|
|
textX = textX-1
|
|
if(textX>=1)then
|
|
if(textX<wIndex)or(textX>=self.w+wIndex)then
|
|
wIndex = textX
|
|
end
|
|
end
|
|
if(textY>1)then
|
|
if(textX<1)then
|
|
textY = textY-1
|
|
textX = lines[textY]:len()+1
|
|
wIndex = textX-self.w+1
|
|
end
|
|
end
|
|
if(textX<1)then textX = 1 end
|
|
if(wIndex<1)then wIndex = 1 end
|
|
end
|
|
end
|
|
|
|
if(event=="char")then
|
|
lines[textY] = lines[textY]:sub(1,textX-1)..key..lines[textY]:sub(textX,lines[textY]:len())
|
|
textX = textX+1
|
|
if(textX>=self.w+wIndex)then wIndex = wIndex+1 end
|
|
self:setValue("")
|
|
end
|
|
|
|
local cursorX = (textX <= lines[textY]:len() and textX-1 or lines[textY]:len())-(wIndex-1)
|
|
if(cursorX>self.x+self.w-1)then cursorX = self.x+self.w-1 end
|
|
local cursorY = (textY-hIndex < self.h and textY-hIndex or textY-hIndex-1)
|
|
if(cursorX<1)then cursorX = 0 end
|
|
self.parent:setCursor(true, obx+cursorX, oby+cursorY, self.fgcolor)
|
|
return true
|
|
end
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self, event, button, x, y))then
|
|
local obx,oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
local anchx,anchy = self:getAnchorPosition()
|
|
if(event=="mouse_click")then
|
|
if(lines[y-oby+hIndex]~=nil)then
|
|
textX = x-obx+wIndex
|
|
textY = y-oby+hIndex
|
|
if(textX>lines[textY]:len())then
|
|
textX = lines[textY]:len()+1
|
|
end
|
|
if(textX<wIndex)then
|
|
wIndex = textX-1
|
|
if(wIndex<1)then wIndex = 1 end
|
|
end
|
|
if(self.parent~=nil)then
|
|
self.parent:setCursor(true, anchx+textX-wIndex, anchy+textY-hIndex)
|
|
end
|
|
end
|
|
end
|
|
|
|
if(event=="mouse_scroll")then
|
|
hIndex = hIndex+button
|
|
if(hIndex>#lines-(self.h-1))then hIndex = #lines-(self.h-1) end
|
|
|
|
if(hIndex<1)then hIndex = 1 end
|
|
|
|
if(self.parent~=nil)then
|
|
if(obx+textX-wIndex>=obx and obx+textX-wIndex <= obx+self.w)and(oby+textY-hIndex >= oby and oby+textY-hIndex <= oby+self.h)then
|
|
self.parent:setCursor(true, anchx+textX-wIndex, anchy+textY-hIndex)
|
|
else
|
|
self.parent:setCursor(false)
|
|
end
|
|
end
|
|
end
|
|
self:setVisualChanged()
|
|
return true
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
for n=1, self.h do
|
|
local text = ""
|
|
if(lines[n+hIndex-1]~=nil)then
|
|
text = lines[n+hIndex-1]
|
|
end
|
|
text = text:sub(wIndex, self.w+wIndex-1)
|
|
local space = self.w-text:len()
|
|
if(space<0)then space = 0 end
|
|
text = text..string.rep(" ", space)
|
|
self.parent:setText(obx, oby+n-1, text)
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function List(name)
|
|
local base = Object(name)
|
|
local typ = "List"
|
|
base.w = 16
|
|
base.h = 6
|
|
base.bgcolor = theme.listBG
|
|
base.fgcolor = theme.listFG
|
|
base:setZIndex(5)
|
|
|
|
local list = {}
|
|
local itemSelectedBG = theme.selectionBG
|
|
local itemSelectedFG = theme.selectionFG
|
|
local selectionColorActive = true
|
|
local align = "left"
|
|
local yOffset = 0
|
|
local scrollable = true
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
addItem = function(self, text, bgCol, fgCol, ...)
|
|
table.insert(list, {text=text, bgCol = bgCol or self.bgcolor, fgCol = fgCol or self.fgcolor, args={...}})
|
|
if(#list==1)then
|
|
self:setValue(list[1])
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setIndexOffset = function(self, yOff)
|
|
yOffset = yOff
|
|
return self
|
|
end;
|
|
|
|
getIndexOffset = function(self)
|
|
return yOffset
|
|
end;
|
|
|
|
removeItem = function(self, index)
|
|
table.remove(list, index)
|
|
return self
|
|
end;
|
|
|
|
getItem = function(self, index)
|
|
return list[index]
|
|
end;
|
|
|
|
getItemIndex = function(self)
|
|
local selected = self:getValue()
|
|
for k,v in pairs(list)do
|
|
if(v==selected)then
|
|
return k
|
|
end
|
|
end
|
|
end;
|
|
|
|
clear = function(self)
|
|
list = {}
|
|
self:setValue({})
|
|
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={...}})
|
|
return self
|
|
end;
|
|
|
|
selectItem = function(self, index)
|
|
self:setValue(list[index] or {})
|
|
return self
|
|
end;
|
|
|
|
setSelectedItem = function(self, bgCol, fgCol, active)
|
|
itemSelectedBG = bgCol or self.bgcolor
|
|
itemSelectedFG = fgCol or self.fgcolor
|
|
selectionColorActive = active
|
|
return self
|
|
end;
|
|
|
|
setScrollable = function(self, scroll)
|
|
scrollable = scroll
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self, event, button, x, y))then
|
|
local obx,oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(event=="mouse_click")or(event=="mouse_drag")then -- remove mouse_drag if i want to make objects moveable uwuwuwuw
|
|
if(button==1)then
|
|
if(#list>0)then
|
|
for n=1,self.h do
|
|
if(list[n+yOffset]~=nil)then
|
|
if(obx<=x)and(obx+self.w>x)and(oby+n-1==y)then
|
|
self:setValue(list[n+yOffset])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if(event=="mouse_scroll")and(scrollable)then
|
|
yOffset = yOffset+button
|
|
if(yOffset<0)then yOffset = 0 end
|
|
if(button>=1)then
|
|
if(#list>self.h)then
|
|
if(yOffset>#list-self.h)then
|
|
yOffset = #list-self.h
|
|
end
|
|
if(yOffset>=#list)then yOffset = #list-1 end
|
|
else
|
|
yOffset = yOffset-1
|
|
end
|
|
end
|
|
end
|
|
self:setVisualChanged()
|
|
return true
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
for n=1, self.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, getTextHorizontalAlign(list[n+yOffset].text, self.w, align), itemSelectedBG, itemSelectedFG)
|
|
else
|
|
self.parent:writeText(obx, oby+n-1, getTextHorizontalAlign(list[n+yOffset].text, self.w, align), list[n+yOffset].bgCol, list[n+yOffset].fgCol)
|
|
end
|
|
else
|
|
self.parent:writeText(obx, oby+n-1, getTextHorizontalAlign(list[n+yOffset].text, self.w, align), list[n+yOffset].bgCol,list[n+yOffset].fgCol)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Menubar(name)
|
|
local base = Object(name)
|
|
local typ = "Menubar"
|
|
|
|
base.w = 30
|
|
base.h = 1
|
|
base.bgcolor = colors.gray
|
|
base.fgcolor = colors.lightGray
|
|
base:setZIndex(5)
|
|
|
|
local list = {}
|
|
local itemSelectedBG = theme.selectionBG
|
|
local itemSelectedFG = theme.selectionFG
|
|
local selectionColorActive = true
|
|
local align = "left"
|
|
local itemOffset = 0
|
|
local space = 2
|
|
local scrollable = false
|
|
|
|
local function maxScroll()
|
|
local mScroll = 0
|
|
local xPos = 1
|
|
for n=1,#list do
|
|
if(xPos + list[n].text:len() + space*2 > base.w)then
|
|
mScroll = mScroll + 1
|
|
end
|
|
xPos = xPos+list[n].text:len()+space*2
|
|
|
|
end
|
|
return mScroll
|
|
end
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
addItem = function(self, text, bgCol, fgCol, ...)
|
|
table.insert(list, {text=text, bgCol = bgCol or self.bgcolor, fgCol = fgCol or self.fgcolor, args={...}})
|
|
if(#list==1)then
|
|
self:setValue(list[1])
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getItemIndex = function(self)
|
|
local selected = self:getValue()
|
|
for k,v in pairs(list)do
|
|
if(v==selected)then
|
|
return k
|
|
end
|
|
end
|
|
end;
|
|
|
|
clear = function(self)
|
|
list = {}
|
|
self:setValue({})
|
|
return self
|
|
end;
|
|
|
|
setSpace = function(self, _space)
|
|
space = _space or space
|
|
return self
|
|
end;
|
|
|
|
setButtonOffset = function(self, offset)
|
|
itemOffset = offset or 0
|
|
if(itemOffset<0)then
|
|
itemOffset = 0
|
|
end
|
|
|
|
local mScroll = maxScroll()
|
|
if(itemOffset>mScroll)then
|
|
itemOffset = mScroll
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setScrollable = function(self, scroll)
|
|
scrollable = scroll
|
|
return self
|
|
end;
|
|
|
|
removeItem = function(self, index)
|
|
table.remove(list, index)
|
|
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={...}})
|
|
return self
|
|
end;
|
|
|
|
selectItem = function(self, index)
|
|
self:setValue(list[index] or {})
|
|
return self
|
|
end;
|
|
|
|
setSelectedItem = function(self, bgCol, fgCol, active)
|
|
itemSelectedBG = bgCol or self.bgcolor
|
|
itemSelectedFG = fgCol or self.fgcolor
|
|
selectionColorActive = active
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self,event,button,x,y))then
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(event=="mouse_click")then
|
|
local xPos = 1
|
|
for n=1+itemOffset,#list do
|
|
if(list[n]~=nil)then
|
|
if(xPos + list[n].text:len() + space*2 <= self.w)then
|
|
if(obx + (xPos-1)<= x)and(obx + (xPos-1) + list[n].text:len() + space*2 > x)and(oby == y)then
|
|
self:setValue(list[n])
|
|
end
|
|
xPos = xPos+list[n].text:len()+space*2
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
if(event=="mouse_scroll")and(scrollable)then
|
|
itemOffset = itemOffset+button
|
|
if(itemOffset<0)then
|
|
itemOffset = 0
|
|
end
|
|
|
|
local mScroll = maxScroll()
|
|
|
|
if(itemOffset>mScroll)then
|
|
itemOffset = mScroll
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
local xPos = 1
|
|
for n=1+itemOffset,#list do
|
|
if(list[n]~=nil)then
|
|
if(xPos + list[n].text:len() + space*2 <= self.w)then
|
|
if(list[n]==self:getValue())then
|
|
self.parent:writeText(obx + (xPos-1), oby, getTextHorizontalAlign((" "):rep(space)..list[n].text..(" "):rep(space), list[n].text:len()+space*2, align), itemSelectedBG or list[n].bgCol, itemSelectedFG or list[n].fgCol)
|
|
else
|
|
self.parent:writeText(obx + (xPos-1), oby, getTextHorizontalAlign((" "):rep(space)..list[n].text..(" "):rep(space), list[n].text:len()+space*2, align), list[n].bgCol, list[n].fgCol)
|
|
end
|
|
xPos = xPos+list[n].text:len()+space*2
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Dropdown(name)
|
|
local base = Object(name)
|
|
local typ = "Dropdown"
|
|
base.w = 12
|
|
base.h = 1
|
|
base.bgcolor = theme.dropdownBG
|
|
base.fgcolor = theme.dropdownFG
|
|
base:setZIndex(6)
|
|
|
|
local list = {}
|
|
local itemSelectedBG = theme.selectionBG
|
|
local itemSelectedFG = theme.selectionFG
|
|
local selectionColorActive = true
|
|
local align = "left"
|
|
local yOffset = 0
|
|
|
|
local dropdownW = 16
|
|
local dropdownH = 6
|
|
local closedSymbol = "\16"
|
|
local openedSymbol = "\31"
|
|
local state = 1
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
setIndexOffset = function(self, yOff)
|
|
yOffset = yOff
|
|
return self
|
|
end;
|
|
|
|
getIndexOffset = 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={...}})
|
|
if(#list==1)then
|
|
self:setValue(list[1])
|
|
end
|
|
return self
|
|
end;
|
|
|
|
removeItem = function(self, index)
|
|
table.remove(list, index)
|
|
return self
|
|
end;
|
|
|
|
getItem = function(self, index)
|
|
return list[index]
|
|
end;
|
|
|
|
getItemIndex = function(self)
|
|
local selected = self:getValue()
|
|
for k,v in pairs(list)do
|
|
if(v==selected)then
|
|
return k
|
|
end
|
|
end
|
|
end;
|
|
|
|
clear = function(self)
|
|
list = {}
|
|
self:setValue({})
|
|
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={...}})
|
|
return self
|
|
end;
|
|
|
|
selectItem = function(self, index)
|
|
self:setValue(list[index] or {})
|
|
return self
|
|
end;
|
|
|
|
setSelectedItem = function(self, bgCol, fgCol, active)
|
|
itemSelectedBG = bgCol or self.bgcolor
|
|
itemSelectedFG = fgCol or self.fgcolor
|
|
selectionColorActive = active
|
|
return self
|
|
end;
|
|
|
|
setDropdownSize = function(self, w, h)
|
|
dropdownW, dropdownH = w, h
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(state == 2)then
|
|
local obx,oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(event=="mouse_click")then -- remove mouse_drag if i want to make objects moveable uwuwuwuw
|
|
if(button==1)then
|
|
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])
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if(event=="mouse_scroll")then
|
|
yOffset = yOffset+button
|
|
if(yOffset<0)then yOffset = 0 end
|
|
if(button==1)then
|
|
if(#list>dropdownH)then
|
|
if(yOffset>#list-dropdownH)then
|
|
yOffset = #list-dropdownH
|
|
end
|
|
else
|
|
yOffset = list-1
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
self:setVisualChanged()
|
|
end
|
|
if(base.mouseHandler(self, event, button, x, y))then
|
|
state = 2
|
|
else
|
|
state = 1
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
local obx, oby = self:getAnchorPosition()
|
|
if(self.parent~=nil)then
|
|
self.parent:drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
if(#list>=1)then
|
|
if(self:getValue().text~=nil)then
|
|
if(state==1)then
|
|
self.parent:writeText(obx, oby, getTextHorizontalAlign(self:getValue().text, self.w, align):sub(1,self.w-1)..closedSymbol, self.bgcolor, self.fgcolor)
|
|
else
|
|
self.parent:writeText(obx, oby, getTextHorizontalAlign(self:getValue().text, self.w, align):sub(1,self.w-1)..openedSymbol, self.bgcolor, self.fgcolor)
|
|
end
|
|
end
|
|
if(state==2)then
|
|
for n=1, dropdownH do
|
|
if(list[n+yOffset]~=nil)then
|
|
if(list[n+yOffset]==self:getValue())then
|
|
if(selectionColorActive)then
|
|
self.parent:writeText(obx, oby+n, getTextHorizontalAlign(list[n+yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG)
|
|
else
|
|
self.parent:writeText(obx, oby+n, getTextHorizontalAlign(list[n+yOffset].text, dropdownW, align), list[n+yOffset].bgCol, list[n+yOffset].fgCol)
|
|
end
|
|
else
|
|
self.parent:writeText(obx, oby+n, getTextHorizontalAlign(list[n+yOffset].text, dropdownW, align), list[n+yOffset].bgCol,list[n+yOffset].fgCol)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Radio(name)
|
|
local base = Object(name)
|
|
local typ = "Radio"
|
|
base.w = 8
|
|
base.bgcolor = theme.listBG
|
|
base.fgcolor = theme.listFG
|
|
base:setZIndex(5)
|
|
|
|
local list = {}
|
|
local itemSelectedBG = theme.selectionBG
|
|
local itemSelectedFG = theme.selectionFG
|
|
local boxSelectedBG = base.bgcolor
|
|
local boxSelectedFG = base.fgcolor
|
|
local selectionColorActive = true
|
|
local symbol = "\7"
|
|
local align = "left"
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
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
|
|
return self
|
|
end;
|
|
|
|
removeItem = function(self, index)
|
|
table.remove(list, index)
|
|
return self
|
|
end;
|
|
|
|
getItem = function(self, index)
|
|
return list[index]
|
|
end;
|
|
|
|
getItemIndex = function(self)
|
|
local selected = self:getValue()
|
|
for k,v in pairs(list)do
|
|
if(v==selected)then
|
|
return k
|
|
end
|
|
end
|
|
end;
|
|
|
|
clear = function(self)
|
|
list = {}
|
|
self:setValue({})
|
|
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={...}})
|
|
return self
|
|
end;
|
|
|
|
selectItem = function(self, index)
|
|
self:setValue(list[index] or {})
|
|
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
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
local obx,oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(event=="mouse_click")then -- remove mouse_drag if i want to make objects moveable uwuwuwuw
|
|
if(button==1)then
|
|
if(#list>0)then
|
|
for _,v in pairs(list)do
|
|
if(obx+v.x-1<=x)and(obx+v.x-1+v.text:len()+2>=x)and(oby+v.y-1==y)then
|
|
self:setValue(v)
|
|
if(self.parent~=nil)then self.parent:setFocusedObject(self) end
|
|
--eventSystem:sendEvent(event, self, event, button, x, y)
|
|
self:setVisualChanged()
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
for _,v in pairs(list)do
|
|
if(v==self:getValue())then
|
|
if(align=="left")then
|
|
self.parent:writeText(v.x+obx-1,v.y+oby-1,symbol,boxSelectedBG,boxSelectedFG)
|
|
self.parent:writeText(v.x+2+obx-1,v.y+oby-1,v.text,itemSelectedBG,itemSelectedFG)
|
|
end
|
|
else
|
|
self.parent:drawBackgroundBox(v.x+obx-1, v.y+oby-1,1,1,self.bgcolor)
|
|
self.parent:writeText(v.x+2+obx-1,v.y+oby-1,v.text,v.bgCol,v.fgCol)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Timer(name)
|
|
local typ = "Timer"
|
|
|
|
local timer = 0
|
|
local savedRepeats = 0
|
|
local repeats = 0
|
|
local timerObj
|
|
local eventSystem = BasaltEvents()
|
|
|
|
local object = {
|
|
name = name,
|
|
getType = function(self)
|
|
return typ
|
|
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;
|
|
|
|
start = function(self)
|
|
repeats = savedRepeats
|
|
timerObj = os.startTimer(timer)
|
|
return self
|
|
end;
|
|
|
|
cancel = function(self)
|
|
if(timerObj~=nil)then
|
|
os.cancelTimer(timerObj)
|
|
end
|
|
return self
|
|
end;
|
|
|
|
onCall = function(self, func)
|
|
eventSystem:registerEvent("timed_event", func)
|
|
return self
|
|
end;
|
|
|
|
eventHandler = function(self, event, tObj)
|
|
if(event=="timer")and(tObj==timerObj)then
|
|
eventSystem:sendEvent("timed_event",self)
|
|
if(repeats>=1)then
|
|
repeats = repeats - 1
|
|
if(repeats >= 1)then
|
|
timerObj = os.startTimer(timer)
|
|
end
|
|
elseif(repeats == -1)then
|
|
timerObj = os.startTimer(timer)
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
object.__index = object
|
|
|
|
return object
|
|
end
|
|
|
|
local function Thread(name)
|
|
local object
|
|
local typ = "Thread"
|
|
|
|
local func
|
|
local cRoutine
|
|
local isActive = false
|
|
|
|
object = {
|
|
name = name,
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
getZIndex = function(self)
|
|
return 1
|
|
end;
|
|
getName = function(self)
|
|
return self.name
|
|
end;
|
|
|
|
start = function(self, f)
|
|
if(f==nil)then error("function is nil") end
|
|
func = f
|
|
cRoutine = coroutine.create(func)
|
|
isActive = true
|
|
local ok, result = coroutine.resume(cRoutine)
|
|
if not(ok)then
|
|
if(result~="Terminated")then
|
|
error("Threaderror - "..result)
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
getStatus = function(self, f)
|
|
if(cRoutine~=nil)then
|
|
return coroutine.status(cRoutine)
|
|
end
|
|
return nil
|
|
end;
|
|
|
|
stop = function(self, f)
|
|
isActive = false
|
|
return self
|
|
end;
|
|
|
|
eventHandler = function(self, event, p1,p2,p3)
|
|
if(isActive)then
|
|
if(coroutine.status(cRoutine)~="dead")then
|
|
local ok, result = coroutine.resume(cRoutine, event,p1,p2,p3)
|
|
if not(ok)then
|
|
if(result~="Terminated")then
|
|
error("Threaderror - "..result)
|
|
end
|
|
end
|
|
else
|
|
isActive = false
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
|
|
object.__index = object
|
|
|
|
return object
|
|
end
|
|
|
|
local function Animation(name)
|
|
local object = {}
|
|
local typ = "Animation"
|
|
|
|
local timerObj
|
|
|
|
local animations = {}
|
|
local index = 1
|
|
|
|
local nextWaitTimer = 0
|
|
local lastFunc
|
|
|
|
local function onPlay()
|
|
if(animations[index]~=nil)then
|
|
animations[index].f(object, index)
|
|
end
|
|
index = index+1
|
|
if(animations[index]~=nil)then
|
|
if(animations[index].t>0)then
|
|
timerObj = os.startTimer(animations[index].t)
|
|
else
|
|
onPlay()
|
|
end
|
|
end
|
|
end
|
|
|
|
object = {
|
|
name = name,
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
getZIndex = function(self)
|
|
return 1
|
|
end;
|
|
|
|
getName = function(self)
|
|
return self.name
|
|
end;
|
|
|
|
add = function(self, func, wait)
|
|
lastFunc = func
|
|
table.insert(animations, {f=func,t = wait or nextWaitTimer})
|
|
return self
|
|
end;
|
|
|
|
wait = function(self, wait)
|
|
nextWaitTimer = wait
|
|
return self
|
|
end;
|
|
|
|
rep = function(self, reps)
|
|
for x=1,reps do
|
|
table.insert(animations, {f=lastFunc,t = nextWaitTimer})
|
|
end
|
|
return self
|
|
end;
|
|
|
|
clear = function(self)
|
|
animations = {}
|
|
lastFunc = nil
|
|
nextWaitTimer = 0
|
|
index = 1
|
|
return self
|
|
end;
|
|
|
|
play = function(self)
|
|
index = 1
|
|
if(animations[index]~=nil)then
|
|
if(animations[index].t>0)then
|
|
timerObj = os.startTimer(animations[index].t)
|
|
else
|
|
onPlay()
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
cancel = function(self)
|
|
os.cancelTimer(timerObj)
|
|
return self
|
|
end;
|
|
|
|
eventHandler = function(self, event, tObj)
|
|
if(event=="timer")and(tObj==timerObj)then
|
|
if(animations[index]~=nil)then
|
|
onPlay()
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
object.__index = object
|
|
|
|
return object
|
|
end
|
|
|
|
local function Slider(name)
|
|
local base = Object(name)
|
|
local typ = "Slider"
|
|
|
|
base.w = 8
|
|
base.bgcolor = colors.lightGray
|
|
base.fgcolor = colors.gray
|
|
base:setValue(1)
|
|
|
|
local barType = "horizontal"
|
|
local symbol = " "
|
|
local symbolColor=colors.black
|
|
local bgSymbol = "\140"
|
|
local maxValue = base.w
|
|
local index = 1
|
|
|
|
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
setSymbol = function(self, _symbol)
|
|
symbol = _symbol:sub(1,1)
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setBackgroundSymbol = function(self, _bgSymbol)
|
|
bgSymbol = string.sub(_bgSymbol,1,1)
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setSymbolColor = function(self, col)
|
|
symbolColor = col
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setBarType = function(self, _typ)
|
|
barType = _typ:lower()
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self,event,button,x,y))then
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(barType=="horizontal")then
|
|
for _index=0,self.w-1 do
|
|
if(obx+_index==x)and(oby<=y)and(oby+self.h>y)then
|
|
index = _index+1
|
|
self:setValue(maxValue/self.w*(index))
|
|
self:setVisualChanged()
|
|
end
|
|
end
|
|
end
|
|
if(barType=="vertical")then
|
|
for _index=0,self.h-1 do
|
|
if(oby+_index==y)and(obx<=x)and(obx+self.w>x)then
|
|
index = _index+1
|
|
self:setValue(maxValue/self.h*(index))
|
|
self:setVisualChanged()
|
|
end
|
|
end
|
|
end
|
|
--[[if(event=="mouse_scroll")then
|
|
self:setValue(self:getValue() + (maxValue/(barType=="vertical" and self.h or self.w))*typ)
|
|
self:setVisualChanged()
|
|
end
|
|
if(self:getValue()>maxValue)then self:setValue(maxValue) end
|
|
if(self:getValue()<maxValue/(barType=="vertical" and self.h or self.w))then self:setValue(maxValue/(barType=="vertical" and self.h or self.w)) end
|
|
]]
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
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, symbolColor, symbolColor)
|
|
self.parent:writeText(obx + index, oby, bgSymbol:rep(self.w - (index)), self.bgcolor, self.fgcolor)
|
|
end
|
|
|
|
if(barType=="vertical")then
|
|
for n = 0, self.h-1 do
|
|
if(n+1 == index)then
|
|
self.parent:writeText(obx, oby + n, symbol, symbolColor, symbolColor)
|
|
else
|
|
self.parent:writeText(obx, oby + n, bgSymbol, self.bgcolor, self.fgcolor)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
local function Scrollbar(name)
|
|
local base = Object(name)
|
|
local typ = "Scrollbar"
|
|
|
|
base.w = 1
|
|
base.h = 8
|
|
base.bgcolor = colors.lightGray
|
|
base.fgcolor = colors.gray
|
|
base:setValue(1)
|
|
base:setZIndex(2)
|
|
|
|
local barType = "vertical"
|
|
local symbol = " "
|
|
local symbolColor=colors.black
|
|
local bgSymbol = "\127"
|
|
local maxValue = base.h
|
|
local index = 1
|
|
local symbolSize = 1
|
|
|
|
|
|
local object = {
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
setSymbol = function(self, _symbol)
|
|
symbol = _symbol:sub(1,1)
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setSymbolSize = function(self, size)
|
|
symbolSize = tonumber(size) or 1
|
|
if(barType=="vertical")then
|
|
self:setValue(index-1 * (maxValue/(self.h-(symbolSize-1)))-(maxValue/(self.h-(symbolSize-1))))
|
|
elseif(barType=="horizontal")then
|
|
self:setValue(index-1 * (maxValue/(self.w-(symbolSize-1)))-(maxValue/(self.w-(symbolSize-1))))
|
|
end
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setMaxValue = function(self, val)
|
|
maxValue = val
|
|
return self
|
|
end;
|
|
|
|
setBackgroundSymbol = function(self, _bgSymbol)
|
|
bgSymbol = string.sub(_bgSymbol,1,1)
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setSymbolColor = function(self, col)
|
|
symbolColor = col
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setBarType = function(self, _typ)
|
|
barType = _typ:lower()
|
|
return self
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
if(base.mouseHandler(self,event,button,x,y))then
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if((event=="mouse_click")or(event=="mouse_drag"))and(button==1)then
|
|
if(barType=="horizontal")then
|
|
for _index=0,self.w do
|
|
if(obx+_index==x)and(oby<=y)and(oby+self.h>y)then
|
|
index = math.min(_index+1, self.w-(symbolSize-1))
|
|
self:setValue(maxValue/self.w*(index))
|
|
self:setVisualChanged()
|
|
end
|
|
end
|
|
end
|
|
if(barType=="vertical")then
|
|
for _index=0,self.h do
|
|
if(oby+_index==y)and(obx<=x)and(obx+self.w>x)then
|
|
index = math.min(_index+1, self.h-(symbolSize-1))
|
|
self:setValue(maxValue/self.h*(index))
|
|
self:setVisualChanged()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if(event=="mouse_scroll")then
|
|
index = index+button
|
|
if(index<1)then index = 1 end
|
|
index = math.min(index, (barType=="vertical" and self.h or self.w)-(symbolSize-1))
|
|
self:setValue(maxValue/(barType=="vertical" and self.h or self.w)*index)
|
|
end
|
|
return true
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(base.draw(self))then
|
|
if(self.parent~=nil)then
|
|
local obx, oby = self:getAnchorPosition()
|
|
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(self.w - (index+symbolSize-1)), self.bgcolor, self.fgcolor)
|
|
end
|
|
|
|
if(barType=="vertical")then
|
|
for n = 0, self.h-1 do
|
|
|
|
if(index==n+1)then
|
|
for curIndexOffset=0,math.min(symbolSize-1,self.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
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end;
|
|
}
|
|
|
|
return setmetatable(object, base)
|
|
end
|
|
|
|
|
|
local function Frame(name,parent) -- Frame
|
|
local base = Object(name)
|
|
local typ = "Frame"
|
|
local objects = {}
|
|
local objZIndex = {}
|
|
local object = {}
|
|
local focusedObject
|
|
base:setZIndex(10)
|
|
|
|
local cursorBlink = false
|
|
local xCursor = 1
|
|
local yCursor = 1
|
|
local cursorColor = colors.white
|
|
|
|
local xOffset, yOffset = 0, 0
|
|
|
|
if(parent~=nil)then
|
|
base.parent = parent
|
|
base.w, base.h = parent.w, parent.h
|
|
base.bgcolor = theme.FrameBG
|
|
base.fgcolor = theme.FrameFG
|
|
else
|
|
local termW, termH = parentTerminal.getSize()
|
|
base.w, base.h = termW, termH
|
|
base.bgcolor = theme.basaltBG
|
|
base.fgcolor = theme.basaltFG
|
|
end
|
|
|
|
local function getObject(name)
|
|
for k,v in pairs(objects)do
|
|
for a,b in pairs(v)do
|
|
if(b.name == name)then
|
|
return v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function addObject(obj)
|
|
local zIndex = obj:getZIndex()
|
|
if(getObject(obj.name)~=nil)then return nil end
|
|
if(objects[zIndex]==nil)then
|
|
for x=1,#objZIndex+1 do
|
|
if(objZIndex[x]~=nil)then
|
|
if(zIndex == objZIndex[x])then break end
|
|
if(zIndex > objZIndex[x])then
|
|
table.insert(objZIndex,x,zIndex)
|
|
break
|
|
end
|
|
else
|
|
table.insert(objZIndex,zIndex)
|
|
end
|
|
end
|
|
if(#objZIndex<=0)then
|
|
table.insert(objZIndex,zIndex)
|
|
end
|
|
objects[zIndex] = {}
|
|
end
|
|
obj.parent = object
|
|
table.insert(objects[zIndex],obj)
|
|
return obj
|
|
end
|
|
|
|
local function removeObject(obj)
|
|
for a,b in pairs(objects)do
|
|
for k,v in pairs(b)do
|
|
if(v==obj)then
|
|
table.remove(objects[a],k)
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
object = {
|
|
barActive = false,
|
|
barBackground = colors.gray,
|
|
barTextcolor = colors.black,
|
|
barText = "New Frame",
|
|
barTextAlign = "left",
|
|
isMoveable = false,
|
|
|
|
getType = function(self)
|
|
return typ
|
|
end;
|
|
|
|
setFocusedObject = function(self, obj)
|
|
for _,index in pairs(objZIndex)do
|
|
for _,v in pairs(objects[index])do
|
|
if(v == obj)then
|
|
if(focusedObject~=nil)then focusedObject:loseFocusHandler() end
|
|
focusedObject = obj
|
|
focusedObject:getFocusHandler()
|
|
end
|
|
end
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setOffset = function(self, xO, yO)
|
|
xOffset = xO ~= nil and math.floor(xO < 0 and math.abs(xO) or -xO) or xOffset
|
|
yOffset = yO ~= nil and math.floor(yO < 0 and math.abs(yO) or -yO) or yOffset
|
|
return self
|
|
end;
|
|
|
|
getFrameOffset = function(self)
|
|
return xOffset, yOffset
|
|
end;
|
|
|
|
removeFocusedObject = function(self)
|
|
if(focusedObject~=nil)then focusedObject:loseFocusHandler() end
|
|
focusedObject = nil
|
|
return self
|
|
end;
|
|
|
|
getFocusedObject = function(self)
|
|
return focusedObject
|
|
end;
|
|
|
|
show = function(self)
|
|
base:show()
|
|
if(self.parent==nil)then
|
|
activeFrame = self
|
|
end
|
|
return self
|
|
end;
|
|
|
|
setCursor = function(self, _blink, _xCursor, _yCursor, color)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
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
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setMoveable = function(self, moveable)
|
|
self.isMoveable = moveable or not self.isMoveable
|
|
self:setVisualChanged()
|
|
return self;
|
|
end;
|
|
|
|
|
|
showBar = function(self, showIt)
|
|
self.barActive = showIt or not self.barActive
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setBar = function(self, text, bgCol, fgCol)
|
|
self.barText = text or ""
|
|
self.barBackground = bgCol or self.barBackground
|
|
self.barTextcolor = fgCol or self.barTextcolor
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
setBarTextAlign = function(self, align)
|
|
self.barTextAlign = align or "left"
|
|
self:setVisualChanged()
|
|
return self
|
|
end;
|
|
|
|
getVisualChanged = function(self)
|
|
local changed = base.getVisualChanged(self)
|
|
for _,index in pairs(objZIndex)do
|
|
if(objects[index]~=nil)then
|
|
for _,v in pairs(objects[index])do
|
|
if(v.getVisualChanged~=nil and v:getVisualChanged())then
|
|
changed = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return changed
|
|
end;
|
|
|
|
loseFocusHandler = function(self)
|
|
base.loseFocusHandler(self)
|
|
end;
|
|
|
|
getFocusHandler = function(self)
|
|
base.getFocusHandler(self)
|
|
if(self.parent~=nil)then
|
|
self.parent:removeObject(self)
|
|
self.parent:addObject(self)
|
|
end
|
|
end;
|
|
|
|
keyHandler = function(self, event, key)
|
|
if(focusedObject~=nil)then
|
|
if(focusedObject.keyHandler~=nil)then
|
|
if(focusedObject:keyHandler(event,key))then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end;
|
|
|
|
eventHandler = function(self, event, p1, p2, p3, p4)
|
|
base.eventHandler(self, event, p1, p2, p3, p4)
|
|
for _,index in pairs(objZIndex)do
|
|
if(objects[index]~=nil)then
|
|
for _,v in pairs(objects[index])do
|
|
if(v.eventHandler~=nil)then
|
|
v:eventHandler(event,p1, p2, p3, p4)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if(event=="terminate")then
|
|
parentTerminal.clear()
|
|
parentTerminal.setCursorPos(1,1)
|
|
basalt.stop()
|
|
end
|
|
end;
|
|
|
|
mouseHandler = function(self, event, button, x, y)
|
|
local xO, yO = self:getOffset()
|
|
xO = xO < 0 and math.abs(xO) or -xO
|
|
yO = yO < 0 and math.abs(yO) or -yO
|
|
if(self.drag)then
|
|
if(event=="mouse_drag")then
|
|
local parentX=1;local parentY=1
|
|
if(self.parent~=nil)then
|
|
parentX,parentY = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
|
|
end
|
|
self:setPosition(x+self.xToRem-(parentX-1) + xO,y-(parentY-1) + yO)
|
|
end
|
|
if(event=="mouse_up")then
|
|
self.drag = false
|
|
end
|
|
return true
|
|
end
|
|
|
|
if(base.mouseHandler(self,event,button,x,y))then
|
|
local fx,fy = self:getAbsolutePosition(self:getAnchorPosition())
|
|
for _,index in pairs(objZIndex)do
|
|
if(objects[index]~=nil)then
|
|
for _,v in rpairs(objects[index])do
|
|
if(v.mouseHandler~=nil)then
|
|
if(v:mouseHandler(event,button,x+xO,y+yO))then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
if(focusedObject~=nil)then focusedObject:loseFocusHandler() end
|
|
end
|
|
end
|
|
|
|
if(self.isMoveable)then
|
|
if(x>=fx)and(x<=fx+self.w-1)and(y==fy)and(event=="mouse_click")then
|
|
self.drag = true
|
|
self.xToRem = fx-x
|
|
end
|
|
end
|
|
if(focusedObject~=nil)then focusedObject:loseFocusHandler() focusedObject = nil end
|
|
return true
|
|
end
|
|
return false
|
|
end;
|
|
|
|
setText = function(self, x, y, text)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(y>=1)and(y<=self.h)then
|
|
if(self.parent~=nil)then
|
|
self.parent:setText(math.max(x+(obx-1),obx)-(self.parent.x-1), oby+y-1-(self.parent.y-1), sub( text, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
else
|
|
drawHelper.setText(math.max(x+(obx-1),obx), oby+y-1, sub( text, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
end
|
|
end
|
|
end;
|
|
|
|
setBG = function(self, x, y, bgCol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(y>=1)and(y<=self.h)then
|
|
if(self.parent~=nil)then
|
|
self.parent:setBG(math.max(x+(obx-1),obx)-(self.parent.x-1), oby+y-1-(self.parent.y-1), sub( bgCol, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
else
|
|
drawHelper.setBG(math.max(x+(obx-1),obx), oby+y-1, sub( bgCol, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
end
|
|
end
|
|
end;
|
|
|
|
setFG = function(self, x, y, fgCol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(y>=1)and(y<=self.h)then
|
|
if(self.parent~=nil)then
|
|
self.parent:setFG(math.max(x+(obx-1),obx)-(self.parent.x-1), oby+y-1-(self.parent.y-1), sub( fgCol, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
else
|
|
drawHelper.setFG(math.max(x+(obx-1),obx), oby+y-1, sub( fgCol, math.max(1 - x + 1, 1), self.w - x + 1 ))
|
|
end
|
|
end
|
|
end;
|
|
|
|
writeText = function(self, x, y, text, bgCol, fgCol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
if(y>=1)and(y<=self.h)then
|
|
if(self.parent~=nil)then
|
|
self.parent:writeText(math.max(x+(obx-1),obx)-(self.parent.x-1), oby+y-1-(self.parent.y-1), sub( text, math.max(1 - x + 1, 1), self.w - x + 1 ), bgCol, fgCol)
|
|
else
|
|
drawHelper.writeText(math.max(x+(obx-1),obx), oby+y-1, sub( text, math.max(1 - x + 1, 1), self.w - x + 1 ), bgCol, fgCol)
|
|
end
|
|
end
|
|
end;
|
|
|
|
drawBackgroundBox = function(self, x, y, w, h, bgCol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
h = (y < 1 and (h+y > self.h and self.h or h+y-1) or (h+y > self.h and self.h-y+1 or h))
|
|
w = (x < 1 and (w+x > self.w and self.w or w+x-1) or (w+x > self.w and self.w-x+1 or w))
|
|
if(self.parent~=nil)then
|
|
self.parent:drawBackgroundBox(math.max(x+(obx-1),obx)-(self.parent.x-1), math.max(y+(oby-1),oby)-(self.parent.y-1), w, h, bgCol)
|
|
else
|
|
drawHelper.drawBackgroundBox(math.max(x+(obx-1),obx), math.max(y+(oby-1),oby), w, h, bgCol)
|
|
end
|
|
end;
|
|
|
|
drawTextBox = function(self, x, y, w, h, symbol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
h = (y < 1 and (h+y > self.h and self.h or h+y-1) or (h+y > self.h and self.h-y+1 or h))
|
|
w = (x < 1 and (w+x > self.w and self.w or w+x-1) or (w+x > self.w and self.w-x+1 or w))
|
|
if(self.parent~=nil)then
|
|
self.parent:drawTextBox(math.max(x+(obx-1),obx)-(self.parent.x-1), math.max(y+(oby-1),oby)-(self.parent.y-1), w, h, symbol:sub(1,1))
|
|
else
|
|
drawHelper.drawTextBox(math.max(x+(obx-1),obx), math.max(y+(oby-1),oby), w, h, symbol:sub(1,1))
|
|
end
|
|
end;
|
|
|
|
drawForegroundBox = function(self, x, y, w, h, fgCol)
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
h = (y < 1 and (h+y > self.h and self.h or h+y-1) or (h+y > self.h and self.h-y+1 or h))
|
|
w = (x < 1 and (w+x > self.w and self.w or w+x-1) or (w+x > self.w and self.w-x+1 or w))
|
|
if(self.parent~=nil)then
|
|
self.parent:drawForegroundBox(math.max(x+(obx-1),obx)-(self.parent.x-1), math.max(y+(oby-1),oby)-(self.parent.y-1), w, h, fgCol)
|
|
else
|
|
drawHelper.drawForegroundBox(math.max(x+(obx-1),obx), math.max(y+(oby-1),oby), w, h, fgCol)
|
|
end
|
|
end;
|
|
|
|
draw = function(self)
|
|
if(self:getVisualChanged())then
|
|
if(base.draw(self))then
|
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
|
local anchx, anchy = self:getAnchorPosition()
|
|
if(self.parent~=nil)then
|
|
self.parent:drawBackgroundBox(anchx, anchy, self.w, self.h, self.bgcolor)
|
|
self.parent:drawForegroundBox(anchx, anchy, self.w, self.h, self.fgcolor)
|
|
self.parent:drawTextBox(anchx, anchy, self.w, self.h, " ")
|
|
else
|
|
drawHelper.drawBackgroundBox(obx, oby, self.w, self.h, self.bgcolor)
|
|
drawHelper.drawForegroundBox(obx, oby, self.w, self.h, self.fgcolor)
|
|
drawHelper.drawTextBox(obx, oby, self.w, self.h, " ")
|
|
end
|
|
parentTerminal.setCursorBlink(false)
|
|
if(self.barActive)then
|
|
if(self.parent~=nil)then
|
|
self.parent:writeText(anchx, anchy, getTextHorizontalAlign(self.barText, self.w, self.barTextAlign), self.barBackground, self.barTextcolor)
|
|
else
|
|
drawHelper.writeText(obx, oby, getTextHorizontalAlign(self.barText, self.w, self.barTextAlign), self.barBackground, self.barTextcolor)
|
|
end
|
|
end
|
|
|
|
for _,index in rpairs(objZIndex)do
|
|
if(objects[index]~=nil)then
|
|
for _,v in pairs(objects[index])do
|
|
if(v.draw~=nil)then
|
|
v:draw()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if(cursorBlink)then
|
|
parentTerminal.setTextColor(cursorColor)
|
|
parentTerminal.setCursorPos(xCursor, yCursor)
|
|
if(self.parent~=nil)then
|
|
parentTerminal.setCursorBlink(self:isFocused())
|
|
else
|
|
parentTerminal.setCursorBlink(cursorBlink)
|
|
end
|
|
end
|
|
self:setVisualChanged(false)
|
|
end
|
|
end
|
|
end;
|
|
|
|
addObject = function(self, obj)
|
|
return addObject(obj)
|
|
end;
|
|
|
|
removeObject = function(self, obj)
|
|
return removeObject(obj)
|
|
end;
|
|
|
|
addButton = function(self, name)
|
|
local obj = Button(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addLabel = function(self, name)
|
|
local obj = Label(name)
|
|
obj.name = name
|
|
obj.bgcolor = self.bgcolor
|
|
obj.fgcolor = self.fgcolor
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addCheckbox = function(self, name)
|
|
local obj = Checkbox(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addInput = function(self, name)
|
|
local obj = Input(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addProgram = function(self, name)
|
|
local obj = Program(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addTextfield = function(self, name)
|
|
local obj = Textfield(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addList = function(self, name)
|
|
local obj = List(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addDropdown = function(self, name)
|
|
local obj = Dropdown(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addRadio = function(self, name)
|
|
local obj = Radio(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addTimer = function(self, name)
|
|
local obj = Timer(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addAnimation = function(self, name)
|
|
local obj = Animation(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addSlider = function(self, name)
|
|
local obj = Slider(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addScrollbar = function(self, name)
|
|
local obj = Scrollbar(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addMenubar = function(self, name)
|
|
local obj = Menubar(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addThread = function(self, name)
|
|
local obj = Thread(name)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
|
|
addFrame = function(self, name)
|
|
local obj = Frame(name, self)
|
|
obj.name = name
|
|
return addObject(obj)
|
|
end;
|
|
}
|
|
setmetatable(object, base)
|
|
if(parent==nil)then
|
|
table.insert(frames, object)
|
|
end
|
|
return object
|
|
end
|
|
|
|
|
|
local updaterActive = false
|
|
local function basaltUpdateEvent(event, p1,p2,p3,p4)
|
|
if(event=="mouse_click")then activeFrame:mouseHandler(event,p1,p2,p3,p4) end
|
|
if(event=="mouse_drag")then activeFrame:mouseHandler(event,p1,p2,p3,p4) end
|
|
if(event=="mouse_up")then activeFrame:mouseHandler(event,p1,p2,p3,p4) end
|
|
if(event=="mouse_scroll")then activeFrame:mouseHandler(event,p1,p2,p3,p4) end
|
|
if(event=="key")or(event=="char")then activeFrame:keyHandler(event,p1,p2,p3,p4) end
|
|
for _,v in pairs(frames)do
|
|
v:eventHandler(event, p1, p2, p3, p4)
|
|
end
|
|
if(updaterActive)then
|
|
activeFrame:draw()
|
|
drawHelper.update()
|
|
end
|
|
end
|
|
|
|
function basalt.autoUpdate(isActive)
|
|
parentTerminal.clear()
|
|
updaterActive = isActive or true
|
|
activeFrame:draw()
|
|
drawHelper.update()
|
|
while updaterActive do
|
|
local event, p1,p2,p3,p4 = os.pullEventRaw() -- change to raw later
|
|
basaltUpdateEvent(event, p1,p2,p3,p4)
|
|
end
|
|
end
|
|
|
|
function basalt.update(event, p1, p2, p3, p4)
|
|
if(event~="nil")then
|
|
basaltUpdateEvent(event, p1,p2,p3,p4)
|
|
else
|
|
activeFrame:draw()
|
|
drawHelper.update()
|
|
end
|
|
end
|
|
|
|
function basalt.stop()
|
|
updaterActive = false
|
|
end
|
|
|
|
function basalt.getFrame(name)
|
|
for k,v in pairs(frames)do
|
|
if(v.name==name)then
|
|
return v
|
|
end
|
|
end
|
|
end
|
|
|
|
function basalt.getActiveFrame()
|
|
return activeFrame
|
|
end
|
|
|
|
function basalt.setActiveFrame(frame)
|
|
if(frame:getType()=="Frame")then
|
|
activeFrame = frame
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function basalt.createFrame(name)
|
|
local frame = Frame(name)
|
|
return frame
|
|
end
|
|
|
|
function basalt.removeFrame(name)
|
|
for k,v in pairs(frames)do
|
|
if(v.name==name)then
|
|
frames[k] = nil
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
if(basalt.debugger)then
|
|
basalt.debugFrame = basalt.createFrame("basaltDebuggingFrame"):showBar():setBackground(colors.lightGray):setBar("Debug",colors.black,colors.gray)
|
|
basalt.debugList = basalt.debugFrame:addList("debugList"):setSize(basalt.debugFrame.w - 2, basalt.debugFrame.h - 3):setPosition(2,3):show()
|
|
basalt.debugFrame:addButton("back"):setAnchor("right"):setSize(1,1):setText("\22"):onClick(function() basalt.oldFrame:show() end):setBackground(colors.red):show()
|
|
basalt.debugLabel = basalt.debugFrame:addLabel("debugLabel"):onClick(function() basalt.oldFrame = activeFrame basalt.debugFrame:show() end):setBackground(colors.black):setForeground(colors.white):setAnchor("bottom"):show()
|
|
end
|
|
|
|
|
|
if(basalt.debugger)then
|
|
function basalt.debug(...)
|
|
local args = {...}
|
|
if(activeFrame.name~="basaltDebuggingFrame")then
|
|
if(activeFrame~=basalt.debugLabel.frame)then
|
|
basalt.debugLabel:setParent(activeFrame)
|
|
end
|
|
end
|
|
local str = ""
|
|
for k,v in pairs(args)do
|
|
str = str..tostring(v)..(#args~=k and ", " or "")
|
|
end
|
|
basalt.debugLabel:setText("[Debug] "..str)
|
|
basalt.debugList:addItem(str)
|
|
if(basalt.debugList:getItemCount()>basalt.debugList.h)then basalt.debugList:removeItem(1) end
|
|
|
|
basalt.debugLabel:show()
|
|
end
|
|
end
|
|
|
|
return basalt |